From 0364f228abcc87ec2260434b36a554f7b26eeabd Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Wed, 18 Feb 2009 05:23:00 +0000
Subject: [PATCH] Track column counter in outchar() rather than putmsg() - this
 is the "right" place to do it, but may need some special handling for
 HTMLterm mode. Parse columns from ANSI cursor position reports. Request
 Telnet "Negotiate Window Size" option during answer since this is more
 reliable than ANSI cursor position reporting (especially with terminals that
 wrap cursor positioning requests). Improve validation of ANSI cursor position
 reports.

---
 src/sbbs3/ansiterm.cpp |  2 +-
 src/sbbs3/answer.cpp   | 22 ++++++++++++++++------
 src/sbbs3/con_out.cpp  | 37 ++++++++++---------------------------
 src/sbbs3/inkey.cpp    | 12 ++++++++----
 src/sbbs3/main.cpp     |  1 +
 src/sbbs3/putmsg.cpp   |  5 +++--
 src/sbbs3/sbbs.h       |  1 +
 7 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/sbbs3/ansiterm.cpp b/src/sbbs3/ansiterm.cpp
index 5d95afcafa..36a1e70742 100644
--- a/src/sbbs3/ansiterm.cpp
+++ b/src/sbbs3/ansiterm.cpp
@@ -102,7 +102,7 @@ void sbbs_t::ansi_getlines()
 	if(sys_status&SS_USERON && useron.misc&ANSI && !useron.rows /* Auto-detect rows */
 		&& online==ON_REMOTE) {									/* Remote */
 		SYNC;
-		putcom("\x1b[s\x1b[99B\x1b[6n\x1b[u");
+		putcom("\x1b[s\x1b[255;255H\x1b[6n\x1b[u");
 		inkey(K_ANSI_CPR,TIMEOUT_ANSI_GETXY*1000); 
 	}
 }
diff --git a/src/sbbs3/answer.cpp b/src/sbbs3/answer.cpp
index 5c7f13b983..256e506282 100644
--- a/src/sbbs3/answer.cpp
+++ b/src/sbbs3/answer.cpp
@@ -181,6 +181,7 @@ bool sbbs_t::answer()
 		request_telnet_opt(TELNET_DO,TELNET_TERM_TYPE);
 		request_telnet_opt(TELNET_DO,TELNET_TERM_SPEED);
 		request_telnet_opt(TELNET_DO,TELNET_SEND_LOCATION);
