Newer
Older
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
6019
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
6047
6048
6049
6050
6051
6052
6053
6054
// 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:
if (gIsSysop)
{
console.crlf();
// Get an array of the extended header info/kludge lines and then
// display them.

nightfox
committed
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(msgHeader, (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
console.print(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
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 (msgAndAttachmentInfo.attachments.length > 0)
{
console.print("\1n");
console.crlf();
console.print("\1c- Download Attached Files -\1n");
// Note: sendAttachedFiles() will output a CRLF at the beginning.
sendAttachedFiles(msgAndAttachmentInfo.attachments);
// 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.
if (gIsSysop)
{
console.crlf();
console.print("\1n\1cFilename:\1h");
var inputLen = console.screen_columns - 10; // 10 = "Filename:" length + 1
var filename = console.getstr(inputLen, K_NOCRLF);
console.print("\1n");
console.crlf();
if (filename.length > 0)
{
var saveMsgRetObj = this.SaveMsgToFile(msgHeader, filename, true);
if (saveMsgRetObj.succeeded)
console.print("\1n\1cThe message has been saved.\1n");
else
console.print("\1n\1y\1hFailed: " + saveMsgRetObj.errorMsg + "\1n");
mswait(ERROR_PAUSE_WAIT_MS);
}
else
{
console.print("\1n\1y\1hMessage not exported\1n");
mswait(ERROR_PAUSE_WAIT_MS);
}
writeMessage = true;
}
else
writeMessage = false;
break;

nightfox
committed
case this.enhReaderKeys.userEdit: // Edit the user who wrote the message
if (gIsSysop)
{
console.print("\1n");
console.crlf();
console.print("- Edit user " + msgHeader.from);
console.crlf();
var editObj = editUser(msgHeader.from);
if (editObj.errorMsg.length != 0)
{
console.print("\1n");
console.crlf();
console.print("\1y\1h" + editObj.errorMsg + "\1n");
console.crlf();
console.pause();
}
}
writeMessage = true;
break;

nightfox
committed
case this.enhReaderKeys.forwardMsg: // Forward the message
console.print("\1n");
console.crlf();
console.print("\1c- Forward message\1n");
console.crlf();
var retStr = this.ForwardMessage(msgHeader, messageText);
if (retStr.length > 0)
{
console.print("\1n\1h\1y* " + retStr + "\1n");
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.print("\1n");
console.crlf();
if (voteRetObj.errorMsg.length > 0)
{
if (voteRetObj.mnemonicsRequiredForErrorMsg)
{
console.mnemonics(voteRetObj.errorMsg);
console.print("\1n");
}
else
console.print("\1y\1h* " + voteRetObj.errorMsg + "\1n");
}
else if (!voteRetObj.savedVote)
console.print("\1y\1h* Failed to save the vote\1n");
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.print("\1n");
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("\1n\1h\1yThere is no voting information for this message\1n");
console.crlf();
}
console.pause();
writeMessage = true;
break;
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
case this.enhReaderKeys.closePoll: // Close a poll message
var pollCloseMsg = "";
console.print("\1n");
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)
{
if ((msgHeader.auxattr & POLL_CLOSED) == 0)
{
// Only let the user close the poll if they created it or if they're a sysop.
if (gIsSysop || userHandleAliasNameMatch(msgHeader.from))
{
// Prompt to confirm whether the user wants to close the poll
if (!console.noyes("Close poll"))
{
// Close the poll
if (closePollWithOpenMsgbase(this.msgbase, msgHeader.number))
{
msgHeader.auxattr |= POLL_CLOSED;
pollCloseMsg = "\1n\1cThis poll was successfully closed.";
}
else
pollCloseMsg = "\1n\1r\1h* Failed to close this poll!";
}
}
else
pollCloseMsg = "\1n\1y\1hCan't close this poll because it's not yours";
}
else
pollCloseMsg = "\1n\1y\1hThis poll is already closed";
}
else
pollCloseMsg = "This message is not a poll";
// Display the poll closing status message
if (strip_ctrl(pollCloseMsg).length > 0)
{
console.print("\1n" + pollCloseMsg + "\1n");
console.crlf();
console.pause();
}
writeMessage = true;
break;
case this.enhReaderKeys.validateMsg: // Validate the message
if (gIsSysop && (this.subBoardCode != "mail") && msg_area.sub[this.subBoardCode].is_moderated)
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
{
var message = "";
if (this.ValidateMsg(this.subBoardCode, msgHeader.number))
{
message = "\1n\1cMessage validation successful";
// Refresh the message header in the arrays
this.RefreshMsgHdrInArrays(msgHeader.number);
// 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.
retObj.newMsgOffset = pOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
continueOn = false;
}
else
{
message = "\1n\1y\1hMessage validation failed!";
writeMessage = true;
}
console.crlf();
console.print(message);
console.print("\1n");
console.crlf();
console.pause();
}
else
writeMessage = false;
break;

nightfox
committed
case this.enhReaderKeys.quit: // Quit
retObj.nextAction = ACTION_QUIT;
continueOn = false;
break;
default:
// No need to do anything
writeMessage = false;
writePromptText = false;
break;
}
}
return retObj;
}
// For the ReadMessageEnhanced methods: This function converts a thread navigation
// key character to its corresponding thread type value
function keypressToThreadType(pKeypress, pEnhReaderKeys)
{
var threadType = THREAD_BY_ID;
switch (pKeypress)
{
case pEnhReaderKeys.prevMsgByTitle:
case pEnhReaderKeys.nextMsgByTitle:
threadType = THREAD_BY_TITLE;
break;
case pEnhReaderKeys.prevMsgByAuthor:
case pEnhReaderKeys.nextMsgByAuthor:
threadType = THREAD_BY_AUTHOR;
break;
case pEnhReaderKeys.prevMsgByToUser:
case pEnhReaderKeys.nextMsgByToUser:
threadType = THREAD_BY_TO_USER;
break;
case pEnhReaderKeys.prevMsgByThreadID:
case pEnhReaderKeys.nextMsgByThreadID:
default:
threadType = THREAD_BY_ID;
break;
}
return threadType;
}
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
// For the DigDistMsgReader class: For the enhanced reader method - Prepares the
// last 2 lines on the screen for propmting the user for something.
//
// Return value: An object containing x and y values representing the cursor
// position, ready to prompt the user.
function DigDistMsgReader_EnhReaderPrepLast2LinesForPrompt()
{
var promptPos = { x: this.msgAreaLeft, y: this.msgAreaBottom };
// Write a line of characters above where the prompt will be placed,
// to help get the user's attention.
console.gotoxy(promptPos.x, promptPos.y-1);
console.print("\1n" + this.colors.enhReaderPromptSepLineColor);
for (var lineCounter = 0; lineCounter < this.msgAreaWidth; ++lineCounter)
console.print(HORIZONTAL_SINGLE);
// Clear the inside of the message area, so as not to overwrite
// the scrollbar character
console.print("\1n");
console.gotoxy(promptPos);
for (var lineCounter = 0; lineCounter < this.msgAreaWidth; ++lineCounter)
console.print(" ");
// Position the cursor at the prompt location
console.gotoxy(promptPos);
return promptPos;
}
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
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
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
// For the DigDistMsgReader class: For the enhanced reader method - Looks for a
// later method that isn't marked for deletion. If none is found, looks for a
// prior message that isn't marked for deletion.
//
// Parameters:
// pOffset: The offset of the message to start at
//
// Return value: An object with the following properties:
// newMsgOffset: The offset of the next readable message
// nextAction: The next action (code) for the enhanced reader
// continueInputLoop: Boolean - Whether or not to continue the input loop
// promptGoToNextArea: Boolean - Whether or not to prompt the user to go
// to the next message area
function DigDistMsgReader_LookForNextOrPriorNonDeletedMsg(pOffset)
{
var retObj = new Object();
retObj.newMsgOffset = 0;
retObj.nextAction = ACTION_NONE;
retObj.continueInputLoop = true;
retObj.promptGoToNextArea = false;
// Look for a later message that isn't marked for deletion.
// If none is found, then look for a prior message that isn't
// marked for deletion.
retObj.newMsgOffset = this.FindNextNonDeletedMsgIdx(pOffset, true);
if (retObj.newMsgOffset > -1)
{
retObj.continueInputLoop = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
else
{
// No later message found, so look for a prior message.
retObj.newMsgOffset = this.FindNextNonDeletedMsgIdx(pOffset, false);
if (retObj.newMsgOffset > -1)
{
retObj.continueInputLoop = false;
retObj.nextAction = ACTION_GO_PREVIOUS_MSG;
}
else
{
// No prior message found. We'll want to return from the enhanced
// reader function (with message index -1) so that this script can
// go onto the next message sub-board/group. Also, set the next
// action such that the calling method will go on to the next
// message/sub-board.
if (!curMsgSubBoardIsLast())
{
if (this.readingPersonalEmail)
{
retObj.continueInputLoop = false;
retObj.nextAction = ACTION_QUIT;
}
else
retObj.promptGoToNextArea = true;
}
else
{
// We're not at the end of the sub-board or the current sub-board
// is the last, so go ahead and exit.
retObj.continueInputLoop = false;
retObj.nextAction = ACTION_GO_NEXT_MSG;
}
}
}
return retObj;
}
// For the DigDistMsgReader class: Writes the help line for enhanced reader
// mode.
//
// Parameters:
// pScreenRow: Optional - The screen row to write the help line on. If not
// specified, the last row on the screen will be used.
// pDisplayChgAreaOpt: Optional boolean - Whether or not to show the "change area" option.
// Defaults to true.
function DigDistMsgReader_DisplayEnhancedMsgReadHelpLine(pScreenRow, pDisplayChgAreaOpt)
{
var displayChgAreaOpt = (typeof(pDisplayChgAreaOpt) == "boolean" ? pDisplayChgAreaOpt : true);
// Move the cursor to the desired location on the screen and display the help line
console.gotoxy(1, typeof(pScreenRow) == "number" ? pScreenRow : console.screen_rows);
console.print(displayChgAreaOpt ? this.enhReadHelpLine : this.enhReadHelpLineWithoutChgArea);
}
// For the DigDistMsgReader class: Goes back to the prior readable sub-board
// (accounting for search results, etc.). Changes the object's subBoardCode,
// msgbase object, etc.
//
// Parameters:
// pAllowChgMsgArea: Boolean - Whether or not the user is allowed to change
// to another message area
// Return value: An object with the following properties:
// changedMsgArea: Boolean - Whether or not this method successfully
// changed to a prior message area
// msgIndex: The message index for the new sub-board. Will be -1
// if there is no new sub-board or otherwise invalid
// scenario.
// shouldStopReading: Whether or not the script should stop letting
// the user read messages
function DigDistMsgReader_GoToPrevSubBoardForEnhReader(pAllowChgMsgArea)
{
var retObj = new Object();
retObj.changedMsgArea = false;
retObj.msgIndex = -1;
retObj.shouldStopReading = false;
// Only allow this if pAllowChgMsgArea is true and we're not reading personal
// email. If we're reading personal email, then msg_area.sub is unavailable
// for the "mail" internal code.
if (pAllowChgMsgArea && (this.subBoardCode != "mail"))
{
// continueGoingToPrevSubBoard specifies whether or not to continue
// going to the previous sub-boards in case there is search text
// specified.
var continueGoingToPrevSubBoard = true;
while (continueGoingToPrevSubBoard)
{
// Allow going to the previous message sub-board/group.
var msgGrpIdx = msg_area.sub[this.subBoardCode].grp_index;
var subBoardIdx = msg_area.sub[this.subBoardCode].index;
var readMsgRetObj = findNextOrPrevNonEmptySubBoard(msgGrpIdx, subBoardIdx, false);
// If a different sub-board was found, then go to that sub-board.
if (readMsgRetObj.foundSubBoard && readMsgRetObj.subChanged)
{
bbs.cursub = 0;
bbs.curgrp = readMsgRetObj.grpIdx;
bbs.cursub = readMsgRetObj.subIdx;
// Open the new sub-board
this.msgbase.close();
this.setSubBoardCode(readMsgRetObj.subCode);
this.msgbase = new MsgBase(this.subBoardCode);
if (this.msgbase.open())
{
if (this.searchType == SEARCH_NONE || !this.SearchingAndResultObjsDefinedForCurSub())
{
continueGoingToPrevSubBoard = false; // No search results, so don't keep going to the previous sub-board.
// Go to the user's last read message. If the message index ends up
// below 0, then go to the last message not marked as deleted.
// We probably shouldn't use GetMsgIdx() yet because the arrays of
// message headers have not been populated for the next area yet
retObj.msgIndex = this.AbsMsgNumToIdx(msg_area.sub[this.subBoardCode].last_read);
//retObj.msgIndex = this.GetMsgIdx(msg_area.sub[this.subBoardCode].last_read);

nightfox
committed
if (retObj.msgIndex >= 0)
retObj.changedMsgArea = true;
else
{
// Look for the last message not marked as deleted
var nonDeletedMsgIdx = this.FindNextNonDeletedMsgIdx(this.NumMessages(), false);

nightfox
committed
// If a non-deleted message was found, then set retObj.msgIndex to it.
// Otherwise, tell the user there are no messages in this sub-board
// and return.
if (nonDeletedMsgIdx > -1)

nightfox
committed
retObj.msgIndex = nonDeletedMsgIdx;
else

nightfox
committed
retObj.msgIndex = this.NumMessages() - 1; // Shouldn't get here
var newLastRead = this.IdxToAbsMsgNum(retObj.msgIndex);
if (newLastRead > -1)
msg_area.sub[this.subBoardCode].last_read = newLastRead;
}
}
// Set the hotkey help line again, as this sub-board might have
// different settings for whether messages can be edited or deleted,
// then refresh it on the screen.
var oldHotkeyHelpLine = this.enhReadHelpLine;
this.SetEnhancedReaderHelpLine();
// If a search is is specified that would populate the search
// results, then populate this.msgSearchHdrs for the current
// sub-board if there is search text specified. If there
// are no search results, then ask the user if they want
// to continue searching the message areas.
if (this.SearchTypePopulatesSearchResults())
{
if (this.PopulateHdrsIfSearch_DispErrorIfNoMsgs(false, true, false))
{
retObj.changedMsgArea = true;
continueGoingToPrevSubBoard = false;

nightfox
committed
retObj.msgIndex = this.NumMessages() - 1;
if (this.scrollingReaderInterface && console.term_supports(USER_ANSI))
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, pAllowChgMsgArea);
}
else // No search results in this sub-board
{
continueGoingToPrevSubBoard = !console.noyes("Continue searching");
if (!continueGoingToPrevSubBoard)
{
retObj.shouldStopReading = true;
return retObj;
}
}
}
else
{
retObj.changedMsgArea = true;
this.PopulateHdrsForCurrentSubBoard();
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
if ((oldHotkeyHelpLine != this.enhReadHelpLine) && this.scrollingReaderInterface && console.term_supports(USER_ANSI))
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, pAllowChgMsgArea);
}
}
else // The message base failed to open
{
console.clear("\1n");
console.print("\1h\1y* \1wUnable to open message sub-board:");
console.crlf();
console.print(subBoardGrpAndName(this.subBoardCode));
console.crlf();
console.pause();
retObj.shouldStopReading = true;
continueGoingToPrevSubBoard = false;
return retObj;
}
}
else
{
// Didn't find a prior sub-board with readable messages.
// We could stop and exit the script here by doing the following,
// but I'd rather let the user exit when they want to.
continueGoingToPrevSubBoard = false;
// Show a message telling the user that there are no prior
// messages or sub-boards. Then, refresh the hotkey help line.
writeWithPause(this.msgAreaLeft, console.screen_rows,
"\1n\1h\1y* No prior messages or no message in prior message areas.",
ERROR_PAUSE_WAIT_MS, "\1n", true);
if (this.scrollingReaderInterface && console.term_supports(USER_ANSI))
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, pAllowChgMsgArea);
}
}
}
return retObj;
}
// For the DigDistMsgReader class: Goes to the next readable sub-board
// (accounting for search results, etc.). Changes the object's subBoardCode,
// msgbase object, etc.
//
// Parameters:
// pAllowChgMsgArea: Boolean - Whether or not the user is allowed to change
// to another message area
// Return value: An object with the following properties:
// changedMsgArea: Boolean - Whether or not this method successfully
// changed to a prior message area
// msgIndex: The message index for the new sub-board. Will be -1
// if there is no new sub-board or otherwise invalid
// scenario.
// shouldStopReading: Whether or not the script should stop letting
// the user read messages
function DigDistMsgReader_GoToNextSubBoardForEnhReader(pAllowChgMsgArea)
{
var retObj = new Object();
retObj.changedMsgArea = false;
retObj.msgIndex = -1;
retObj.shouldStopReading = false;
// Only allow this if pAllowChgMsgArea is true and we're not reading personal
// email. If we're reading personal email, then msg_area.sub is unavailable
// for the "mail" internal code.
if (pAllowChgMsgArea && (this.subBoardCode != "mail"))
{
// continueGoingToNextSubBoard specifies whether or not to continue
// advancing to the next sub-boards in case there is search text
// specified.
var continueGoingToNextSubBoard = true;
while (continueGoingToNextSubBoard)
{
// Allow going to the next message sub-board/group.
var msgGrpIdx = msg_area.sub[this.subBoardCode].grp_index;
var subBoardIdx = msg_area.sub[this.subBoardCode].index;
var readMsgRetObj = findNextOrPrevNonEmptySubBoard(msgGrpIdx, subBoardIdx, true);
// If a different sub-board was found, then go to that sub-board.
if (readMsgRetObj.foundSubBoard && readMsgRetObj.subChanged)
{
retObj.msgIndex = 0;
bbs.cursub = 0;
bbs.curgrp = readMsgRetObj.grpIdx;
bbs.cursub = readMsgRetObj.subIdx;
// Open the new sub-board
this.msgbase.close();
this.setSubBoardCode(readMsgRetObj.subCode);
this.msgbase = new MsgBase(this.subBoardCode);
if (this.msgbase.open())
{
if ((this.searchType == SEARCH_NONE) || !this.SearchingAndResultObjsDefinedForCurSub())
{
continueGoingToNextSubBoard = false; // No search results, so don't keep going to the next sub-board.
// Go to the user's last read message. If the message index ends up
// below 0, then go to the first message not marked as deleted.
retObj.msgIndex = this.AbsMsgNumToIdx(msg_area.sub[this.subBoardCode].last_read);
// We probably shouldn't use GetMsgIdx() yet because the arrays of
// message headers have not been populated for the next area yet
//retObj.msgIndex = this.GetMsgIdx(msg_area.sub[this.subBoardCode].last_read);

nightfox
committed
if (retObj.msgIndex >= 0)
retObj.changedMsgArea = true;
else
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
{
// Set the index of the message to display - Look for the
// first message not marked as deleted
var nonDeletedMsgIdx = this.FindNextNonDeletedMsgIdx(this.NumMessages()-1, true);
// If a non-deleted message was found, then set retObj.msgIndex to it.
// Otherwise, tell the user there are no messages in this sub-board
// and return.
if (nonDeletedMsgIdx > -1)
{
retObj.msgIndex = nonDeletedMsgIdx;
retObj.changedMsgArea = true;
var newLastRead = this.IdxToAbsMsgNum(nonDeletedMsgIdx);
if (newLastRead > -1)
msg_area.sub[this.subBoardCode].last_read = newLastRead;
}
}
}
// Set the hotkey help line again, as this sub-board might have
// different settings for whether messages can be edited or deleted,
// then refresh it on the screen.
var oldHotkeyHelpLine = this.enhReadHelpLine;
this.SetEnhancedReaderHelpLine();
// If a search is is specified that would populate the search
// results, then populate this.msgSearchHdrs for the current
// sub-board if there is search text specified. If there
// are no search results, then ask the user if they want
// to continue searching the message areas.
if (this.SearchTypePopulatesSearchResults())
{
if (this.PopulateHdrsIfSearch_DispErrorIfNoMsgs(false, true, false))
{
retObj.changedMsgArea = true;
continueGoingToNextSubBoard = false;
this.PopulateHdrsForCurrentSubBoard();
retObj.msgIndex = 0;
if (this.scrollingReaderInterface && console.term_supports(USER_ANSI))
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, pAllowChgMsgArea);
}
else // No search results in this sub-board
{
continueGoingToNextSubBoard = !console.noyes("Continue searching");
if (!continueGoingToNextSubBoard)
{
retObj.shouldStopReading = true;
return retObj;
}
}
}
else
{
// There is no search. Populate the arrays of all headers
// for this sub-board
this.PopulateHdrsForCurrentSubBoard();
retObj.msgIndex = this.GetMsgIdx(msg_area.sub[this.subBoardCode].last_read);

nightfox
committed
if (retObj.msgIndex == -1)
retObj.msgIndex = 0;
}
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
}
else // The message base failed to open
{
console.clear("\1n");
console.print("\1h\1y* \1wUnable to open message sub-board:");
console.crlf();
console.print(subBoardGrpAndName(this.subBoardCode));
console.crlf();
console.pause();
retObj.shouldStopReading = true;
continueGoingToNextSubBoard = false;
return retObj;
}
}
else
{
// Didn't find later sub-board with readable messages.
// We could stop and exit the script here by doing the following,
// but I'd rather let the user exit when they want to.
//retObj.shouldStopReading = true;
//return retObj;
continueGoingToNextSubBoard = false;
// Show a message telling the user that there are no more
// messages or sub-boards. Then, refresh the hotkey help line.
writeWithPause(this.msgAreaLeft, console.screen_rows,
"\1n\1h\1y* No more messages or message areas.",
ERROR_PAUSE_WAIT_MS, "\1n", true);
if (this.scrollingReaderInterface && console.term_supports(USER_ANSI))
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, pAllowChgMsgArea);
}
}
}
return retObj;
}

