Newer
Older
/* This is a message reader/lister door for Synchronet. Features include:
* - Listing messages in the user's current message area with the ability to
* navigate forwards & backwards through the list (and for ANSI users, a
* lightbar interface will be used, or optionally can be set to use a more
* traditional interface for ANSI users)
* - The user can select a message from the list to read and optionally reply to
* - For ANSI users, reading messages is done with an enhanced user interface,
* with the ability to scroll up & down through the message, move to the next
* or previous message using the right & left arrow keys, display the message
* list to choose another message to read, etc.
* - The ability to start up with the message list or reading messages in the
* user's current message area (AKA sub-board)
* - Message searching
*
* Author: Eric Oulashin (AKA Nightfox)
* BBS: Digital Distortion
* BBS address: digitaldistortionbbs.com (or digdist.bbsindex.com)
*
* Date Author Description
* 2014-09-13 Eric Oulashin Started (based on my message lister script)
* ... Comments trimmed ...

Eric Oulashin
committed
* 2023-09-22 Eric Oulashin Version 1.80 beta
* Improved speed of new-to-you scans, and to an extent (hopefully) overall speed
* Bug fix: Setting reverseListOrder to "ask" in the .cfg file works properly again.
* Bug fix: When listing messages in reverse order, the selected menu index
* (for lightbar mode) is now correct.
* Bug fix: If the user is allowed to read deleted messages, then allow
* the left & right arrow keys to to the next/previous message if it's deleted.
* Small fixes for indexed scanning mode.
* New: For personal email, unread emails will have an 'unread' message indicator
* in the message list as a U between the message number and the 'from' name.
* New user setting: "Quit from reader to message list": When enabled,
* quitting from reader mode goes to the message list instead of exiting
* out of DDMsgReader fully.
* New user setting: Enter/selection from indexed mode menu shows message list
* (instead of going into reader mode)
* New user setting: List messages in reverse order
* 2023-10-10 Eric Oulashin Version 1.80
* Releasing this version
* 2023-10-11 Eric Oulashin Version 1.81
* Updated permission check functions (speed improvement)

Eric Oulashin
committed
* 2023-10-18 Eric Oulashin Version 1.82
* Fix for # posts and missing dates in sub-board list when changing sub-board

Eric Oulashin
committed
* 2023-10-25 Eric Oulashin Version 1.83
* Personal emails to the sysop received as "sysop" (or starting with "sysop")
* are now correctly identified and marked as read when read

Eric Oulashin
committed
* 2023-10-26 Eric Oulashin Version 1.84
* Fix in reader mode for refreshing the message area after
* closing another window (necessary with recent changes to
* substrWithAttrCodes())
Eric Oulashin
committed
* 2023-11-01 Eric Oulashin Version 1.85
* Mark personal email as read if the user is just reading personal email

Eric Oulashin
committed
* 2023-11-09 Eric Oulashin Version 1.86
* New feature: For indexed mode, when choosing a sub-board, the R key
* can be used to mark all messages as read in the sub-board.
* Fix: For continuous newscan or browse newscan (SCAN_BACK),
* call the stock Synchronet behavior (DDMsgReader did this previously,
* as DDMsgReader doesn't implement those yet).
* Fix: In the message list, to-user alternate colors weren't being used
* unless the message was read. The correct colors are used again.

Eric Oulashin
committed
* 2023-11-09 Eric Oulashin Version 1.87 Beta
* Trying to speed things up by not getting vote headers all the time
* when calling get_all_msg_headers(), unless the vote headers are needed
* (when the sysop views who votes on a message when viewing tally info)
* New: User setting to only show new messages in a newscan (defaults to true/enabled)
* In the message list, there is now an additional space before the
* 'from' name, in case one of the status characters is a letter (this should
* look better).
* New: In lightbar mode, the indexed newscan menu can optionally 'snap' to
* the next sub-board with new messages when showing/returning to the menu
* Fix: When listing personal email, messages to the user were written
* with the to-user color wuen unread. Now the regular colors are always
* used (since all of a user's personal emails are 'to' them).
* Fix: For indexed newscan, if there are no sub-boards selected for scan
* in the user's newscan configuration, then output a message and return.
* Otherwise, it would end up in an infinite loop.
* Updated how user settings are loaded, to ensure that default user settings
* from DDMsgReader.cfg actually get set properly in the user settings.

Eric Oulashin
committed
* 2023-11-23 Eric Oulashin Version 1.88
* New user setting/configuration option to prompt the user whether or
* not to delete a personal email after replying to it (defaults to false).
* New: Displays whether a personal email has been replied to.
* Fix: Now displaying message vote score in the default header again.
* Fix: When viewing message headers (for the sysop), now correctly
* shows the message attributes.

Eric Oulashin
committed
* 2023-11-30 Eric Oulashin Version 1.89
* New: User option to toggle whether to display the email 'replied' indicator
* (defaults to true).
* Fix for setting colors for the key help lines so that the background
* won't get un-done if the other help line colors have a N (normal) attribute.

Eric Oulashin
committed
* 2023-12-02 Eric Oulashin Version 1.90 Beta
* New: operator menu for read mode, with the option to add the author to the
* twit list, etc.
* Fix: When refreshing a rectangular area of a message, if it's a poll message,
* the background color for the voted responses was used for the non-selected
* responses.
* Removed the setting useScrollingInterfaceForANSIMessages.
* 2023-12-04 Eric Oulashin Version 1.90
* Releasing this version

Eric Oulashin
committed
* 2023-12-12 Eric Oulashin Version 1.90a
* New configurable colors in the theme file for the indexed mode newscan menu:
* indexMenuSeparatorLine (sub-board separator line) and indexMenuSeparatorText
* (sub-board separator text)

Eric Oulashin
committed
* 2023-12-15 Eric Oulashin Version 1.90b
* New configurable colors in the theme file for the indexed newscan menu
* header text (indexMenuHeader), "NEW" indicator text (indexMenuNewIndicator),
* and highlighted "NEW" indicator text (indexMenuNewIndicatorHighlight)

Eric Oulashin
committed
* 2023-12-26 Eric Oulashin Version 1.91
* New sysop features while reading a message: Show message hex (with the X key)
* and save message hex to a file (with Ctrl-X)

Eric Oulashin
committed
* 2023-12-29 Eric Oulashin Version 1.92
* Indexed newscan: By default, if there are no new messages, it now shows
* "No new messages." (578 QWKNoNewMessages from text.dat). There's a new user
* setting to toggle whether to use the indexed newscan menu even if there are
* no new messages. New configuration file option: displayIndexedModeMenuIfNoNewMessages,
* which is a default for the user setting.

Eric Oulashin
committed
* 2024-01-01 Eric Oulashin Version 1.93
* New user-toggleable behavior: Show indexed menu after reading all new messages.
* Also, indexed reader mode (started with the -indexedMode command-line option)
* now lists ALL sub-boards, rather than only sub-boards the user has enabled
* for newscan. It also prompts the user to list sub-boards in the current group
* or all.
*/
"use strict";
/* Command-line arguments (in -arg=val format, or -arg format to enable an
option):
-search: A search type. Available options:
keyword_search: Do a keyword search in message subject/body text (current message area)
from_name_search: 'From' name search (current message area)
to_name_search: 'To' name search (current message area)
to_user_search: To user search (current message area)
new_msg_scan: New message scan (prompt for current sub-board, current
group, or all)
new_msg_scan_all: New message scan (all sub-boards)
new_msg_scan_cur_grp: New message scan (current message group only)

nightfox
committed
new_msg_scan_cur_sub: New message scan (current sub-board only). This
can (optionally) be used with the -subBoard
command-line parameter, which specifies an internal
code for a sub-board, which may be different from
the user's currently selected sub-board.
to_user_new_scan: Scan for new (unread) messages to the user (prompt
for current sub-board, current group, or all)
to_user_new_scan_all: Scan for new (unread) messages to the user
(all sub-boards)
to_user_new_scan_cur_grp: Scan for new (unread) messages to the user
(current group)
to_user_new_scan_cur_sub: Scan for new (unread) messages to the user
(current sub-board)
to_user_all_scan: Scan for all messages to the user (prompt for current
sub-board, current group, or all)
prompt: Prompt the user for one of several search/scan options to
choose from
Note that if the -personalEmail option is specified (to read personal
email), the only valid search types are keyword_search and
from_name_search.
-suppressSearchTypeText: Disable the search type text that would appear
above searches or scans (such as "New To You
Message Scan", etc.)
-startMode: Startup mode. Available options:
list (or lister): Message list mode
read (or reader): Message read mode
-configFilename: Specifies the name of the configuration file to use.
Defaults to DDMsgReader.cfg.
-personalEmail: Read personal email to the user. This is a true/false value.
It doesn't need to explicitly have a =true or =false afterward;
simply including -personalEmail will enable it. If this is specified,
the -chooseAreaFirst and -subBoard options will be ignored.
-personalEmailSent: Read personal email to the user. This is a true/false
value. It doesn't need to explicitly have a =true or =false
afterward; simply including -personalEmailSent will enable it.
-allPersonalEmail: Read all personal email (to/from all)
-userNum: Specify a user number (for the personal email options)
-chooseAreaFirst: Display the message area chooser before reading/listing
messages. This is a true/false value. It doesn't need
to explicitly have a =true or =false afterward; simply
including -chooseAreaFirst will enable it. If -personalEmail
or -subBoard is specified, then this option won't have any
effect.
-subBoard: The sub-board (internal code or number) to read, other than the user's
current sub-board. If this is specified, the -chooseAreaFirst option
will be ignored.
-verboseLogging: Enable logging to the system log & node log. Currently, there
isn't much that will be logged, but more log messages could be
added in the future.
*/
// - For pageUp & pageDown, enable alternate keys:
// - When reading a message - scrollTextLines()
// - When listing messages
// - When listing message groups & sub-boards for sub-board selection
// - For sub-board area search:
// - Enable searching in traditional interface
// - Update the keys in the lightbar help line and traditional interface

