svn commit: trunk/busybox/editors

vda at busybox.net vda at busybox.net
Fri Dec 21 21:34:38 UTC 2007


Author: vda
Date: 2007-12-21 13:34:37 -0800 (Fri, 21 Dec 2007)
New Revision: 20661

Log:
vi: fix a problem with displaying overlong lines



Modified:
   trunk/busybox/editors/vi.c


Changeset:
Modified: trunk/busybox/editors/vi.c
===================================================================
--- trunk/busybox/editors/vi.c	2007-12-21 16:32:30 UTC (rev 20660)
+++ trunk/busybox/editors/vi.c	2007-12-21 21:34:37 UTC (rev 20661)
@@ -35,6 +35,7 @@
 enum {
 	MAX_LINELEN = CONFIG_FEATURE_VI_MAX_LEN,
 	MAX_SCR_COLS = CONFIG_FEATURE_VI_MAX_LEN,
+	MAX_TABSTOP = 32, // sanity limit
 };
 
 // Misc. non-Ascii keys that report an escape sequence
@@ -116,7 +117,8 @@
 static int save_argc;           // how many file names on cmd line
 static int cmdcnt;              // repetition count
 static int rows, columns;       // the terminal screen is this size
-static int crow, ccol, offset;  // cursor is on Crow x Ccol with Horz Ofset
+static int crow, ccol;          // cursor is on Crow x Ccol
+static int offset;              // chars scrolled off the screen to the left
 static char *status_buffer;     // mesages to the user
 #define STATUS_BUFFER_LEN  200
 static int have_status_msg;     // is default edit status needed?
@@ -253,6 +255,9 @@
 static int file_insert(const char *, char *);
 #endif
 static int file_write(char *, char *, char *);
+#if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
+#define place_cursor(a, b, optimize) place_cursor(a, b)
+#endif
 static void place_cursor(int, int, int);
 static void screen_erase(void);
 static void clear_to_eol(void);
@@ -266,7 +271,7 @@
 static void ni(const char *);		// display messages
 static int format_edit_status(void);	// format file status on status line
 static void redraw(int);	// force a full screen refresh
-static void format_line(char*, char*, int);
+static int format_line(char*, char*, int);
 static void refresh(int);	// update the terminal from screen[]
 
 static void Indicate_Error(void);       // use flash or beep to indicate error
@@ -992,7 +997,7 @@
 			/* tabstopXXXX */
 			if (strncasecmp(argp + i, "tabstop=%d ", 7) == 0) {
 				sscanf(strchr(argp + i, '='), "tabstop=%d" + 7, &ch);
-				if (ch > 0 && ch < columns - 1)
+				if (ch > 0 && ch <= MAX_TABSTOP)
 					tabstop = ch;
 			}
 			while (*argp && *argp != ' ')
@@ -1252,7 +1257,7 @@
 	return p;
 }
 
-static inline char *dollar_line(char * p) // return pointer to just before NL line
+static char *dollar_line(char * p) // return pointer to just before NL line
 {
 	while (p < end - 1 && *p != '\n')
 		p++;			// go to cur line E-o-l
@@ -1923,7 +1928,7 @@
 	);
 }
 
-static inline void print_literal(char * buf, const char * s) // copy s to buf, convert unprintable
+static void print_literal(char * buf, const char * s) // copy s to buf, convert unprintable
 {
 	unsigned char c;
 	char b[2];
@@ -2055,7 +2060,7 @@
 	}
 }
 
-static inline char *swap_context(char * p) // goto new context for '' command make this the current context
+static char *swap_context(char * p) // goto new context for '' command make this the current context
 {
 	char *tmp;
 
@@ -2147,7 +2152,7 @@
 	return safe_poll(pfd, 1, hund*10) > 0;
 }
 
-static int readed_for_parse;
+static int chars_to_parse;
 
 //----- IO Routines --------------------------------------------
 static char readit(void)	// read (maybe cursor) key from stdin
@@ -2199,7 +2204,7 @@
 
 	alarm(0);	// turn alarm OFF while we wait for input
 	fflush(stdout);
-	n = readed_for_parse;
+	n = chars_to_parse;
 	// get input from User- are there already input chars in Q?
 	if (n <= 0) {
 		// the Q is empty, wait for a typed char
@@ -2228,7 +2233,7 @@
 					n += r;
 			}
 		}
-		readed_for_parse = n;
+		chars_to_parse = n;
 	}
 	c = readbuffer[0];
 	if (c == 27 && n > 1) {
@@ -2256,7 +2261,7 @@
 		n = 1;
 	}
 	// remove key sequence from Q
