vi: fix a problem with displaying overlong lines
This commit is contained in:
parent
619879246d
commit
26b6fba9d3
231
editors/vi.c
231
editors/vi.c
@ -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 fn_start; // index of first cmd line file name
|
||||
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 *, int);
|
||||
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 psbs(const char *, ...); // Print Status Buf in standout mode
|
||||
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 @@ static void colon(char * buf)
|
||||
/* 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 @@ static char *end_line(char * p) // return pointer to NL of cur line line
|
||||
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 void show_help(void)
|
||||
);
|
||||
}
|
||||
|
||||
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 void check_context(char cmd)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds
|
||||
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 @@ static char readit(void) // read (maybe cursor) key from stdin
|
||||
|
||||
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 @@ static char readit(void) // read (maybe cursor) key from stdin
|
||||
n += r;
|
||||
}
|
||||
}
|
||||
readed_for_parse = n;
|
||||
chars_to_parse = n;
|
||||
}
|
||||
c = readbuffer[0];
|
||||
if (c == 27 && n > 1) {
|
||||
@ -2256,7 +2261,7 @@ static char readit(void) // read (maybe cursor) key from stdin
|
||||
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 @@ static char readit(void) // read (maybe cursor) key from stdin
|
||||
//----- 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 @@ static char get_one_char(void)
|
||||
} 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 @@ static char get_one_char(void)
|
||||
#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 @@ static char *get_input_line(const char * prompt) // get input line- use "status
|
||||
// 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 @@ static char *get_input_line(const char * prompt) // get input line- use "status
|
||||
}
|
||||
}
|
||||
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 @@ static int file_write(char * fn, char * first, char * last)
|
||||
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,22 +2462,13 @@ static int file_write(char * fn, char * first, char * last)
|
||||
// . ... .
|
||||
// . ... .
|
||||
// 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;
|
||||
@ -2484,45 +2478,42 @@ static void place_cursor(int row, int col, int opti)
|
||||
//----- 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--;
|
||||
//----- find the minimum # of chars to move cursor -------------
|
||||
//----- 2. Try moving with discreet chars (Newline, [back]space, ...)
|
||||
cm2[0] = '\0';
|
||||
|
||||
// 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++;
|
||||
}
|
||||
|
||||
// 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
|
||||
if (strlen(cm2) < strlen(cm)) {
|
||||
cm = cm2;
|
||||
}
|
||||
}
|
||||
while (row > Rrow) {
|
||||
// the cursor has to move down
|
||||
strcat(cm2, CMdown);
|
||||
Rrow++;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
//----- 3. Try some other way of moving cursor
|
||||
//---------------------------------------------
|
||||
|
||||
// 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;
|
||||
} */
|
||||
#endif /* FEATURE_VI_OPTIMIZE_CURSOR */
|
||||
pc0:
|
||||
write1(cm); // move the cursor
|
||||
write1(cm);
|
||||
}
|
||||
|
||||
//----- Erase from cursor to end of line -----------------------
|
||||
@ -2721,11 +2712,15 @@ static void redraw(int full_screen)
|
||||
}
|
||||
|
||||
//----- 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)
|
||||
{
|
||||
int co;
|
||||
char c;
|
||||
int co;
|
||||
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 @@ static void format_line(char *dest, char *src, int li)
|
||||
// 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 @@ static void refresh(int full_screen)
|
||||
|
||||
// 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 @@ static void refresh(int full_screen)
|
||||
// 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 @@ static void refresh(int full_screen)
|
||||
}
|
||||
|
||||
// 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 @@ static void refresh(int full_screen)
|
||||
// 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 @@ static void refresh(int full_screen)
|
||||
int nic = ce - cs + 1;
|
||||
char *out = sp + cs;
|
||||
|
||||
while (nic-- > 0) {
|
||||
while (--nic >= 0) {
|
||||
bb_putchar(*out);
|
||||
out++;
|
||||
}
|
||||
@ -2877,8 +2891,7 @@ static void refresh(int full_screen)
|
||||
place_cursor(crow, ccol, FALSE);
|
||||
#endif
|
||||
|
||||
if (offset != old_offset)
|
||||
old_offset = offset;
|
||||
old_offset = offset;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@ -3230,7 +3243,7 @@ static void do_cmd(char c)
|
||||
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 @@ static void crash_dummy()
|
||||
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 @@ static void crash_dummy()
|
||||
}
|
||||
strcat(readbuffer, "\033");
|
||||
}
|
||||
readed_for_parse = strlen(readbuffer);
|
||||
chars_to_parse = strlen(readbuffer);
|
||||
cd1:
|
||||
totalcmds++;
|
||||
if (sleeptime > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user