Newer
Older

Eric Oulashin
committed
msgListIdxes.dateStart = msgListIdxes.subjEnd;
msgListIdxes.dateEnd = msgListIdxes.dateStart + +this.DATE_LEN + 1;
msgListIdxes.timeStart = msgListIdxes.dateEnd;
msgListIdxes.timeEnd = console.screen_columns - 1; // msgListIdxes.timeStart + +this.TIME_LEN + 1;
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
var msgListMenuHeight = console.screen_rows - this.lightbarMsgListStartScreenRow;
var msgListMenu = new DDLightbarMenu(1, this.lightbarMsgListStartScreenRow, console.screen_columns, msgListMenuHeight);
msgListMenu.scrollbarEnabled = true;
msgListMenu.borderEnabled = false;
msgListMenu.SetColors({
itemColor: [{start: msgListIdxes.msgNumStart, end: msgListIdxes.msgNumEnd, attrs: this.colors.msgListMsgNumColor},
{start: msgListIdxes.selectMarkStart, end: msgListIdxes.selectMarkEnd, attrs: this.colors.selectedMsgMarkColor},
{start: msgListIdxes.fromNameStart, end: msgListIdxes.fromNameEnd, attrs: this.colors.msgListFromColor},
{start: msgListIdxes.toNameStart, end: msgListIdxes.toNameEnd, attrs: this.colors.msgListToColor},
{start: msgListIdxes.subjStart, end: msgListIdxes.subjEnd, attrs: this.colors.msgListSubjectColor},
{start: msgListIdxes.dateStart, end: msgListIdxes.dateEnd, attrs: this.colors.msgListDateColor},
{start: msgListIdxes.timeStart, end: msgListIdxes.timeEnd, attrs: this.colors.msgListTimeColor}],
altItemColor: [{start: msgListIdxes.msgNumStart, end: msgListIdxes.msgNumEnd, attrs: this.colors.msgListToUserMsgNumColor},
{start: msgListIdxes.selectMarkStart, end: msgListIdxes.selectMarkEnd, attrs: this.colors.selectedMsgMarkColor},
{start: msgListIdxes.fromNameStart, end: msgListIdxes.fromNameEnd, attrs: this.colors.msgListToUserFromColor},
{start: msgListIdxes.toNameStart, end: msgListIdxes.toNameEnd, attrs: this.colors.msgListToUserToColor},
{start: msgListIdxes.subjStart, end: msgListIdxes.subjEnd, attrs: this.colors.msgListToUserSubjectColor},
{start: msgListIdxes.dateStart, end: msgListIdxes.dateEnd, attrs: this.colors.msgListToUserDateColor},
{start: msgListIdxes.timeStart, end: msgListIdxes.timeEnd, attrs: this.colors.msgListToUserTimeColor}],
selectedItemColor: [{start: msgListIdxes.msgNumStart, end: msgListIdxes.msgNumEnd, attrs: this.colors.msgListMsgNumHighlightColor},
{start: msgListIdxes.selectMarkStart, end: msgListIdxes.selectMarkEnd, attrs: this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor},
{start: msgListIdxes.fromNameStart, end: msgListIdxes.fromNameEnd, attrs: this.colors.msgListFromHighlightColor},
{start: msgListIdxes.toNameStart, end: msgListIdxes.toNameEnd, attrs: this.colors.msgListToHighlightColor},
{start: msgListIdxes.subjStart, end: msgListIdxes.subjEnd, attrs: this.colors.msgListSubjHighlightColor},
{start: msgListIdxes.dateStart, end: msgListIdxes.dateEnd, attrs: this.colors.msgListDateHighlightColor},
{start: msgListIdxes.timeStart, end: msgListIdxes.timeEnd, attrs: this.colors.msgListTimeHighlightColor}],
altSelectedItemColor: [{start: msgListIdxes.msgNumStart, end: msgListIdxes.msgNumEnd, attrs: this.colors.msgListMsgNumHighlightColor},
{start: msgListIdxes.selectMarkStart, end: msgListIdxes.selectMarkEnd, attrs: this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor},
{start: msgListIdxes.fromNameStart, end: msgListIdxes.fromNameEnd, attrs: this.colors.msgListFromHighlightColor},
{start: msgListIdxes.toNameStart, end: msgListIdxes.toNameEnd, attrs: this.colors.msgListToHighlightColor},
{start: msgListIdxes.subjStart, end: msgListIdxes.subjEnd, attrs: this.colors.msgListSubjHighlightColor},
{start: msgListIdxes.dateStart, end: msgListIdxes.dateEnd, attrs: this.colors.msgListDateHighlightColor},
{start: msgListIdxes.timeStart, end: msgListIdxes.timeEnd, attrs: this.colors.msgListTimeHighlightColor}]
});

Eric Oulashin
committed
// If we are to show message vote scores in the list (i.e., if the
// user's terminal is wide enough), then splice in color specifiers
// for the score column.
if (this.showScoresInMsgList)
{
msgListMenu.colors.itemColor.splice(5, 0, {start: msgListIdxes.scoreStart, end: msgListIdxes.scoreEnd, attrs: this.colors.msgListScoreColor});
msgListMenu.colors.altItemColor.splice(5, 0, {start: msgListIdxes.scoreStart, end: msgListIdxes.scoreEnd, attrs: this.colors.msgListToUserScoreColor});
msgListMenu.colors.selectedItemColor.splice(5, 0, {start: msgListIdxes.scoreStart, end: msgListIdxes.scoreEnd, attrs: this.colors.msgListScoreHighlightColor + this.colors.msgListHighlightBkgColor});
msgListMenu.colors.altSelectedItemColor.splice(5, 0, {start: msgListIdxes.scoreStart, end: msgListIdxes.scoreEnd, attrs: this.colors.msgListScoreHighlightColor + this.colors.msgListHighlightBkgColor});
}
msgListMenu.multiSelect = false;
msgListMenu.ampersandHotkeysInItems = false;
msgListMenu.wrapNavigation = false;
// Add additional keypresses for quitting the menu's input loop so we can
// respond to these keys

Eric Oulashin
committed
// Ctrl-A: Select all messages
var additionalQuitKeys = "EeqQgGcCsS ?0123456789" + CTRL_A + this.msgListKeys.batchDelete + this.msgListKeys.userSettings;
if (this.CanDelete() || this.CanDeleteLastMsg())

