Newer
Older
}
else
{
writeMessage = false; // Don't refresh the whole message
if (valRetObj.refreshBottomLine)
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
if (valRetObj.optionBoxTopLeftX > 0 && valRetObj.optionBoxTopLeftY > 0 && valRetObj.optionBoxWidth > 0 && valRetObj.optionBoxHeight > 0)
this.RefreshMsgAreaRectangle(msgInfo.messageLines, topMsgLineIdx, valRetObj.optionBoxTopLeftX, valRetObj.optionBoxTopLeftY, valRetObj.optionBoxWidth, valRetObj.optionBoxHeight);
}
}
else
writeMessage = false;
break;
case this.enhReaderKeys.bypassSubBoardInNewScan:
writeMessage = false; // TODO: Finish
/*
if (this.doingMsgScan)
{
console.attributes = "N";
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
var originalCurpos = console.getxy();
// The 2nd to last row of the screen is where the user will
// be prompted for confirmation to delete the message.
// Ideally, I'd like to put the cursor on the last row of
// the screen for this, but console.noyes() lets the enter
// key shift everything on screen up one row, and there's
// no way to avoid that. So, to optimize screen refreshing,
// the cursor is placed on the 2nd to the last row on the
// screen to prompt for confirmation.
var promptPos = this.EnhReaderPrepLast2LinesForPrompt();
if (!console.noyes("Bypass this sub-board in newscans"))
{
continueOn = false;
msg_area.sub[this.subBoardCode].scan_cfg &= SCAN_CFG_NEW;
}
else
{
this.DisplayEnhReaderError("", msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
// Move the cursor back to its original position
console.gotoxy(originalCurpos);
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
}
}
else
writeMessage = false;
*/
break;

Eric Oulashin
committed
case this.enhReaderKeys.userSettings:
// Make a backup copy of the this.userSettings.useEnhReaderScrollbar setting in case it changes, so we can tell if we need to refresh the scrollbar
var oldUseEnhReaderScrollbar = this.userSettings.useEnhReaderScrollbar;

Eric Oulashin
committed
var userSettingsRetObj = this.DoUserSettings_Scrollable(function(pReader) { pReader.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea); });

Eric Oulashin
committed
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
retObj.lastKeypress = "";
writeMessage = userSettingsRetObj.needWholeScreenRefresh;
// In case the user changed their twitlist, re-filter the messages for this sub-board
if (userSettingsRetObj.userTwitListChanged)
{
console.gotoxy(1, console.screen_rows);
console.crlf();
console.print("\x01nTwitlist changed; re-filtering..");
var tmpMsgbase = new MsgBase(this.subBoardCode);
if (tmpMsgbase.open())
{
continueOn = false;
writeMessage = false;
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true);
tmpMsgbase.close();
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true);
// If the user is currently reading a message a message by someone who is now
// in their twit list, change the message currently being viewed.
if (this.MsgHdrFromOrToInUserTwitlist(msgHeader))
{
var findNextMsgRetObj = this.ScrollableReaderNextReadableMessage(pOffset, msgInfo, topMsgLineIdx, msgLineFormatStr, solidBlockStartRow, numSolidScrollBlocks);
if (findNextMsgRetObj.newMsgOffset > -1)
{
retObj.newMsgOffset = findNextMsgRetObj.newMsgOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
}
else
retObj.nextAction = ACTION_GO_NEXT_MSG_AREA;
}
else
{
// If there are still messages in this sub-board, and the message offset is beyond the last
// message, then show the last message in the sub-board. Otherwise, go to the next message area.
if (this.hdrsForCurrentSubBoard.length > 0)
{
if (pOffset > this.hdrsForCurrentSubBoard.length)
{
//this.hdrsForCurrentSubBoard[this.hdrsForCurrentSubBoard.length-1].number
retObj.newMsgOffset = this.hdrsForCurrentSubBoard.length - 1;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
}
}
else
retObj.nextAction = ACTION_GO_NEXT_MSG_AREA;
}
}
else
console.print("\x01y\x01hFailed to open the messagbase!\x01\r\n\x01p");
this.SetUpLightbarMsgListVars();
writeMessage = true;
}
if (userSettingsRetObj.needWholeScreenRefresh)
{
this.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
if (this.userSettings.useEnhReaderScrollbar)

Eric Oulashin
committed
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
else
{
// TODO
}

Eric Oulashin
committed
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
}
else

