diff --git a/exec/SlyEdit.js b/exec/SlyEdit.js
index 9428251c894a89683ab65e88f8ccdbe7cfea7286..b9207ad34dac633ad368e7cc0e80236bb7223493 100644
--- a/exec/SlyEdit.js
+++ b/exec/SlyEdit.js
@@ -21,6 +21,12 @@
  *                              configuration option allowEditQuoteLines.
  * 2017-12-17 Eric Oulashin     Version 1.52
  *                              Releasing this version
+ * 2017-12-18 Eric Oulashin     Version 1.53
+ *                              Updated the PageUp and PageDown keys to ensure they
+ *                              match what's in sbbsdefs.js, since Synchronet added
+ *                              key codes for those keys on December 17, 2018.  SlyEdit
+ *                              should still work with older and newer builds of
+ *                              Synchronet, with or without the updated sbbsdefs.js.
  */
 
 /* Command-line arguments:
@@ -98,8 +104,8 @@ if (!console.term_supports(USER_ANSI))
 }
 
 // Constants
-const EDITOR_VERSION = "1.52";
-const EDITOR_VER_DATE = "2016-12-17";
+const EDITOR_VERSION = "1.53";
+const EDITOR_VER_DATE = "2016-12-18";
 
 
 // Program variables
@@ -5794,60 +5800,60 @@ function doUserSettings(pCurpos, pReturnCursorToOriginalPos)
 //  tagline: String - The tag line that was selected
 function doTaglineSelection()
 {
-   var retObj = new Object();
-   retObj.taglineWasSelected = false;
-   retObj.tagline = "";
-
-   // Read the tagline file
-   var taglines = readTxtFileIntoArray(gConfigSettings.tagLineFilename, true, true, 5000);
-   if (taglines.length == 0)
-      return;
+	var retObj = {
+		taglineWasSelected: false,
+		tagline: ""
+	};
+
+	// Read the tagline file
+	var taglines = readTxtFileIntoArray(gConfigSettings.tagLineFilename, true, true, 5000);
+	if (taglines.length == 0)
+		return retObj;
 
-   // If the configuration option to shuffle the taglines is enabled, then
-   // shuffle them.
-   if (gConfigSettings.shuffleTaglines)
-      shuffleArray(taglines);
-
-   // Create the list box for the taglines.  Make the box up to 14 lines tall.
-   var boxHeight = (taglines.length > 12 ? 14 : taglines.length+2);
-   var boxTopRow = gEditTop + Math.floor((gEditHeight/2) - (boxHeight/2));
-   var taglineBox = new ChoiceScrollbox(gEditLeft, boxTopRow, gEditWidth, boxHeight,
-                                         "Taglines", gConfigSettings, true, false);
-   var bottomBorderText = "nhcb, cb, cNy)bext, cPy)brev, "
-     + "cFy)birst, cLy)bast, cHOMEb, cENDb, cEntery=bSelect, "
-     + "cRy)bandom, cESCnc/hcQy=bEnd";
-   taglineBox.setBottomBorderText(bottomBorderText, false, false);
-   // Add R as an input loop exit key, to choose a random tagline.
-   taglineBox.addInputLoopExitKey("R");
-   taglineBox.addInputLoopExitKey("r");
-
-   // Set the tagline item array in the list box.  Don't strip control characters
-   // because we've already done that when we read the file.
-   taglineBox.setItemArray(taglines, false);
-   // Let the user choose a tagline
-   var taglineRetObj = taglineBox.doInputLoop(true);
-   retObj.taglineWasSelected = taglineRetObj.itemWasSelected;
-   if (retObj.taglineWasSelected)
-      retObj.tagline = taglineRetObj.selectedItem;
-   // If the R key was pressed, then choose a random tagline.
-   else if ((taglineRetObj.lastKeypress == "R") || (taglineRetObj.lastKeypress == "r"))
-   {
-      retObj.tagline = taglines[random(taglines.length)];
-      retObj.taglineWasSelected = true;
-   }
+	// If the configuration option to shuffle the taglines is enabled, then
+	// shuffle them.
+	if (gConfigSettings.shuffleTaglines)
+		shuffleArray(taglines);
+
+	// Create the list box for the taglines.  Make the box up to 14 lines tall.
+	var boxHeight = (taglines.length > 12 ? 14 : taglines.length+2);
+	var boxTopRow = gEditTop + Math.floor((gEditHeight/2) - (boxHeight/2));
+	var taglineBox = new ChoiceScrollbox(gEditLeft, boxTopRow, gEditWidth, boxHeight, "Taglines", gConfigSettings, true, false);
+	var bottomBorderText = "nhcb, cb, cNy)bext, cPy)brev, "
+	                     + "cFy)birst, cLy)bast, cHOMEb, cENDb, cEntery=bSelect, "
+	                     + "cRy)bandom, cESCnc/hcQy=bEnd";
+	taglineBox.setBottomBorderText(bottomBorderText, false, false);
+	// Add R as an input loop exit key, to choose a random tagline.
+	taglineBox.addInputLoopExitKey("R");
+	taglineBox.addInputLoopExitKey("r");
+
+	// Set the tagline item array in the list box.  Don't strip control characters
+	// because we've already done that when we read the file.
+	taglineBox.setItemArray(taglines, false);
+	// Let the user choose a tagline
+	var taglineRetObj = taglineBox.doInputLoop(true);
+	retObj.taglineWasSelected = taglineRetObj.itemWasSelected;
+	if (retObj.taglineWasSelected)
+		retObj.tagline = taglineRetObj.selectedItem;
+	// If the R key was pressed, then choose a random tagline.
+	else if ((taglineRetObj.lastKeypress == "R") || (taglineRetObj.lastKeypress == "r"))
+	{
+		retObj.tagline = taglines[random(taglines.length)];
+		retObj.taglineWasSelected = true;
+	}
 
-   // If a tagline was selected, then add the tagline prefix in front of it, and
-   // also quote the tagline if the option to do so is enabled.
-   if (retObj.taglineWasSelected)
-   {
-      if (gConfigSettings.taglinePrefix.length > 0)
-         retObj.tagline = gConfigSettings.taglinePrefix + retObj.tagline;
-      // If the option to quote taglines is enabled, then do it.
-      if (gConfigSettings.quoteTaglines)
-         retObj.tagline = "\"" + retObj.tagline + "\"";
-   }
+	// If a tagline was selected, then add the tagline prefix in front of it, and
+	// also quote the tagline if the option to do so is enabled.
+	if (retObj.taglineWasSelected)
+	{
+		if (gConfigSettings.taglinePrefix.length > 0)
+			retObj.tagline = gConfigSettings.taglinePrefix + retObj.tagline;
+		// If the option to quote taglines is enabled, then do it.
+		if (gConfigSettings.quoteTaglines)
+			retObj.tagline = "\"" + retObj.tagline + "\"";
+	}
 
-   return retObj;
+	return retObj;
 }
 
 // Sets the quote prefix, gQuotePrefix (the text to use for prefixing quote lines).
diff --git a/exec/SlyEdit_Misc.js b/exec/SlyEdit_Misc.js
index e53bc1200d930861d9f42ea2187374b2f17967de..e7b6b73100db75466dfb7a070943ef82c12565ed 100644
--- a/exec/SlyEdit_Misc.js
+++ b/exec/SlyEdit_Misc.js
@@ -66,10 +66,12 @@
  *                              quote lines.
  * 2017-12-16 Eric Oulashin     Updated ReadSlyEditConfigFile() to include the
  *                              allowEditQuoteLines option.
+ * 2017-12-18 Eric Oulashin     Update the KEY_PAGE_UP and KEY_PAGE_DOWN keys to
+ *                              ensure they mat what's in sbbsdef.js
  */
  
  load("text.js");