Eric Oulashin
committed
additionalQuitKeys += this.msgListKeys.deleteMessage + this.msgListKeys.undeleteMessage.toLowerCase() + this.msgListKeys.undeleteMessage.toUpperCase();
if (this.CanEdit())

Eric Oulashin
committed
additionalQuitKeys += this.msgListKeys.editMsg;
msgListMenu.AddAdditionalQuitKeys(additionalQuitKeys);
// Change the menu's NumItems() and GetItem() function to reference
// the message list in this object rather than add the menu items
// to the menu
msgListMenu.msgReader = this; // Add this object to the menu object
msgListMenu.NumItems = function() {
return this.msgReader.NumMessages();
};
msgListMenu.GetItem = function(pItemIndex) {
var menuItemObj = this.MakeItemWithRetval(-1);
var itemIdx = (this.msgReader.reverseListOrder ? this.msgReader.NumMessages() - pItemIndex - 1 : pItemIndex);

Eric Oulashin
committed
// In order to get vote score information (displayed if the user's terminal is wide
// enough), the 2nd parameter to GetMsgHdrByIdx() should be true.
var msgHdr = this.msgReader.GetMsgHdrByIdx(itemIdx, this.msgReader.showScoresInMsgList);
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
if (msgHdr != null)
{
// When setting the item text, call PrintMessageInfo with true as
// the last parameter to return the string instead
menuItemObj.text = strip_ctrl(this.msgReader.PrintMessageInfo(msgHdr, false, itemIdx+1, true));
menuItemObj.retval = msgHdr.number;
if (this.msgReader.subBoardCode != "mail")
menuItemObj.useAltColors = userHandleAliasNameMatch(msgHdr.to);
// If the message is marked as deleted, ensure the correct color is used
// for the mark character in the menu
if ((msgHdr.attr & MSG_DELETE) == MSG_DELETE)
{
var fromColor = this.msgReader.colors.msgListFromColor;
var toColor = this.msgReader.colors.msgListToColor;
var subjColor = this.msgReader.colors.msgListSubjectColor;
if ((this.msgReader.subBoardCode != "mail") && (userHandleAliasNameMatch(msgHdr.to)))
{
fromColor = this.msgReader.colors.msgListToUserFromColor;
toColor = this.msgReader.colors.msgListToUserToColor;
subjColor = this.msgReader.colors.msgListToUserSubjectColor;
}
menuItemObj.itemColor = [{start: msgListIdxes.msgNumStart, end: msgListIdxes.msgNumEnd, attrs: this.msgReader.colors.msgListMsgNumColor},
{start: msgListIdxes.selectMarkStart, end: msgListIdxes.selectMarkEnd, attrs: "\x01r\x01h\x01i"},
{start: msgListIdxes.fromNameStart, end: msgListIdxes.fromNameEnd, attrs: fromColor},
{start: msgListIdxes.toNameStart, end: msgListIdxes.toNameEnd, attrs: toColor},
{start: msgListIdxes.subjStart, end: msgListIdxes.subjEnd, attrs: subjColor},
{start: msgListIdxes.dateStart, end: msgListIdxes.dateEnd, attrs: this.msgReader.colors.msgListDateColor},
{start: msgListIdxes.timeStart, end: msgListIdxes.timeEnd, attrs: this.msgReader.colors.msgListTimeColor}];
menuItemObj.itemSelectedColor = [{start: msgListIdxes.msgNumStart, end: msgListIdxes.msgNumEnd, attrs: this.msgReader.colors.msgListMsgNumHighlightColor},
{start: msgListIdxes.selectMarkStart, end: msgListIdxes.selectMarkEnd, attrs: "\x01r\x01h\x01i" + this.msgReader.colors.msgListHighlightBkgColor},
{start: msgListIdxes.fromNameStart, end: msgListIdxes.fromNameEnd, attrs: this.msgReader.colors.msgListFromHighlightColor},
{start: msgListIdxes.toNameStart, end: msgListIdxes.toNameEnd, attrs: this.msgReader.colors.msgListToHighlightColor},
{start: msgListIdxes.subjStart, end: msgListIdxes.subjEnd, attrs: this.msgReader.colors.msgListSubjHighlightColor},
{start: msgListIdxes.dateStart, end: msgListIdxes.dateEnd, attrs: this.msgReader.colors.msgListDateHighlightColor},
{start: msgListIdxes.timeStart, end: msgListIdxes.timeEnd, attrs: this.msgReader.colors.msgListTimeHighlightColor}];
}
}
return menuItemObj;
};
// Adjust the menu indexes to ensure they're correct for the current sub-board
this.AdjustLightbarMsgListMenuIdxes(msgListMenu);
return msgListMenu;
}
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
// For the DigDistMsgLister class: Creates a DDLightbarMenu object for the user to choose
// a message group.
//
// Return value: A DDLightbarMenu object set up to let the user choose a message group
function DigDistMsgReader_CreateLightbarMsgGrpMenu()
{
// Start & end indexes for the various items in each mssage group list row
// Selected mark, group#, description, # sub-boards
var msgGrpListIdxes = {
markCharStart: 0,
markCharEnd: 1,
grpNumStart: 1,
grpNumEnd: 2 + (+this.areaNumLen)
};
msgGrpListIdxes.descStart = msgGrpListIdxes.grpNumEnd;
msgGrpListIdxes.descEnd = msgGrpListIdxes.descStart + +this.msgGrpDescLen;
msgGrpListIdxes.numItemsStart = msgGrpListIdxes.descEnd;
msgGrpListIdxes.numItemsEnd = msgGrpListIdxes.numItemsStart + +this.numItemsLen;
// Set numItemsEnd to -1 to let the whole rest of the lines be colored
msgGrpListIdxes.numItemsEnd = -1;
var listStartRow = this.areaChangeHdrLines.length + 2;
var msgGrpMenuHeight = console.screen_rows - listStartRow;
var msgGrpMenu = new DDLightbarMenu(1, listStartRow, console.screen_columns, msgGrpMenuHeight);
msgGrpMenu.scrollbarEnabled = true;
msgGrpMenu.borderEnabled = false;
msgGrpMenu.SetColors({
itemColor: [{start: msgGrpListIdxes.markCharStart, end: msgGrpListIdxes.markCharEnd, attrs: this.colors.areaChooserMsgAreaMarkColor},
{start: msgGrpListIdxes.grpNumStart, end: msgGrpListIdxes.grpNumEnd, attrs: this.colors.areaChooserMsgAreaNumColor},
{start: msgGrpListIdxes.descStart, end: msgGrpListIdxes.descEnd, attrs: this.colors.areaChooserMsgAreaDescColor},
{start: msgGrpListIdxes.numItemsStart, end: msgGrpListIdxes.numItemsEnd, attrs: this.colors.areaChooserMsgAreaNumItemsColor}],
selectedItemColor: [{start: msgGrpListIdxes.markCharStart, end: msgGrpListIdxes.markCharEnd, attrs: this.colors.areaChooserMsgAreaMarkColor + this.colors.areaChooserMsgAreaBkgHighlightColor},
{start: msgGrpListIdxes.grpNumStart, end: msgGrpListIdxes.grpNumEnd, attrs: this.colors.areaChooserMsgAreaNumHighlightColor},
{start: msgGrpListIdxes.descStart, end: msgGrpListIdxes.descEnd, attrs: this.colors.areaChooserMsgAreaDescHighlightColor},
{start: msgGrpListIdxes.numItemsStart, end: msgGrpListIdxes.numItemsEnd, attrs: this.colors.areaChooserMsgAreaNumItemsHighlightColor}]
});
msgGrpMenu.multiSelect = false;
msgGrpMenu.ampersandHotkeysInItems = false;
msgGrpMenu.wrapNavigation = false;
// Add additional keypresses for quitting the menu's input loop so we can
// respond to these keys
msgGrpMenu.AddAdditionalQuitKeys("nNqQ ?0123456789/" + CTRL_F);
// Change the menu's NumItems() and GetItem() function to reference
// the message list in this object rather than add the menu items
// to the menu
msgGrpMenu.msgReader = this; // Add this object to the menu object
msgGrpMenu.NumItems = function() {
return msg_area.grp_list.length;
};
msgGrpMenu.GetItem = function(pGrpIndex) {
var menuItemObj = this.MakeItemWithRetval(-1);
if ((pGrpIndex >= 0) && (pGrpIndex < msg_area.grp_list.length))
{
menuItemObj.text = format(((typeof(bbs.curgrp) == "number") && (pGrpIndex == msg_area.sub[this.msgReader.subBoardCode].grp_index)) ? "*" : " ");
menuItemObj.text += format(this.msgReader.msgGrpListPrintfStr, +(pGrpIndex+1),
msg_area.grp_list[pGrpIndex].description.substr(0, this.msgReader.msgGrpDescLen),
msg_area.grp_list[pGrpIndex].sub_list.length);
menuItemObj.text = strip_ctrl(menuItemObj.text);
menuItemObj.retval = pGrpIndex;
}
return menuItemObj;
};
// Set the currently selected item to the current group
msgGrpMenu.selectedItemIdx = msg_area.sub[this.subBoardCode].grp_index;
if (msgGrpMenu.selectedItemIdx >= msgGrpMenu.topItemIdx+msgGrpMenu.GetNumItemsPerPage())
msgGrpMenu.topItemIdx = msgGrpMenu.selectedItemIdx - msgGrpMenu.GetNumItemsPerPage() + 1;
return msgGrpMenu;
}
// For the DigDistMsgLister class: Creates a DDLightbarMenu object for the user to choose
// a sub-board within a message group.
//
// Parameters:
// pGrpIdx: The index of the group to list sub-boards for
//
// Return value: A DDLightbarMenu object set up to let the user choose a sub-board within the
// given message group
function DigDistMsgReader_CreateLightbarSubBoardMenu(pGrpIdx)
{
// Start & end indexes for the various items in each sub-board list row
// Selected mark, group#, description, # sub-boards
var subBrdListIdxes = {
markCharStart: 0,
markCharEnd: 1,
subNumStart: 1,
subNumEnd: 2 + (+this.areaNumLen)
};
subBrdListIdxes.descStart = subBrdListIdxes.subNumEnd;
subBrdListIdxes.descEnd = subBrdListIdxes.descStart + +(this.subBoardListPrintfInfo[pGrpIdx].nameLen) + 1;
subBrdListIdxes.numItemsStart = subBrdListIdxes.descEnd;
subBrdListIdxes.numItemsEnd = subBrdListIdxes.numItemsStart + +(this.subBoardListPrintfInfo[pGrpIdx].numMsgsLen) + 1;
subBrdListIdxes.dateStart = subBrdListIdxes.numItemsEnd;
subBrdListIdxes.dateEnd = subBrdListIdxes.dateStart + +this.dateLen + 1;
subBrdListIdxes.timeStart = subBrdListIdxes.dateEnd;
// Set timeEnd to -1 to let the whole rest of the lines be colored
subBrdListIdxes.timeEnd = -1;
var listStartRow = this.areaChangeHdrLines.length + 3;
var subBrdMenuHeight = console.screen_rows - listStartRow;
var subBoardMenu = new DDLightbarMenu(1, listStartRow, console.screen_columns, subBrdMenuHeight);
subBoardMenu.scrollbarEnabled = true;
subBoardMenu.borderEnabled = false;
subBoardMenu.SetColors({
itemColor: [{start: subBrdListIdxes.markCharStart, end: subBrdListIdxes.markCharEnd, attrs: this.colors.areaChooserMsgAreaMarkColor},
{start: subBrdListIdxes.subNumStart, end: subBrdListIdxes.subNumEnd, attrs: this.colors.areaChooserMsgAreaNumColor},
{start: subBrdListIdxes.descStart, end: subBrdListIdxes.descEnd, attrs: this.colors.areaChooserMsgAreaDescColor},
{start: subBrdListIdxes.numItemsStart, end: subBrdListIdxes.numItemsEnd, attrs: this.colors.areaChooserMsgAreaNumItemsColor},
{start: subBrdListIdxes.dateStart, end: subBrdListIdxes.dateEnd, attrs: this.colors.areaChooserMsgAreaLatestDateColor},
{start: subBrdListIdxes.timeStart, end: subBrdListIdxes.timeEnd, attrs: this.colors.areaChooserMsgAreaLatestTimeColor}],
selectedItemColor: [{start: subBrdListIdxes.markCharStart, end: subBrdListIdxes.markCharEnd, attrs: this.colors.areaChooserMsgAreaMarkColor + this.colors.areaChooserMsgAreaBkgHighlightColor},
{start: subBrdListIdxes.subNumStart, end: subBrdListIdxes.subNumEnd, attrs: this.colors.areaChooserMsgAreaNumHighlightColor},
{start: subBrdListIdxes.descStart, end: subBrdListIdxes.descEnd, attrs: this.colors.areaChooserMsgAreaDescHighlightColor},
{start: subBrdListIdxes.numItemsStart, end: subBrdListIdxes.numItemsEnd, attrs: this.colors.areaChooserMsgAreaNumItemsHighlightColor},
{start: subBrdListIdxes.dateStart, end: subBrdListIdxes.dateEnd, attrs: this.colors.areaChooserMsgAreaDateHighlightColor},
{start: subBrdListIdxes.timeStart, end: subBrdListIdxes.timeEnd, attrs: this.colors.areaChooserMsgAreaTimeHighlightColor}]
});
subBoardMenu.multiSelect = false;
subBoardMenu.ampersandHotkeysInItems = false;
subBoardMenu.wrapNavigation = false;
// Add additional keypresses for quitting the menu's input loop so we can
// respond to these keys
subBoardMenu.AddAdditionalQuitKeys("nNqQ ?0123456789/" + CTRL_F);
// Change the menu's NumItems() and GetItem() function to reference
// the message list in this object rather than add the menu items
// to the menu
subBoardMenu.msgReader = this; // Add this object to the menu object
subBoardMenu.grpIdx = pGrpIdx;
subBoardMenu.NumItems = function() {
return msg_area.grp_list[pGrpIdx].sub_list.length;
};
subBoardMenu.GetItem = function(pSubIdx) {
var menuItemObj = this.MakeItemWithRetval(-1);
if ((pSubIdx >= 0) && (pSubIdx < msg_area.grp_list[this.grpIdx].sub_list.length))
{
//var highlight = (msg_area.grp_list[this.grpIdx].sub_list[pSubIdx].code.toUpperCase() == this.msgReader.subBoardCode.toUpperCase());
menuItemObj.text = this.msgReader.GetMsgSubBoardLine(this.grpIdx, pSubIdx, false);
menuItemObj.text = strip_ctrl(menuItemObj.text);
menuItemObj.retval = pSubIdx;
}
return menuItemObj;
};
// Set the currently selected item to the current group
if (msg_area.sub[this.subBoardCode].grp_index == pGrpIdx)
{
subBoardMenu.selectedItemIdx = msg_area.sub[this.subBoardCode].index;
if (subBoardMenu.selectedItemIdx >= subBoardMenu.topItemIdx+subBoardMenu.GetNumItemsPerPage())
subBoardMenu.topItemIdx = subBoardMenu.selectedItemIdx - subBoardMenu.GetNumItemsPerPage() + 1;
}
else
{
subBoardMenu.selectedItemIdx = 0;
subBoardMenu.topItemIdx = 0;
}
return subBoardMenu;
}
// For the DigDistMsgLister class: Adjusts lightbar menu indexes for a message list menu
function DigDistMsgReader_AdjustLightbarMsgListMenuIdxes(pMsgListMenu)
{
pMsgListMenu.selectedItemIdx = this.lightbarListSelectedMsgIdx;
pMsgListMenu.topItemIdx = this.lightbarListTopMsgIdx;
// In the DDLightbarMenu class, the top index on the last page should
// allow for displaying a full page of items. So if
// this.lightbarListTopMsgIdx is beyond the top index for the last
// page in the menu object, then adjust this.lightbarListTopMsgIdx.
var menuTopItemIdxOnLastPage = pMsgListMenu.GetTopItemIdxOfLastPage();
if (pMsgListMenu.topItemIdx > menuTopItemIdxOnLastPage)
{
pMsgListMenu.topItemIdx = menuTopItemIdxOnLastPage;
this.lightbarListTopMsgIdx = menuTopItemIdxOnLastPage;
}
// TODO: Ensure this.lightbarListTopMsgIdx is always correct for the last page
}
// For the DigDistMsgListerClass: Prints a line of information about
// a message.
//
// Parameters:
// pMsgHeader: The message header object, returned by MsgBase.get_msg_header().
// pHighlight: Optional boolean - Whether or not to highlight the line (true) or
// use the standard colors (false).
// pMsgNum: Optional - A number to use for the message instead of the number/offset
// in the message header
// pReturnStrInstead: Optional boolean - Whether or not to return a formatted string
// instead of printing to the console. Defaults to false.
function DigDistMsgReader_PrintMessageInfo(pMsgHeader, pHighlight, pMsgNum, pReturnStrInstead)
{
// pMsgHeader must be a valid object.
if (typeof(pMsgHeader) == "undefined")
return;
if (pMsgHeader == null)
return;
var highlight = false;
if (typeof(pHighlight) == "boolean")
highlight = pHighlight;
// Get the message's import date & time as strings. If
// this.msgList_displayMessageDateImported is true, use the message import date.
// Otherwise, use the message written date.
var sDate;
var sTime;
if (this.msgList_displayMessageDateImported)
{
sDate = strftime("%Y-%m-%d", pMsgHeader.when_imported_time);
sTime = strftime("%H:%M:%S", pMsgHeader.when_imported_time);
}
else
{
//sDate = strftime("%Y-%m-%d", pMsgHeader.when_written_time);
//sTime = strftime("%H:%M:%S", pMsgHeader.when_written_time);
var msgWrittenLocalTime = msgWrittenTimeToLocalBBSTime(pMsgHeader);
if (msgWrittenLocalTime != -1)
{
sDate = strftime("%Y-%m-%d", msgWrittenLocalTime);
sTime = strftime("%H:%M:%S", msgWrittenLocalTime);
}
else
{
sDate = strftime("%Y-%m-%d", pMsgHeader.when_written_time);
sTime = strftime("%H:%M:%S", pMsgHeader.when_written_time);
}
}
//var msgNum = (typeof(pMsgNum) == "number" ? pMsgNum : pMsgHeader.offset+1);
var msgNum = (typeof(pMsgNum) == "number" ? pMsgNum : this.GetMsgIdx(pMsgHeader.number)+1);

nightfox
committed
if (msgNum == 0) // In case GetMsgIdx() returns -1 for failure
msgNum = 1;
// Determine if the message has been deleted.
var msgDeleted = ((pMsgHeader.attr & MSG_DELETE) == MSG_DELETE);
// msgIndicatorChar will contain (possibly) a character to display after
// the message number to indicate whether it has been deleted, selected,
// etc. If not, then it will just be a space.
var msgIndicatorChar = " ";
// Get the message score value
var msgVoteInfo = getMsgUpDownvotesAndScore(pMsgHeader);
// Ensure the score number can fit within 4 digits
if (msgVoteInfo.voteScore > 9999)
msgVoteInfo.voteScore = 9999;
else if (msgVoteInfo.voteScore < -999)
msgVoteInfo.voteScore = -999;
// Generate the string with the message header information.
var msgHdrStr = "";
// Note: The message header has the following fields:
// 'number': The message number
// 'offset': The message offset
// 'to': Who the message is directed to (string)
// 'from' Who wrote the message (string)
// 'subject': The message subject (string)
// 'date': The date - Full text (string)
// To access one of these, use brackets; i.e., msgHeader['to']
if (highlight)
{
// For any indicator character next to the message, prioritize selected, then deleted, then attachments
if (this.MessageIsSelected(this.subBoardCode, msgNum-1))
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + CHECK_CHAR + "\x01n";
else if (msgDeleted)
msgIndicatorChar = "\x01n\x01r\x01h\x01i" + this.colors.msgListHighlightBkgColor + "*\x01n";
else if (msgHdrHasAttachmentFlag(pMsgHeader))
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + "A\x01n";
var fromName = pMsgHeader.from;
// If the message was posted anonymously and the logged-in user is
// not the sysop, then show "Anonymous" for the 'from' name.
Eric Oulashin
committed
if (!user.is_sysop && ((pMsgHeader.attr & MSG_ANONYMOUS) == MSG_ANONYMOUS))
fromName = "Anonymous";
if (this.showScoresInMsgList)
{
msgHdrStr += format(this.sMsgInfoFormatHighlightStr, msgNum, msgIndicatorChar,
fromName.substr(0, this.FROM_LEN),
pMsgHeader.to.substr(0, this.TO_LEN),
pMsgHeader.subject.substr(0, this.SUBJ_LEN),
msgVoteInfo.voteScore, sDate, sTime);
}
else
{
msgHdrStr += format(this.sMsgInfoFormatHighlightStr, msgNum, msgIndicatorChar,
fromName.substr(0, this.FROM_LEN),
pMsgHeader.to.substr(0, this.TO_LEN),
pMsgHeader.subject.substr(0, this.SUBJ_LEN),
sDate, sTime);
}
}
else
{
// For any indicator character next to the message, prioritize selected, then deleted, then attachments
if (this.MessageIsSelected(this.subBoardCode, msgNum-1))
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + CHECK_CHAR + "\x01n";
else if (msgDeleted)
msgIndicatorChar = "\x01n\x01r\x01h\x01i*\x01n";
else if (msgHdrHasAttachmentFlag(pMsgHeader))
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + "A\x01n";
// Determine whether to use the normal, "to-user", or "from-user" format string.
// The differences are the colors. Then, output the message information line.
var toNameUpper = pMsgHeader.to.toUpperCase();
var msgToUser = ((toNameUpper == user.alias.toUpperCase()) || (toNameUpper == user.name.toUpperCase()) || (toNameUpper == user.handle.toUpperCase()));
var fromNameUpper = pMsgHeader.from.toUpperCase();
var msgIsFromUser = ((fromNameUpper == user.alias.toUpperCase()) || (fromNameUpper == user.name.toUpperCase()) || (fromNameUpper == user.handle.toUpperCase()));
var formatStr = ""; // Format string for printing the message information
if (this.readingPersonalEmail)
formatStr = this.sMsgInfoFormatStr;
else
formatStr = (msgToUser ? this.sMsgInfoToUserFormatStr : (msgIsFromUser ? this.sMsgInfoFromUserFormatStr : this.sMsgInfoFormatStr));
var fromName = pMsgHeader.from;
// If the message was posted anonymously and the logged-in user is
// not the sysop, then show "Anonymous" for the 'from' name.
Eric Oulashin
committed
if (!user.is_sysop && ((pMsgHeader.attr & MSG_ANONYMOUS) == MSG_ANONYMOUS))
fromName = "Anonymous";
if (this.showScoresInMsgList)
{
msgHdrStr += format(formatStr, msgNum, msgIndicatorChar, fromName.substr(0, this.FROM_LEN),
pMsgHeader.to.substr(0, this.TO_LEN), pMsgHeader.subject.substr(0, this.SUBJ_LEN),
msgVoteInfo.voteScore, sDate, sTime);
}
else
{
msgHdrStr += format(formatStr, msgNum, msgIndicatorChar, fromName.substr(0, this.FROM_LEN),
pMsgHeader.to.substr(0, this.TO_LEN), pMsgHeader.subject.substr(0, this.SUBJ_LEN),
sDate, sTime);
}
}
var returnStrInstead = (typeof(pReturnStrInstead) == "boolean" ? pReturnStrInstead : false);
if (!returnStrInstead)
{
console.print(msgHdrStr);
console.cleartoeol("\x01n"); // To clear away any extra text that may have been entered by the user
}
return msgHdrStr;
}
// For the traditional interface of DigDistMsgListerClass: Prompts the user to
// continue or read a message (by number).
//
// Parameters:
// pStart: Whether or not we're on the first page (true or false)
// pEnd: Whether or not we're at the last page (true or false)

