diff --git a/ctrl/modopts.d/xtrnmenu.ini b/ctrl/modopts.d/xtrnmenu.ini index 752b38fe80092740f021b1c24109430ab056cd80..561fb774ea100c6e3d16bae9da860d275e0805f4 100644 --- a/ctrl/modopts.d/xtrnmenu.ini +++ b/ctrl/modopts.d/xtrnmenu.ini @@ -20,7 +20,10 @@ clear_screen = true ; uncomment and modify any of the below to change the look of the external programs menu ; to remove titles or underline, set to the text ' ' ;multicolumn_separator: " " -;singlecolumn_margin=7 + +; set the singlecolumn margin to the number of lines of your footer, if you have one +;singlecolumn_margin=2 + ;header_fmt: \1n\1c\1h%s \1n\1cExternal Programs:\r\n\r\n ;titles: \1n\1cKey \1h\xb3\1n\1c Name \1n\1c multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-32.32s \1h diff --git a/exec/load/xtrnmenulib.js b/exec/load/xtrnmenulib.js index e982c10c63e15e78c7758a71c277e9f83942ad3e..71e6e790c4bf2278e337328dbdbddd6611a1341d 100644 --- a/exec/load/xtrnmenulib.js +++ b/exec/load/xtrnmenulib.js @@ -168,12 +168,6 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) { ? this.xtrn_custommenu_options.singlecolumn_margin : this.options.singlecolumn_margin; if (typeof bbs !== "undefined") { - this.options.singlecolumn_height = (typeof this.xtrn_custommenu_options.singlecolumn_height !== "undefined") - ? this.xtrn_custommenu_options.singlecolumn_height : this.options.singlecolumn_height; - - if (this.options.singlecolumn_height === undefined) - this.options.singlecolumn_height = console.screen_rows - this.options.singlecolumn_margin; - // override and turn off multicolumn if terminal width is less than 80 if (console.screen_columns < 80) options.multicolumn = false; diff --git a/exec/xtrnmenu.js b/exec/xtrnmenu.js index b0c436c7cc877108af7d276f72fd66efd8fd5c5f..3fa3fed9d1535663cc624bd2ef45ab5a15f31a0a 100644 --- a/exec/xtrnmenu.js +++ b/exec/xtrnmenu.js @@ -637,8 +637,18 @@ function external_menu_custom(menuid) // then display that, otherwise dynamiic if (!bbs.menu("xtrnmenu_" + menuid, P_NOERROR)) { + // determine lines left. we can't know the size of the footer so + // let the sysop use singlecolumn_margin to specify that. Below + // calcution will always leave room for titles and underline even + // if they aren't rendered + var linesleft = console.screen_rows - console.line_counter - options.singlecolumn_margin + - 2 - 2; // -2 for header_fmt/crlf and -2 for crlf and footer + if(options.titles.trimRight() != '') linesleft = linesleft - 1; + if(options.underline.trimRight() != '') linesleft = linesleft - 2; + + multicolumn = menuitemsfiltered.length > linesleft; + // if no custom menu file in text/menu, create a dynamic one - multicolumn = options.multicolumn && menuitemsfiltered.length > options.singlecolumn_height; printf(options.header_fmt, menuobj.title); if(options.titles.trimRight() != '') write(options.titles); @@ -760,8 +770,8 @@ function external_menu_custom(menuid) if (selected_index == j) { if (menuitemsfiltered[j].type == 'quit') { printf(multicolumn ? return_multicolumn_fmt_inverse : return_singlecolumn_fmt_inverse, - menuitemsfiltered[i].input.toString().toUpperCase(), - menuitemsfiltered[i].title, + menuitemsfiltered[j].input.toString().toUpperCase(), + menuitemsfiltered[j].title, '' ); } else { @@ -1066,8 +1076,18 @@ function special_menu(menutype, title, itemcount) { type: 'quit', }); + // determine lines left. we can't know the size of the footer so + // let the sysop use singlecolumn_margin to specify that. Below + // calcution will always leave room for titles and underline even + // if they aren't rendered + var linesleft = console.screen_rows - console.line_counter - options.singlecolumn_margin + - 2 - 2; // -2 for header_fmt/crlf and -2 for crlf and footer + if(options.titles.trimRight() != '') linesleft = linesleft - 1; + if(options.underline.trimRight() != '') linesleft = linesleft - 2; + + multicolumn = menuitemsfiltered.length > linesleft; + // if no custom menu file in text/menu, create a dynamic one - multicolumn = options.multicolumn && menuitemsfiltered.length > options.singlecolumn_height; printf(options.header_fmt, title); if(options.titles.trimRight() != '') write(options.titles); @@ -1462,9 +1482,17 @@ function search_menu(title, itemcount) { type: 'quit', }); - // if no custom menu file in text/menu, create a dynamic one - multicolumn = options.multicolumn && menuitemsfiltered.length > options.singlecolumn_height; - + // determine lines left. we can't know the size of the footer so + // let the sysop use singlecolumn_margin to specify that. Below + // calcution will always leave room for titles and underline even + // if they aren't rendered + var linesleft = console.screen_rows - console.line_counter - options.singlecolumn_margin + - 2 - 2; // -2 for header_fmt/crlf and -2 for crlf and footer + if(options.titles.trimRight() != '') linesleft = linesleft - 1; + if(options.underline.trimRight() != '') linesleft = linesleft - 2; + + multicolumn = menuitemsfiltered.length > linesleft; + if(options.titles.trimRight() != '') write(options.titles); if(multicolumn) { @@ -1825,9 +1853,18 @@ function favorites_menu(title, itemcount) { target: '', type: 'remove' }); - - // if no custom menu file in text/menu, create a dynamic one - multicolumn = options.multicolumn && menuitemsfiltered.length > options.singlecolumn_height; + + // determine lines left. we can't know the size of the footer so + // let the sysop use singlecolumn_margin to specify that. Below + // calcution will always leave room for titles and underline even + // if they aren't rendered + var linesleft = console.screen_rows - console.line_counter - options.singlecolumn_margin + - 2 - 2; // -2 for header_fmt/crlf and -2 for crlf and footer + if(options.titles.trimRight() != '') linesleft = linesleft - 1; + if(options.underline.trimRight() != '') linesleft = linesleft - 2; + + multicolumn = menuitemsfiltered.length > linesleft; + printf(options.header_fmt, title); if(options.titles.trimRight() != '') write(options.titles); diff --git a/exec/xtrnmenucfg.js b/exec/xtrnmenucfg.js index 7e731e93dbe3b93a3700d0d631e8492d72c438b2..531018e90d807385e02a4b6d675f98501ac2d973 100644 --- a/exec/xtrnmenucfg.js +++ b/exec/xtrnmenucfg.js @@ -189,12 +189,12 @@ var editItems = function(menuid) { editItem(menu.id, 0); } */ - + uifc.help_text = word_wrap("This menu allows editing the various items in this menu.\r\n\r\n" + "If you leave input key blank, it will use an auto-generated number at display time.\r\n\r\n" + "Choose a type first and the dropdown to choose the target will allow you to select your target.\r\n\r\n" + "Access string only applies to custom menu items, commands, and special menus. For external sections or external programs, use the access settings in scfg.\r\n\r\n", - 72); + 72); while(1) { items = []; @@ -209,7 +209,7 @@ var editItems = function(menuid) { itemids.push(i); } selection = uifc.list( - WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC|WIN_XTR|WIN_INS|WIN_DEL|WIN_CUT|WIN_COPY|WIN_PASTE|WIN_PASTEXTR|WIN_SAV, + WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC|WIN_XTR|WIN_INS|WIN_DEL|WIN_CUT|WIN_COPY|WIN_PASTE|WIN_PASTEXTR|WIN_SAV, menu.title + ": Items", items, ctxm @@ -261,7 +261,7 @@ var editItems = function(menuid) { // if item already exists in list, modify if since you can't have dupes (except empty input keys) for (var i in menu.items) { if ((menu.items[i].input == copyitem.input) - && (copyitem.input !== null) && (copyitem.input !== "")) { + && (copyitem.input !== null) && (copyitem.input !== "")) { oktopaste = true; while(1) { selection2 = uifc.input(WIN_MID, "Enter New Input Key", "", 3, K_EDIT); @@ -301,13 +301,13 @@ var editItems = function(menuid) { ctxm.cur = i-1; pushed = true; } - menuitems2.push(menu.items[i]); - } + menuitems2.push(menu.items[i]); + } if (!pushed) { - // add to end - menuitems2.push(copyitem); - ctxm.cur = menuitems2.length-1; - } + // add to end + menuitems2.push(copyitem); + ctxm.cur = menuitems2.length-1; + } menu.items = menuitems2; } } @@ -332,7 +332,7 @@ var editItem = function(menuid, itemindex) { var displayoptions = [], displayoptionids = [], newitems = []; // used for building target selection var custommenuitems = [], custommenuitemsids = [], custommenunames = []; - + if (typeof menuid === "undefined") { uifc.msg("Menu could not be found"); return; @@ -347,13 +347,13 @@ var editItem = function(menuid, itemindex) { if (typeof menu.items[itemindex] === "undefined") { // new item - // + // menu.items.push({ - "input": null, - "title": "New Item " + time(), - "type": null, - "target": null, - "access_string": null, + input: null, + title: null, + type: null, + target: null, + access_string: null, }); itemindex = menu.items.length - 1; present_select_targettype(menu.items[itemindex]); @@ -379,80 +379,80 @@ var editItem = function(menuid, itemindex) { displayoptionids.push("type"); switch (item.type) { - case 'recentall': - case 'recentuser': - case 'mostlaunchedall': - case 'mostlauncheduser': - case 'longestrunall': - case 'longestrunuser': - case 'search': - case 'favorites': - displayoptions.push(format("%23s: %s", "count", - ("target" in item ? item.target : ""))); - displayoptionids.push("target"); - break; - case 'custommenu': - case 'xtrnmenu': - case 'xtrnprog': - case 'command': - default: - displayoptions.push(format("%23s: %s", "target", - ("target" in item ? item.target : ""))); - displayoptionids.push("target"); - break; - } + case 'recentall': + case 'recentuser': + case 'mostlaunchedall': + case 'mostlauncheduser': + case 'longestrunall': + case 'longestrunuser': + case 'search': + case 'favorites': + displayoptions.push(format("%23s: %s", "count", + ("target" in item ? item.target : ""))); + displayoptionids.push("target"); + break; + case 'custommenu': + case 'xtrnmenu': + case 'xtrnprog': + case 'command': + default: + displayoptions.push(format("%23s: %s", "target", + ("target" in item ? item.target : ""))); + displayoptionids.push("target"); + break; + } switch (item.type) { - case 'custommenu': - case 'command': - case 'recentall': - case 'recentuser': - case 'mostlaunchedall': - case 'mostlauncheduser': - case 'longestrunuser': - case 'longestrunall': - case 'search': - case 'favorites': - displayoptions.push(format("%23s: %s", "access_string", - ("access_string" in item ? item.access_string : "(default)"))); - displayoptionids.push("access_string"); - break; - case 'xtrnmenu': - case 'xtrnprog': - default: - break; - } + case 'custommenu': + case 'command': + case 'recentall': + case 'recentuser': + case 'mostlaunchedall': + case 'mostlauncheduser': + case 'longestrunuser': + case 'longestrunall': + case 'search': + case 'favorites': + displayoptions.push(format("%23s: %s", "access_string", + ("access_string" in item ? item.access_string : "(default)"))); + displayoptionids.push("access_string"); + break; + case 'xtrnmenu': + case 'xtrnprog': + default: + break; + } selection = uifc.list(WIN_ORG | WIN_MID | WIN_ACT | WIN_ESC, menu.title + ": Item " + itemindex, displayoptions, itemctx); if (selection < 0) { if (!item.title || !item.type) { - if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) { - // delete item and continue - newitems = []; - for (i in menu.items) { - if (i != itemindex) { - newitems.push(menu.items[i]); - } - } - menu.items = newitems; - break; - } - } else if (!item.target && ((item.type == "custommenu") || (item.type == "command") - || (item.type == "xtrnmenu") || (item.type == "xtrnprog"))) { - if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) { - // delete item and continue - newitems = []; - for (i in menu.items) { - if (i != itemindex) { - newitems.push(menu.items[i]); - } - } - menu.items = newitems; - break; - } - break; + if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) { + // delete item and continue + newitems = []; + for (i in menu.items) { + if (i != itemindex) { + newitems.push(menu.items[i]); + } + } + menu.items = newitems; + break; + } + } else if (!item.target && ((item.type == "custommenu") || (item.type == "command") + || (item.type == "xtrnmenu") || (item.type == "xtrnprog"))) { + if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) { + // delete item and continue + newitems = []; + for (i in menu.items) { + if (i != itemindex) { + newitems.push(menu.items[i]); + } + } + menu.items = newitems; + break; + } + break; } else { // leave menu break; @@ -483,10 +483,10 @@ var editItem = function(menuid, itemindex) { keyused = true; } } - - if (selection2 == "Q") { - uifc.msg("This input key Q is reserved"); - } else if (keyused) { + + if (selection2 == "Q") { + uifc.msg("This input key Q is reserved"); + } else if (keyused) { uifc.msg("This input key is already used by another item."); } else { item.input = selection2; @@ -542,16 +542,16 @@ function present_select_targettype(item) + "xtrnmenu is a standard Syncrhonet External Section Menu (refer to the scfg tool).\r\n\r\n" + "xtrnprog is a direct link to an external program (refer to the scfg tool)" + "command is a synchronet command line. See http://wiki.synchro.net/config:cmdline" - + "recentall is a special menu of most recently used games, by all users" - + "recentuser is a special menu of most recently used games, for current user" - + "mostlaunchedall is a special menu of most launched games, by all users" - + "mostlauncheduser is a special menu of most launched games, for current user" - + "longestrunall is a special menu of games that users spent the most time in" - + "longestrunuser is a special menu of games that current user spent the most time in" - + "search is a special menu item to perform a search" - + "favorites is a special menu to let the user pick favorite games to play", 72); - - var targetypectx = uifc.list.CTX(0, 0, 0, 0, 0); + + "recentall is a special menu of most recently used games, by all users" + + "recentuser is a special menu of most recently used games, for current user" + + "mostlaunchedall is a special menu of most launched games, by all users" + + "mostlauncheduser is a special menu of most launched games, for current user" + + "longestrunall is a special menu of games that users spent the most time in" + + "longestrunuser is a special menu of games that current user spent the most time in" + + "search is a special menu item to perform a search" + + "favorites is a special menu to let the user pick favorite games to play", 72); + + // for existing items, set the popup to the correct value if (typeof item.type !== "undefined") { switch (item.type) { case 'custommenu': @@ -570,44 +570,44 @@ function present_select_targettype(item) targetypectx.cur = 3; targetypectx.bar = 3; break; - case 'recentall': - targetypectx.cur = 4; - targetypectx.bar = 4; - break; - case 'recentuser': - targetypectx.cur = 5; - targetypectx.bar = 5; - break; - case 'mostlaunchedall': - targetypectx.cur = 6; - targetypectx.bar = 6; - break; - case 'mostlauncheduser': - targetypectx.cur = 7; - targetypectx.bar = 7; - break; - case 'longestrunall': - targetypectx.cur = 8; - targetypectx.bar = 8; - break; - case 'longestrunuser': - targetypectx.cur = 9; - targetypectx.bar = 9; - break; - case 'search': - targetypectx.cur = 10; - targetypectx.bar = 10; - break; - case 'favorites': - targetypectx.cur = 11; - targetypectx.bar = 11; - break; - } + case 'recentall': + targetypectx.cur = 4; + targetypectx.bar = 4; + break; + case 'recentuser': + targetypectx.cur = 5; + targetypectx.bar = 5; + break; + case 'mostlaunchedall': + targetypectx.cur = 6; + targetypectx.bar = 6; + break; + case 'mostlauncheduser': + targetypectx.cur = 7; + targetypectx.bar = 7; + break; + case 'longestrunall': + targetypectx.cur = 8; + targetypectx.bar = 8; + break; + case 'longestrunuser': + targetypectx.cur = 9; + targetypectx.bar = 9; + break; + case 'search': + targetypectx.cur = 10; + targetypectx.bar = 10; + break; + case 'favorites': + targetypectx.cur = 11; + targetypectx.bar = 11; + break; + } } switch (uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target Type", ["custommenu", "xtrnmenu", "xtrnprog", "command", "recentall", - "recentuser", "mostlaunchedall", "mostlauncheduser", "longestrunall", - "longestrunuser", "search", "favorites"], targetypectx)) { + "recentuser", "mostlaunchedall", "mostlauncheduser", "longestrunall", + "longestrunuser", "search", "favorites"], targetypectx)) { case 0: item.type = "custommenu"; break; @@ -620,31 +620,31 @@ function present_select_targettype(item) case 3: item.type = "command"; break; - case 4: - item.type = "recentall"; - break; - case 5: - item.type = "recentuser"; - break; - case 6: - item.type = "mostlaunchedall"; - break; - case 7: - item.type = "mostlauncheduser"; - break; - case 8: - item.type = "longestrunall"; - break; - case 9: - item.type = "longestrunuser"; - break; - case 10: - item.type = "search"; - break; - case 11: - item.type = "favorites"; - break; - default: + case 4: + item.type = "recentall"; + break; + case 5: + item.type = "recentuser"; + break; + case 6: + item.type = "mostlaunchedall"; + break; + case 7: + item.type = "mostlauncheduser"; + break; + case 8: + item.type = "longestrunall"; + break; + case 9: + item.type = "longestrunuser"; + break; + case 10: + item.type = "search"; + break; + case 11: + item.type = "favorites"; + break; + default: // includes escape key break; } @@ -656,9 +656,7 @@ function present_select_targettype(item) function present_select_target(item) { uifc.help_text = word_wrap("This is the ID of the custom menu, external program section, or external program to link to. " - + "For special menus (recentall, etc.), it is the number of items to display.", 72); - - var targetctx = uifc.list.CTX(0, 0, 0, 0, 0); + + "For special menus (recentall, etc.), it is the number of items to display.", 72); var custommenuitems = []; var custommenuitemsids = []; @@ -678,23 +676,31 @@ function present_select_target(item) if ((typeof item.target !== "undefined") && item.target) { for (var p in custommenuitemsids) { if (custommenuitemsids[p] == item.target) { - targetctx.cur = p; - targetctx.bar = p; + targetctxmenu.cur = p; + targetctxmenu.bar = p; } } } - - selection2 = uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target", custommenuitems, targetctx); + + selection2 = uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target", custommenuitems, targetctxmenu); if ((selection2 < 0) || (selection2 == null)) { // escape key break; } + // increment counter for rapid bulk adding + if (targetctxmenu.cur < custommenuitemsids.length) { + ++targetctxmenu.cur; + ++targetctxmenu.bar; + } + item.target = custommenuitemsids[selection2]; while(1) { - if (uifc.list(WIN_ORG | WIN_MID, "Replace item title with sections's name?", ["Yes", "No"]) == 0) { + if ((item.title !== null) && uifc.list(WIN_ORG | WIN_MID, "Replace item title with menus's name?", ["Yes", "No"]) == 0) { item.title = custommenunames[selection2]; // for external program, change title to program name + } else if (item.title === null) { + item.title = custommenunames[selection2]; } break; } @@ -717,23 +723,31 @@ function present_select_target(item) if ((typeof item.target !== "undefined") && item.target) { for (var p in custommenuitemsids) { if (custommenuitemsids[p].toLowerCase() == item.target.toLowerCase()) { - targetctx.cur = p; - targetctx.bar = p; + targetctxsection.cur = p; + targetctxsection.bar = p; } } - } + } - selection2 = uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target", custommenuitems, targetctx); + selection2 = uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target", custommenuitems, targetctxsection); if ((selection2 < 0) || (selection2 == null)) { // escape key break; } + + // increment counter for rapid bulk adding + if (targetctxsection.cur < custommenuitemsids.length) { + ++targetctxsection.cur; + ++targetctxsection.bar; + } item.target = custommenuitemsids[selection2]; while(1) { - if (uifc.list(WIN_ORG | WIN_MID, "Replace item title with sections's name?", ["Yes", "No"]) == 0) { + if ((item.title !== null) && uifc.list(WIN_ORG | WIN_MID, "Replace item title with sections's name?", ["Yes", "No"]) == 0) { item.title = custommenunames[selection2]; // for external program, change title to program name + } else if (item.title === null) { + item.title = custommenunames[selection2]; } break; } @@ -757,30 +771,39 @@ function present_select_target(item) if ((typeof item.target !== "undefined") && item.target) { for (var p in custommenuitemsids) { if (custommenuitemsids[p].toLowerCase() == item.target.toLowerCase()) { - targetctx.cur = p; - targetctx.bar = p; + targetctxprog.cur = p; + targetctxprog.bar = p; } } - } - - selection2 = uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target", custommenuitems, targetctx); + } + + selection2 = uifc.list(WIN_ORG | WIN_MID | WIN_SAV, "Target", custommenuitems, targetctxprog); if ((selection2 < 0) || (selection2 == null)) { // escape key break; } + + // increment counter for rapid bulk adding + if (targetctxprog.cur < custommenuitemsids.length) { + ++targetctxprog.cur; + ++targetctxprog.bar; + } + if (selection2 || selection2 === 0) { item.target = custommenuitemsids[selection2]; while(1) { - if (uifc.list(WIN_ORG | WIN_MID, "Replace item title with sections's name?", ["Yes", "No"]) == 0) { + if ((item.title !== null) && uifc.list(WIN_ORG | WIN_MID, "Replace item title with programs's name?", ["Yes", "No"]) == 0) { item.title = custommenunames[selection2]; // for external program, change title to program name + } else if (item.title === null) { + item.title = custommenunames[selection2]; } break; } } break; - case "command": - selection2 = uifc.input(WIN_ORG | WIN_MID, "Command", item.target, 63, K_EDIT); + case "command": + selection2 = uifc.input(WIN_ORG | WIN_MID, "Command", item.target, 63, K_EDIT); if ((selection2 < 0) || (selection2 == null)) { // escape key break; @@ -788,23 +811,23 @@ function present_select_target(item) item.target = selection2; break; - case "recentall": - case "recentuser": - case "mostlaunchedall": - case "mostlauncheduser": - case "longestrunall": - case "longestrunuser": - case "search": - case "favorites": - selection2 = uifc.input(WIN_ORG | WIN_MID, "Number of Items to Display", item.target, 63, K_EDIT); - if ((selection2 < 0) || (selection2 == null)) { - // escape key - break; - } - item.target = selection2; - break; - break; - + case "recentall": + case "recentuser": + case "mostlaunchedall": + case "mostlauncheduser": + case "longestrunall": + case "longestrunuser": + case "search": + case "favorites": + selection2 = uifc.input(WIN_ORG | WIN_MID, "Number of Items to Display", item.target, 63, K_EDIT); + if ((selection2 < 0) || (selection2 == null)) { + // escape key + break; + } + item.target = selection2; + break; + break; + default: selection2 = uifc.input(WIN_ORG | WIN_MID, "Target", item.target, 50, K_EDIT); if ((selection2 < 0) || (selection2 == null)) { @@ -843,6 +866,13 @@ try { var menuconfig = {}; var copyitem = {}; // for menu item copy/paste var config_file = new File(file_cfgname(system.ctrl_dir, "xtrnmenu.cfg")); + // this is made to persist so that if adding multiple items, it will + // remember the position of the target type (good for bulk adds) + var targetypectx = uifc.list.CTX(0, 0, 0, 0, 0); + var targetctxmenu = uifc.list.CTX(0, 0, 0, 0, 0); + var targetctxsection = uifc.list.CTX(0, 0, 0, 0, 0); + var targetctxprog = uifc.list.CTX(0, 0, 0, 0, 0); + if (config_file.open('r+')) { var config_src = config_file.read(); try {