-
+ 
 // Note: These variables are declared with "var" instead of "const" to avoid
 // multiple declaration errors when this file is loaded more than once.
 
@@ -161,15 +163,26 @@ var CTRL_X = "\x18";
 var CTRL_Y = "\x19";
 var CTRL_Z = "\x1a";
 var KEY_ESC = "\x1b";
-// Key code strings returned by getKeyWithESCChars() - Not real key codes, as
-// the keys they represent are returned as multiple key captures.
-var KEY_PAGE_UP = "\1PgUp";
-var KEY_PAGE_DOWN = "\1PgDn";
 var KEY_F1 = "\1F1";
 var KEY_F2 = "\1F2";
 var KEY_F3 = "\1F3";
 var KEY_F4 = "\1F4";
 var KEY_F5 = "\1F5";
+// PageUp & PageDown keys - Synchronet 3.17 as of about December 18, 2017
+// use CTRL-P and CTRL-N for PageUp and PageDown, respectively.  sbbsdefs.js
+// defines them as KEY_PAGEUP and KEY_PAGEDN; I've used slightly different names
+// in this script so that this script will work with Synchronet systems before
+// and after the update containing those key definitions.
+var KEY_PAGE_UP = CTRL_P;
+var KEY_PAGE_DOWN = CTRL_N;
+// Ensure KEY_PAGE_UP and KEY_PAGE_DOWN are set to what's defined in sbbs.js
+// for KEY_PAGEUP and KEY_PAGEDN in case they change.  Note that this relies
+// on sbbsdefs.js being loaded; SlyEdit.js loads sbbsdefs.js before this file,
+// so this should work.
+if (typeof(KEY_PAGEUP) === "string")
+	KEY_PAGE_UP = KEY_PAGEUP;
+if (typeof(KEY_PAGEDN) === "string")
+	KEY_PAGE_DOWN = KEY_PAGEDN;
 
 // Store the full path & filename of the Digital Distortion Message
 // Lister, since it will be used more than once.