nightfox
committed
// pAllowChgSubBoard: Optional - A boolean to specify whether or not to allow
// changing to another sub-board. Defaults to true.
//
// Return value: An object with the following properties:
// continueOn: Boolean, whether or not the user wants to continue
// listing the messages
// userInput: The user's input
// selectedMsgOffset: The offset of the message selected to read,
// if one was selected. If a message was not
// selected, this will be -1.
function DigDistMsgReader_PromptContinueOrReadMsg(pStart, pEnd, pAllowChgSubBoard)
{

nightfox
committed
// Create the return object and set some initial default values
var retObj = {
continueOn: true,
userInput: "",
selectedMsgOffset: -1
};

nightfox
committed
var allowChgSubBoard = (typeof(pAllowChgSubBoard) == "boolean" ? pAllowChgSubBoard : true);
var continueOn = true;
// Prompt the user whether or not to continue or to read a message
// (by message number). Make use of the different prompt texts,
// depending whether we're at the beginning, in the middle, or at
// the end of the message list.
var userInput = "";
var allowedKeys = "?GS"; // ? = help, G = Go to message #, S = Select message(s), Ctrl-D: Batch delete

Eric Oulashin
committed
allowedKeys += this.msgListKeys.userSettings;

nightfox
committed
if (allowChgSubBoard)
allowedKeys += "C"; // Change to another message area
if (this.CanDelete() || this.CanDeleteLastMsg())

nightfox
committed
allowedKeys += "D"; // Delete
if (this.CanEdit())
allowedKeys += "E"; // Edit
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
if (pStart && pEnd)
{
// This is the only page.
console.print(this.msgListOnlyOnePageContinuePrompt);
// Get input from the user. Allow only Q (quit).
allowedKeys += "Q";
}
else if (pStart)
{
// We're on the first page.
console.print(this.sStartContinuePrompt);
// Get input from the user. Allow only L (last), N (next), or Q (quit).
allowedKeys += "LNQ";
}
else if (pEnd)
{
// We're on the last page.
console.print(this.sEndContinuePrompt);
// Get input from the user. Allow only F (first), P (previous), or Q (quit).
allowedKeys += "FPQ";
}
else
{
// We're neither on the first nor last page. Allow F (first), L (last),
// N (next), P (previous), or Q (quit).
console.print(this.sContinuePrompt);
allowedKeys += "FLNPQ";
}
// Get the user's input. Allow CTRL-D (batch delete) without echoing it.
// If the user didn't press CTRL-L, allow the keys in allowedKeys or a number from 1
// to the highest message number.
userInput = console.getkey(K_NOECHO);
if (userInput != CTRL_D)
{
console.ungetstr(userInput);
userInput = console.getkeys(allowedKeys, this.HighestMessageNum()).toString();
}
if (userInput == "Q")
continueOn = false;
// If the user has typed all numbers, then read that message.
if ((userInput != "") && /^[0-9]+$/.test(userInput))
{
// If the user entered a valid message number, then let the user read the message.
// The message number might be invalid if there are search results that
// have non-continuous message numbers.
if (this.IsValidMessageNum(userInput))
{
// See if the current message header has our "isBogus" property and it's true.
// Only let the user read the message if it's not a bogus message header.
// The message header could have the "isBogus" property, for instance, if
// it's a vote message (introduced in Synchronet 3.17).
var tmpMsgHdr = this.GetMsgHdrByIdx(+(userInput-1), false);
var hdrIsBogus = (tmpMsgHdr.hasOwnProperty("isBogus") ? tmpMsgHdr.isBogus : false);
if (!hdrIsBogus)
{
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
// Confirm with the user whether to read the message
var readMsg = true;
if (this.promptToReadMessage)
{
var sReadMsgConfirmText = this.colors["readMsgConfirmColor"]
+ "Read message "
+ this.colors["readMsgConfirmNumberColor"]
+ userInput + this.colors["readMsgConfirmColor"]
+ ": Are you sure";
readMsg = console.yesno(sReadMsgConfirmText);
}
if (readMsg)
{
// Update the message list screen variables
this.CalcMsgListScreenIdxVarsFromMsgNum(+userInput);
// Return from here so that the calling function can switch
// into reader mode.
retObj.continueOn = continueOn;
retObj.userInput = userInput;
retObj.selectedMsgOffset = userInput-1;
return retObj;
}
else
this.deniedReadingMessage = true;
// Prompt the user whether or not to continue listing
// messages.
if (this.promptToContinueListingMessages)
{
continueOn = console.yesno(this.colors["afterReadMsg_ListMorePromptColor"] +
"Continue listing messages");
}
}
else
{
console.print("\x01n\x01h\x01yThat's not a readable message.\x01n");
console.crlf();
console.pause();
}
}
else
{
// The user entered an invalid message number.
console.print("\x01n\x01h\x01w" + userInput + " \x01y is not a valid message number.\x01n");
console.crlf();
console.pause();
continueOn = true;
}
}
// Make sure color highlighting is turned off
console.print("\x01n");
// Fill the return object with the required values, and return it.
retObj.continueOn = continueOn;
retObj.userInput = userInput;
return retObj;
}
// For the DigDistMsgReader Class: Given a message number of a message in the
// current message area, lets the user read a message and allows the user to
// respond, etc. This is an enhanced version that allows scrolling up & down
// the message with the up & down arrow keys, and the left & right arrow keys
// will return from the function to allow calling code to navigate back & forth
// through the message sub-board.
//
// Parameters:
// pOffset: The offset of the message to be read
// pAllowChgArea: Optional boolean - Whether or not to allow changing the
// message area
//
// Return value: And object with the following properties:
// offsetValid: Boolean - Whether or not the passed-in offset was valid
// msgDeleted: Boolean - Whether or not the message is marked as deleted
// (not deleted by the user in the reader)
// userReplied: Boolean - Whether or not the user replied to the message.
// lastKeypress: The last keypress from the user - For navigation purposes
// newMsgOffset: The offset of another message to read, if the user
// input another message number. If the user did not
// input another message number, this will be -1.
// nextAction: The next action for the caller to take. This will be
// one of the values specified by the ACTION_* constants.
// This defaults to ACTION_NONE on error.
// refreshEnhancedRdrHelpLine: Boolean - Whether or not to refresh the
// enhanced reader help line on the screen
// (for instance, if switched to the traditional
// non-scrolling interface to read the message)
function DigDistMsgReader_ReadMessageEnhanced(pOffset, pAllowChgArea)
{
var retObj = {
offsetValid: true,
msgNotReadable: false,
userReplied: false,
lastKeypress: "",
newMsgOffset: -1,
nextAction: ACTION_NONE,
refreshEnhancedRdrHelpLine: false
};
// Get the message header. Don't expand fields since we may need to save
// the header later with the MSG_READ attribute.
//var msgHeader = this.GetMsgHdrByIdx(pOffset, false);
// Get the message header. Get expanded fields so that we can show any
// voting stats/responses that may be included with the message.
var msgHeader = this.GetMsgHdrByIdx(pOffset, true);
if (msgHeader == null)
{
console.print("\x01n" + replaceAtCodesInStr(format(this.text.invalidMsgNumText, +(pOffset+1))) + "\x01n");
console.crlf();
console.inkey(K_NONE, ERROR_PAUSE_WAIT_MS);
retObj.offsetValid = false;
return retObj;
}

nightfox
committed
// If this message is not readable for the user (it's marked as deleted and
// the system is set to not show deleted messages, etc.), then don't let the
// user read it, and just silently return.
// TODO: If the message is not readable, this will end up causing an infinite loop.

nightfox
committed
retObj.msgNotReadable = !isReadableMsgHdr(msgHeader, this.subBoardCode);
if (retObj.msgNotReadable)
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
return retObj;
// Update the message list index variables so that the message list is in
// the right spot for the message currently being read
this.CalcMsgListScreenIdxVarsFromMsgNum(pOffset+1);
// Check the pAllowChgArea parameter. If it's a boolean, then use it. If
// not, then check to see if we're reading personal mail - If not, then allow
// the user to change to a different message area.
var allowChgMsgArea = true;
if (typeof(pAllowChgArea) == "boolean")
allowChgMsgArea = pAllowChgArea;
else
allowChgMsgArea = (this.subBoardCode != "mail");
// Hack: If the "from" name in the header is empty (as it might be sometimes), then
// set it to "All". This prevents Synchronet from crashing, and it will also default
// the "to" name in the user's reply to "All".
if (msgHeader.from.length == 0)
msgHeader.from = "All";

nightfox
committed
// Get the message text and see if it has any ANSI codes. Remove any pause
// codes it might have. If it has ANSI codes, then don't use the scrolling
// interface so that the ANSI gets displayed properly.
var messageText = this.GetMsgBody(msgHeader);
if (msgHdrHasAttachmentFlag(msgHeader))
{
messageText = "\x01n\x01g\x01h- This message contains one or more attachments. Press CTRL-A to download.\x01n\r\n"
+ "\x01n\x01g\x01h--------------------------------------------------------------------------\x01n\r\n"
+ messageText;
}
var useScrollingInterface = this.scrollingReaderInterface && console.term_supports(USER_ANSI);
// If we switch to the non-scrolling interface here, then the calling method should
// refresh the enhanced reader help line on the screen.
retObj.refreshEnhancedRdrHelpLine = (this.scrollingReaderInterface && !useScrollingInterface);
// If the current message is new to the user, update the number of posts read this session.
if (pOffset > this.GetScanPtrMsgIdx())
++bbs.posts_read;
// Use the scrollable reader interface if the setting is enabled & the user's
// terminal supports ANSI. Otherwise, use a more traditional user interface.
if (useScrollingInterface)
retObj = this.ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgArea, messageText, pOffset);
else
retObj = this.ReadMessageEnhanced_Traditional(msgHeader, allowChgMsgArea, messageText, pOffset);
// Mark the message as read if it was written to the current user
if (userNameHandleAliasMatch(msgHeader.to) && ((msgHeader.attr & MSG_READ) == 0))
{
// Using applyAttrsInMsgHdrInMessagbase(), which loads the header without
// expanded fields and saves the attributes with that header.
var saveRetObj = applyAttrsInMsgHdrInMessagbase(this.subBoardCode, msgHeader.number, MSG_READ);
if (this.SearchTypePopulatesSearchResults() && saveRetObj.saveSucceeded)
this.RefreshHdrInSavedArrays(pOffset, MSG_READ, true);
}
// If not reading personal email and not doing a search, then update the
// scan & last read message pointers.
if ((this.subBoardCode != "mail") && (this.searchType == SEARCH_NONE))
{
if (msgHeader.number > GetScanPtrOrLastMsgNum(this.subBoardCode))
msg_area.sub[this.subBoardCode].scan_ptr = msgHeader.number;
msg_area.sub[this.subBoardCode].last_read = msgHeader.number;
}
return retObj;
}
// Helper method for ReadMessageEnhanced() - Does the scrollable reader interface
function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgArea, messageText, pOffset)
{
var retObj = {
offsetValid: true,
msgNotReadable: false,
userReplied: false,
lastKeypress: "",
newMsgOffset: -1,
nextAction: ACTION_NONE,
refreshEnhancedRdrHelpLine: false
};
Eric Oulashin
committed
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
// This is a scrollbar update function for use when viewing the message.
function msgScrollbarUpdateFn(pFractionToLastPage)
{
// Update the scrollbar position for the message, depending on the
// value of pFractionToLastMessage.
fractionToLastPage = pFractionToLastPage;
solidBlockStartRow = msgReaderObj.msgAreaTop + Math.floor(numNonSolidScrollBlocks * pFractionToLastPage);
if (solidBlockStartRow != solidBlockLastStartRow)
msgReaderObj.UpdateEnhancedReaderScollbar(solidBlockStartRow, solidBlockLastStartRow, numSolidScrollBlocks);
solidBlockLastStartRow = solidBlockStartRow;
console.gotoxy(1, console.screen_rows);
}
// This is a scrollbar update function for use when viewing the header info/kludge lines.
function msgInfoScrollbarUpdateFn(pFractionToLastPage)
{
var infoSolidBlockStartRow = msgReaderObj.msgAreaTop + Math.floor(numNonSolidInfoScrollBlocks * pFractionToLastPage);
if (infoSolidBlockStartRow != lastInfoSolidBlockStartRow)
msgReaderObj.UpdateEnhancedReaderScollbar(infoSolidBlockStartRow, lastInfoSolidBlockStartRow, numInfoSolidScrollBlocks);
lastInfoSolidBlockStartRow = infoSolidBlockStartRow;
console.gotoxy(1, console.screen_rows);
}
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);
// If the message has ANSI content, then use a Graphic object to help make
// the message look good. Also, remove any ANSI clear screen codes from the
// message text.
var msgHasANSICodes = messageText.indexOf("\x1b[") >= 0;
if (msgHasANSICodes)
{
messageText = messageText.replace(/\u001b\[[012]J/gi, "");
var graphic = new Graphic(this.msgAreaWidth, this.msgAreaHeight-1);
graphic.auto_extend = true;
graphic.ANSI = ansiterm.expand_ctrl_a(messageText);
graphic.width = this.msgAreaWidth;
messageText = graphic.MSG;
}
// Show the message header
this.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
// Get the message text, interpret any @-codes in it, replace tabs with spaces
// to prevent weirdness when displaying the message lines, and word-wrap the
// text so that it looks good on the screen,
var msgInfo = this.GetMsgInfoForEnhancedReader(msgHeader, true, true, true, messageText);
var topMsgLineIdxForLastPage = msgInfo.topMsgLineIdxForLastPage;
var numSolidScrollBlocks = msgInfo.numSolidScrollBlocks;
var numNonSolidScrollBlocks = msgInfo.numNonSolidScrollBlocks;
var solidBlockStartRow = msgInfo.solidBlockStartRow;
var solidBlockLastStartRow = solidBlockStartRow;
var topMsgLineIdx = 0;
var fractionToLastPage = 0;
if (topMsgLineIdxForLastPage != 0)
fractionToLastPage = topMsgLineIdx / topMsgLineIdxForLastPage;
Eric Oulashin
committed
// Draw an initial scrollbar on the rightmost column of the message area showing
// the fraction of the message shown and what part of the message is currently
// being shown. The scrollbar will be updated minimally in the input loop to
// minimize screen redraws.
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
// Input loop (for scrolling the message up & down)
var msgLineFormatStr = "%-" + this.msgAreaWidth + "s";
var writeMessage = true;
// msgAreaHeight, msgReaderObj, and scrollbarUpdateFunction are for use
// with scrollTextLines().
var msgAreaHeight = this.msgAreaBottom - this.msgAreaTop + 1;
var msgReaderObj = this;
var msgHasAttachments = msgHdrHasAttachmentFlag(msgHeader);
// User input loop
var continueOn = true;
while (continueOn)
{
// Display the message lines (depending on the value of writeMessage)
// and handle scroll keys via scrollTextLines(). Handle other keypresses
// here.
Eric Oulashin
committed
var scrollbarInfoObj = {
solidBlockLastStartRow: 0,
numSolidScrollBlocks: 0
};
scrollbarInfoObj.solidBlockLastStartRow = solidBlockLastStartRow;
scrollbarInfoObj.numSolidScrollBlocks = numSolidScrollBlocks;
var scrollRetObj = scrollTextLines(msgInfo.messageLines, topMsgLineIdx,
this.colors.msgBodyColor, writeMessage,
this.msgAreaLeft, this.msgAreaTop, this.msgAreaWidth,
msgAreaHeight, 1, console.screen_rows,

Eric Oulashin
committed
msgScrollbarUpdateFn, scrollbarInfoObj);
topMsgLineIdx = scrollRetObj.topLineIdx;
retObj.lastKeypress = scrollRetObj.lastKeypress;
switch (retObj.lastKeypress)
{
case this.enhReaderKeys.deleteMessage: // Delete message
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();
// 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 and the user can't view deleted messages,
// 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, promptPos, true, true, this.msgAreaWidth, 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 (this.EnhReaderPromptYesNo(replaceAtCodesInStr(this.text.goToNextMsgAreaPromptText), msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr, solidBlockStartRow, numSolidScrollBlocks))
{
// 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
}
}
else
{
this.DisplayEnhReaderError("", msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
// Move the cursor back to its original position
console.gotoxy(originalCurpos);
writeMessage = false;
}
break;
case this.enhReaderKeys.selectMessage: // Select message (for batch delete, etc.)
var originalCurpos = console.getxy();
var promptPos = this.EnhReaderPrepLast2LinesForPrompt();
if (this.EnhReaderPromptYesNo("Select this message", msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr, solidBlockStartRow, numSolidScrollBlocks, true))
this.ToggleSelectedMessage(this.subBoardCode, pOffset, true);
else
this.ToggleSelectedMessage(this.subBoardCode, pOffset, false);
writeMessage = false; // No need to refresh the message
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 messaage
if (this.CanEdit())
{
// Move the cursor to the last line in the message area so
// the edit confirmation prompt will appear there. Not using
// the last line on the screen because the yes/no prompt will
// output a carriage return and move everything on the screen
// up one line, which is not ideal in case the user says No.
var promptPos = this.EnhReaderPrepLast2LinesForPrompt();
// Let the user edit the message if they want to
var editReturnObj = this.EditExistingMsg(pOffset);
// If the user didn't confirm, then we only have to refresh the bottom
// help line. Otherwise, we need to refresh everything on the screen.
if (!editReturnObj.userConfirmed)
{
// For some reason, the yes/no prompt erases the last character
// of the scrollbar - So, figure out which block was there and
// refresh it.
//var scrollBarBlock = "\x01n\x01h\x01k" + BLOCK1; // Dim block
// Dim block
var scrollBarBlock = this.colors.scrollbarBGColor + this.text.scrollbarBGChar;
if (solidBlockStartRow + numSolidScrollBlocks - 1 == this.msgAreaBottom)
{
//scrollBarBlock = "\x01w" + BLOCK2; // Bright block
// Bright block
scrollBarBlock = this.colors.scrollbarScrollBlockColor + this.text.scrollbarScrollBlockChar;
}
console.gotoxy(this.msgAreaRight+1, this.msgAreaBottom);
console.print(scrollBarBlock);
// Refresh the last 2 message lines on the screen, then display
// the key help line
this.DisplayEnhReaderError("", msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
writeMessage = false;
}
else
{
// 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.
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
continueOn = false;
retObj.newMsgOffset = editReturnObj.newMsgIdx;
}
else
{
// The message was not edited. Refresh everything on the screen.
// If the enhanced message header width is less than the console
// width, then clear the screen to remove anything that might be
// left on the screen by the message editor.
if (this.enhMsgHeaderWidth < console.screen_columns)
console.clear("\x01n");
// Display the message header and key help line
this.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
// Display the scrollbar again, and ensure it's in the correct position
solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
writeMessage = true; // We want to refresh the message on the screen
}
}
}
else
writeMessage = false; // Don't write the current message again
break;

nightfox
committed
case this.enhReaderKeys.showHelp: // Show the help screen
this.DisplayEnhancedReaderHelp(allowChgMsgArea, msgHasAttachments);