Eric Oulashin
committed
// This script requires Synchronet version 3.18 or higher (for mouse hotspot support).
// Exit if the Synchronet version is below the minimum.

Eric Oulashin
committed
if (system.version_num < 31800)
{
var message = "\x01n\x01h\x01y\x01i* Warning:\x01n\x01h\x01w Digital Distortion Message Reader "

Eric Oulashin
committed
+ "requires version \x01g3.18\x01w or\r\n"
+ "higher of Synchronet. This BBS is using version \x01g" + system.version
+ "\x01w. Please notify the sysop.";
console.crlf();
console.print(message);
console.crlf();
console.pause();
exit();
}
Eric Oulashin
committed
require("sbbsdefs.js", "K_UPPER");
require("text.js", "Email"); // Text string definitions (referencing text.dat)
require("utf8_cp437.js", "utf8_cp437");
require("userdefs.js", "USER_UTF8");
require("dd_lightbar_menu.js", "DDLightbarMenu");
require("html2asc.js", 'html2asc');
require("attr_conv.js", "convertAttrsToSyncPerSysCfg");
require("graphic.js", 'Graphic');

Eric Oulashin
committed
require("smbdefs.js", "SMB_POLL_ANSWER");
Eric Oulashin
committed
load('822header.js');
var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a');

Eric Oulashin
committed
var hexdump = load('hexdump_lib.js');
Eric Oulashin
committed
// Reader version information

Eric Oulashin
committed
var READER_VERSION = "1.93";
var READER_DATE = "2024-01-01";
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// Keyboard key codes for displaying on the screen
var UP_ARROW = ascii(24);
var DOWN_ARROW = ascii(25);
var LEFT_ARROW = ascii(17);
var RIGHT_ARROW = ascii(16);
// Ctrl keys for input
var CTRL_A = "\x01";
var CTRL_B = "\x02";
var CTRL_C = "\x03";
var CTRL_D = "\x04";
var CTRL_E = "\x05";
var CTRL_F = "\x06";
var CTRL_G = "\x07";
var BEEP = CTRL_G;
var CTRL_H = "\x08";
var BACKSPACE = CTRL_H;
var CTRL_I = "\x09";
var TAB = CTRL_I;
var CTRL_J = "\x0a";
var CTRL_K = "\x0b";
var CTRL_L = "\x0c";
var CTRL_M = "\x0d";
var CTRL_N = "\x0e";
var CTRL_O = "\x0f";
var CTRL_P = "\x10";
var CTRL_Q = "\x11";
var XOFF = CTRL_Q;
var CTRL_R = "\x12";
var CTRL_S = "\x13";
var XON = CTRL_S;
var CTRL_T = "\x14";
var CTRL_U = "\x15";
var CTRL_V = "\x16";
var KEY_INSERT = CTRL_V;
var CTRL_W = "\x17";
var CTRL_X = "\x18";
var CTRL_Y = "\x19";
var CTRL_Z = "\x1a";
//var KEY_ESC = "\x1b";
var KEY_ESC = ascii(27);
var KEY_ENTER = CTRL_M;
// PageUp & PageDown keys - Synchronet 3.17 as of about December 18, 2017
// use CTRL-P and CTRL-N for PageUp and PageDown, respectively. sbbsdefs.js
// defines them as KEY_PAGEUP and KEY_PAGEDN; I've used slightly different names
// in this script so that this script will work with Synchronet systems before
// and after the update containing those key definitions.
var KEY_PAGE_UP = CTRL_P;
var KEY_PAGE_DOWN = CTRL_N;
// Ensure KEY_PAGE_UP and KEY_PAGE_DOWN are set to what's defined in sbbs.js
// for KEY_PAGEUP and KEY_PAGEDN in case they change
if (typeof(KEY_PAGEUP) === "string")
KEY_PAGE_UP = KEY_PAGEUP;
if (typeof(KEY_PAGEDN) === "string")
KEY_PAGE_DOWN = KEY_PAGEDN;
// These are defined in sbbsdefs.js:
//var KEY_UP ='\x1e'; // ctrl-^ (up arrow)
//var KEY_DOWN ='\x0a'; // ctrl-j (dn arrow)
//var KEY_RIGHT ='\x06'; // ctrl-f (rt arrow)
//var KEY_LEFT ='\x1d'; // ctrl-] (lf arrow)
//var KEY_HOME ='\x02'; // ctrl-b (home)
//var KEY_END ='\x05'; // ctrl-e (end)
//var KEY_DEL ='\x7f'; // (del)
// These were added to sbbsdef.js around December 17, 2017:
//var KEY_PAGEUP ='\x10'; /* ctrl-p (Page Up) */
//var KEY_PAGEDN ='\x0e'; /* ctrl-n (Page Down) */
// Characters for display
// Box-drawing/border characters: Single-line
var UPPER_LEFT_SINGLE = "\xDA";
var HORIZONTAL_SINGLE = "\xC4";
var UPPER_RIGHT_SINGLE = "\xBF";
var VERTICAL_SINGLE = "\xB3";
var LOWER_LEFT_SINGLE = "\xC0";
var LOWER_RIGHT_SINGLE = "\xD9";
var T_SINGLE = "\xC2";
var LEFT_T_SINGLE = "\xC3";
var RIGHT_T_SINGLE = "\xB4";
var BOTTOM_T_SINGLE = "\xC1";
var CROSS_SINGLE = "\xC5";
// Box-drawing/border characters: Double-line
var UPPER_LEFT_DOUBLE = "\xC9";
var HORIZONTAL_DOUBLE = "\xCD";
var UPPER_RIGHT_DOUBLE = "\xBB";
var VERTICAL_DOUBLE = "\xBA";
var LOWER_LEFT_DOUBLE = "\xC8";
var LOWER_RIGHT_DOUBLE = "\xBC";
var T_DOUBLE = "\xCB";
var LEFT_T_DOUBLE = "\xCC";
var RIGHT_T_DOUBLE = "\xB9";
var BOTTOM_T_DOUBLE = "\xCA";
var CROSS_DOUBLE = "\xCE";
// Box-drawing/border characters: Vertical single-line with horizontal double-line
var UPPER_LEFT_VSINGLE_HDOUBLE = "\xD5";
var UPPER_RIGHT_VSINGLE_HDOUBLE = "\xB8";
var LOWER_LEFT_VSINGLE_HDOUBLE = "\xD4";
var LOWER_RIGHT_VSINGLE_HDOUBLE = "\xBE";
// Other special characters
var DOT_CHAR = "\xF9";
var CHECK_CHAR = "\xFB";
var THIN_RECTANGLE_LEFT = "\xDD";
var THIN_RECTANGLE_RIGHT = "\xDE";