-	readed_for_parse -= n;
+	chars_to_parse -= n;
 	memmove(readbuffer, readbuffer + n, MAX_LINELEN - n);
 	alarm(3);	// we are done waiting for input, turn alarm ON
 	return c;
@@ -2265,7 +2270,7 @@
 //----- IO Routines --------------------------------------------
 static char get_one_char(void)
 {
-	static char c;
+	char c;
 
 #if ENABLE_FEATURE_VI_DOT_CMD
 	// ! adding2q  && ioq == 0  read()
@@ -2290,7 +2295,7 @@
 	} else {
 		// adding STDIN chars to q
 		c = readit();	// get the users input
-		if (last_modifying_cmd != 0) {
+		if (last_modifying_cmd != NULL) {
 			int len = strlen(last_modifying_cmd);
 			if (len >= MAX_LINELEN - 1) {
 				psbs("last_modifying_cmd overrun");
@@ -2303,17 +2308,18 @@
 #else
 	c = readit();		// get the users input
 #endif /* FEATURE_VI_DOT_CMD */
-	return c;			// return the char, where ever it came from
+	return c;
 }
 
 static char *get_input_line(const char * prompt) // get input line- use "status line"
 {
-	static char *obufp;
+	static char *buf; // [MAX_LINELEN]
 
-	char buf[MAX_LINELEN];
 	char c;
 	int i;
 
+	if (!buf) buf = xmalloc(MAX_LINELEN);
+
 	strcpy(buf, prompt);
 	last_status_cksum = 0;	// force status update
 	place_cursor(rows - 1, 0, FALSE);	// go to Status line, bottom of screen
@@ -2329,7 +2335,7 @@
 			// user wants to erase prev char
 			i--;		// backup to prev char
 			buf[i] = '\0';	// erase the char
-			buf[i + 1] = '\0';	// null terminate buffer
+			//buf[i + 1] = '\0';	// null terminate buffer
 			write1("\b \b");     // erase char on screen
 			if (i <= 0) {	// user backs up before b-o-l, exit
 				break;
@@ -2342,9 +2348,7 @@
 		}
 	}
 	refresh(FALSE);
-	free(obufp);
-	obufp = xstrdup(buf);
-	return obufp;
+	return buf;
 }
 
 static int file_size(const char *fn) // what is the byte size of "fn"
@@ -2434,12 +2438,11 @@
 		return -2;
 	}
 	charcnt = 0;
-	// FIXIT- use the correct umask()
-	fd = open(fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664);
+	fd = open(fn, (O_WRONLY | O_CREAT | O_TRUNC), 0666);
 	if (fd < 0)
 		return -1;
 	cnt = last - first + 1;
-	charcnt = write(fd, first, cnt);
+	charcnt = full_write(fd, first, cnt);
 	if (charcnt == cnt) {
 		// good write
 		//file_modified = FALSE; // the file has not been modified
@@ -2459,23 +2462,14 @@
 //  .       ...     .
 //  .       ...     .
 //  22,0    ...     22,79
-//  23,0    ...     23,79   status line
-//
+//  23,0    ...     23,79   <- status line
 
 //----- Move the cursor to row x col (count from 0, not 1) -------
-static void place_cursor(int row, int col, int opti)
+static void place_cursor(int row, int col, int optimize)
 {
-	char cm1[MAX_LINELEN];
+	char cm1[32];
 	char *cm;
-#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
-	char cm2[MAX_LINELEN];
-	char *screenp;
-	// char cm3[MAX_LINELEN];
-	int Rrow = last_row;
-#endif
 
-	memset(cm1, '\0', MAX_LINELEN);  // clear the buffer
-
 	if (row < 0) row = 0;
 	if (row >= rows) row = rows - 1;
 	if (col < 0) col = 0;
@@ -2484,45 +2478,42 @@
 	//----- 1.  Try the standard terminal ESC sequence
 	sprintf(cm1, CMrc, row + 1, col + 1);
 	cm = cm1;
-	if (!opti)
-		goto pc0;
 
 #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
-	//----- find the minimum # of chars to move cursor -------------
-	//----- 2.  Try moving with discreet chars (Newline, [back]space, ...)
-	memset(cm2, '\0', MAX_LINELEN);  // clear the buffer
+	if (optimize && col < 16) {
+		char cm2[MAX_LINELEN]; // better size estimate?
+		char *screenp;
+		int Rrow = last_row;
 
-	// move to the correct row
-	while (row < Rrow) {
-		// the cursor has to move up
-		strcat(cm2, CMup);
-		Rrow--;
-	}
-	while (row > Rrow) {
-		// the cursor has to move down
-		strcat(cm2, CMdown);
-		Rrow++;
-	}
+		//----- find the minimum # of chars to move cursor -------------
+		//----- 2.  Try moving with discreet chars (Newline, [back]space, ...)
+		cm2[0] = '\0';
 
-	// now move to the correct column
-	strcat(cm2, "\r");			// start at col 0
-	// just send out orignal source char to get to correct place
-	screenp = &screen[row * columns];	// start of screen line
-	strncat(cm2, screenp, col);
+		// move to the correct row
+		while (row < Rrow) {
+			// the cursor has to move up
+			strcat(cm2, CMup);
+			Rrow--;
+		}
+		while (row > Rrow) {
+			// the cursor has to move down
+			strcat(cm2, CMdown);
+			Rrow++;
+		}
 
-	//----- 3.  Try some other way of moving cursor
-	//---------------------------------------------
+		// now move to the correct column
+		strcat(cm2, "\r");			// start at col 0
+		// just send out orignal source char to get to correct place
+		screenp = &screen[row * columns];	// start of screen line
+		strncat(cm2, screenp, col);
 
-	// pick the shortest cursor motion to send out
-	cm = cm1;
-	if (strlen(cm2) < strlen(cm)) {
-		cm = cm2;
-	}  /* else if (strlen(cm3) < strlen(cm)) {
-		cm= cm3;
-	} */
+		// pick the shortest cursor motion to send out
+		if (strlen(cm2) < strlen(cm)) {
+			cm = cm2;
+		}
+	}
 #endif /* FEATURE_VI_OPTIMIZE_CURSOR */
- pc0:
-	write1(cm);                 // move the cursor
+	write1(cm);
 }
 
 //----- Erase from cursor to end of line -----------------------
@@ -2721,11 +2712,15 @@
 }
 
 //----- Format a text[] line into a buffer ---------------------
-static void format_line(char *dest, char *src, int li)
+// Returns number of leading chars which should be ignored
+// (return value is always <= offset)
+static int format_line(char *dest, char *src, int li)
 {
+	char c;
 	int co;
-	char c;
+	int ofs = offset;
 
+	memset(dest, ' ', MAX_SCR_COLS);
 	for (co = 0; co < MAX_SCR_COLS; co++) {
 		c = ' ';		// assume blank
 		if (li > 0 && co == 0) {
@@ -2734,33 +2729,52 @@
 		// are there chars in text[] and have we gone past the end
 		if (text < end && src < end) {
 			c = *src++;
-		}
-		if (c == '\n')
-			break;
-		if ((c & 0x80) && !Isprint(c)) {
-			c = '.';
-		}
-		if ((unsigned char)(c) < ' ' || c == 0x7f) {
-			if (c == '\t') {
-				c = ' ';
-				//       co %    8     !=     7
-				for (; (co % tabstop) != (tabstop - 1); co++) {
-					dest[co] = c;
+
+			if (c == '\n')
+				break;
+			if ((c & 0x80) && !Isprint(c)) {
+				c = '.';
+			}
+			if ((unsigned char)(c) < ' ' || c == 0x7f) {
+				if (c == '\t') {
+					c = ' ';
+					//      co %    8     !=     7
+					while ((co % tabstop) != (tabstop - 1)) {
+						dest[co++] = c;
+						if (co >= MAX_SCR_COLS)
+							goto ret;
+					}
+				} else {
+					dest[co++] = '^';
+					if (co >= MAX_SCR_COLS)
+						goto ret;
+					if (c == 0x7f)
+						c = '?';
+					else
+						c += '@';       // make it visible
 				}
-			} else {
-				dest[co++] = '^';
-				if (c == 0x7f)
-					c = '?';
-				else
-					c += '@';       // make it visible
 			}
 		}
 		// the co++ is done here so that the column will
 		// not be overwritten when we blank-out the rest of line
 		dest[co] = c;
+		// discard scrolled-off portion, in tabstop-sized pieces
+		if (ofs >= tabstop && co >= tabstop) {
+			co -= tabstop;
+			ofs -= tabstop;
+			memset(&dest[co + 1], ' ', tabstop);
+		}
 		if (src >= end)
 			break;
 	}
+ ret:
+	if (co < ofs) {
+		// entire line has scrolled off, make it entirely blank
+		memset(dest, ' ', MAX_SCR_COLS);
+		ofs = 0;
+	}
+	dest[MAX_SCR_COLS-1] = '\0';
+	return ofs;
 }
 
 //----- Refresh the changed screen lines -----------------------
@@ -2786,19 +2800,19 @@
 
 	// compare text[] to screen[] and mark screen[] lines that need updating
 	for (li = 0; li < rows - 1; li++) {
+		int ofs;
 		int cs, ce;				// column start & end
-		memset(buf, ' ', MAX_SCR_COLS);		// blank-out the buffer
-		buf[MAX_SCR_COLS-1] = 0;		// NULL terminate the buffer
 		// format current text line into buf
-		format_line(buf, tp, li);
+		ofs = format_line(buf, tp, li);
 
 		// skip to the end of the current text[] line
-		while (tp < end && *tp++ != '\n') /*no-op*/;
+		while (tp < end && *tp++ != '\n')
+			continue;
 
 		// see if there are any changes between vitual screen and buf
 		changed = FALSE;	// assume no change
-		cs= 0;
-		ce= columns-1;
+		cs = 0;
+		ce = columns - 1;
 		sp = &screen[li * columns];	// start of screen line
 		if (full_screen) {
 			// force re-draw of every single column from 0 - columns-1
@@ -2807,15 +2821,15 @@
 		// compare newly formatted buffer with virtual screen
 		// look forward for first difference between buf and screen
 		for (; cs <= ce; cs++) {
-			if (buf[cs + offset] != sp[cs]) {
+			if (buf[cs + ofs] != sp[cs]) {
 				changed = TRUE;	// mark for redraw
 				break;
 			}
 		}
 
 		// look backward for last difference between buf and screen
-		for ( ; ce >= cs; ce--) {
-			if (buf[ce + offset] != sp[ce]) {
+		for (; ce >= cs; ce--) {
+			if (buf[ce + ofs] != sp[ce]) {
 				changed = TRUE;	// mark for redraw
 				break;
 			}
@@ -2829,13 +2843,13 @@
 		}
 
 		// make a sanity check of columns indexes
-		if (cs < 0) cs= 0;
-		if (ce > columns-1) ce= columns-1;
-		if (cs > ce) {  cs= 0;  ce= columns-1;  }
+		if (cs < 0) cs = 0;
+		if (ce > columns - 1) ce = columns - 1;
+		if (cs > ce) { cs = 0; ce = columns - 1; }
 		// is there a change between vitual screen and buf
 		if (changed) {
-			//  copy changed part of buffer to virtual screen
-			memmove(sp+cs, buf+(cs+offset), ce-cs+1);
+			// copy changed part of buffer to virtual screen
+			memmove(sp+cs, buf+(cs+ofs), ce-cs+1);
 
 			// move cursor to column of first change
 			if (offset != old_offset) {
@@ -2848,7 +2862,7 @@
 				//  try to optimize cursor movement
 				//  otherwise, use standard ESC sequence
 				place_cursor(li, cs, li == (last_li+1) ? TRUE : FALSE);
-				last_li= li;
+				last_li = li;
 #else
 				place_cursor(li, cs, FALSE);	// use standard ESC sequence
 #endif /* FEATURE_VI_OPTIMIZE_CURSOR */
@@ -2859,7 +2873,7 @@
 				int nic = ce - cs + 1;
 				char *out = sp + cs;
 
-				while (nic-- > 0) {
+				while (--nic >= 0) {
 					bb_putchar(*out);
 					out++;
 				}
@@ -2877,8 +2891,7 @@
 	place_cursor(crow, ccol, FALSE);
 #endif
 
-	if (offset != old_offset)
-		old_offset = offset;
+	old_offset = offset;
 }
 
 //---------------------------------------------------------------------
@@ -3230,7 +3243,7 @@
 	case '.':			// .- repeat the last modifying command
 		// Stuff the last_modifying_cmd back into stdin
 		// and let it be re-executed.
-		if (last_modifying_cmd != 0) {
+		if (last_modifying_cmd != NULL) {
 			ioq = ioq_start = xstrdup(last_modifying_cmd);
 		}
 		break;
@@ -3844,7 +3857,7 @@
 	cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL";
 
 	// is there already a command running?
-	if (readed_for_parse > 0)
+	if (chars_to_parse > 0)
 		goto cd1;
  cd0:
 	startrbi = rbi = 0;
@@ -3921,7 +3934,7 @@
 		}
 		strcat(readbuffer, "\033");
 	}
-	readed_for_parse = strlen(readbuffer);
+	chars_to_parse = strlen(readbuffer);
  cd1:
 	totalcmds++;
 	if (sleeptime > 0)




More information about the busybox-cvs mailing list