nightfox
committed
// For the DigDistMsgReader Class: Prepares the variables that keep track of the
// traditional-interface message list position, current messsage number, etc.
function DigDistMsgReader_SetUpTraditionalMsgListVars()
{
// If a search is specified, then just start at the first message.
// If no search is specified, then get the index of the user's last read
// message. Then, figure out which page it's on and set the lightbar list
// index & cursor position variables accordingly.
var lastReadMsgIdx = 0;
if (!this.SearchingAndResultObjsDefinedForCurSub())
{
lastReadMsgIdx = this.GetLastReadMsgIdx();
if (lastReadMsgIdx == -1)
lastReadMsgIdx = 0;
}
var pageNum = findPageNumOfItemNum(lastReadMsgIdx+1, this.tradMsgListNumLines, this.NumMessages(),
this.reverseListOrder);

nightfox
committed
this.CalcTraditionalMsgListTopIdx(pageNum);
if (!this.reverseListOrder && (this.tradListTopMsgIdx > lastReadMsgIdx))

nightfox
committed
this.tradListTopMsgIdx -= this.tradMsgListNumLines;
}
// For the DigDistMsgReader Class: Prepares the variables that keep track of the
// lightbar message list position, current messsage number, etc.
function DigDistMsgReader_SetUpLightbarMsgListVars()
{
// If no search is specified or if reading personal email, then get the index
// of the user's last read message. Then, figure out which page it's on and
// set the lightbar list index & cursor position variables accordingly.

nightfox
committed
var lastReadMsgIdx = 0;
if (!this.SearchingAndResultObjsDefinedForCurSub() || this.readingPersonalEmail)

nightfox
committed
{
lastReadMsgIdx = this.GetLastReadMsgIdx();
if (lastReadMsgIdx == -1)
lastReadMsgIdx = 0;
}
else
{
// A search was specified. If reading personal email, then set the
// message index to the last read message.
if (this.readingPersonalEmail)
{
lastReadMsgIdx = this.GetLastReadMsgIdx();
if (lastReadMsgIdx == -1)
lastReadMsgIdx = 0;
}
}

nightfox
committed
var pageNum = findPageNumOfItemNum(lastReadMsgIdx+1, this.lightbarMsgListNumLines, this.NumMessages(),
this.reverseListOrder);

nightfox
committed
this.CalcLightbarMsgListTopIdx(pageNum);
var initialCursorRow = 0;
if (this.reverseListOrder)

nightfox
committed
initialCursorRow = this.lightbarMsgListStartScreenRow+(this.lightbarListTopMsgIdx-lastReadMsgIdx);
else
{
if (this.lightbarListTopMsgIdx > lastReadMsgIdx)
this.lightbarListTopMsgIdx -= this.lightbarMsgListNumLines;
initialCursorRow = this.lightbarMsgListStartScreenRow+(lastReadMsgIdx-this.lightbarListTopMsgIdx);
}
this.lightbarListSelectedMsgIdx = lastReadMsgIdx;
this.lightbarListCurPos = { x: 1, y: initialCursorRow };
}
// For the DigDistMsgReader Class: Writes the message list column headers at the
// top of the screen.
function DigDistMsgReader_WriteMsgListScreenTopHeader()
{
console.home();
// If we will be displaying the message group and sub-board in the
// header at the top of the screen (an additional 2 lines), then
// update nMaxLines and nListStartLine to account for this.
if (this.displayBoardInfoInHeader && canDoHighASCIIAndANSI()) // console.term_supports(USER_ANSI)
{
var curpos = console.getxy();
// Figure out the message group name
var msgGroupName = "";
// For the message group name, we can also use this.msgbase.cfg.grp_name in
// Synchronet 3.12 and higher.
if (this.msgbase.cfg != null)
msgGroupName = msg_area.grp_list[this.msgbase.cfg.grp_number].description;
else
msgGroupName = "Unspecified";
// Figure out the sub-board name
var subBoardName = "";
if (this.msgbase.cfg != null)
subBoardName = this.msgbase.cfg.description;
else if ((this.msgbase.subnum == -1) || (this.msgbase.subnum == 65535))
subBoardName = "Electronic Mail";
else
subBoardName = "Unspecified";
// Display the message group name
console.print(this.colors["msgListHeaderMsgGroupTextColor"] + "Msg group: " +
this.colors["msgListHeaderMsgGroupNameColor"] + msgGroupName);
console.cleartoeol(); // Fill to the end of the line with the current colors
// Display the sub-board name on the next line
++curpos.y;
console.gotoxy(curpos);
console.print(this.colors["msgListHeaderSubBoardTextColor"] + "Sub-board: " +
this.colors["msgListHeaderMsgSubBoardName"] + subBoardName);
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
console.cleartoeol(); // Fill to the end of the line with the current colors
++curpos.y;
console.gotoxy(curpos);
}
// Write the message listing column headers
printf(this.colors["msgListColHeader"] + this.sHdrFormatStr, "Msg#", "From", "To", "Subject", "Date", "Time");
// Set the normal text attribute
console.print("\1n");
}
// For the DigDistMsgReader Class: Lists a screenful of message header information.
//
// Parameters:
// pTopIndex: The index (offset) of the top message
// pMaxLines: The maximum number of lines to output to the screen
//
// Return value: Boolean, whether or not the last message output to the
// screen is the last message in the sub-board.
function DigDistMsgReader_ListScreenfulOfMessages(pTopIndex, pMaxLines)
{
var atLastPage = false;
var curpos = console.getxy();
var msgIndex = 0;
if (this.reverseListOrder)
{
var endIndex = pTopIndex - pMaxLines + 1; // The index of the last message to display
for (msgIndex = pTopIndex; (msgIndex >= 0) && (msgIndex >= endIndex); --msgIndex)
{
// The following line which sets console.line_counter to 0 is a
// kludge to disable Synchronet's automatic pausing after a
// screenful of text, so that this script can have more control
// over screen pausing.
console.line_counter = 0;
// Get the message header (it will be a MsgHeader object) and
// display it.
msgHeader = this.GetMsgHdrByIdx(msgIndex);
if (msgHeader == null)
continue;
// Display the message info
this.PrintMessageInfo(msgHeader, false, msgIndex+1);
if (console.term_supports(USER_ANSI))
{
++curpos.y;
console.gotoxy(curpos);
}
else
console.crlf();
}
atLastPage = (msgIndex < 0);
}
else
{
var endIndex = pTopIndex + pMaxLines; // One past the last message index to display
for (msgIndex = pTopIndex; (msgIndex < this.NumMessages()) && (msgIndex < endIndex); ++msgIndex)
{
// The following line which sets console.line_counter to 0 is a
// kludge to disable Synchronet's automatic pausing after a
// screenful of text, so that this script can have more control
// over screen pausing.
console.line_counter = 0;
// Get the message header (it will be a MsgHeader object) and
// display it.
msgHeader = this.GetMsgHdrByIdx(msgIndex);
if (msgHeader == null)
continue;
// Display the message info
this.PrintMessageInfo(msgHeader, false, msgIndex+1);
if (console.term_supports(USER_ANSI))
{
++curpos.y;
console.gotoxy(curpos);
}
else
console.crlf();
}
atLastPage = (msgIndex == this.NumMessages());
}
return atLastPage;
}

