diff --git a/src/sbbs3/getstr.cpp b/src/sbbs3/getstr.cpp
index 4674d28c29349a4b9e123983ab3341a257741fd3..44266f2de42b73d7396c50228d2c487c1a61bfad 100644
--- a/src/sbbs3/getstr.cpp
+++ b/src/sbbs3/getstr.cpp
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -53,16 +53,18 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
     uchar	ch;
 	uchar	ins=0,atr;
 
-	console&=~CON_UPARROW;
+	console&=~(CON_UPARROW|CON_LEFTARROW|CON_BACKSPACE);
 	sys_status&=~SS_ABORT;
 	if(mode&K_LINE && useron.misc&ANSI && !(mode&K_NOECHO)) {
 		attr(cfg.color[clr_inputline]);
 		for(i=0;i<maxlen;i++)
 			outchar(SP);
-		bprintf("\x1b[%dD",maxlen); }
+		bprintf("\x1b[%dD",maxlen); 
+	}
 	if(wordwrap[0]) {
 		strcpy(str1,wordwrap);
-		wordwrap[0]=0; }
+		wordwrap[0]=0; 
+	}
 	else str1[0]=0;
 	if(mode&K_EDIT)
 		strcat(str1,strout);
@@ -75,10 +77,12 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 		if(mode&K_AUTODEL && str1[0]) {
 			i=(cfg.color[clr_inputline]&0x77)<<4;
 			i|=(cfg.color[clr_inputline]&0x77)>>4;
-			attr(i); }
+			attr(i); 
+		}
 		rputs(str1);
 		if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && useron.misc&ANSI)
-			bputs("\x1b[K");  /* destroy to eol */ }
+			bputs("\x1b[K");  /* destroy to eol */ 
+	}
 
 	i=l=strlen(str1);
 	if(mode&K_AUTODEL && str1[0] && !(mode&K_NOECHO)) {
@@ -87,22 +91,42 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 		if(isprint(ch) || ch==DEL) {
 			for(i=0;i<l;i++)
 				bputs("\b \b");
-			i=l=0; }
+			i=l=0; 
+		}
 		else {
 			for(i=0;i<l;i++)
 				outchar(BS);
 			rputs(str1);
-			i=l; }
+			i=l; 
+		}
 		if(ch!=SP && ch!=TAB)
-			ungetkey(ch); }
+			ungetkey(ch); 
+	}
 
-	while(!(sys_status&SS_ABORT) && (ch=getkey(mode|K_GETSTR))!=CR && online) {
-		if(!input_thread_running)
+	if(mode&K_USEOFFSET) {
+		i=getstr_offset;
+		if(i>l)
+			i=l;
+		if(l-i) {
+			if(useron.misc&ANSI)
+				bprintf("\x1b[%dD",l-i);
+			else
+				for(i=0;i<l-i;i++)
+					outchar(BS);
+		}
+	}
+
+	while(!(sys_status&SS_ABORT) && online && input_thread_running) {
+		if(console&(CON_UPARROW|CON_LEFTARROW|CON_BACKSPACE))
+			break;
+		if((ch=getkey(mode|K_GETSTR))==CR)
 			break;
-		if(sys_status&SS_ABORT)
+		if(sys_status&SS_ABORT || !online)
 			break;
-		if(ch==LF && mode&K_MSG) /* Down-arrow same as CR */
+		if(ch==LF && mode&K_MSG) { /* Down-arrow same as CR */
+			console|=CON_DOWNARROW;
 			break;
+		}
 		if(ch==TAB && (mode&K_TAB || !(mode&K_WRAP)))	/* TAB same as CR */
 			break;
 		if(!i && mode&K_UPRLWR && (ch==SP || ch==TAB))
@@ -111,7 +135,10 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 			if(strstr(str1,"��")) {
 				bputs("\r\n\r\nYou must set your terminal to NO PARITY, "
 					"8 DATA BITS, and 1 STOP BIT (N-8-1).\7\r\n");
-				return(0); } }
+				return(0); 
+			} 
+		}
+		getstr_offset=i;
 		switch(ch) {
 			case CTRL_A: /* Ctrl-A for ANSI */
 				if(!(mode&K_MSG) || useron.rest&FLAG('A') || i>maxlen-3)
@@ -124,43 +151,52 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 					rprintf("%.*s",l-i,str1+i);
 					rprintf("\x1b[%dD",l-i);
 					if(i==maxlen-1)
-						ins=0; }
+						ins=0; 
+				}
 				outchar(str1[i++]=1);
 				break;
 			case CTRL_B: /* Ctrl-B Beginning of Line */
 				if(useron.misc&ANSI && i && !(mode&K_NOECHO)) {
 					bprintf("\x1b[%dD",i);
-					i=0; }
+					i=0; 
+				}
 				break;
 			case CTRL_D: /* Ctrl-D Delete word right */
 				if(i<l) {
 					x=i;
 					while(x<l && str1[x]!=SP) {
 						outchar(SP);
-						x++; }
+						x++; 
+					}
 					while(x<l && str1[x]==SP) {
 						outchar(SP);
-						x++; }
+						x++; 
+					}
 					bprintf("\x1b[%dD",x-i);   /* move cursor back */
 					z=i;
 					while(z<l-(x-i))  {             /* move chars in string */
 						outchar(str1[z]=str1[z+(x-i)]);
-						z++; }
+						z++; 
+					}
 					while(z<l) {                    /* write over extra chars */
 						outchar(SP);
-						z++; }
+						z++; 
+					}
 					bprintf("\x1b[%dD",z-i);