Eric Oulashin
committed
var BLOCK1 = "\xB0"; // Dimmest block
var BLOCK2 = "\xB1";
var BLOCK3 = "\xB2";
var BLOCK4 = "\xDB"; // Brightest block

Eric Oulashin
committed
var MID_BLOCK = ascii(254);

Eric Oulashin
committed
var TALL_UPPER_MID_BLOCK = "\xFE";
var UPPER_CENTER_BLOCK = "\xDF";
var LOWER_CENTER_BLOCK = "\xDC";
const ERROR_PAUSE_WAIT_MS = 1500;
// Reader mode definitions:
const READER_MODE_LIST = 0;
const READER_MODE_READ = 1;
// Search types
const SEARCH_NONE = -1;
const SEARCH_KEYWORD = 2;
const SEARCH_FROM_NAME = 3;
const SEARCH_TO_NAME_CUR_MSG_AREA = 4;
const SEARCH_TO_USER_CUR_MSG_AREA = 5;
const SEARCH_MSG_NEWSCAN = 6;
const SEARCH_MSG_NEWSCAN_CUR_SUB = 7;
const SEARCH_MSG_NEWSCAN_CUR_GRP = 8;
const SEARCH_MSG_NEWSCAN_ALL = 9;
const SEARCH_TO_USER_NEW_SCAN = 10;
const SEARCH_TO_USER_NEW_SCAN_CUR_SUB = 11;
const SEARCH_TO_USER_NEW_SCAN_CUR_GRP = 12;
const SEARCH_TO_USER_NEW_SCAN_ALL = 13;
const SEARCH_ALL_TO_USER_SCAN = 14;
// Message threading types

nightfox
committed
const THREAD_BY_ID = 15;
const THREAD_BY_TITLE = 16;
const THREAD_BY_AUTHOR = 17;
const THREAD_BY_TO_USER = 18;
// Scan scopes
const SCAN_SCOPE_SUB_BOARD = 0;
const SCAN_SCOPE_GROUP = 1;
const SCAN_SCOPE_ALL = 2;
// Reader mode - Actions

nightfox
committed
const ACTION_NONE = 19;
const ACTION_GO_NEXT_MSG = 20;
const ACTION_GO_PREVIOUS_MSG = 21;
const ACTION_GO_SPECIFIC_MSG = 22;
const ACTION_GO_FIRST_MSG = 23;
const ACTION_GO_LAST_MSG = 24;
const ACTION_DISPLAY_MSG_LIST = 25;
const ACTION_CHG_MSG_AREA = 26;
const ACTION_GO_PREV_MSG_AREA = 27;
const ACTION_GO_NEXT_MSG_AREA = 28;
const ACTION_QUIT = 29;
// Actions for indexed Mode
const INDEXED_MODE_SUBBOARD_MENU = 30;
// Definitions for help line refresh parameters for error functions
const REFRESH_MSG_AREA_CHG_LIGHTBAR_HELP_LINE = 0;
// Message list sort types
const MSG_LIST_SORT_DATETIME_RECEIVED = 0;
const MSG_LIST_SORT_DATETIME_WRITTEN = 1;

Eric Oulashin
committed
// Special value for passing to PopulateHdrsForCurrentSubBoard(): Start populating
// message headers from the scan pointer.
// This is a negative number so it won't get confuesd with a message header index.
const POPULATE_MSG_HDRS_FROM_SCAN_PTR = -1;
const POPULATE_NEWSCAN_FORCE_GET_ALL_HDRS = -2; // Get all message headers even for a newscan
// Misc. defines
var ERROR_WAIT_MS = 1500;
var SEARCH_TIMEOUT_MS = 10000;

nightfox
committed
// A regular expression to check whether a string is an email address

nightfox
committed
var gEmailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
// A regular expression to check whether a string is a FidoNet email address
var gFTNEmailRegex = /^.*@[0-9]+:[0-9]+\/[0-9]+$/;

nightfox
committed
// An array of regular expressions for checking for ANSI codes (globally in a string & ignore case)
var gANSIRegexes = [ new RegExp(ascii(27) + "\[[0-9]+[mM]", "gi"),
new RegExp(ascii(27) + "\[[0-9]+(;[0-9]+)+[mM]", "gi"),
new RegExp(ascii(27) + "\[[0-9]+[aAbBcCdD]", "gi"),
new RegExp(ascii(27) + "\[[0-9]+;[0-9]+[hHfF]", "gi"),
new RegExp(ascii(27) + "\[[sSuUkK]", "gi"),
new RegExp(ascii(27) + "\[2[jJ]", "gi") ];
// Determine the script's startup directory.
// This code is a trick that was created by Deuce, suggested by Rob Swindell
// as a way to detect which directory the script was executed in. I've
// shortened the code a little.
var gStartupPath = '.';
try { throw dig.dist(dist); } catch(e) { gStartupPath = e.fileName; }
gStartupPath = backslash(gStartupPath.replace(/[\/\\][^\/\\]*$/,''));
// See if we're running in Windows or not. Until early 2015, the word_wrap()
// function seemed to have a bug where the wrapping length in Linux was one
// less than what it uses in Windows). That seemed to be fixed in one of the
// Synchronet 3.16 builds in early 2015.
var gRunningInWindows = /^WIN/.test(system.platform.toUpperCase());
// Temporary directory (in the logged-in user's node directory) to store
// file attachments, etc.
var gFileAttachDir = backslash(system.node_dir + "DDMsgReader_Attachments");
// If the temporary attachments directory exists, then delete it (in case the last
// user hung up while running this script, etc.)
if (file_exists(gFileAttachDir))
deltree(gFileAttachDir);