nightfox
committed
// For the DigDistMsgReader Class: Displays the help screen for the message list.
//
// Parameters:

nightfox
committed
// pChgSubBoardAllowed: Whether or not changing to another sub-board is allowed
// pPauseAtEnd: Boolean, whether or not to pause at the end.

nightfox
committed
function DigDistMsgReader_DisplayMsgListHelp(pChgSubBoardAllowed, pPauseAtEnd)
{
DisplayProgramInfo();
// Display help specific to which interface is being used.
if (this.msgListUseLightbarListInterface)

nightfox
committed
this.DisplayLightbarMsgListHelp(false, pChgSubBoardAllowed);
else

nightfox
committed
this.DisplayTraditionalMsgListHelp(false, pChgSubBoardAllowed);
// If pPauseAtEnd is true, then output a newline and
// prompt the user whether or not to continue.
if (pPauseAtEnd)
console.pause();
}

nightfox
committed
// For the DigDistMsgReader Class: Displays help for the traditional-interface
// message list
//
// Parameters:
// pDisplayHeader: Whether or not to display a help header at the beginning

nightfox
committed
// pChgSubBoardAllowed: Whether or not changing to another sub-board is allowed
// pPauseAtEnd: Boolean, whether or not to pause at the end.

nightfox
committed
function DigDistMsgReader_DisplayTraditionalMsgListHelp(pDisplayHeader, pChgSubBoardAllowed, pPauseAtEnd)