-					l-=x-i; }                       /* l=new length */
+					l-=x-i;							/* l=new length */
+				}
 				break;
 			case CTRL_E: /* Ctrl-E End of line */
 				if(useron.misc&ANSI && i<l) {
 					bprintf("\x1b[%dC",l-i);  /* move cursor to eol */
-					i=l; }
+					i=l; 
+				}
 				break;
 			case CTRL_F: /* Ctrl-F move cursor forewards */
 				if(i<l && (useron.misc&ANSI)) {
 					bputs("\x1b[C");   /* move cursor right one */
-					i++; }
+					i++; 
+				}
 				break;
 			case CTRL_G: /* Bell */
 				if(!(mode&K_MSG))
@@ -173,7 +209,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 							if(l+5<maxlen)
 								l+=6;
 							if(i==maxlen-1)
-								ins=0; }
+								ins=0; 
+						}
 						str1[i++]='(';
 						str1[i++]='b';
 						str1[i++]='e';
@@ -181,25 +218,32 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						str1[i++]='p';
 						str1[i++]=')';
 						if(!(mode&K_NOECHO))
-							bputs("(beep)"); }
+							bputs("(beep)"); 
+					}
 					if(ins)
 						redrwstr(str1,i,l,0);
-					break; }
-				 if(ins) {
+					break; 
+				}
+				if(ins) {
 					if(l<maxlen)
 						l++;
 					for(x=l;x>i;x--)
 						str1[x]=str1[x-1];
 					if(i==maxlen-1)
-						ins=0; }
-				 if(i<maxlen) {
+						ins=0; 
+				}
+				if(i<maxlen) {
 					str1[i++]=BEL;
 					if(!(mode&K_NOECHO))
-						outchar(BEL); }
-				 break;
+						outchar(BEL); 
+				}
+				break;
 			case CTRL_H:	/* Ctrl-H/Backspace */
-				if(!i)
+				if(i==0) {
+					if(mode&K_LEFTEXIT)
+						console|=CON_BACKSPACE;
 					break;
+				}
 				i--;
 				l--;
 				if(i!=l) {              /* Deleting char in middle of line */
@@ -207,9 +251,11 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 					z=i;
 					while(z<l)  {       /* move the characters in the line */
 						outchar(str1[z]=str1[z+1]);
-						z++; }
+						z++; 
+					}
 					outchar(SP);        /* write over the last char */
-					bprintf("\x1b[%dD",(l-i)+1); }
+					bprintf("\x1b[%dD",(l-i)+1); 
+				}
 				else if(!(mode&K_NOECHO))
 					bputs("\b \b");
 				break;
@@ -221,10 +267,12 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						for(x=l;x>i;x--)
 							str1[x]=str1[x-1];
 						if(i==maxlen-1)
-							ins=0; }
+							ins=0; 
+					}
 					str1[i++]=SP;
 					if(!(mode&K_NOECHO))
-						outchar(SP); }
+						outchar(SP); 
+				}
 				while(i<maxlen && i%EDIT_TABSIZE) {
 					if(ins) {
 						if(l<maxlen)
@@ -232,10 +280,12 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						for(x=l;x>i;x--)
 							str1[x]=str1[x-1];
 						if(i==maxlen-1)
-							ins=0; }
+							ins=0; 
+					}
 					str1[i++]=SP;
 					if(!(mode&K_NOECHO))
