From 4c9e9c4314e6f997f37814fffc6b49ebd24bd6be Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 20 Oct 2008 08:59:03 +0000 Subject: vi: handle chars 0x80, 0x81... correctly --- editors/vi.c | 125 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 64 insertions(+), 61 deletions(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index 50dda7f3a..55154dcd7 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -57,29 +57,33 @@ enum { MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, }; -// Misc. non-Ascii keys that report an escape sequence -#define VI_K_UP (char)128 // cursor key Up -#define VI_K_DOWN (char)129 // cursor key Down -#define VI_K_RIGHT (char)130 // Cursor Key Right -#define VI_K_LEFT (char)131 // cursor key Left -#define VI_K_HOME (char)132 // Cursor Key Home -#define VI_K_END (char)133 // Cursor Key End -#define VI_K_INSERT (char)134 // Cursor Key Insert -#define VI_K_DELETE (char)135 // Cursor Key Insert -#define VI_K_PAGEUP (char)136 // Cursor Key Page Up -#define VI_K_PAGEDOWN (char)137 // Cursor Key Page Down -#define VI_K_FUN1 (char)138 // Function Key F1 -#define VI_K_FUN2 (char)139 // Function Key F2 -#define VI_K_FUN3 (char)140 // Function Key F3 -#define VI_K_FUN4 (char)141 // Function Key F4 -#define VI_K_FUN5 (char)142 // Function Key F5 -#define VI_K_FUN6 (char)143 // Function Key F6 -#define VI_K_FUN7 (char)144 // Function Key F7 -#define VI_K_FUN8 (char)145 // Function Key F8 -#define VI_K_FUN9 (char)146 // Function Key F9 -#define VI_K_FUN10 (char)147 // Function Key F10 -#define VI_K_FUN11 (char)148 // Function Key F11 -#define VI_K_FUN12 (char)149 // Function Key F12 +// "Keycodes" that report an escape sequence. +// We use something which fits into signed char, +// yet doesn't represent any valid Unicode characher. +enum { + VI_K_UP = -1, // cursor key Up + VI_K_DOWN = -2, // cursor key Down + VI_K_RIGHT = -3, // Cursor Key Right + VI_K_LEFT = -4, // cursor key Left + VI_K_HOME = -5, // Cursor Key Home + VI_K_END = -6, // Cursor Key End + VI_K_INSERT = -7, // Cursor Key Insert + VI_K_DELETE = -8, // Cursor Key Insert + VI_K_PAGEUP = -9, // Cursor Key Page Up + VI_K_PAGEDOWN = -10, // Cursor Key Page Down + VI_K_FUN1 = -11, // Function Key F1 + VI_K_FUN2 = -12, // Function Key F2 + VI_K_FUN3 = -13, // Function Key F3 + VI_K_FUN4 = -14, // Function Key F4 + VI_K_FUN5 = -15, // Function Key F5 + VI_K_FUN6 = -16, // Function Key F6 + VI_K_FUN7 = -17, // Function Key F7 + VI_K_FUN8 = -18, // Function Key F8 + VI_K_FUN9 = -19, // Function Key F9 + VI_K_FUN10 = -20, // Function Key F10 + VI_K_FUN11 = -21, // Function Key F11 + VI_K_FUN12 = -22, // Function Key F12 +}; /* vt102 typical ESC sequence */ /* terminal standout start/normal ESC sequence */ @@ -171,9 +175,9 @@ struct globals { char *screen; // pointer to the virtual screen buffer int screensize; // and its size int tabstop; + int last_forward_char; // last char searched for with 'f' (int because of Unicode) char erase_char; // the users erase character char last_input_char; // last char read from user - char last_forward_char; // last char searched for with 'f' #if ENABLE_FEATURE_VI_DOT_CMD smallint adding2q; // are we currently adding user input to q @@ -298,7 +302,7 @@ struct globals { static int init_text_buffer(char *); // init from file or create new static void edit_file(char *); // edit one file -static void do_cmd(char); // execute a command +static void do_cmd(int); // execute a command static int next_tabstop(int); static void sync_cursor(char *, int *, int *); // synchronize the screen cursor to dot static char *begin_line(char *); // return pointer to cur line B-o-l @@ -334,8 +338,8 @@ static void rawmode(void); // set "raw" mode on tty static void cookmode(void); // return to "cooked" mode on tty // sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready) static int mysleep(int); -static char readit(void); // read (maybe cursor) key from stdin -static char get_one_char(void); // read 1 char from stdin +static int readit(void); // read (maybe cursor) key from stdin +static int get_one_char(void); // read 1 char from stdin static int file_size(const char *); // what is the byte size of "fn" #if ENABLE_FEATURE_VI_READONLY static int file_insert(const char *, char *, int); @@ -524,7 +528,7 @@ static void edit_file(char *fn) #if ENABLE_FEATURE_VI_YANKMARK #define cur_line edit_file__cur_line #endif - char c; + int c; int size; #if ENABLE_FEATURE_VI_USE_SIGNALS int sig; @@ -622,8 +626,10 @@ static void edit_file(char *fn) // These are commands that change text[]. // Remember the input for the "." command if (!adding2q && ioq_start == NULL - && cmd_mode == 0 /* command mode */ - && c != '\0' && strchr(modifying_cmds, c) + && cmd_mode == 0 // command mode + && c > '\0' // exclude NUL and non-ASCII chars + && c < 0x7f // (Unicode and such) + && strchr(modifying_cmds, c) ) { start_new_cmd_q(c); } @@ -1198,7 +1204,7 @@ static void colon(char *buf) static void Hit_Return(void) { - char c; + int c; standout_start(); write1("[Hit return to continue]"); @@ -2191,15 +2197,15 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds } //----- IO Routines -------------------------------------------- -static char readit(void) // read (maybe cursor) key from stdin +static int readit(void) // read (maybe cursor) key from stdin { - char c; + int c; int n; // Known escape sequences for cursor and function keys. static const struct esc_cmds { const char seq[4]; - char val; //TODO: int? Need to make it at least 8-bit clean! + signed char val; } esccmds[] = { {"OA" , VI_K_UP }, // Cursor Key Up {"OB" , VI_K_DOWN }, // Cursor Key Down @@ -2256,7 +2262,7 @@ static char readit(void) // read (maybe cursor) key from stdin } // Grab character to return from buffer - c = readbuffer[0]; + c = (unsigned char)readbuffer[0]; // Returning NUL from this routine would be bad. if (c == '\0') c = ' '; @@ -2302,7 +2308,7 @@ static char readit(void) // read (maybe cursor) key from stdin break; // try next seq i++; if (i == 4 || !eindex->seq[i]) { // entire seq matched - c = eindex->val; + c = eindex->val; // sign extended! n = 0; // n -= i; memmove(...); // would be more correct, @@ -2322,9 +2328,9 @@ static char readit(void) // read (maybe cursor) key from stdin } //----- IO Routines -------------------------------------------- -static char get_one_char(void) +static int get_one_char(void) { - char c; + int c; #if ENABLE_FEATURE_VI_DOT_CMD if (!adding2q) { @@ -2335,7 +2341,8 @@ static char get_one_char(void) c = readit(); // get the users input } else { // there is a queue to get chars from first - c = *ioq++; + // careful with correct sign expansion! + c = (unsigned char)*ioq++; if (c == '\0') { // the end of the q, read from STDIN free(ioq_start); @@ -2365,7 +2372,7 @@ static char *get_input_line(const char *prompt) // char [MAX_INPUT_LEN] #define buf get_input_line__buf - char c; + int c; int i; strcpy(buf, prompt); @@ -2384,7 +2391,8 @@ static char *get_input_line(const char *prompt) write1("\b \b"); // erase char on screen if (i <= 0) // user backs up before b-o-l, exit break; - } else { + } else if (c > 0 && c < 256) { // exclude Unicode + // (TODO: need to handle Unicode) buf[i] = c; buf[++i] = '\0'; bb_putchar(c); @@ -2987,13 +2995,14 @@ static void refresh(int full_screen) //--------------------------------------------------------------------- //----- Execute a Vi Command ----------------------------------- -static void do_cmd(char c) +static void do_cmd(int c) { const char *msg = msg; // for compiler - char c1, *p, *q, *save_dot; + char *p, *q, *save_dot; char buf[12]; int dir = dir; // for compiler int cnt, i, j; + int c1; // c1 = c; // quiet the compiler // cnt = yf = 0; // quiet the compiler @@ -3173,21 +3182,18 @@ static void do_cmd(char c) break; #if ENABLE_FEATURE_VI_YANKMARK case '"': // "- name a register to use for Delete/Yank - c1 = get_one_char(); - c1 = tolower(c1); - if (islower(c1)) { - YDreg = c1 - 'a'; + c1 = (get_one_char() | 0x20) - 'a'; // | 0x20 is tolower() + if ((unsigned)c1 <= 25) { // a-z? + YDreg = c1; } else { indicate_error(c); } break; case '\'': // '- goto a specific mark - c1 = get_one_char(); - c1 = tolower(c1); - if (islower(c1)) { - c1 = c1 - 'a'; + c1 = (get_one_char() | 0x20) - 'a'; + if ((unsigned)c1 <= 25) { // a-z? // get the b-o-l - q = mark[(unsigned char) c1]; + q = mark[c1]; if (text <= q && q < end) { dot = q; dot_begin(); // go to B-o-l @@ -3206,12 +3212,10 @@ static void do_cmd(char c) // between text[0] and dot then this mark will not point to the // correct location! It could be off by many lines! // Well..., at least its quick and dirty. - c1 = get_one_char(); - c1 = tolower(c1); - if (islower(c1)) { - c1 = c1 - 'a'; + c1 = (get_one_char() | 0x20) - 'a'; + if ((unsigned)c1 <= 25) { // a-z? // remember the line - mark[(int) c1] = dot; + mark[c1] = dot; } else { indicate_error(c); } @@ -3546,12 +3550,11 @@ static void do_cmd(char c) end_cmd_q(); // stop adding to q #endif break; - case 'g': // 'gg' goto a line number (from vim) - // (default to first line in file) + case 'g': // 'gg' goto a line number (vim) (default: very first line) c1 = get_one_char(); if (c1 != 'g') { buf[0] = 'g'; - buf[1] = c1; + buf[1] = c1; // TODO: if Unicode? buf[2] = '\0'; not_implemented(buf); break; @@ -3804,7 +3807,7 @@ static void do_cmd(char c) do_cmd(';'); if (*dot == last_forward_char) dot_left(); - last_forward_char= 0; + last_forward_char = 0; break; case 'w': // w- forward a word if (cmdcnt-- > 1) { -- cgit v1.2.3