diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-20 08:59:03 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-20 08:59:03 +0000 |
commit | 4c9e9c4314e6f997f37814fffc6b49ebd24bd6be (patch) | |
tree | 5df6ccef20e28a939ee1a1cebcb60ee1b4f94c7b | |
parent | 078323010b5d88485748d05e512d451b876992b5 (diff) | |
download | busybox-w32-4c9e9c4314e6f997f37814fffc6b49ebd24bd6be.tar.gz busybox-w32-4c9e9c4314e6f997f37814fffc6b49ebd24bd6be.tar.bz2 busybox-w32-4c9e9c4314e6f997f37814fffc6b49ebd24bd6be.zip |
vi: handle chars 0x80, 0x81... correctly
-rw-r--r-- | editors/vi.c | 125 |
1 files changed, 64 insertions, 61 deletions
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 { | |||
57 | MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, | 57 | MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | // Misc. non-Ascii keys that report an escape sequence | 60 | // "Keycodes" that report an escape sequence. |
61 | #define VI_K_UP (char)128 // cursor key Up | 61 | // We use something which fits into signed char, |
62 | #define VI_K_DOWN (char)129 // cursor key Down | 62 | // yet doesn't represent any valid Unicode characher. |
63 | #define VI_K_RIGHT (char)130 // Cursor Key Right | 63 | enum { |
64 | #define VI_K_LEFT (char)131 // cursor key Left | 64 | VI_K_UP = -1, // cursor key Up |
65 | #define VI_K_HOME (char)132 // Cursor Key Home | 65 | VI_K_DOWN = -2, // cursor key Down |
66 | #define VI_K_END (char)133 // Cursor Key End | 66 | VI_K_RIGHT = -3, // Cursor Key Right |
67 | #define VI_K_INSERT (char)134 // Cursor Key Insert | 67 | VI_K_LEFT = -4, // cursor key Left |
68 | #define VI_K_DELETE (char)135 // Cursor Key Insert | 68 | VI_K_HOME = -5, // Cursor Key Home |
69 | #define VI_K_PAGEUP (char)136 // Cursor Key Page Up | 69 | VI_K_END = -6, // Cursor Key End |
70 | #define VI_K_PAGEDOWN (char)137 // Cursor Key Page Down | 70 | VI_K_INSERT = -7, // Cursor Key Insert |
71 | #define VI_K_FUN1 (char)138 // Function Key F1 | 71 | VI_K_DELETE = -8, // Cursor Key Insert |
72 | #define VI_K_FUN2 (char)139 // Function Key F2 | 72 | VI_K_PAGEUP = -9, // Cursor Key Page Up |
73 | #define VI_K_FUN3 (char)140 // Function Key F3 | 73 | VI_K_PAGEDOWN = -10, // Cursor Key Page Down |
74 | #define VI_K_FUN4 (char)141 // Function Key F4 | 74 | VI_K_FUN1 = -11, // Function Key F1 |
75 | #define VI_K_FUN5 (char)142 // Function Key F5 | 75 | VI_K_FUN2 = -12, // Function Key F2 |
76 | #define VI_K_FUN6 (char)143 // Function Key F6 | 76 | VI_K_FUN3 = -13, // Function Key F3 |
77 | #define VI_K_FUN7 (char)144 // Function Key F7 | 77 | VI_K_FUN4 = -14, // Function Key F4 |
78 | #define VI_K_FUN8 (char)145 // Function Key F8 | 78 | VI_K_FUN5 = -15, // Function Key F5 |
79 | #define VI_K_FUN9 (char)146 // Function Key F9 | 79 | VI_K_FUN6 = -16, // Function Key F6 |
80 | #define VI_K_FUN10 (char)147 // Function Key F10 | 80 | VI_K_FUN7 = -17, // Function Key F7 |
81 | #define VI_K_FUN11 (char)148 // Function Key F11 | 81 | VI_K_FUN8 = -18, // Function Key F8 |
82 | #define VI_K_FUN12 (char)149 // Function Key F12 | 82 | VI_K_FUN9 = -19, // Function Key F9 |
83 | VI_K_FUN10 = -20, // Function Key F10 | ||
84 | VI_K_FUN11 = -21, // Function Key F11 | ||
85 | VI_K_FUN12 = -22, // Function Key F12 | ||
86 | }; | ||
83 | 87 | ||
84 | /* vt102 typical ESC sequence */ | 88 | /* vt102 typical ESC sequence */ |
85 | /* terminal standout start/normal ESC sequence */ | 89 | /* terminal standout start/normal ESC sequence */ |
@@ -171,9 +175,9 @@ struct globals { | |||
171 | char *screen; // pointer to the virtual screen buffer | 175 | char *screen; // pointer to the virtual screen buffer |
172 | int screensize; // and its size | 176 | int screensize; // and its size |
173 | int tabstop; | 177 | int tabstop; |
178 | int last_forward_char; // last char searched for with 'f' (int because of Unicode) | ||
174 | char erase_char; // the users erase character | 179 | char erase_char; // the users erase character |
175 | char last_input_char; // last char read from user | 180 | char last_input_char; // last char read from user |
176 | char last_forward_char; // last char searched for with 'f' | ||
177 | 181 | ||
178 | #if ENABLE_FEATURE_VI_DOT_CMD | 182 | #if ENABLE_FEATURE_VI_DOT_CMD |
179 | smallint adding2q; // are we currently adding user input to q | 183 | smallint adding2q; // are we currently adding user input to q |
@@ -298,7 +302,7 @@ struct globals { | |||
298 | 302 | ||
299 | static int init_text_buffer(char *); // init from file or create new | 303 | static int init_text_buffer(char *); // init from file or create new |
300 | static void edit_file(char *); // edit one file | 304 | static void edit_file(char *); // edit one file |
301 | static void do_cmd(char); // execute a command | 305 | static void do_cmd(int); // execute a command |
302 | static int next_tabstop(int); | 306 | static int next_tabstop(int); |
303 | static void sync_cursor(char *, int *, int *); // synchronize the screen cursor to dot | 307 | static void sync_cursor(char *, int *, int *); // synchronize the screen cursor to dot |
304 | static char *begin_line(char *); // return pointer to cur line B-o-l | 308 | 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 | |||
334 | static void cookmode(void); // return to "cooked" mode on tty | 338 | static void cookmode(void); // return to "cooked" mode on tty |
335 | // sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready) | 339 | // sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready) |
336 | static int mysleep(int); | 340 | static int mysleep(int); |
337 | static char readit(void); // read (maybe cursor) key from stdin | 341 | static int readit(void); // read (maybe cursor) key from stdin |
338 | static char get_one_char(void); // read 1 char from stdin | 342 | static int get_one_char(void); // read 1 char from stdin |
339 | static int file_size(const char *); // what is the byte size of "fn" | 343 | static int file_size(const char *); // what is the byte size of "fn" |
340 | #if ENABLE_FEATURE_VI_READONLY | 344 | #if ENABLE_FEATURE_VI_READONLY |
341 | static int file_insert(const char *, char *, int); | 345 | static int file_insert(const char *, char *, int); |
@@ -524,7 +528,7 @@ static void edit_file(char *fn) | |||
524 | #if ENABLE_FEATURE_VI_YANKMARK | 528 | #if ENABLE_FEATURE_VI_YANKMARK |
525 | #define cur_line edit_file__cur_line | 529 | #define cur_line edit_file__cur_line |
526 | #endif | 530 | #endif |
527 | char c; | 531 | int c; |
528 | int size; | 532 | int size; |
529 | #if ENABLE_FEATURE_VI_USE_SIGNALS | 533 | #if ENABLE_FEATURE_VI_USE_SIGNALS |
530 | int sig; | 534 | int sig; |
@@ -622,8 +626,10 @@ static void edit_file(char *fn) | |||
622 | // These are commands that change text[]. | 626 | // These are commands that change text[]. |
623 | // Remember the input for the "." command | 627 | // Remember the input for the "." command |
624 | if (!adding2q && ioq_start == NULL | 628 | if (!adding2q && ioq_start == NULL |
625 | && cmd_mode == 0 /* command mode */ | 629 | && cmd_mode == 0 // command mode |
626 | && c != '\0' && strchr(modifying_cmds, c) | 630 | && c > '\0' // exclude NUL and non-ASCII chars |
631 | && c < 0x7f // (Unicode and such) | ||
632 | && strchr(modifying_cmds, c) | ||
627 | ) { | 633 | ) { |
628 | start_new_cmd_q(c); | 634 | start_new_cmd_q(c); |
629 | } | 635 | } |
@@ -1198,7 +1204,7 @@ static void colon(char *buf) | |||
1198 | 1204 | ||
1199 | static void Hit_Return(void) | 1205 | static void Hit_Return(void) |
1200 | { | 1206 | { |
1201 | char c; | 1207 | int c; |
1202 | 1208 | ||
1203 | standout_start(); | 1209 | standout_start(); |
1204 | write1("[Hit return to continue]"); | 1210 | write1("[Hit return to continue]"); |
@@ -2191,15 +2197,15 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds | |||
2191 | } | 2197 | } |
2192 | 2198 | ||
2193 | //----- IO Routines -------------------------------------------- | 2199 | //----- IO Routines -------------------------------------------- |
2194 | static char readit(void) // read (maybe cursor) key from stdin | 2200 | static int readit(void) // read (maybe cursor) key from stdin |
2195 | { | 2201 | { |
2196 | char c; | 2202 | int c; |
2197 | int n; | 2203 | int n; |
2198 | 2204 | ||
2199 | // Known escape sequences for cursor and function keys. | 2205 | // Known escape sequences for cursor and function keys. |
2200 | static const struct esc_cmds { | 2206 | static const struct esc_cmds { |
2201 | const char seq[4]; | 2207 | const char seq[4]; |
2202 | char val; //TODO: int? Need to make it at least 8-bit clean! | 2208 | signed char val; |
2203 | } esccmds[] = { | 2209 | } esccmds[] = { |
2204 | {"OA" , VI_K_UP }, // Cursor Key Up | 2210 | {"OA" , VI_K_UP }, // Cursor Key Up |
2205 | {"OB" , VI_K_DOWN }, // Cursor Key Down | 2211 | {"OB" , VI_K_DOWN }, // Cursor Key Down |
@@ -2256,7 +2262,7 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2256 | } | 2262 | } |
2257 | 2263 | ||
2258 | // Grab character to return from buffer | 2264 | // Grab character to return from buffer |
2259 | c = readbuffer[0]; | 2265 | c = (unsigned char)readbuffer[0]; |
2260 | // Returning NUL from this routine would be bad. | 2266 | // Returning NUL from this routine would be bad. |
2261 | if (c == '\0') | 2267 | if (c == '\0') |
2262 | c = ' '; | 2268 | c = ' '; |
@@ -2302,7 +2308,7 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2302 | break; // try next seq | 2308 | break; // try next seq |
2303 | i++; | 2309 | i++; |
2304 | if (i == 4 || !eindex->seq[i]) { // entire seq matched | 2310 | if (i == 4 || !eindex->seq[i]) { // entire seq matched |
2305 | c = eindex->val; | 2311 | c = eindex->val; // sign extended! |
2306 | n = 0; | 2312 | n = 0; |
2307 | // n -= i; memmove(...); | 2313 | // n -= i; memmove(...); |
2308 | // would be more correct, | 2314 | // would be more correct, |
@@ -2322,9 +2328,9 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2322 | } | 2328 | } |
2323 | 2329 | ||
2324 | //----- IO Routines -------------------------------------------- | 2330 | //----- IO Routines -------------------------------------------- |
2325 | static char get_one_char(void) | 2331 | static int get_one_char(void) |
2326 | { | 2332 | { |
2327 | char c; | 2333 | int c; |
2328 | 2334 | ||
2329 | #if ENABLE_FEATURE_VI_DOT_CMD | 2335 | #if ENABLE_FEATURE_VI_DOT_CMD |
2330 | if (!adding2q) { | 2336 | if (!adding2q) { |
@@ -2335,7 +2341,8 @@ static char get_one_char(void) | |||
2335 | c = readit(); // get the users input | 2341 | c = readit(); // get the users input |
2336 | } else { | 2342 | } else { |
2337 | // there is a queue to get chars from first | 2343 | // there is a queue to get chars from first |
2338 | c = *ioq++; | 2344 | // careful with correct sign expansion! |
2345 | c = (unsigned char)*ioq++; | ||
2339 | if (c == '\0') { | 2346 | if (c == '\0') { |
2340 | // the end of the q, read from STDIN | 2347 | // the end of the q, read from STDIN |
2341 | free(ioq_start); | 2348 | free(ioq_start); |
@@ -2365,7 +2372,7 @@ static char *get_input_line(const char *prompt) | |||
2365 | // char [MAX_INPUT_LEN] | 2372 | // char [MAX_INPUT_LEN] |
2366 | #define buf get_input_line__buf | 2373 | #define buf get_input_line__buf |
2367 | 2374 | ||
2368 | char c; | 2375 | int c; |
2369 | int i; | 2376 | int i; |
2370 | 2377 | ||
2371 | strcpy(buf, prompt); | 2378 | strcpy(buf, prompt); |
@@ -2384,7 +2391,8 @@ static char *get_input_line(const char *prompt) | |||
2384 | write1("\b \b"); // erase char on screen | 2391 | write1("\b \b"); // erase char on screen |
2385 | if (i <= 0) // user backs up before b-o-l, exit | 2392 | if (i <= 0) // user backs up before b-o-l, exit |
2386 | break; | 2393 | break; |
2387 | } else { | 2394 | } else if (c > 0 && c < 256) { // exclude Unicode |
2395 | // (TODO: need to handle Unicode) | ||
2388 | buf[i] = c; | 2396 | buf[i] = c; |
2389 | buf[++i] = '\0'; | 2397 | buf[++i] = '\0'; |
2390 | bb_putchar(c); | 2398 | bb_putchar(c); |
@@ -2987,13 +2995,14 @@ static void refresh(int full_screen) | |||
2987 | //--------------------------------------------------------------------- | 2995 | //--------------------------------------------------------------------- |
2988 | 2996 | ||
2989 | //----- Execute a Vi Command ----------------------------------- | 2997 | //----- Execute a Vi Command ----------------------------------- |
2990 | static void do_cmd(char c) | 2998 | static void do_cmd(int c) |
2991 | { | 2999 | { |
2992 | const char *msg = msg; // for compiler | 3000 | const char *msg = msg; // for compiler |
2993 | char c1, *p, *q, *save_dot; | 3001 | char *p, *q, *save_dot; |
2994 | char buf[12]; | 3002 | char buf[12]; |
2995 | int dir = dir; // for compiler | 3003 | int dir = dir; // for compiler |
2996 | int cnt, i, j; | 3004 | int cnt, i, j; |
3005 | int c1; | ||
2997 | 3006 | ||
2998 | // c1 = c; // quiet the compiler | 3007 | // c1 = c; // quiet the compiler |
2999 | // cnt = yf = 0; // quiet the compiler | 3008 | // cnt = yf = 0; // quiet the compiler |
@@ -3173,21 +3182,18 @@ static void do_cmd(char c) | |||
3173 | break; | 3182 | break; |
3174 | #if ENABLE_FEATURE_VI_YANKMARK | 3183 | #if ENABLE_FEATURE_VI_YANKMARK |
3175 | case '"': // "- name a register to use for Delete/Yank | 3184 | case '"': // "- name a register to use for Delete/Yank |
3176 | c1 = get_one_char(); | 3185 | c1 = (get_one_char() | 0x20) - 'a'; // | 0x20 is tolower() |
3177 | c1 = tolower(c1); | 3186 | if ((unsigned)c1 <= 25) { // a-z? |
3178 | if (islower(c1)) { | 3187 | YDreg = c1; |
3179 | YDreg = c1 - 'a'; | ||
3180 | } else { | 3188 | } else { |
3181 | indicate_error(c); | 3189 | indicate_error(c); |
3182 | } | 3190 | } |
3183 | break; | 3191 | break; |
3184 | case '\'': // '- goto a specific mark | 3192 | case '\'': // '- goto a specific mark |
3185 | c1 = get_one_char(); | 3193 | c1 = (get_one_char() | 0x20) - 'a'; |
3186 | c1 = tolower(c1); | 3194 | if ((unsigned)c1 <= 25) { // a-z? |
3187 | if (islower(c1)) { | ||
3188 | c1 = c1 - 'a'; | ||
3189 | // get the b-o-l | 3195 | // get the b-o-l |
3190 | q = mark[(unsigned char) c1]; | 3196 | q = mark[c1]; |
3191 | if (text <= q && q < end) { | 3197 | if (text <= q && q < end) { |
3192 | dot = q; | 3198 | dot = q; |
3193 | dot_begin(); // go to B-o-l | 3199 | dot_begin(); // go to B-o-l |
@@ -3206,12 +3212,10 @@ static void do_cmd(char c) | |||
3206 | // between text[0] and dot then this mark will not point to the | 3212 | // between text[0] and dot then this mark will not point to the |
3207 | // correct location! It could be off by many lines! | 3213 | // correct location! It could be off by many lines! |
3208 | // Well..., at least its quick and dirty. | 3214 | // Well..., at least its quick and dirty. |
3209 | c1 = get_one_char(); | 3215 | c1 = (get_one_char() | 0x20) - 'a'; |
3210 | c1 = tolower(c1); | 3216 | if ((unsigned)c1 <= 25) { // a-z? |
3211 | if (islower(c1)) { | ||
3212 | c1 = c1 - 'a'; | ||
3213 | // remember the line | 3217 | // remember the line |
3214 | mark[(int) c1] = dot; | 3218 | mark[c1] = dot; |
3215 | } else { | 3219 | } else { |
3216 | indicate_error(c); | 3220 | indicate_error(c); |
3217 | } | 3221 | } |
@@ -3546,12 +3550,11 @@ static void do_cmd(char c) | |||
3546 | end_cmd_q(); // stop adding to q | 3550 | end_cmd_q(); // stop adding to q |
3547 | #endif | 3551 | #endif |
3548 | break; | 3552 | break; |
3549 | case 'g': // 'gg' goto a line number (from vim) | 3553 | case 'g': // 'gg' goto a line number (vim) (default: very first line) |
3550 | // (default to first line in file) | ||
3551 | c1 = get_one_char(); | 3554 | c1 = get_one_char(); |
3552 | if (c1 != 'g') { | 3555 | if (c1 != 'g') { |
3553 | buf[0] = 'g'; | 3556 | buf[0] = 'g'; |
3554 | buf[1] = c1; | 3557 | buf[1] = c1; // TODO: if Unicode? |
3555 | buf[2] = '\0'; | 3558 | buf[2] = '\0'; |
3556 | not_implemented(buf); | 3559 | not_implemented(buf); |
3557 | break; | 3560 | break; |
@@ -3804,7 +3807,7 @@ static void do_cmd(char c) | |||
3804 | do_cmd(';'); | 3807 | do_cmd(';'); |
3805 | if (*dot == last_forward_char) | 3808 | if (*dot == last_forward_char) |
3806 | dot_left(); | 3809 | dot_left(); |
3807 | last_forward_char= 0; | 3810 | last_forward_char = 0; |
3808 | break; | 3811 | break; |
3809 | case 'w': // w- forward a word | 3812 | case 'w': // w- forward a word |
3810 | if (cmdcnt-- > 1) { | 3813 | if (cmdcnt-- > 1) { |