-						outchar(SP); }
+						outchar(SP); 
+				}
 				if(ins && !(mode&K_NOECHO))
 					redrwstr(str1,i,l,0);
 				break;
@@ -259,7 +309,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						bputs("\b");
 					bputs(strout);
 					if(mode&K_LINE)
-						attr(LIGHTGRAY); }
+						attr(LIGHTGRAY); 
+				}
 				CRLF;
 				return(l);
 
@@ -270,7 +321,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						i++;
 					while(str1[i]==SP && i<l)
 						i++;
-					bprintf("\x1b[%dC",i-x); }
+					bprintf("\x1b[%dC",i-x); 
+				}
 				break;
 			case CTRL_R:    /* Ctrl-R Redraw Line */
 				if(!(mode&K_NOECHO))
@@ -281,7 +333,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 					break;
 				if(ins) {
 					ins=0;
-					redrwstr(str1,i,l,0); }
+					redrwstr(str1,i,l,0); 
+				}
 				else if(i<l) {
 					ins=1;
 					bprintf("\x1b[s\x1b[79C");    	/* save pos  */
@@ -289,37 +342,45 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 					attr(z|BLINK|HIGH);
 					outchar('�');
 					attr(z);
-					bputs("\x1b[u"); }  /* restore pos */
+					bputs("\x1b[u");				/* restore pos */
+				}
 				break;
 			case CTRL_W:    /* Ctrl-W   Delete word left */
 				if(i<l) {
 					x=i;                            /* x=original offset */
 					while(i && str1[i-1]==SP) {
 						outchar(BS);
-						i--; }
+						i--; 
+					}
 					while(i && str1[i-1]!=SP) {
 						outchar(BS);
-						i--; }
+						i--; 
+					}
 					z=i;                            /* i=z=new offset */
 					while(z<l-(x-i))  {             /* move chars in string */
 						outchar(str1[z]=str1[z+(x-i)]);
-						z++; }
+						z++; 
+					}
 					while(z<l) {                    /* write over extra chars */
 						outchar(SP);
-						z++; }
+						z++; 
+					}
 					bprintf("\x1b[%dD",z-i);        /* back to new x corridnant */
-					l-=x-i; }                       /* l=new length */
-				else {
+					l-=x-i;                         /* l=new length */
+				} else {
 					while(i && str1[i-1]==SP) {
 						i--;
 						l--;
 						if(!(mode&K_NOECHO))
-							bputs("\b \b"); }
+							bputs("\b \b"); 
+					}
 					while(i && str1[i-1]!=SP) {
 						i--;
 						l--;
 						if(!(mode&K_NOECHO))
-							bputs("\b \b"); } }
+							bputs("\b \b"); 
+					} 
+				}
 				break;
 			case CTRL_X:    /* Ctrl-X   Delete entire line */
 				if(mode&K_NOECHO)
@@ -327,16 +388,20 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 				else {
 					while(i<l) {
 						outchar(SP);
-						i++; }
+						i++; 
+					}
 					while(l) {
 						l--;
-						bputs("\b \b"); } }
+						bputs("\b \b"); 
+					} 
+				}
 				i=0;
 				break;
 			case CTRL_Y:    /* Ctrl-Y   Delete to end of line */
 				if(useron.misc&ANSI && !(mode&K_NOECHO)) {
 					bputs("\x1b[K");
-					l=i; }
+					l=i; 
+				}
 				break;
 			case 28:    /* Ctrl-\ Previous word */
 				if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
@@ -345,16 +410,24 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						i--;
 					while(str1[i-1]!=SP && i)
 						i--;
-					bprintf("\x1b[%dD",x-i); }
+					bprintf("\x1b[%dD",x-i); 
+				}
 				break;
 			case 29:  /* Ctrl-]/Left Arrow  Reverse Cursor Movement */
-				if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
+				if(i==0) {
+					if(mode&K_LEFTEXIT)
+						console|=CON_LEFTARROW;
+					break;
+				}
+				if((useron.misc&ANSI) && !(mode&K_NOECHO)) {
 					bputs("\x1b[D");   /* move cursor left one */
-					i--; }
+					i--; 
+				}
 				break;
 			case 30:  /* Ctrl-^/Up Arrow */
 				if(!(mode&K_EDIT))
 					break;