@@ -434,7 +447,7 @@ function ChoiceScrollbox_MinWidth()
 //                           spaces in the top border text with border characters.
 //                           Defaults to false.
 function ChoiceScrollbox(pLeftX, pTopY, pWidth, pHeight, pTopBorderText, pSlyEdCfgObj,
-                          pAddTCharsAroundTopText, pReplaceTopTextSpacesWithBorderChars)
+                         pAddTCharsAroundTopText, pReplaceTopTextSpacesWithBorderChars)
 {
    // The default is to add left & right T characters around the top border
    // text.  But also use pAddTCharsAroundTopText if it's a boolean.
@@ -821,295 +834,298 @@ function ChoiceScrollbox_RefreshItemCharOnScreen(pItemIndex, pCharIndex)
 }
 function ChoiceScrollbox_DoInputLoop(pDrawBorder)
 {
-   var retObj = new Object();
-   retObj.itemWasSelected = false;
-   retObj.selectedIndex = -1;
-   retObj.selectedItem = "";
-   retObj.lastKeypress = "";
+	var retObj = {
+		itemWasSelected: false,
+		selectedIndex: -1,
+		selectedItem: "",
+		lastKeypress: ""
+	};
 
-   // Don't do anything if the item list doesn't contain any items
-   if (this.txtItemList.length == 0)
-      return retObj;
+	// Don't do anything if the item list doesn't contain any items
+	if (this.txtItemList.length == 0)
+		return retObj;
 
-   //////////////////////////////////
-   // Locally-defined functions
-
-   // This function returns the index of the bottommost item that
-   // can be displayed in the box.
-   //
-   // Parameters:
-   //  pArray: The array containing the items
-   //  pTopindex: The index of the topmost item displayed in the box
-   //  pNumItemsPerPage: The number of items per page
-   function getBottommostItemIndex(pArray, pTopIndex, pNumItemsPerPage)
-   {
-      var bottomIndex = pTopIndex + pNumItemsPerPage - 1;
-      // If bottomIndex is beyond the last index, then adjust it.
-      if (bottomIndex >= pArray.length)
-         bottomIndex = pArray.length - 1;
-      return bottomIndex;
-   }
+	//////////////////////////////////
+	// Locally-defined functions
 
+	// This function returns the index of the bottommost item that
+	// can be displayed in the box.
+	//
+	// Parameters:
+	//  pArray: The array containing the items
+	//  pTopindex: The index of the topmost item displayed in the box
+	//  pNumItemsPerPage: The number of items per page
+	function getBottommostItemIndex(pArray, pTopIndex, pNumItemsPerPage)
+	{
+		var bottomIndex = pTopIndex + pNumItemsPerPage - 1;
+		// If bottomIndex is beyond the last index, then adjust it.
+		if (bottomIndex >= pArray.length)
+			bottomIndex = pArray.length - 1;
+		return bottomIndex;
+	}
 
 
-   //////////////////////////////////
-   // Code
 
-   // Variables for keeping track of the item list
-   const numItemsPerPage = this.dimensions.height - 2;
-   this.topItemIndex = 0;    // The index of the message group at the top of the list
-   // Figure out the index of the last message group to appear on the screen.
-   this.bottomItemIndex = getBottommostItemIndex(this.txtItemList, this.topItemIndex, numItemsPerPage);
-   const numPages = Math.ceil(this.txtItemList.length / numItemsPerPage);
-   const topIndexForLastPage = (numItemsPerPage * numPages) - numItemsPerPage;
+	//////////////////////////////////
+	// Code
 
-   if (pDrawBorder)
-      this.drawBorder();
+	// Variables for keeping track of the item list
+	const numItemsPerPage = this.dimensions.height - 2;
+	this.topItemIndex = 0;    // The index of the message group at the top of the list
+	// Figure out the index of the last message group to appear on the screen.
+	this.bottomItemIndex = getBottommostItemIndex(this.txtItemList, this.topItemIndex, numItemsPerPage);
+	const numPages = Math.ceil(this.txtItemList.length / numItemsPerPage);
+	const topIndexForLastPage = (numItemsPerPage * numPages) - numItemsPerPage;
 
-   // User input loop
-   // For the horizontal location of the page number text for the box border:
-   // Based on the fact that there can be up to 9999 text replacements and 10
-   // per page, there will be up to 1000 pages of replacements.  To write the
-   // text, we'll want to be 20 characters to the left of the end of the border
-   // of the box.
-   const pageNumTxtStartX = this.dimensions.topLeftX + this.dimensions.width - 19;
-   const maxItemWidth = this.dimensions.width - 2;
-   var pageNum = 0;
-   var startArrIndex = 0;
-   this.chosenTextItemIndex = retObj.selectedIndex = 0;
-   var endArrIndex = 0; // One past the last array item
-   var screenY = 0;
-   var curpos = new Object(); // For keeping track of the current cursor position
-   curpos.x = 0;
-   curpos.y = 0;
-   var refreshList = true; // For screen redraw optimizations
-   var continueOn = true;
-   while (continueOn)
-   {
-      if (refreshList)
-      {
-         this.bottomItemIndex = getBottommostItemIndex(this.txtItemList, this.topItemIndex, numItemsPerPage);
-
-         // Write the list of items for the current page
-         startArrIndex = pageNum * numItemsPerPage;
-         endArrIndex = startArrIndex + numItemsPerPage;
-         if (endArrIndex > this.txtItemList.length)
-            endArrIndex = this.txtItemList.length;
-         var selectedItemRow = this.dimensions.topLeftY+1;
-         screenY = this.dimensions.topLeftY + 1;
-         for (var i = startArrIndex; i < endArrIndex; ++i)
-         {
-            console.gotoxy(this.dimensions.topLeftX+1, screenY);
-            if (i == retObj.selectedIndex)
-            {
-               printf(this.listIemHighlightFormatStr, this.txtItemList[i].substr(0, maxItemWidth));
-               selectedItemRow = screenY;
-            }
-            else
-               printf(this.listIemFormatStr, this.txtItemList[i].substr(0, maxItemWidth));
-            ++screenY;
-         }
-         // If the current screen row is below the bottom row inside the box,
-         // continue and write blank lines to the bottom of the inside of the box
-         // to blank out any text that might still be there.
-         while (screenY < this.dimensions.topLeftY+this.dimensions.height-1)
-         {
-            console.gotoxy(this.dimensions.topLeftX+1, screenY);
-            printf(this.listIemFormatStr, "");
-            ++screenY;
-         }
+	if (pDrawBorder)
+		this.drawBorder();
 
-         // Update the page number in the top border of the box.
-         console.gotoxy(pageNumTxtStartX, this.dimensions.topLeftY);
-         printf("n" + this.SlyEdCfgObj.genColors.listBoxBorderText + "Page %4d of %4d", pageNum+1, numPages);
+	// User input loop
+	// For the horizontal location of the page number text for the box border:
+	// Based on the fact that there can be up to 9999 text replacements and 10
+	// per page, there will be up to 1000 pages of replacements.  To write the
+	// text, we'll want to be 20 characters to the left of the end of the border
+	// of the box.
+	const pageNumTxtStartX = this.dimensions.topLeftX + this.dimensions.width - 19;
+	const maxItemWidth = this.dimensions.width - 2;
+	var pageNum = 0;
+	var startArrIndex = 0;
+	this.chosenTextItemIndex = retObj.selectedIndex = 0;
+	var endArrIndex = 0; // One past the last array item
+	var screenY = 0;
+	var curpos = new Object(); // For keeping track of the current cursor position
+	curpos.x = 0;
+	curpos.y = 0;
+	var refreshList = true; // For screen redraw optimizations
+	var continueOn = true;
+	while (continueOn)
+	{
+		if (refreshList)
+		{
+			this.bottomItemIndex = getBottommostItemIndex(this.txtItemList, this.topItemIndex, numItemsPerPage);
+
+			// Write the list of items for the current page
+			startArrIndex = pageNum * numItemsPerPage;
+			endArrIndex = startArrIndex + numItemsPerPage;
+			if (endArrIndex > this.txtItemList.length)
+				endArrIndex = this.txtItemList.length;
+			var selectedItemRow = this.dimensions.topLeftY+1;
+			screenY = this.dimensions.topLeftY + 1;
+			for (var i = startArrIndex; i < endArrIndex; ++i)
+			{
+				console.gotoxy(this.dimensions.topLeftX+1, screenY);
+				if (i == retObj.selectedIndex)
+				{
+					printf(this.listIemHighlightFormatStr, this.txtItemList[i].substr(0, maxItemWidth));
+					selectedItemRow = screenY;
+				}
+				else
+					printf(this.listIemFormatStr, this.txtItemList[i].substr(0, maxItemWidth));
+				++screenY;
+			}
+			// If the current screen row is below the bottom row inside the box,
+			// continue and write blank lines to the bottom of the inside of the box
+			// to blank out any text that might still be there.
+			while (screenY < this.dimensions.topLeftY+this.dimensions.height-1)
+			{
+				console.gotoxy(this.dimensions.topLeftX+1, screenY);
+				printf(this.listIemFormatStr, "");
+				++screenY;
+			}
 
-         // Just for sane appearance: Move the cursor to the first character of
-         // the currently-selected row and set the appropriate color.
-         curpos.x = this.dimensions.topLeftX+1;
-         curpos.y = selectedItemRow;
-         console.gotoxy(curpos.x, curpos.y);
-         console.print(this.SlyEdCfgObj.genColors.listBoxItemHighlight);
+			// Update the page number in the top border of the box.
+			console.gotoxy(pageNumTxtStartX, this.dimensions.topLeftY);
+			printf("\1n" + this.SlyEdCfgObj.genColors.listBoxBorderText + "Page %4d of %4d", pageNum+1, numPages);
 
-         refreshList = false;
-      }
+			// Just for sane appearance: Move the cursor to the first character of
+			// the currently-selected row and set the appropriate color.
+			curpos.x = this.dimensions.topLeftX+1;
+			curpos.y = selectedItemRow;
+			console.gotoxy(curpos.x, curpos.y);
+			console.print(this.SlyEdCfgObj.genColors.listBoxItemHighlight);
 
-      // Get a key from the user (upper-case) and take action based upon it.
-      retObj.lastKeypress = getUserKey(K_UPPER|K_NOCRLF|K_NOSPIN, this.SlyEdCfgObj);
-      switch (retObj.lastKeypress)
-      {
-         case 'N': // Next page
-            refreshList = (pageNum < numPages-1);
-            if (refreshList)
-            {
-               ++pageNum;
-               this.topItemIndex += numItemsPerPage;
-               this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
-               // Note: this.bottomItemIndex is refreshed at the top of the loop
-            }
-            break;
-         case 'P': // Previous page
-            refreshList = (pageNum > 0);
-            if (refreshList)
-            {
-               --pageNum;
-               this.topItemIndex -= numItemsPerPage;
-               this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
-               // Note: this.bottomItemIndex is refreshed at the top of the loop
-            }
-            break;
-         case 'F': // First page
-            refreshList = (pageNum > 0);
-            if (refreshList)
-            {
-               pageNum = 0;
-               this.topItemIndex = 0;
-               this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
-               // Note: this.bottomItemIndex is refreshed at the top of the loop
-            }
-            break;
-         case 'L': // Last page
-            refreshList = (pageNum < numPages-1);
-            if (refreshList)
-            {
-               pageNum = numPages-1;
-               this.topItemIndex = topIndexForLastPage;
-               this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
-               // Note: this.bottomItemIndex is refreshed at the top of the loop
-            }
-            break;
-         case KEY_UP:
-            // Move the cursor up one item
-            if (retObj.selectedIndex > 0)
-            {
-               // If the previous item index is on the previous page, then we'll
-               // want to display the previous page.
-               var previousItemIndex = retObj.selectedIndex - 1;
-               if (previousItemIndex < this.topItemIndex)
-               {
-                  --pageNum;
-                  this.topItemIndex -= numItemsPerPage;
-                  // Note: this.bottomItemIndex is refreshed at the top of the loop
-                  refreshList = true;
-               }
-               else
-               {
-                  // Display the current line un-highlighted
-                  console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
-                  printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
-                  // Display the previous line highlighted
-                  curpos.x = this.dimensions.topLeftX+1;
-                  --curpos.y;
-                  console.gotoxy(curpos);
-                  printf(this.listIemHighlightFormatStr, this.txtItemList[previousItemIndex].substr(0, maxItemWidth));
-                  console.gotoxy(curpos); // Move the cursor into place where it should be
-                  refreshList = false;
-               }
-               this.chosenTextItemIndex = retObj.selectedIndex = previousItemIndex;
-            }
-            break;
-         case KEY_DOWN:
-            // Move the cursor down one item
-            if (retObj.selectedIndex < this.txtItemList.length - 1)
-            {
-               // If the next item index is on the next page, then we'll want to
-               // display the next page.
-               var nextItemIndex = retObj.selectedIndex + 1;
-               if (nextItemIndex > this.bottomItemIndex)
-               {
-                  ++pageNum;
-                  this.topItemIndex += numItemsPerPage;
-                  // Note: this.bottomItemIndex is refreshed at the top of the loop
-                  refreshList = true;
-               }
-               else
-               {
-                  // Display the current line un-highlighted
-                  console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
-                  printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
-                  // Display the previous line highlighted
-                  curpos.x = this.dimensions.topLeftX+1;
-                  ++curpos.y;
-                  console.gotoxy(curpos);
-                  printf(this.listIemHighlightFormatStr, this.txtItemList[nextItemIndex].substr(0, maxItemWidth));
-                  console.gotoxy(curpos); // Move the cursor into place where it should be
-                  refreshList = false;
-               }
-               this.chosenTextItemIndex = retObj.selectedIndex = nextItemIndex;
-            }
-            break;
-         case KEY_HOME: // Go to the first row in the box
-            if (retObj.selectedIndex > this.topItemIndex)
-            {
-               // Display the current line un-highlighted
-               console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
-               printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
-               // Select the top item, and display it highlighted.
-               this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
-               curpos.x = this.dimensions.topLeftX+1;
-               curpos.y = this.dimensions.topLeftY+1;
-               console.gotoxy(curpos);
-               printf(this.listIemHighlightFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
-               console.gotoxy(curpos); // Move the cursor into place where it should be
-               refreshList = false;
-            }
-            break;
-         case KEY_END: // Go to the last row in the box
-            if (retObj.selectedIndex < this.bottomItemIndex)
-            {
-               // Display the current line un-highlighted
-               console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
-               printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
-               // Select the bottommost item, and display it highlighted.
-               this.chosenTextItemIndex = retObj.selectedIndex = this.bottomItemIndex;
-               curpos.x = this.dimensions.topLeftX+1;
-               curpos.y = this.dimensions.bottomRightY-1;
-               console.gotoxy(curpos);
-               printf(this.listIemHighlightFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
-               console.gotoxy(curpos); // Move the cursor into place where it should be
-               refreshList = false;
-            }
-            break;
-         case KEY_ENTER:
-            // If the enter key override function is set, then call it and pass
-            // this object into it.  Otherwise, just select the item and quit.
-            if (this.enterKeyOverrideFn !== null)
-               this.enterKeyOverrideFn(this);
-            else
-            {
-               retObj.itemWasSelected = true;
-               // Note: retObj.selectedIndex is already set.
-               retObj.selectedItem = this.txtItemList[retObj.selectedIndex];
-               refreshList = false;
-               continueOn = false;
-            }
-            break;
-         case KEY_ESC: // Quit
-         case CTRL_A:  // Quit
-         case 'Q':     // Quit
-            this.chosenTextItemIndex = retObj.selectedIndex = -1;
-            refreshList = false;
-            continueOn = false;
-            break;
-         default:
-            // If the keypress is an additional key to exit the input loop, then
-            // do so.
-            if (this.inputLoopExitKeys.hasOwnProperty(retObj.lastKeypress))
-            {
-               this.chosenTextItemIndex = retObj.selectedIndex = -1;
-               refreshList = false;
-               continueOn = false;
-            }
-            else
-            {
-               // Unrecognized command.  Don't refresh the list of the screen.
-               refreshList = false;
-            }
-            break;
-      }
-   }
+			refreshList = false;
+		}
 
-   console.print("n"); // To prevent outputting highlight colors, etc..
-   return retObj;
+		// Get a key from the user (upper-case) and take action based upon it.
+		retObj.lastKeypress = getKeyWithESCChars(K_UPPER|K_NOCRLF|K_NOSPIN, this.SlyEdCfgObj);
+		switch (retObj.lastKeypress)
+		{
+			case 'N': // Next page
+			case KEY_PAGE_DOWN:
+				refreshList = (pageNum < numPages-1);
+				if (refreshList)
+				{
+					++pageNum;
+					this.topItemIndex += numItemsPerPage;
+					this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
+					// Note: this.bottomItemIndex is refreshed at the top of the loop
+				}
+				break;
+			case 'P': // Previous page
+			case KEY_PAGE_UP:
+				refreshList = (pageNum > 0);
+				if (refreshList)
+				{
+					--pageNum;
+					this.topItemIndex -= numItemsPerPage;
+					this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
+					// Note: this.bottomItemIndex is refreshed at the top of the loop
+				}
+				break;
+			case 'F': // First page
+				refreshList = (pageNum > 0);
+				if (refreshList)
+				{
+					pageNum = 0;
+					this.topItemIndex = 0;
+					this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
+					// Note: this.bottomItemIndex is refreshed at the top of the loop
+				}
+				break;
+			case 'L': // Last page
+				refreshList = (pageNum < numPages-1);
+				if (refreshList)
+				{
+					pageNum = numPages-1;
+					this.topItemIndex = topIndexForLastPage;
+					this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
+					// Note: this.bottomItemIndex is refreshed at the top of the loop
+				}
+				break;
+			case KEY_UP:
+				// Move the cursor up one item
+				if (retObj.selectedIndex > 0)
+				{
+					// If the previous item index is on the previous page, then we'll
+					// want to display the previous page.
+					var previousItemIndex = retObj.selectedIndex - 1;
+					if (previousItemIndex < this.topItemIndex)
+					{
+						--pageNum;
+						this.topItemIndex -= numItemsPerPage;
+						// Note: this.bottomItemIndex is refreshed at the top of the loop
+						refreshList = true;
+					}
+					else
+					{
+						// Display the current line un-highlighted
+						console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
+						printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
+						// Display the previous line highlighted
+						curpos.x = this.dimensions.topLeftX+1;
+						--curpos.y;
+						console.gotoxy(curpos);
+						printf(this.listIemHighlightFormatStr, this.txtItemList[previousItemIndex].substr(0, maxItemWidth));
+						console.gotoxy(curpos); // Move the cursor into place where it should be
+						refreshList = false;
+					}
+					this.chosenTextItemIndex = retObj.selectedIndex = previousItemIndex;
+				}
+				break;
+			case KEY_DOWN:
+				// Move the cursor down one item
+				if (retObj.selectedIndex < this.txtItemList.length - 1)
+				{
+					// If the next item index is on the next page, then we'll want to
+					// display the next page.
+					var nextItemIndex = retObj.selectedIndex + 1;
+					if (nextItemIndex > this.bottomItemIndex)
+					{
+						++pageNum;
+						this.topItemIndex += numItemsPerPage;
+						// Note: this.bottomItemIndex is refreshed at the top of the loop
+						refreshList = true;
+					}
+					else
+					{
+						// Display the current line un-highlighted
+						console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
+						printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
+						// Display the previous line highlighted
+						curpos.x = this.dimensions.topLeftX+1;
+						++curpos.y;
+						console.gotoxy(curpos);
+						printf(this.listIemHighlightFormatStr, this.txtItemList[nextItemIndex].substr(0, maxItemWidth));
+						console.gotoxy(curpos); // Move the cursor into place where it should be
+						refreshList = false;
+					}
+					this.chosenTextItemIndex = retObj.selectedIndex = nextItemIndex;
+				}
+				break;
+			case KEY_HOME: // Go to the first row in the box
+				if (retObj.selectedIndex > this.topItemIndex)
+				{
+					// Display the current line un-highlighted
+					console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
+					printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
+					// Select the top item, and display it highlighted.
+					this.chosenTextItemIndex = retObj.selectedIndex = this.topItemIndex;
+					curpos.x = this.dimensions.topLeftX+1;
+					curpos.y = this.dimensions.topLeftY+1;
+					console.gotoxy(curpos);
+					printf(this.listIemHighlightFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
+					console.gotoxy(curpos); // Move the cursor into place where it should be
+					refreshList = false;
+				}
+				break;
+			case KEY_END: // Go to the last row in the box
+				if (retObj.selectedIndex < this.bottomItemIndex)
+				{
+					// Display the current line un-highlighted
+					console.gotoxy(this.dimensions.topLeftX+1, curpos.y);
+					printf(this.listIemFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
+					// Select the bottommost item, and display it highlighted.
+					this.chosenTextItemIndex = retObj.selectedIndex = this.bottomItemIndex;
+					curpos.x = this.dimensions.topLeftX+1;
+					curpos.y = this.dimensions.bottomRightY-1;
+					console.gotoxy(curpos);
+					printf(this.listIemHighlightFormatStr, this.txtItemList[retObj.selectedIndex].substr(0, maxItemWidth));
+					console.gotoxy(curpos); // Move the cursor into place where it should be
+					refreshList = false;
+				}
+				break;
+			case KEY_ENTER:
+				// If the enter key override function is set, then call it and pass
+				// this object into it.  Otherwise, just select the item and quit.
+				if (this.enterKeyOverrideFn !== null)
+				this.enterKeyOverrideFn(this);
+				else
+				{
+					retObj.itemWasSelected = true;
+					// Note: retObj.selectedIndex is already set.
+					retObj.selectedItem = this.txtItemList[retObj.selectedIndex];
+					refreshList = false;
+					continueOn = false;
+				}
+				break;
+			case KEY_ESC: // Quit
+			case CTRL_A:  // Quit
+			case 'Q':     // Quit
+				this.chosenTextItemIndex = retObj.selectedIndex = -1;
+				refreshList = false;
+				continueOn = false;
+				break;
+			default:
+				// If the keypress is an additional key to exit the input loop, then
+				// do so.
+				if (this.inputLoopExitKeys.hasOwnProperty(retObj.lastKeypress))
+				{
+					this.chosenTextItemIndex = retObj.selectedIndex = -1;
+					refreshList = false;
+					continueOn = false;
+				}
+				else
+				{
+					// Unrecognized command.  Don't refresh the list of the screen.
+					refreshList = false;
+				}
+				break;
+		}
+	}
+
+	console.print("\1n"); // To prevent outputting highlight colors, etc..
+	return retObj;
 }
 
 
@@ -4232,7 +4248,7 @@ function consolePauseWithESCChars(pCfgObj)
 // Inputs a keypress from the user and handles some ESC-based
 // characters such as PageUp, PageDown, and ESC.  If PageUp
 // or PageDown are pressed, this function will return the
-// string "\1PgUp" (KEY_PAGE_UP) or "\1Pgdn" (KEY_PAGE_DOWN),
+// string defined by KEY_PAGE_UP or EY_PAGE_DOWN,
 // respectively.  Also, F1-F5 will be returned as "\1F1"
 // through "\1F5", respectively.
 // Thanks goes to Psi-Jack for the original impementation