Eric Oulashin
committed
// See if the avatar support file is available, and load is if so

nightfox
committed
var gAvatar = null;

Eric Oulashin
committed
if (file_exists(backslash(system.exec_dir) + "load/avatar_lib.js"))

nightfox
committed
gAvatar = load({}, "avatar_lib.js");

Eric Oulashin
committed
// User twitlist filename (and settings filename)
var gUserTwitListFilename = backslash(system.data_dir + "user") + format("%04d", user.number) + ".DDMsgReader_twitlist";

Eric Oulashin
committed
var gUserSettingsFilename = backslash(system.data_dir + "user") + format("%04d", user.number) + ".DDMsgReader_Settings";

Eric Oulashin
committed
/////////////////////////////////////////////
// Script execution code
// Parse the command-line arguments
var gCmdLineArgVals = parseArgs(argv);
if (gCmdLineArgVals.exitNow)
exit(0);
var gAllPersonalEmailOptSpecified = (gCmdLineArgVals.hasOwnProperty("allpersonalemail") && gCmdLineArgVals.allpersonalemail);
// Check to see if the command-line argument for reading personal email is enabled
var gListPersonalEmailCmdLineOpt = ((gCmdLineArgVals.hasOwnProperty("personalemail") && gCmdLineArgVals.personalemail) ||
(gCmdLineArgVals.hasOwnProperty("personalemailsent") && gCmdLineArgVals.personalemailsent) ||
gAllPersonalEmailOptSpecified);
// If the command-line parameter "search" is specified as "prompt", then
// prompt the user for the type of search to perform.

nightfox
committed
var gDoDDMR = true; // If the user doesn't choose a search type, this will be set to false
if (gCmdLineArgVals.hasOwnProperty("search") && (gCmdLineArgVals.search.toLowerCase() == "prompt"))
{
console.attributes = "N";
console.crlf();
console.print("\x01cMessage search:");
console.crlf();
var allowedKeys = "";
if (!gListPersonalEmailCmdLineOpt)
{
allowedKeys = "ANKFTYUS";
console.print(" \x01g\x01hN\x01y = \x01n\x01cNew message scan");
console.crlf();
console.print(" \x01g\x01hK\x01y = \x01n\x01cKeyword");
console.crlf();
console.print(" \x01h\x01gF\x01y = \x01n\x01cFrom name");
console.crlf();
console.print(" \x01h\x01gT\x01y = \x01n\x01cTo name");
console.crlf();
console.print(" \x01h\x01gY\x01y = \x01n\x01cTo you");
console.crlf();
console.print(" \x01h\x01gU\x01y = \x01n\x01cUnread (new) messages to you");
console.crlf();
console.print(" \x01h\x01gS\x01y = \x01n\x01cScan for msgs to you");
console.crlf();
}
else
{
// Reading personal email - Allow fewer choices
allowedKeys = "KF";
console.print(" \x01g\x01hK\x01y = \x01n\x01cKeyword");
console.crlf();
console.print(" \x01h\x01gF\x01y = \x01n\x01cFrom name");
console.crlf();
}
console.print(" \x01h\x01gA\x01y = \x01n\x01cAbort");
console.crlf();
console.print("\x01n\x01cMake a selection\x01g\x01h: \x01c");
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
// TODO: Check to see if keyword & from name search work when reading
// personal email
switch (console.getkeys(allowedKeys))
{
case "N":
gCmdLineArgVals["search"] = "new_msg_scan";
break;
case "K":
gCmdLineArgVals["search"] = "keyword_search";
break;
case "F":
gCmdLineArgVals["search"] = "from_name_search";
break;
case "T":
gCmdLineArgVals["search"] = "to_name_search";
break;
case "Y":
gCmdLineArgVals["search"] = "to_user_search";
break;
case "U":
gCmdLineArgVals["search"] = "to_user_new_scan";
break;
case "S":
gCmdLineArgVals["search"] = "to_user_all_scan";
break;
case "A": // Abort
default:

nightfox
committed
gDoDDMR = false;
console.print("\x01n\x01h\x01y\x01iAborted\x01n");
console.crlf();
console.pause();
break;
}
}