+		request_telnet_opt(TELNET_DO,TELNET_NEGOTIATE_WINDOW_SIZE);
 	}
 #ifdef USE_CRYPTLIB
 	if(sys_status&SS_SSH) {
@@ -251,7 +252,8 @@ bool sbbs_t::answer()
 	rioctl(IOFI);		/* flush input buffer */
 	putcom( "\r\n"		/* locate cursor at column 1 */
 			"\x1b[s"	/* save cursor position (necessary for HyperTerm auto-ANSI) */
-    		"\x1b[99B_"	/* locate cursor as far down as possible */
+    		"\x1b[255;255H"	/* locate cursor as far down and right as possible */
+			"_"			/* need a printable at this location to actually move cursor */
 			"\x1b[6n"	/* Get cursor position */
 			"\x1b[u"	/* restore cursor position */
 			"\x1b[!_"	/* RIP? */
@@ -290,14 +292,22 @@ bool sbbs_t::answer()
 	str[l]=0;
 
     if(l) {
-        if(str[0]==ESC && str[1]=='[') {	/* TODO: verify this is actually a cursor position report */
+		c_escape_str(str,tmp,sizeof(tmp),TRUE);
+		lprintf(LOG_DEBUG,"Node %d Terminal type detection response: '%s'"
+			,cfg.node_num,tmp);
+        if(str[0]==ESC && str[1]=='[' && str[l-1]=='R') {
+			int	x,y;
+
 			if(terminal[0]==0)
 				SAFECOPY(terminal,"ANSI");
 			autoterm|=(ANSI|COLOR);
-            rows=atoi(str+2);
-			lprintf(LOG_DEBUG,"Node %d ANSI cursor position report: %u rows"
-				,cfg.node_num, rows);
-			if(rows<10 || rows>99) rows=24; 
+			if(sscanf(str+2,"%u;%u",&y,&x)==2) {
+				lprintf(LOG_DEBUG,"Node %d ANSI cursor position report: %ux%u"
+					,cfg.node_num, x, y);
+				/* Sanity check the coordinates in the response: */
+				if(x>=10 && x<=255) cols=x; 
+				if(y>=40 && y<=255) rows=y;
+			}
 		}
 		truncsp(str);
 		if(strstr(str,"RIPSCRIP")) {
diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp
index f37bf9c72d..55c54d0281 100644
--- a/src/sbbs3/con_out.cpp
+++ b/src/sbbs3/con_out.cpp
@@ -196,29 +196,8 @@ void sbbs_t::outchar(char ch)
 			pause();
 			while(lncntr && online && !(sys_status&SS_ABORT))
 				pause(); 
-#if 0	/* This line was added in rev 1.41, but it prevents Ctrl-C or 'N' 
-			from the forced-pause prompt from aborting the currently displayed file: */
-			sys_status&=~SS_ABORT;
-#endif
-		}
-	}
-#if 0
-	if(sys_status&SS_CAP	/* Writes to Capture File */
-		&& (sys_status&SS_ANSCAP || (ch!=ESC /* && !lclaes() */)))
-		fwrite(&ch,1,1,capfile);
-#endif
-#if 0 
-	if(console&CON_L_ECHO) {
-		if(console&CON_L_ECHOX && (uchar)ch>=' ')
-			putch(password_char);
-		else if(cfg.node_misc&NM_NOBEEP && ch==BEL);	 /* Do nothing if beep */
-		else if(ch==BEL) {
-				sbbs_beep(2000,110);
-				nosound(); 
 		}
-		else putch(ch); 
 	}
-#endif
 
 	if(online==ON_REMOTE && console&CON_R_ECHO) {
 		if(console&CON_R_ECHOX && (uchar)ch>=' ' && !outchar_esc) {
@@ -249,14 +228,18 @@ void sbbs_t::outchar(char ch)
 			} 
 		} 
 	}
-	if(ch==LF) {
+	if(!outchar_esc && isprint(ch))
+		column++;
+	if(ch==LF || column>=cols) {
 		lncntr++;
 		lbuflen=0;
 		tos=0;
+		column=0;
 	} else if(ch==FF) {
 		lncntr=0;
 		lbuflen=0;
 		tos=1;
+		column=0;
 	} else {
 		if(!lbuflen)
 			latr=curatr;
@@ -365,17 +348,17 @@ void sbbs_t::cursor_left(int count)
 
 void sbbs_t::cleartoeol(void)
 {
+	int i,j;
+
 	if(term_supports(ANSI))
 		rputs("\x1b[K");
-#if 0
 	else {
-		i=j=lclwx();	/* commented out */
-		while(i++<79)
+		i=j=column;
+		while(i++<cols)
 			outchar(' ');
-		while(j++<79)
+		while(j++<cols)
 			outchar(BS); 
 	}
-#endif                
 }
 
 /****************************************************************************/
diff --git a/src/sbbs3/inkey.cpp b/src/sbbs3/inkey.cpp
index 9d7bdac6f1..421b021a10 100644
--- a/src/sbbs3/inkey.cpp
+++ b/src/sbbs3/inkey.cpp
@@ -313,11 +313,15 @@ char sbbs_t::handle_ctrlkey(char ch, long mode)
 				}
 				if(ch=='R') {       /* cursor position report */
 					if(mode&K_ANSI_CPR && i && !(useron.rows)) {	/* auto-detect rows */
+						int	x,y;
 						str[i]=0;
-						rows=atoi(str);
-						lprintf(LOG_DEBUG,"Node %d ANSI cursor position report: %u rows"
-							,cfg.node_num, rows);
-						if(rows<10 || rows>99) rows=24; 
+						if(sscanf(str,"%u;%u",&y,&x)==2) {
+							lprintf(LOG_DEBUG,"Node %d ANSI cursor position report: %ux%u"
+								,cfg.node_num, x, y);
+							/* Sanity check the coordinates in the response: */
+							if(x>=10 && x<=255) cols=x; 
+							if(y>=40 && y<=255) rows=y;
+						}
 					}
 					return(0); 
 				}
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 8429907068..1b48a359c0 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -2856,6 +2856,7 @@ sbbs_t::sbbs_t(ushort node_num, DWORD addr, const char* name, SOCKET sd,
 	telnet_last_rxch=0;
 
 	sys_status=lncntr=tos=criterrs=slcnt=0L;
+	column=0;
 	curatr=LIGHTGRAY;
 	attr_sp=0;	/* attribute stack pointer */
 	errorlevel=0;
diff --git a/src/sbbs3/putmsg.cpp b/src/sbbs3/putmsg.cpp
index fb0ea21682..bd197dae35 100644
--- a/src/sbbs3/putmsg.cpp
+++ b/src/sbbs3/putmsg.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 2006 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2009 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,7 +53,6 @@ char sbbs_t::putmsg(const char *str, long mode)
 	uchar	exatr=0;
 	int 	orgcon=console,i;
 	ulong	l=0,sys_status_sav=sys_status;
-	long	col=0;
 	int		defered_pause=FALSE;
 
 	attr_sp=0;	/* clear any saved attributes */
@@ -254,10 +253,12 @@ char sbbs_t::putmsg(const char *str, long mode)
 			}
 			if(str[l]!=CTRL_Z) {
 				outchar(str[l]);
+#if 0
 				if(!(mode&P_HTML) && !exatr && !outchar_esc && lncntr && lbuflen && cols && ++col==cols)
 					lncntr++;
 				else
 					col=0;
+#endif
 			}
 			l++; 
 		} 
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 9d5b337f77..d4fa7f0f52 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -296,6 +296,7 @@ public:
 	long 	tos;			/* Top of Screen */
 	long 	rows;			/* Current number of Rows for User */
 	long	cols;			/* Current number of Columns for User */
+	long	column;			/* Current column counter (for line counter) */
 	long 	autoterm;		/* Autodetected terminal type */
 	char 	slbuf[SAVE_LINES][LINE_BUFSIZE+1]; /* Saved for redisplay */
 	char 	slatr[SAVE_LINES];	/* Starting attribute of each line */
-- 
GitLab