Eric Oulashin
committed
{
// If the message scrollbar was toggled, then draw/erase the scrollbar
if (this.userSettings.useEnhReaderScrollbar != oldUseEnhReaderScrollbar)

Eric Oulashin
committed
{
msgAreaWidth = this.userSettings.useEnhReaderScrollbar ? this.msgAreaWidth : this.msgAreaWidth + 1;

Eric Oulashin
committed
// If the message is ANSI, then re-create the Graphic object to account for the
// new width
if (msgHasANSICodes)
{
//var graphic = new Graphic(msgAreaWidth, this.msgAreaHeight-1);
// To help ensure ANSI messages look good, it seems the Graphic object should have
// its with later set to 1 less than the width used to create it.
var graphicWidth = (msgAreaWidth < console.screen_columns ? msgAreaWidth+1 : console.screen_columns);
var graphic = new Graphic(graphicWidth, this.msgAreaHeight-1);

Eric Oulashin
committed
graphic.auto_extend = true;
graphic.ANSI = ansiterm.expand_ctrl_a(messageText);
//graphic.width = msgAreaWidth;
graphic.width = graphicWidth - 1;

Eric Oulashin
committed
messageText = graphic.MSG;
}
// Display or erase the scrollbar
if (this.userSettings.useEnhReaderScrollbar)

Eric Oulashin
committed
{
solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
}
else
{
// Erase the scrollbar
console.attributes = "N";
for (var screenY = this.msgAreaTop; screenY <= this.msgAreaBottom; ++screenY)
{
console.gotoxy(this.msgAreaRight+1, screenY);
console.print(" ");
}
}
}

Eric Oulashin
committed
this.RefreshMsgAreaRectangle(msgInfo.messageLines, topMsgLineIdx, userSettingsRetObj.optionBoxTopLeftX, userSettingsRetObj.optionBoxTopLeftY, userSettingsRetObj.optionBoxWidth, userSettingsRetObj.optionBoxHeight);

Eric Oulashin
committed
}

Eric Oulashin
committed
break;

nightfox
committed
case this.enhReaderKeys.quit: // Quit

Eric Oulashin
committed
case KEY_ESC:
// Normally, if quitFromReaderGoesToMsgList is enabled, then do that
if (this.userSettings.quitFromReaderGoesToMsgList)
{
console.attributes = "N";
console.crlf();
console.print("Loading...");
retObj.nextAction = ACTION_DISPLAY_MSG_LIST;
}
else
retObj.nextAction = ACTION_QUIT;
continueOn = false;
break;
default:
writeMessage = false;
break;
}
}
return retObj;
}