+#if 0
 				if(i>l)
 					l=i;
 				str1[l]=0;
@@ -365,6 +438,10 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 					attr(LIGHTGRAY);
 				console|=CON_UPARROW;
 				return(l);
+#else
+				console|=CON_UPARROW;
+				break;
+#endif
 			case DEL:  /* Ctrl-BkSpc (DEL) Delete current char */
 				if(i==l) {	/* Backspace if end of line */
 					if(i) {
@@ -379,7 +456,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 				z=i;
 				while(z<l)  {       /* move the characters in the line */
 					outchar(str1[z]=str1[z+1]);
-					z++; }
+					z++; 
+				}
 				outchar(SP);        /* write over the last char */
 				bprintf("\x1b[%dD",(l-i)+1);
 				break;
@@ -392,7 +470,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 							redrwstr(strout,i,l,K_MSG);
 						if(!(mode&K_NOECHO))
 							CRLF;
-						return(i); }
+						return(i); 
+					}
 					x=i-1;
 					z=1;
 					wordwrap[0]=ch;
@@ -405,12 +484,14 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 							redrwstr(strout,i,l,K_MSG);
 						if(!(mode&K_NOECHO))
 							CRLF;
-						return(i); }
+						return(i); 
+					}
 					wordwrap[z]=0;
 					if(!(mode&K_NOECHO))
 						while(z--) {
 							bputs("\b \b");
-							i--; }
+							i--; 
+						}
 					strrev(wordwrap);
 					str1[x]=0;
 					strcpy(strout,str1);
@@ -418,7 +499,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						redrwstr(strout,i,x,(char)mode);
 					if(!(mode&K_NOECHO))
 						CRLF;
-					return(x); }
+					return(x); 
+				}
 				if(i<maxlen && ch>=SP) {
 					if(mode&K_UPRLWR)
 						if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
@@ -435,14 +517,20 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 						rprintf("\x1b[%dD",l-i);
 						if(i==maxlen-1) {
 							bputs("  \b\b");
-							ins=0; } }
+							ins=0; 
+						} 
+					}
 					str1[i++]=ch;
 					if(!(mode&K_NOECHO))
-						outchar(ch); } }
+						outchar(ch); 
+				} 
+		}
 		if(i>l)
 			l=i;
 		if(mode&K_CHAT && !l)
-			return(0); }
+			return(0); 
+	}
+	getstr_offset=i;
 	if(!online)
 		return(0);
 	if(i>l)
@@ -451,7 +539,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 	if(!(sys_status&SS_ABORT)) {
 		strcpy(strout,str1);
 		if((strip_invalid_attr(strout) || ins) && !(mode&K_NOECHO))
-			redrwstr(strout,i,l,K_MSG); }
+			redrwstr(strout,i,l,K_MSG); 
+	}
 	else
 		l=0;
 	if(mode&K_LINE && !(mode&K_NOECHO)) attr(LIGHTGRAY);
@@ -459,7 +548,8 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
 		outchar(CR);
 		if(!(mode&K_MSG && sys_status&SS_ABORT))
 			outchar(LF);
-		lncntr=0; }
+		lncntr=0; 
+	}
 	return(l);
 }
 
@@ -483,22 +573,27 @@ long sbbs_t::getnum(ulong max)
 				ch=getkey(K_UPPER);
 			if(ch==BS || ch==DEL) {
 				bputs("\b \b");
-				continue; }
+				continue; 
+			}
 			CRLF;
 			lncntr=0;
-			return(-1); }
+			return(-1); 
+		}
 		else if(sys_status&SS_ABORT) {
 			CRLF;
 			lncntr=0;
-			return(-1); }
+			return(-1); 
+		}
 		else if(ch==CR) {
 			CRLF;
 			lncntr=0;
-			return(i); }
+			return(i); 
+		}
 		else if((ch==BS || ch==DEL) && n) {
 			bputs("\b \b");
 			i/=10;
-			n--; }
+			n--; 
+		}
 		else if(isdigit(ch) && (i*10UL)+(ch&0xf)<=max && (ch!='0' || n)) {
 			i*=10L;
 			n++;
@@ -507,6 +602,9 @@ long sbbs_t::getnum(ulong max)
 			if(i*10UL>max && !(useron.misc&COLDKEYS)) {
 				CRLF;
 				lncntr=0;
-				return(i); } } }
+				return(i); 
+			} 
+		} 
+	}
 	return(0);
 }