nightfox
committed
if (gDoDDMR)
{

Eric Oulashin
committed
// Write the user's default twitlist if it doesn't already exist
writeDefaultUserTwitListIfNotExist();
// When exiting this script, make sure to set the ctrl key pasthru back to what it was originally
js.on_exit("console.ctrlkey_passthru = " + console.ctrlkey_passthru);

Eric Oulashin
committed
// Set a control key pass-thru so we can capture certain control keys that we normally wouldn't be able to
var gOldCtrlKeyPassthru = console.ctrlkey_passthru; // Backup to be restored later

Eric Oulashin
committed
console.ctrlkey_passthru = "+AGKLOPQRTUVWXYZ_";

Eric Oulashin
committed
// Create an instance of the DigDistMsgReader class and use it to read/list the
// messages in the user's current sub-board. Pass the parsed command-line
// argument values object to its constructor.
var readerSubCode = (gListPersonalEmailCmdLineOpt ? "mail" : bbs.cursub_code);
// If the -subBoard option was specified and the "read personal email" option was
// not specified, then use the sub-board specified by the -subBoard command-line
// option.
if (gCmdLineArgVals.hasOwnProperty("subboard") && !gListPersonalEmailCmdLineOpt)
{
// If the specified sub-board option is all digits, then treat it as the
// sub-board number. Otherwise, treat it as an internal sub-board code.
if (/^[0-9]+$/.test(gCmdLineArgVals["subboard"]))
readerSubCode = getSubBoardCodeFromNum(Number(gCmdLineArgVals["subboard"]));
else
readerSubCode = gCmdLineArgVals["subboard"];
}
var msgReader = new DigDistMsgReader(readerSubCode, gCmdLineArgVals);

Eric Oulashin
committed
if (gCmdLineArgVals.indexedmode)

Eric Oulashin
committed
{
console.attributes = "N";
console.crlf();
console.mnemonics("Indexed read: ~Group: @GRP@, or ~@All@: ");
var scopeChar = console.getkeys("GA").toString();
if (typeof(scopeChar) === "string" && scopeChar != "")
{
var scanScope = SCAN_SCOPE_ALL;
if (scopeChar == "G")
scanScope = SCAN_SCOPE_GROUP;
else if (scopeChar == "G")
scanScope = SCAN_SCOPE_ALL;
msgReader.DoIndexedMode(scanScope, false);
}
else
{
console.putmsg(bbs.text(Aborted), P_SAVEATR);
console.pause();
}
}

Eric Oulashin
committed
else
{

Eric Oulashin
committed
// If the option to choose a message area first was enabled on the command-line
// (and neither the -subBoard nor the -personalEmail options were specified),
// then let the user choose a sub-board now.
if (gCmdLineArgVals.hasOwnProperty("chooseareafirst") && gCmdLineArgVals["chooseareafirst"] && !gCmdLineArgVals.hasOwnProperty("subboard") && !gListPersonalEmailCmdLineOpt)
msgReader.SelectMsgArea();
// Back up the user's current sub-board so that we can change back
// to it after searching is done, if a search is done.
var originalMsgGrpIdx = bbs.curgrp;
var originalSubBoardIdx = bbs.cursub;
var restoreOriginalSubCode = true;
// Based on the reader's start mode/search type, do the appropriate thing.
switch (msgReader.searchType)
{
case SEARCH_NONE:
restoreOriginalSubCode = false;
if (msgReader.subBoardCode != "mail")
{
console.attributes = "N";

Eric Oulashin
committed
console.crlf();
console.print("Loading " + subBoardGrpAndName(msgReader.subBoardCode) + "....");
console.line_counter = 0; // To prevent a pause before the message list comes up
}
msgReader.ReadOrListSubBoard();
break;
case SEARCH_KEYWORD:
var txtToSearch = (gCmdLineArgVals.hasOwnProperty("searchtext") ? gCmdLineArgVals.searchtext : null);
var subBoardCode = (gCmdLineArgVals.hasOwnProperty("subboard") ? gCmdLineArgVals.subboard : null);
msgReader.SearchMsgScan("keyword_search", txtToSearch, subBoardCode);
break;
case SEARCH_FROM_NAME:
msgReader.SearchMessages("from_name_search");
break;
case SEARCH_TO_NAME_CUR_MSG_AREA:
msgReader.SearchMessages("to_name_search");
break;
case SEARCH_TO_USER_CUR_MSG_AREA:
msgReader.SearchMessages("to_user_search");
break;
case SEARCH_MSG_NEWSCAN:
if (!gCmdLineArgVals.suppresssearchtypetext)
{
console.crlf();

Eric Oulashin
committed
console.putmsg(msgReader.text.newMsgScanText);

Eric Oulashin
committed
}
msgReader.MessageAreaScan(SCAN_CFG_NEW, SCAN_NEW);
break;
case SEARCH_MSG_NEWSCAN_CUR_SUB:
msgReader.MessageAreaScan(SCAN_CFG_NEW, SCAN_NEW, "S");
break;
case SEARCH_MSG_NEWSCAN_CUR_GRP:
msgReader.MessageAreaScan(SCAN_CFG_NEW, SCAN_NEW, "G");
break;
case SEARCH_MSG_NEWSCAN_ALL:
msgReader.MessageAreaScan(SCAN_CFG_NEW, SCAN_NEW, "A");
break;
case SEARCH_TO_USER_NEW_SCAN:
if (!gCmdLineArgVals.suppresssearchtypetext)
{
console.crlf();

Eric Oulashin
committed
console.putmsg(msgReader.text.newToYouMsgScanText);

Eric Oulashin
committed
}
msgReader.MessageAreaScan(SCAN_CFG_TOYOU/*SCAN_CFG_YONLY*/, SCAN_UNREAD);
break;
case SEARCH_TO_USER_NEW_SCAN_CUR_SUB:
msgReader.MessageAreaScan(SCAN_CFG_TOYOU/*SCAN_CFG_YONLY*/, SCAN_UNREAD, "S");
break;
case SEARCH_TO_USER_NEW_SCAN_CUR_GRP:
msgReader.MessageAreaScan(SCAN_CFG_TOYOU/*SCAN_CFG_YONLY*/, SCAN_UNREAD, "G");
break;
case SEARCH_TO_USER_NEW_SCAN_ALL:
msgReader.MessageAreaScan(SCAN_CFG_TOYOU/*SCAN_CFG_YONLY*/, SCAN_UNREAD, "A");
break;
case SEARCH_ALL_TO_USER_SCAN:
if (!gCmdLineArgVals.suppresssearchtypetext)
{
console.crlf();

Eric Oulashin
committed
console.putmsg(msgReader.text.allToYouMsgScanText);

Eric Oulashin
committed
}
msgReader.MessageAreaScan(SCAN_CFG_TOYOU, SCAN_TOYOU);
break;
}
// If we should restore the user's original message area, then do so.
if (restoreOriginalSubCode)
{
bbs.cursub = 0;
bbs.curgrp = originalMsgGrpIdx;
bbs.cursub = originalSubBoardIdx;
}
}
// Remove the temporary attachments & ANSI temp directories if they exists
deltree(gFileAttachDir);
deltree(backslash(system.node_dir + "DDMsgReaderANSIMsgTemp"));
// Before this script finishes, make sure the terminal attributes are set back
// to normal (in case there are any attributes left on, such as background,
// blink, etc.)

Eric Oulashin
committed
console.attributes = "N";
}
Eric Oulashin
committed
exit();
// End of script execution. Functions below:
// Generates an internal enhanced reader header line for the 'To' user.
//
// Parameters:
// pColors: A JSON object containing the color settings read from the
// theme configuration file. This function will use the
// 'msgHdrToColor' or 'msgHdrToUserColor' property, depending
// on the pToReadingUser property.
// pToReadingUser: Boolean - Whether or not to generate the line with
// the color/attribute for the reading user
//
// Return value: A string containing the internal enhanced reader header
// line specifying the 'to' user
function genEnhHdrToUserLine(pColors, pToReadingUser)
{
var toHdrLine = "\x01n\x01h\x01k" + VERTICAL_SINGLE + BLOCK1 + BLOCK2 + BLOCK3
+ "\x01gT\x01n\x01go \x01h\x01c: " +
(pToReadingUser ? pColors.msgHdrToUserColor : pColors.msgHdrToColor) +
"@MSG_TO-L";
var numChars = console.screen_columns - 21;
for (var i = 0; i < numChars; ++i)
toHdrLine += "#";
toHdrLine += "@\x01k" + VERTICAL_SINGLE;
return toHdrLine;
}
///////////////////////////////////////////////////////////////////////////////////
// DigDistMsgReader class stuff
// DigDistMsgReader class constructor: Constructs a
// DigDistMsgReader object, to be used for listing messages
// in a message area.
//
// Parameters:
// pSubBoardCode: Optional - The Synchronet sub-board code, or "mail"
// for personal email.
// pScriptArgs: Optional - An object containing key/value pairs representing
// the command-line arguments & values, as returned by parseArgs().
function DigDistMsgReader(pSubBoardCode, pScriptArgs)
{
// Set the methods for the object
this.setSubBoardCode = DigDistMsgReader_SetSubBoardCode;
this.RecalcMsgListWidthsAndFormatStrs = DigDistMsgReader_RecalcMsgListWidthsAndFormatStrs;
this.NumMessages = DigDistMsgReader_NumMessages;
this.SearchingAndResultObjsDefinedForCurSub = DigDistMsgReader_SearchingAndResultObjsDefinedForCurSub;
this.PopulateHdrsForCurrentSubBoard = DigDistMsgReader_PopulateHdrsForCurrentSubBoard;
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard = DigDistMsgReader_FilterMsgHdrsIntoHdrsForCurrentSubBoard;
this.GetMsgIdx = DigDistMsgReader_GetMsgIdx;
this.RefreshSearchResultMsgHdr = DigDistMsgReader_RefreshSearchResultMsgHdr; // Refreshes a message header in the search results
this.SearchMessages = DigDistMsgReader_SearchMessages; // Prompts the user for search text, then lists/reads messages, performing the search
Eric Oulashin
committed
this.SearchMsgScan = DigDistMsgReader_SearchMsgScan;
this.RefreshHdrInSubBoardHdrs = DigDistMsgReader_RefreshHdrInSubBoardHdrs;
this.RefreshHdrInSavedArrays = DigDistMsgReader_RefreshHdrInSavedArrays;
this.ReadMessages = DigDistMsgReader_ReadMessages;
this.DisplayEnhancedMsgReadHelpLine = DigDistMsgReader_DisplayEnhancedMsgReadHelpLine;
this.GoToPrevSubBoardForEnhReader = DigDistMsgReader_GoToPrevSubBoardForEnhReader;
this.GoToNextSubBoardForEnhReader = DigDistMsgReader_GoToNextSubBoardForEnhReader;
this.SetUpTraditionalMsgListVars = DigDistMsgReader_SetUpTraditionalMsgListVars;
this.SetUpLightbarMsgListVars = DigDistMsgReader_SetUpLightbarMsgListVars;
this.ListMessages = DigDistMsgReader_ListMessages;
this.ListMessages_Traditional = DigDistMsgReader_ListMessages_Traditional;
this.ListMessages_Lightbar = DigDistMsgReader_ListMessages_Lightbar;
this.CreateLightbarMsgListMenu = DigDistMsgReader_CreateLightbarMsgListMenu;
this.CreateLightbarMsgGrpMenu = DigDistMsgReader_CreateLightbarMsgGrpMenu;
this.CreateLightbarSubBoardMenu = DigDistMsgReader_CreateLightbarSubBoardMenu;
this.AdjustLightbarMsgListMenuIdxes = DigDistMsgReader_AdjustLightbarMsgListMenuIdxes;
this.ClearSearchData = DigDistMsgReader_ClearSearchData;
this.ReadOrListSubBoard = DigDistMsgReader_ReadOrListSubBoard;
this.PopulateHdrsIfSearch_DispErrorIfNoMsgs = DigDistMsgReader_PopulateHdrsIfSearch_DispErrorIfNoMsgs;
this.SearchTypePopulatesSearchResults = DigDistMsgReader_SearchTypePopulatesSearchResults;
this.SearchTypeRequiresSearchText = DigDistMsgReader_SearchTypeRequiresSearchText;
this.MessageAreaScan = DigDistMsgReader_MessageAreaScan;
this.PromptContinueOrReadMsg = DigDistMsgReader_PromptContinueOrReadMsg;
this.WriteMsgListScreenTopHeader = DigDistMsgReader_WriteMsgListScreenTopHeader;
this.ReadMessageEnhanced = DigDistMsgReader_ReadMessageEnhanced;
this.ReadMessageEnhanced_Scrollable = DigDistMsgReader_ReadMessageEnhanced_Scrollable;

Eric Oulashin
committed
this.ShowHdrOrKludgeLines_Scrollable = DigDistMsgReader_ShowHdrOrKludgeLines_Scrollable;
this.ShowVoteInfo_Scrollable = DigDistMsgReader_ShowVoteInfo_Scrollable;

Eric Oulashin
committed
this.ScrollableReaderNextReadableMessage = DigDistMsgReader_ScrollableReaderNextReadableMessage;
this.ScrollReaderDetermineClickCoordAction = DigDistMsgReader_ScrollReaderDetermineClickCoordAction;
this.ReadMessageEnhanced_Traditional = DigDistMsgReader_ReadMessageEnhanced_Traditional;

Eric Oulashin
committed
this.ShowReadModeOpMenuAndGetSelection = DigDistMsgReader_ShowReadModeOpMenuAndGetSelection;
this.CreateReadModeOpMenu = DigDistMsgReader_CreateReadModeOpMenu;
this.EnhReaderPrepLast2LinesForPrompt = DigDistMsgReader_EnhReaderPrepLast2LinesForPrompt;
this.LookForNextOrPriorNonDeletedMsg = DigDistMsgReader_LookForNextOrPriorNonDeletedMsg;
this.PrintMessageInfo = DigDistMsgReader_PrintMessageInfo;
this.ListScreenfulOfMessages = DigDistMsgReader_ListScreenfulOfMessages;
this.DisplayMsgListHelp = DigDistMsgReader_DisplayMsgListHelp;
this.DisplayTraditionalMsgListHelp = DigDistMsgReader_DisplayTraditionalMsgListHelp;
this.DisplayLightbarMsgListHelp = DigDistMsgReader_DisplayLightbarMsgListHelp;
this.DisplayMessageListNotesHelp = DigDistMsgReader_DisplayMessageListNotesHelp;
this.SetMsgListPauseTextAndLightbarHelpLine = DigDistMsgReader_SetMsgListPauseTextAndLightbarHelpLine;
this.SetEnhancedReaderHelpLine = DigDistMsgReader_SetEnhancedReaderHelpLine;
this.EditExistingMsg = DigDistMsgReader_EditExistingMsg;
this.EditExistingMessageOldWay = DigDistMsgReader_EditExistingMessageOldWay;
this.CanDelete = DigDistMsgReader_CanDelete;
this.CanDeleteLastMsg = DigDistMsgReader_CanDeleteLastMsg;
this.CanEdit = DigDistMsgReader_CanEdit;
this.CanQuote = DigDistMsgReader_CanQuote;
this.ReadConfigFile = DigDistMsgReader_ReadConfigFile;

Eric Oulashin
committed
this.ReadUserSettingsFile = DigDistMsgReader_ReadUserSettingsFile;

Eric Oulashin
committed
this.WriteUserSettingsFile = DigDistMsgReader_WriteUserSettingsFile;

Eric Oulashin
committed
// TODO: Is this.DisplaySyncMsgHeader even needed anymore? Looks like it's not being called.
this.DisplaySyncMsgHeader = DigDistMsgReader_DisplaySyncMsgHeader;
this.GetMsgHdrFilenameFull = DigDistMsgReader_GetMsgHdrFilenameFull;
this.GetMsgHdrByIdx = DigDistMsgReader_GetMsgHdrByIdx;
this.GetMsgHdrByMsgNum = DigDistMsgReader_GetMsgHdrByMsgNum;
this.GetMsgHdrByAbsoluteNum = DigDistMsgReader_GetMsgHdrByAbsoluteNum;
this.AbsMsgNumToIdx = DigDistMsgReader_AbsMsgNumToIdx;
this.IdxToAbsMsgNum = DigDistMsgReader_IdxToAbsMsgNum;
this.NonDeletedMessagesExist = DigDistMsgReader_NonDeletedMessagesExist;
this.HighestMessageNum = DigDistMsgReader_HighestMessageNum;
this.IsValidMessageNum = DigDistMsgReader_IsValidMessageNum;
this.PromptForMsgNum = DigDistMsgReader_PromptForMsgNum;
this.ParseMsgAtCodes = DigDistMsgReader_ParseMsgAtCodes;
this.ReplaceMsgAtCodeFormatStr = DigDistMsgReader_ReplaceMsgAtCodeFormatStr;

Eric Oulashin
committed
this.FindNextReadableMsgIdx = DigDistMsgReader_FindNextReadableMsgIdx;
this.ChangeSubBoard = DigDistMsgReader_ChangeSubBoard;
this.EnhancedReaderChangeSubBoard = DigDistMsgReader_EnhancedReaderChangeSubBoard;
this.ReplyToMsg = DigDistMsgReader_ReplyToMsg;
this.DoPrivateReply = DigDistMsgReader_DoPrivateReply;
this.DisplayEnhancedReaderHelp = DigDistMsgReader_DisplayEnhancedReaderHelp;
this.DisplayEnhancedMsgHdr = DigDistMsgReader_DisplayEnhancedMsgHdr;
this.DisplayAreaChgHdr = DigDistMsgReader_DisplayAreaChgHdr;
this.DisplayEnhancedReaderWholeScrollbar = DigDistMsgReader_DisplayEnhancedReaderWholeScrollbar;

Eric Oulashin
committed
this.UpdateEnhancedReaderScrollbar = DigDistMsgReader_UpdateEnhancedReaderScrollbar;
this.MessageIsDeleted = DigDistMsgReader_MessageIsDeleted;
this.MessageIsLastFromUser = DigDistMsgReader_MessageIsLastFromUser;
this.DisplayEnhReaderError = DigDistMsgReader_DisplayEnhReaderError;
this.EnhReaderPromptYesNo = DigDistMsgReader_EnhReaderPromptYesNo;
this.PromptAndDeleteOrUndeleteMessage = DigDistMsgReader_PromptAndDeleteOrUndeleteMessage;
this.PromptAndDeleteOrUndeleteSelectedMessages = DigDistMsgReader_PromptAndDeleteOrUndeleteSelectedMessages;
this.GetExtdMsgHdrInfo = DigDistMsgReader_GetExtdMsgHdrInfo;

Eric Oulashin
committed
this.GetMsgHdrFieldListText = DigDistMsgReader_GetMsgHdrFieldListText;
this.GetMsgInfoForEnhancedReader = DigDistMsgReader_GetMsgInfoForEnhancedReader;

Eric Oulashin
committed
this.ShowMsgHex_Scrolling = DigDistMsgReader_ShowMsgHex_Scrolling;
this.GetMsgHexInfo = DigDistMsgReader_GetMsgHexInfo;
this.SaveMsgHexDumpToFile = DigDistMsgReader_SaveMsgHexDumpToFile;
this.GetLastReadMsgIdxAndNum = DigDistMsgReader_GetLastReadMsgIdxAndNum;
this.GetScanPtrMsgIdx = DigDistMsgReader_GetScanPtrMsgIdx;
this.RemoveFromSearchResults = DigDistMsgReader_RemoveFromSearchResults;
this.FindThreadNextOffset = DigDistMsgReader_FindThreadNextOffset;
this.FindThreadPrevOffset = DigDistMsgReader_FindThreadPrevOffset;
this.SaveMsgToFile = DigDistMsgReader_SaveMsgToFile;
this.ToggleSelectedMessage = DigDistMsgReader_ToggleSelectedMessage;
this.MessageIsSelected = DigDistMsgReader_MessageIsSelected;
this.AllSelectedMessagesCanBeDeleted = DigDistMsgReader_AllSelectedMessagesCanBeDeleted;
this.DeleteOrUndeleteSelectedMessages = DigDistMsgReader_DeleteOrUndeleteSelectedMessages;
this.NumSelectedMessages = DigDistMsgReader_NumSelectedMessages;
this.ForwardMessage = DigDistMsgReader_ForwardMessage;
this.VoteOnMessage = DigDistMsgReader_VoteOnMessage;
this.HasUserVotedOnMsg = DigDistMsgReader_HasUserVotedOnMsg;
this.GetUpvoteAndDownvoteInfo = DigDistMsgReader_GetUpvoteAndDownvoteInfo;
this.GetMsgBody = DigDistMsgReader_GetMsgBody;
this.RefreshMsgHdrInArrays = DigDistMsgReader_RefreshMsgHdrInArrays;
this.WriteLightbarKeyHelpErrorMsg = DigDistMsgReader_WriteLightbarKeyHelpErrorMsg;
// startMode specifies the mode for the reader to start in - List mode
// or reader mode, etc. This is a setting that is read from the configuration
// file. The configuration file can be either READER_MODE_READ or
// READER_MODE_LIST, but the optional "mode" parameter in the command-line
// arguments can specify another mode.
// Note: This isn't used for "indexed" reader mode (but maybe it should be in the future)
this.startMode = READER_MODE_LIST;
// hdrsForCurrentSubBoard is an array that will be populated with the
// message headers for the current sub-board.
this.hdrsForCurrentSubBoard = [];
// hdrsForCurrentSubBoardByMsgNum is an object that maps absolute message numbers
// to their index to hdrsForCurrentSubBoard

Eric Oulashin
committed
this.msgNumToIdxMap = {};
// msgSearchHdrs is an object containing message headers found via searching.
// It is indexed by internal message area code. Each internal code index
// will specify an object containing the following properties:
// indexed: A standard 0-based array containing message headers
this.msgSearchHdrs = {};
this.searchString = ""; // To be used for message searching
// this.searchType will specify the type of search:
// SEARCH_NONE (-1): No search
// SEARCH_KEYWORD: Keyword search in message subject & body
// SEARCH_FROM_NAME: Search by 'from' name
// SEARCH_TO_NAME_CUR_MSG_AREA: Search by 'to' name
// SEARCH_TO_USER_CUR_MSG_AREA: Search by 'to' name, to the current user
// SEARCH_MSG_NEWSCAN: New (unread) message scan (prompt the user for sub, group, or all)
// SEARCH_MSG_NEWSCAN_CUR_SUB: New (unread) message scan (current sub-board)
// SEARCH_MSG_NEWSCAN_CUR_GRP: New (unread) message scan (current message group)
// SEARCH_MSG_NEWSCAN_ALL: New (unread) message scan (all message sub-boards)
// SEARCH_TO_USER_NEW_SCAN: New (unread) messages to the current user (prompt the user for sub, group, or all)
// SEARCH_TO_USER_NEW_SCAN_CUR_SUB: New (unread) messages to the current user (current sub-board)
// SEARCH_TO_USER_NEW_SCAN_CUR_GRP: New (unread) messages to the current user (current group)
// SEARCH_TO_USER_NEW_SCAN_ALL: New (unread) messages to the current user (all sub-board)
// SEARCH_ALL_TO_USER_SCAN: All messages to the current user
this.searchType = SEARCH_NONE;
this.doingMsgScan = false; // Set to true in MessageAreaScan()

Eric Oulashin
committed
this.doingNewscan = false; // Whether or not we're doing a newscan
this.subBoardCode = bbs.cursub_code; // The message sub-board code
this.readingPersonalEmail = false;
// Whether or not we're in indexed reader mode
this.indexedMode = false;
// For indexed reader mode, whether or not to enable caching the message
// header lists for performance
this.enableIndexedModeMsgListCache = true;
// this.colors will be an array of colors to use in the message list
this.colors = getDefaultColors();
this.readingPersonalEmailFromUser = false;

nightfox
committed
if (typeof(pSubBoardCode) == "string")
{

nightfox
committed
var subCodeLowerCase = pSubBoardCode.toLowerCase();
if (subBoardCodeIsValid(subCodeLowerCase))
{
this.setSubBoardCode(subCodeLowerCase);
if (gCmdLineArgVals.hasOwnProperty("personalemailsent") && gCmdLineArgVals.personalemailsent)
this.readingPersonalEmailFromUser = true;
}
}
// This property controls whether or not the user will be prompted to
// continue listing messages after selecting a message to read. Only for
// regular reading, not for newscans etc.
this.promptToContinueListingMessages = false;
// Whether or not to prompt the user to confirm to read a message
this.promptToReadMessage = false;
// For enhanced reader mode (reading only, not for newscan, etc.): Whether or
// not to ask the user whether to post on the sub-board in reader mode after
// reading the last message instead of prompting to go to the next sub-board.
// This is like the stock Synchronet behavior.
this.readingPostOnSubBoardInsteadOfGoToNext = false;
// String lengths for the columns to write
// Fixed field widths: Message number, date, and time
// TODO: It might be good to figure out the longest message number for a
// sub-board and set the message number length dynamically. It would have
// to change whenever the user changes to a different sub-board, and the
// message list format string would have to change too.
//this.MSGNUM_LEN = 4;
this.MSGNUM_LEN = 5;
this.DATE_LEN = 10; // i.e., YYYY-MM-DD
this.TIME_LEN = 8; // i.e., HH:MM:SS
// Variable field widths: From, to, and subject

Eric Oulashin
committed
this.FROM_LEN = ((console.screen_columns * (15/console.screen_columns)).toFixed(0)) - 1; // - 1 to make room for the space after the message indicator character
this.TO_LEN = ((console.screen_columns * (15/console.screen_columns)).toFixed(0)) - 1; // - 1 to account for the spaces around the status character

Eric Oulashin
committed
//var colsLeftForSubject = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces
//this.SUBJ_LEN = (console.screen_columns * (colsLeftForSubject/console.screen_columns)).toFixed(0);

Eric Oulashin
committed
this.SUBJ_LEN = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-8; // 8 to account for the spaces
// For showing message scores in the message list
this.SCORE_LEN = 4;
// Whether or not to show message scores in the message list: Only if the terminal
// is at least 86 characters wide and if vote functions exist in the running build
// of Synchronet
this.showScoresInMsgList = ((console.screen_columns >= 86) && (typeof((new MsgBase("mail")).vote_msg) === "function"));

Eric Oulashin
committed
if (this.showScoresInMsgList)
this.SUBJ_LEN -= (this.SCORE_LEN + 1); // + 1 to account for a space
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
// Whether or not the user chose to read a message
this.readAMessage = false;
// Whether or not the user denied confirmation to read a message
this.deniedReadingMessage = false;
// msgListUseLightbarListInterface specifies whether or not to use the lightbar
// interface for the message list. The lightbar interface will only be used if
// the user's terminal supports ANSI.
this.msgListUseLightbarListInterface = true;
// Whether or not to use the scrolling interface when reading a message
// (will only be used for ANSI terminals).
this.scrollingReaderInterface = true;
// displayBoardInfoInHeader specifies whether or not to display
// the message group and sub-board lines in the header at the
// top of the screen (an additional 2 lines).
this.displayBoardInfoInHeader = false;
// msgList_displayMessageDateImported specifies whether or not to use the
// message import date as the date displayed in the message list. If false,
// the message written date will be displayed.
this.msgList_displayMessageDateImported = true;
// The number of spaces to use for tab characters - Used in the
// extended read mode
this.numTabSpaces = 3;
// this.text is an object containing text used for various prompts & functions.
this.text = {
scrollbarBGChar: BLOCK1,
scrollbarScrollBlockChar: BLOCK2,
goToPrevMsgAreaPromptText: "\x01n\x01c\x01hGo to the previous message area",
goToNextMsgAreaPromptText: "\x01n\x01c\x01hGo to the next message area",
newMsgScanText: "\x01c\x01hN\x01n\x01cew \x01hM\x01n\x01cessage \x01hS\x01n\x01ccan",
newToYouMsgScanText: "\x01c\x01hN\x01n\x01cew \x01hT\x01n\x01co \x01hY\x01n\x01cou \x01hM\x01n\x01cessage \x01hS\x01n\x01ccan",
allToYouMsgScanText: "\x01c\x01hA\x01n\x01cll \x01hM\x01n\x01cessages \x01hT\x01n\x01co \x01hY\x01n\x01cou \x01hS\x01n\x01ccan",
goToMsgNumPromptText: "\x01n\x01cGo to message # (or \x01hENTER\x01n\x01c to cancel)\x01g\x01h: \x01c",
msgScanAbortedText: "\x01n\x01h\x01cM\x01n\x01cessage scan \x01h\x01y\x01iaborted\x01n",

Eric Oulashin
committed
msgSearchAbortedText: "\x01n\x01h\x01cM\x01n\x01cessage search \x01h\x01y\x01iaborted\x01n",
deleteMsgNumPromptText: "\x01n\x01cNumber of the message to be deleted (or \x01hENTER\x01n\x01c to cancel)\x01g\x01h: \x01c",
editMsgNumPromptText: "\x01n\x01cNumber of the message to be edited (or \x01hENTER\x01n\x01c to cancel)\x01g\x01h: \x01c",
searchingSubBoardAbovePromptText: "\x01n\x01cSearching (current sub-board: \x01b\x01h%s\x01n\x01c)",
searchingSubBoardText: "\x01n\x01cSearching \x01h%s\x01n\x01c...",
scanningSubBoardText: "\x01n\x01cScanning \x01h%s\x01n\x01c...",
noMessagesInSubBoardText: "\x01n\x01h\x01bThere are no messages in the area \x01w%s\x01b.",
Eric Oulashin
committed
noSearchResultsInSubBoardText: "\x01n\x01h\x01bNo messages were found in \x01w%s\x01b with the given search criteria.",
msgScanCompleteText: "\x01n\x01h\x01cM\x01n\x01cessage scan complete\x01h\x01g.\x01n",
invalidMsgNumText: "\x01n\x01y\x01hInvalid message number: %d",
readMsgNumPromptText: "\x01n\x01g\x01h\x01i* \x01n\x01cRead message #: \x01h",
msgHasBeenDeletedText: "\x01n\x01h\x01g* \x01yMessage #\x01w%d \x01yhas been deleted.",