Eric Oulashin
committed
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
// Helper method for ReadMessageEnhanced_Scrollable(): Determines if there is a readable message after the
// one at the given offset.
//
// Parameters:
// pOfset: The offset of the current message
// pMsgInfo: An object contaiining message information
// pTopMsgLineIdx: The index of the message line at the top of the reader area
// pMsgLineFormatStr: A format string for the message line
// pSolidBlockStartRow: The screen row of where the solid blocks start for the scrollbar
// pNumSolidScrollBlocks: The number of solid blocks in the scrollbar
//
// Return value: An object containing the following properties:
// newMsgOffset: The offset of the next readable message, if available. If not available, this will be -1.
// writeMessage: Boolean - Whether or not to write the whole message again (for the scrollable interface)
// continueOn: Boolean - Whether or not to continue with the reader input loop
// nextAction: A value indicating the next action for the reader to take after leaving the reader function
function DigDistMsgReader_ScrollableReaderNextReadableMessage(pOffset, pMsgInfo, pTopMsgLineIdx, pMsgLineFormatStr, pSolidBlockStartRow, pNumSolidScrollBlocks)
{
var retObj = {
newMsgOffset: -1,
writeMessage: true,
continueOn: true,
nextAction: ACTION_NONE
};

Eric Oulashin
committed
// Look for the next readable message. Even if we don't find one, we'll still
// want to return from this function (with message index -1) so that this script
// can go onto the next message sub-board/group.
retObj.newMsgOffset = this.FindNextReadableMsgIdx(pOffset, true);

Eric Oulashin
committed
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
// Note: Unlike the left arrow key, we want to exit this method when
// navigating to the next message, regardless of whether or not the
// user is allowed to change to a different sub-board, so that processes
// that require continuation (such as new message scan) can continue.
// Still, if there are no more readable messages in the current sub-board
// (and thus the user would go onto the next message area), prompt the
// user whether they want to continue onto the next message area.
if (retObj.newMsgOffset == -1 && !curMsgSubBoardIsLast())
{
// For personal mail, don't do anything, and don't refresh the
// message. In a sub-board, ask the user if they want to go
// to the next one.
if (this.readingPersonalEmail)
retObj.writeMessage = false;
else
{
// If configured to allow the user to post in the sub-board
// instead of going to the next message area and we're not
// scanning, then do so.
if (this.readingPostOnSubBoardInsteadOfGoToNext && !this.doingMsgScan)
{
console.attributes = "N";

Eric Oulashin
committed
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
console.crlf();
// Ask the user if they want to post on the sub-board.
// If they say yes, then do so before exiting.
var grpNameAndDesc = this.GetGroupNameAndDesc();
if (!console.noyes(replaceAtCodesInStr(format(this.text.postOnSubBoard, grpNameAndDesc.grpName, grpNameAndDesc.grpDesc))))
bbs.post_msg(this.subBoardCode);
retObj.continueOn = false;
retObj.nextAction = ACTION_QUIT;
}
else
{
// Prompt the user whether they want to go to the next message area
if (this.EnhReaderPromptYesNo(replaceAtCodesInStr(this.text.goToNextMsgAreaPromptText), pMsgInfo.messageLines, pTopMsgLineIdx, pMsgLineFormatStr, pSolidBlockStartRow, pNumSolidScrollBlocks))
{
// Let this method exit and let the caller go to the next sub-board
retObj.continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
else
retObj.writeMessage = false; // No need to refresh the message
}
}
}
else
{
// We're not at the end of the sub-board, so it's okay to exit this
// method and go to the next message.
retObj.continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
return retObj;
}
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
// Helper method for ReadMessageEnhanced() - Determines the next keypress for a click
// coordinate outside the scroll area.
//
// Parameters:
// pScrollRetObj: The return object of the message scroll function
// pEnhReadHelpLineClickCoords: An array of click coordinates & action strings
//
// Return value: An object containing the following properties:
// actionStr: A string containing the next action for the enhanced reader,
// or an empty string if there was no valid action found.
function DigDistMsgReader_ScrollReaderDetermineClickCoordAction(pScrollRetObj, pEnhReadHelpLineClickCoords)
{
var retObj = {
actionStr: ""
};
for (var coordIdx = 0; coordIdx < pEnhReadHelpLineClickCoords.length; ++coordIdx)
{
if ((pScrollRetObj.mouse.x == pEnhReadHelpLineClickCoords[coordIdx].x) && (pScrollRetObj.mouse.y == pEnhReadHelpLineClickCoords[coordIdx].y))
{
// The up arrow, down arrow, PageUp, PageDown, Home, and End aren't handled
// here - Those are handled in scrollTextLines().
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
if (pEnhReadHelpLineClickCoords[coordIdx].actionStr == LEFT_ARROW)
retObj.actionStr = this.enhReaderKeys.previousMsg;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr == RIGHT_ARROW)
retObj.actionStr = this.enhReaderKeys.nextMsg;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("DEL") == 0)
retObj.actionStr = this.enhReaderKeys.deleteMessage;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("E)") == 0)
retObj.actionStr = this.enhReaderKeys.editMsg;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("F") == 0)
retObj.actionStr = this.enhReaderKeys.firstMsg;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("L") == 0)
retObj.actionStr = this.enhReaderKeys.lastMsg;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("R") == 0)
retObj.actionStr = this.enhReaderKeys.reply;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("C") == 0)
retObj.actionStr = this.enhReaderKeys.chgMsgArea;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("Q") == 0)
retObj.actionStr = this.enhReaderKeys.quit;
else if (pEnhReadHelpLineClickCoords[coordIdx].actionStr.indexOf("?") == 0)
retObj.actionStr = this.enhReaderKeys.showHelp;
break;
}
}
return retObj;
}
// Helper method for ReadMessageEnhanced() - Does the traditional (non-scrollable) reader interface
function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsgArea, messageText, pOffset, pmode)
{
var retObj = {
offsetValid: true,
msgNotReadable: false,
userReplied: false,
lastKeypress: "",
newMsgOffset: -1,
nextAction: ACTION_NONE,
refreshEnhancedRdrHelpLine: false
};
Eric Oulashin
committed
// We could word-wrap the message to ensure words aren't split across lines, but
// doing so could make some messages look bad (i.e., messages with drawing characters),
// and word_wrap also might not handle ANSI or other color/attribute codes..
//if (!textHasDrawingChars(messageText))
// messageText = word_wrap(messageText, this.msgAreaWidth);
var msgHasAttachments = msgHdrHasAttachmentFlag(msgHeader);

Eric Oulashin
committed
// Only interpret @-codes if the user is reading personal email and the sender is a sysop. There
// are many @-codes that do some action such as move the cursor, execute a
// script, etc., and I don't want users on message networks to do anything
// malicious to users on other BBSes.

Eric Oulashin
committed
if (this.readingPersonalEmail && msgSenderIsASysop(msgHeader))
messageText = replaceAtCodesInStr(messageText); // Or this.ParseMsgAtCodes(messageText, msgHeader) to replace only some @ codes
var msgHasANSICodes = messageText.indexOf("\x1b[") >= 0;
var msgTextWrapped = (msgHasANSICodes ? messageText : word_wrap(messageText, console.screen_columns-1));
// Generate the key help text
var keyHelpText = "\x01n\x01c\x01h#\x01n\x01b, \x01c\x01hLeft\x01n\x01b, \x01c\x01hRight\x01n\x01b, ";
if (this.CanDelete() || this.CanDeleteLastMsg())
keyHelpText += "\x01c\x01hDEL\x01b, ";
if (this.CanEdit())
keyHelpText += "\x01c\x01hE\x01y)\x01n\x01cdit\x01b, ";
keyHelpText += "\x01c\x01hF\x01y)\x01n\x01cirst\x01b, \x01c\x01hL\x01y)\x01n\x01cast\x01b, \x01c\x01hR\x01y)\x01n\x01ceply\x01b, ";
// If the user is allowed to change to a different message area, then
// include that option.
if (allowChgMsgArea)
{
// If there's room for the private reply option, then include that
// before the change area option.
if (console.screen_columns >= 89)
keyHelpText += "\x01c\x01hP\x01y)\x01n\x01crivate reply\x01b, ";
keyHelpText += "\x01c\x01hC\x01y)\x01n\x01chg area\x01b, ";
}
else
{
// The user isn't allowed to change to a different message area.
// Go ahead and include the private reply option.
keyHelpText += "\x01c\x01hP\x01y)\x01n\x01crivate reply\x01b, ";
}
keyHelpText += "\x01c\x01hQ\x01y)\x01n\x01cuit\x01b, \x01c\x01h?\x01g: \x01c";
// User input loop
var writeMessage = true;
var writePromptText = true;
var continueOn = true;
while (continueOn)
{
if (writeMessage)
{
if (console.term_supports(USER_ANSI))
console.clear("\x01n");
// Write the message header & message body to the screen
this.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
console.print("\x01n" + this.colors.msgBodyColor);
console.putmsg(msgTextWrapped, pmode|P_NOATCODES);
}
// Write the prompt text
if (writePromptText)
console.print(keyHelpText);
// Default the writing of the message & input prompt to true for the
// next iteration.
writeMessage = true;
writePromptText = true;
// Input a key from the user and take action based on the keypress.
//retObj.lastKeypress = getKeyWithESCChars(K_UPPER|K_NOCRLF|K_NOECHO|K_NOSPIN);
retObj.lastKeypress = getKeyWithESCChars(K_UPPER);
switch (retObj.lastKeypress)
{
case this.enhReaderKeys.deleteMessage: // Delete message

Eric Oulashin
committed
case '\x7f':
case '\x08':
console.crlf();
// Prompt the user for confirmation to delete the message.
// Note: this.PromptAndDeleteOrUndeleteMessage() will check to see if the user
// is a sysop or the message was posted by the user.
// If the message was deleted, then exit this read method
// and return KEY_RIGHT as the last keypress so that the
// calling method will go to the next message/sub-board.
// Otherwise (if the message was not deleted), refresh the
// last 2 lines of the message on the screen.
var msgWasDeleted = this.PromptAndDeleteOrUndeleteMessage(pOffset, null, true);
if (msgWasDeleted && !canViewDeletedMsgs())
{
var msgSearchObj = this.LookForNextOrPriorNonDeletedMsg(pOffset);
continueOn = msgSearchObj.continueInputLoop;
retObj.newMsgOffset = msgSearchObj.newMsgOffset;
retObj.nextAction = msgSearchObj.nextAction;
if (msgSearchObj.promptGoToNextArea)
{
Eric Oulashin
committed
if (console.yesno(replaceAtCodesInStr(this.text.goToNextMsgAreaPromptText)))
{
// Let this method exit and let the caller go to the next sub-board
continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
else
writeMessage = false; // No need to refresh the message
}
}
break;
case this.enhReaderKeys.selectMessage: // Select message (for batch delete, etc.)
console.crlf();
var selectMessage = !console.noyes("Select this message");
this.ToggleSelectedMessage(this.subBoardCode, pOffset, selectMessage);
break;
case this.enhReaderKeys.batchDelete:
// TODO: Write this? Not sure yet if it makes much sense to
// have batch delete in the reader interface.
// Prompt the user for confirmation, and use
// this.DeleteOrUndeleteSelectedMessages() to mark the selected messages
// as deleted.
// Returns an object with the following properties:
// deletedAll: Boolean - Whether or not all messages were successfully marked
// for deletion
// failureList: An object containing indexes of messages that failed to get
// marked for deletion, indexed by internal sub-board code, then
// containing messages indexes as properties. Reasons for failing
// to mark messages deleted can include the user not having permission
// to delete in a sub-board, failure to open the sub-board, etc.
writeMessage = false; // No need to refresh the message
break;

nightfox
committed
case this.enhReaderKeys.editMsg: // Edit the message
if (this.CanEdit())
{
console.crlf();
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
// Let the user edit the message if they want to
var editReturnObj = this.EditExistingMsg(pOffset);
// If the user confirmed editing the message, then see if the
// message was edited and refresh the screen accordingly.
if (editReturnObj.userConfirmed)
{
// If the message was edited, then refresh the text lines
// array and update the other message-related variables.
if (editReturnObj.msgEdited && (editReturnObj.newMsgIdx > -1))
{
// When the message is edited, the old message will be
// deleted and the edited message will be posted as a new
// message. So we should return to the caller and have it
// go directly to that new message.
continueOn = false;
retObj.newMsgOffset = editReturnObj.newMsgIdx;
}
}
}
else
{
writeMessage = false;
writePromptText = false;
}
break;

nightfox
committed
case this.enhReaderKeys.showHelp: // Show help
if (!console.term_supports(USER_ANSI))
{
console.crlf();
console.crlf();
}
this.DisplayEnhancedReaderHelp(allowChgMsgArea, msgHasAttachments);
if (!console.term_supports(USER_ANSI))
{
console.crlf();
console.crlf();
}
break;
case this.enhReaderKeys.reply: // Reply to the message
case this.enhReaderKeys.privateReply: // Private reply
// If the user pressed the private reply key while reading private
// mail, then do nothing (allow only the regular reply key to reply).
// If not reading personal email, go ahead and let the user reply
// with either the reply or private reply keypress.
var privateReply = (retObj.lastKeypress == this.enhReaderKeys.privateReply);
if (privateReply && this.readingPersonalEmail)
{
writeMessage = false; // Don't re-write the current message again
writePromptText = false; // Don't write the prompt text again
}
else
{
console.crlf();
// Get the message header with fields expanded so we can get the most info possible.
//var extdMsgHdr = this.GetMsgHdrByAbsoluteNum(msgHeader.number, true);
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
var extdMsgHdr = msgbase.get_msg_header(false, msgHeader.number, true);
msgbase.close();
// Let the user reply to the message
var replyRetObj = this.ReplyToMsg(extdMsgHdr, messageText, privateReply, pOffset);
retObj.userReplied = replyRetObj.postSucceeded;
//retObj.msgNotReadable = replyRetObj.msgWasDeleted;
var msgWasDeleted = replyRetObj.msgWasDeleted;
if (msgWasDeleted && !canViewDeletedMsgs())
{
var msgSearchObj = this.LookForNextOrPriorNonDeletedMsg(pOffset);
continueOn = msgSearchObj.continueInputLoop;
retObj.newMsgOffset = msgSearchObj.newMsgOffset;
retObj.nextAction = msgSearchObj.nextAction;
if (msgSearchObj.promptGoToNextArea)
{
Eric Oulashin
committed
if (console.yesno(replaceAtCodesInStr(this.text.goToNextMsgAreaPromptText)))
{
// Let this method exit and let the caller go to the next sub-board
continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
else
writeMessage = true; // We want to refresh the message on the screen
}
}
}
else // msgbase failed to open
{
console.attributes = "N";
console.crlf();
console.print("\x01h\x01yFailed to open the sub-board. Aborting.\x01n");
mswait(ERROR_PAUSE_WAIT_MS);
}
}
break;

nightfox
committed
case this.enhReaderKeys.postMsg: // Post a message
if (!this.readingPersonalEmail)
{
// Let the user post a message.
if (bbs.post_msg(this.subBoardCode))
{
// TODO: If the user is doing a search, it might be
// useful to search their new message and add it to
// the search results if it's a match.. but maybe
// not?
}
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
console.pause();
// We'll want to refresh the message & prompt text on the screen
writeMessage = true;
writePromptText = true;
}
else
{
// Don't write the current message or prompt text in the next iteration
writeMessage = false;
writePromptText = false;
}
break;
// Numeric digit: The start of a number of a message to read
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
console.crlf();
// Put the user's input back in the input buffer to
// be used for getting the rest of the message number.
console.ungetstr(retObj.lastKeypress);
// Prompt for the message number
Eric Oulashin
committed
var msgNumInput = this.PromptForMsgNum(null, replaceAtCodesInStr(this.text.readMsgNumPromptText), false, ERROR_PAUSE_WAIT_MS, false);
// Only allow reading the message if the message number is valid
// and it's not the same message number that was passed in.
if ((msgNumInput > 0) && (msgNumInput-1 != pOffset))
{
// If the message is marked as deleted, then output an error
if (this.MessageIsDeleted(msgNumInput-1))
{
console.crlf();
console.print("\x01n" + replaceAtCodesInStr(format(this.text.msgHasBeenDeletedText, msgNumInput)) + "\x01n");
console.crlf();
console.pause();
}
else
{
// Confirm with the user whether to read the message
var readMsg = true;
if (this.promptToReadMessage)
{
readMsg = console.yesno("\x01n" + this.colors["readMsgConfirmColor"]
+ "Read message "
+ this.colors["readMsgConfirmNumberColor"]
+ msgNumInput + this.colors["readMsgConfirmColor"]
+ ": Are you sure");
}
if (readMsg)
{
continueOn = false;
retObj.newMsgOffset = msgNumInput - 1;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
}
}
}
break;
case this.enhReaderKeys.prevMsgByTitle: // Previous message by title
case this.enhReaderKeys.prevMsgByAuthor: // Previous message by author
case this.enhReaderKeys.prevMsgByToUser: // Previous message by 'to user'
case this.enhReaderKeys.prevMsgByThreadID: // Previous message by thread ID
// Only allow this if we aren't doing a message search.
if (!this.SearchingAndResultObjsDefinedForCurSub())
{
console.crlf(); // For the "Searching..." text
var threadPrevMsgOffset = this.FindThreadPrevOffset(msgHeader,
keypressToThreadType(retObj.lastKeypress, this.enhReaderKeys),
false);
if (threadPrevMsgOffset > -1)
{
retObj.newMsgOffset = threadPrevMsgOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
continueOn = false;
}
}
else
{
writeMessage = false;
writePromptText = false;
}
break;
case this.enhReaderKeys.nextMsgByTitle: // Next message by title (subject)
case this.enhReaderKeys.nextMsgByAuthor: // Next message by author
case this.enhReaderKeys.nextMsgByToUser: // Next message by 'to user'
case this.enhReaderKeys.nextMsgByThreadID: // Next message by thread ID
// Only allow this if we aren't doing a message search.
if (!this.SearchingAndResultObjsDefinedForCurSub())
{
console.crlf(); // For the "Searching..." text
var threadNextMsgOffset = this.FindThreadNextOffset(msgHeader,
keypressToThreadType(retObj.lastKeypress, this.enhReaderKeys),
false);
if (threadNextMsgOffset > -1)
{
retObj.newMsgOffset = threadNextMsgOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
continueOn = false;
}
}
else
{
writeMessage = false;
writePromptText = false;
}
break;

nightfox
committed
case this.enhReaderKeys.previousMsg: // Previous message
// TODO: Change the key for this?
// Look for a prior message that isn't marked for deletion. Even
// if we don't find one, we'll still want to return from this
// function (with message index -1) so that this script can go
// onto the previous message sub-board/group.

Eric Oulashin
committed
retObj.newMsgOffset = this.FindNextReadableMsgIdx(pOffset, false);
var goToPrevMessage = false;
if ((retObj.newMsgOffset > -1) || allowChgMsgArea)
{
if (retObj.newMsgOffset == -1 && !curMsgSubBoardIsLast())
{
console.crlf();
Eric Oulashin
committed
goToPrevMessage = console.yesno(replaceAtCodesInStr(this.text.goToPrevMsgAreaPromptText));
}
else
{
// We're not at the beginning of the sub-board, so it's okay to exit this
// method and go to the previous message.
goToPrevMessage = true;
}
}
if (goToPrevMessage)
{
continueOn = false;
retObj.nextAction = ACTION_GO_PREVIOUS_MSG;
}
break;

nightfox
committed
case this.enhReaderKeys.nextMsg: // Next message
case KEY_ENTER:
// Look for a later message that isn't marked for deletion. Even
// if we don't find one, we'll still want to return from this
// function (with message index -1) so that this script can go
// onto the next message sub-board/group.

Eric Oulashin
committed
retObj.newMsgOffset = this.FindNextReadableMsgIdx(pOffset, true);
// Note: Unlike the left arrow key, we want to exit this method when
// navigating to the next message, regardless of whether or not the
// user is allowed to change to a different sub-board, so that processes
// that require continuation (such as new message scan) can continue.
// Still, if there are no more readable messages in the current sub-board
// (and thus the user would go onto the next message area), prompt the
// user whether they want to continue onto the next message area.
if (retObj.newMsgOffset == -1 && !curMsgSubBoardIsLast())
{
console.attributes = "N";
console.crlf();
// If configured to allow the user to post in the sub-board
// instead of going to the next message area and we're not
// scanning, then do so.
if (this.readingPostOnSubBoardInsteadOfGoToNext && !this.doingMsgScan)
{
// Ask the user if they want to post on the sub-board.
// If they say yes, then do so before exiting.
var grpNameAndDesc = this.GetGroupNameAndDesc();
Eric Oulashin
committed
if (!console.noyes(replaceAtCodesInStr(format(this.text.postOnSubBoard, grpNameAndDesc.grpName, grpNameAndDesc.grpDesc))))
bbs.post_msg(this.subBoardCode);
continueOn = false;
retObj.nextAction = ACTION_QUIT;
}
else
{
Eric Oulashin
committed
if (console.yesno(replaceAtCodesInStr(this.text.goToNextMsgAreaPromptText)))
{
// Let this method exit and let the caller go to the next sub-board
continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
}
}
else
{
// We're not at the end of the sub-board, so it's okay to exit this
// method and go to the next message.
continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
break;

nightfox
committed
case this.enhReaderKeys.firstMsg: // First message
// Only leave this function if we aren't already on the first message.
if (pOffset > 0)
{
continueOn = false;
retObj.nextAction = ACTION_GO_FIRST_MSG;
}
else
{
writeMessage = false;
writePromptText = false;
}
break;

nightfox
committed
case this.enhReaderKeys.lastMsg: // Last message
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
// Only leave this function if we aren't already on the last message.
if (pOffset < this.NumMessages() - 1)
{
continueOn = false;
retObj.nextAction = ACTION_GO_LAST_MSG;
}
else
{
writeMessage = false;
writePromptText = false;
}
break;
case "-": // Go to the previous message area
if (allowChgMsgArea)
{
continueOn = false;
retObj.nextAction = ACTION_GO_PREV_MSG_AREA;
}
else
{
writeMessage = false;
writePromptText = false;
}
break;
case "+": // Go to the next message area
if (allowChgMsgArea || this.doingMultiSubBoardScan)
{
continueOn = false;
retObj.nextAction = ACTION_GO_NEXT_MSG_AREA;
}
else
{
writeMessage = false;
writePromptText = false;
}
break;

nightfox
committed
// H and K: Display the extended message header info/kludge lines
// (for the sysop)
case this.enhReaderKeys.showHdrInfo:
case this.enhReaderKeys.showKludgeLines:
Eric Oulashin
committed
if (user.is_sysop)
{
console.crlf();
// Get an array of the extended header info/kludge lines and then
// display them.

Eric Oulashin
committed
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(this.subBoardCode, msgHeader.number, (retObj.lastKeypress == this.enhReaderKeys.showKludgeLines));
if (extdHdrInfoLines.length > 0)
{
console.crlf();
for (var infoIter = 0; infoIter < extdHdrInfoLines.length; ++infoIter)
{
console.print(extdHdrInfoLines[infoIter]);
console.crlf();
}
console.pause();
}
else
{
// There are no kludge lines for this message
Eric Oulashin
committed
console.print(replaceAtCodesInStr(this.text.noKludgeLinesForThisMsgText));
console.crlf();
console.pause();
}
}
else // The user is not a sysop
{
writeMessage = false;
writePromptText = false;
}
break;
// Message list, change message area: Quit out of this input loop
// and let the calling function, this.ReadMessages(), handle the
// action.

nightfox
committed
case this.enhReaderKeys.showMsgList: // Message list
console.attributes = "N";
console.crlf();
console.print("Loading...");
retObj.nextAction = ACTION_DISPLAY_MSG_LIST;
continueOn = false;
break;

nightfox
committed
case this.enhReaderKeys.chgMsgArea: // Change message area, if allowed
if (allowChgMsgArea)
{
retObj.nextAction = ACTION_CHG_MSG_AREA;
continueOn = false;
}
else
{
writeMessage = false;
writePromptText = false;
}
break;
case this.enhReaderKeys.downloadAttachments: // Download attachments
if (msgHasAttachments)
{
console.attributes = "N";
console.crlf();
console.print("\x01c- Download Attached Files -\x01n");
allowUserToDownloadMessage_NewInterface(msgHeader, this.subBoardCode);
// Ensure the message is refreshed on the screen
writeMessage = true;
writePromptText = true;
}
else
{
writeMessage = false;
writePromptText = false;
}
break;
case this.enhReaderKeys.saveToBBSMachine:
// Save the message to the BBS machine - Only allow this
// if the user is a sysop.
Eric Oulashin
committed
if (user.is_sysop)
{
console.crlf();
console.print("\x01n\x01cFilename:\x01h");
var inputLen = console.screen_columns - 10; // 10 = "Filename:" length + 1
var filename = console.getstr(inputLen, K_NOCRLF);
console.attributes = "N";
console.crlf();
if (filename.length > 0)
{
var saveMsgRetObj = this.SaveMsgToFile(msgHeader, filename);
if (saveMsgRetObj.succeeded)
console.print("\x01n\x01cThe message has been saved.\x01n");
if (msgHdrHasAttachmentFlag(msgHeader))
console.print(" Attachments not saved.");
console.attributes = "N";
else
console.print("\x01n\x01y\x01hFailed: " + saveMsgRetObj.errorMsg + "\x01n");
mswait(ERROR_PAUSE_WAIT_MS);
}
else
{
console.print("\x01n\x01y\x01hMessage not exported\x01n");
mswait(ERROR_PAUSE_WAIT_MS);
}
writeMessage = true;
}
else
writeMessage = false;
break;

nightfox
committed
case this.enhReaderKeys.userEdit: // Edit the user who wrote the message
Eric Oulashin
committed
if (user.is_sysop)
{
console.attributes = "N";
console.crlf();
console.print("- Edit user " + msgHeader.from);
console.crlf();
var editObj = editUser(msgHeader.from);
if (editObj.errorMsg.length != 0)
{
console.attributes = "N";
console.crlf();
console.print("\x01y\x01h" + editObj.errorMsg + "\x01n");
console.crlf();
console.pause();
}
}
writeMessage = true;
break;

nightfox
committed
case this.enhReaderKeys.forwardMsg: // Forward the message
console.attributes = "N";

nightfox
committed
console.crlf();
console.print("\x01c- Forward message\x01n");

nightfox
committed
console.crlf();
var retStr = this.ForwardMessage(msgHeader, messageText);
if (retStr.length > 0)
{
console.print("\x01n\x01h\x01y* " + retStr + "\x01n");

nightfox
committed
console.crlf();
console.pause();
}
writeMessage = true;
break;
case this.enhReaderKeys.vote: // Vote on the message
var voteRetObj = this.VoteOnMessage(msgHeader);
if (voteRetObj.BBSHasVoteFunction)
{
if (!voteRetObj.userQuit)
{
if ((voteRetObj.errorMsg.length > 0) || (!voteRetObj.savedVote))
{
console.attributes = "N";
console.crlf();
if (voteRetObj.errorMsg.length > 0)
{
if (voteRetObj.mnemonicsRequiredForErrorMsg)
{
console.mnemonics(voteRetObj.errorMsg);
console.attributes = "N";
}
else
console.print("\x01y\x01h* " + voteRetObj.errorMsg + "\x01n");
}
else if (!voteRetObj.savedVote)
console.print("\x01y\x01h* Failed to save the vote\x01n");
console.crlf();
console.pause();
}
else
msgHeader = voteRetObj.updatedHdr; // To get updated vote information
}
// If this message is a poll, then exit out of the reader
// and come back to read the same message again so that the
// voting results are re-loaded and displayed on the screen.
if ((typeof(MSG_TYPE_POLL) != "undefined") && (msgHeader.type & MSG_TYPE_POLL) == MSG_TYPE_POLL)
{
retObj.newMsgOffset = pOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
continueOn = false;
}
else
writeMessage = true; // We want to refresh the message on the screen
}
else
writeMessage = false;
break;
case this.enhReaderKeys.showVotes: // Show votes
if (msgHeader.hasOwnProperty("total_votes") && msgHeader.hasOwnProperty("upvotes"))
{
console.attributes = "N";
console.crlf();

nightfox
committed
var voteInfo = this.GetUpvoteAndDownvoteInfo(msgHeader);
for (var voteInfoIdx = 0; voteInfoIdx < voteInfo.length; ++voteInfoIdx)
{

nightfox
committed
console.print(voteInfo[voteInfoIdx]);
console.crlf();
}
}
else
{
console.print("\x01n\x01h\x01yThere is no voting information for this message\x01n");
console.crlf();
}
console.pause();
writeMessage = true;
break;
case this.enhReaderKeys.closePoll: // Close a poll message
var pollCloseMsg = "";
console.attributes = "N";
console.crlf();
// If this message is a poll, then allow closing it.
if ((typeof(MSG_TYPE_POLL) != "undefined") && (msgHeader.type & MSG_TYPE_POLL) == MSG_TYPE_POLL)