diff --git a/ChangeLog b/ChangeLog index 39a4f04fae6996e2f5fa2ab090ee9e0750106d56..6fc29c9d2e5964611f6a20d7056d61be1819830f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,21 +34,20 @@ CVS code - properly again. (DLR, found by Arthur Ivanov) - Massively overhaul the input and output routines to support buffered input and output, the first steps toward - wide/multibyte character input and output, and - double-Escape/verbatim input of double-byte Unicode characters - instead of single-byte ASCII characters. New functions - is_byte_char(), get_buffer(), get_buffer_len(), - buffer_to_keys(), unget_input(), get_input(), parse_kbinput(), - and parse_verbatim_kbinput(); new macro charcpy(); changes to - do_char() (renamed to do_output()), get_edit_input() (renamed - to do_input() and moved to nano.c), get_edit_mouse() (renamed - do_mouse() and moved to nano.c), do_verbatim_input(), - do_tab(), main(), and get_ascii_kbinput() (renamed to - get_word_kbinput()). The wide version of ncurses is required - in order for wide/multibyte input and output to work properly. - (DLR; buffered input/output based on ideas from mutt 1.4.2.1; - double-Escape input of Unicode characters suggested by Michael - Piefel) + wide/multibyte character input and output, and verbatim input + of double-byte Unicode characters instead of single-byte ASCII + characters. New functions is_byte_char(), get_buffer(), + get_buffer_len(), buffer_to_keys(), unget_input(), + get_input(), parse_kbinput(), and parse_verbatim_kbinput(); + new macro charcpy(); changes to do_char() (renamed to + do_output()), get_edit_input() (renamed to do_input() and + moved to nano.c), get_edit_mouse() (renamed do_mouse() and + moved to nano.c), do_verbatim_input(), do_tab(), main(), and + get_ascii_kbinput() (renamed to get_word_kbinput()). The wide + version of ncurses is required in order for wide/multibyte + input and output to work properly. (DLR; buffered input/output + based on ideas from mutt 1.4.2.1; input of Unicode characters + in hexadecimal suggested by Michael Piefel) - More steps toward wide character/multibyte character support. Movement and cursor display in the edit window should now work properly with files containing multibyte characters, and text @@ -190,7 +189,8 @@ CVS code - - Typo fixes. (DLR) - doc/faq.html: - Remove now-inaccurate note about verbatim input's not working - at prompts. (DLR) + at prompts, and update its description to mention that it + handles hexadecimal values now. (DLR) - doc/nanorc.sample: - Add return to the "c-file" regexes. (DLR) diff --git a/doc/faq.html b/doc/faq.html index fa7a55db4f4cfd77f2004f85f349359db9623a2f..906f6bd84c1a9238c90df2a86f8746164ed2156a 100644 --- a/doc/faq.html +++ b/doc/faq.html @@ -166,7 +166,7 @@ <p>You can move between the buffers you have open with the <b>Meta-<</b> and <b>Meta-></b> keys, or more easily with <b>Meta-,</b> and <b>Meta-.</b> (clear as mud, right? =-). When you have more than one file buffer open, the ^X shortcut will say "Close", instead of the normal "Exit" when only one buffer is open.</p></blockquote> <h2><a name="3.8"></a>3.8. Tell me more about this verbatim input stuff!</h2> <blockquote><p>To use verbatim input, you must be using nano 1.3.1 or newer. When you want to insert a literal character into the file you're editing, such as a control character that nano usually treats as a command, first press <b>Meta-V</b>. (If you're not at a prompt, you'll get the message "Verbatim input".) Then press the key(s) that generate the character you want.</p> - <p>Alternatively, you can press <b>Meta-V</b> and then type a three-digit ASCII code from 000 to 255, and the character with that ASCII code will be inserted instead.</p></blockquote> + <p>Alternatively, you can press <b>Meta-V</b> and then type a four-digit hexadecimal code from 0000 to ffff (case-insensitive), and the character with the corresponding value will be inserted instead.</p></blockquote> <h2><a name="3.9"></a>3.9. How do I make a .nanorc file that nano will read when I start it?</h2> <blockquote><p>It's not hard at all! But, your version of nano must have been compiled with <b>--enable-nanorc</b>, and again must be version 1.1.12 or newer (use nano -V to check your version and compiled features). Then simply copy the <b>nanorc.sample</b> that came with the nano source or your nano package (most likely in /usr/doc/nano) to .nanorc in your home directory. If you didn't get one, the syntax is simple. Flags are turned on and off by using the word <b>set</b> and the getopt_long flag for the feature, for example "set nowrap" or "set suspend".</p></blockquote> <hr width="100%"> @@ -244,7 +244,7 @@ <h2><a name="8"></a>8. ChangeLog</h2> <blockquote> <p> -2005/01/02 - Remove now-inaccurate note about verbatim input's not working at prompts. (DLR) +2005/01/03 - Remove now-inaccurate note about verbatim input's not working at prompts, and update its description to mention that it handles hexadecimal values now. (DLR) 2004/11/21 - List sh as an example of a Bourne shell. (DLR) 2004/11/05 - Fixed inaccuracy: Pico compatibility mode was made the default in nano 1.1.99pre1, not 1.2.2. Also added question about how to type F13-F16 on terminals lacking keys past F12 (suggested by Chris), question about how to select text for the clipboard in X terminals with nano's mouse support turned on (answer found by Joseph Birthisel), and misc. fixes and link updates. (DLR)<br> 2004/04/07 - Removed NumLock glitch question, as it's no longer needed. (DLR)<br> diff --git a/src/nano.c b/src/nano.c index 866e7ecf61247c215a8f38b7677ddcaa304b6464..021d3097abc4e0278fd78f13d46afbc6dabd9fc7 100644 --- a/src/nano.c +++ b/src/nano.c @@ -372,9 +372,9 @@ void help_init(void) "(M) symbol and can be entered using either the Esc, Alt or " "Meta key depending on your keyboard setup. Also, pressing Esc " "twice and then typing a three-digit number from 000 to 255 " - "will enter the character with the corresponding ASCII code. " - "The following keystrokes are available in the main editor " - "window. Alternative keys are shown in parentheses:\n\n"); + "will enter the character with the corresponding value. The " + "following keystrokes are available in the main editor window. " + "Alternative keys are shown in parentheses:\n\n"); htx = _(htx); diff --git a/src/proto.h b/src/proto.h index bd6fd72abba10f5739af697cd98ec8ea432f561b..6801d0a6c935b7f1a0d9a1815c9022abd1a3e82b 100644 --- a/src/proto.h +++ b/src/proto.h @@ -555,6 +555,11 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool *ignore_seq); int get_escape_seq_abcd(int kbinput); +int get_byte_kbinput(int kbinput +#ifndef NANO_SMALL + , bool reset +#endif + ); int get_word_kbinput(int kbinput #ifndef NANO_SMALL , bool reset diff --git a/src/winio.c b/src/winio.c index 79e2f16e0b96f422c843e5572b35832e10d82b35..a4df2577cc29cc2a67ec68b767491c2425bd5fb3 100644 --- a/src/winio.c +++ b/src/winio.c @@ -121,6 +121,7 @@ static bool resetstatuspos = FALSE; void reset_kbinput(void) { parse_kbinput(NULL, NULL, NULL, TRUE); + get_byte_kbinput(0, TRUE); get_word_kbinput(0, TRUE); } #endif @@ -439,14 +440,14 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key ) { - static int escapes = 0, word_digits = 0; + static int escapes = 0, byte_digits = 0; buffer *kbinput; int retval = ERR; #ifndef NANO_SMALL if (reset) { escapes = 0; - word_digits = 0; + byte_digits = 0; return ERR; } #endif @@ -646,48 +647,47 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key break; case 2: /* Two escapes followed by one or more decimal - * digits: word sequence mode. If the word - * sequence's range is limited to 6XXXX (the - * first digit is in the '0' to '6' range and - * it's the first digit, or it's in the '0' to - * '9' range and it's not the first digit), - * increment the word sequence counter and - * interpret the digit. If the word sequence's - * range is not limited to 6XXXX, fall - * through. */ + * digits: byte sequence mode. If the word + * sequence's range is limited to 2XX (the first + * digit is in the '0' to '2' range and it's the + * first digit, or it's in the '0' to '9' range + * and it's not the first digit), increment the + * byte sequence counter and interpret the + * digit. If the byte sequence's range is not + * limited to 2XX, fall through. */ if (('0' <= kbinput->key && kbinput->key <= '6' - && word_digits == 0) || + && byte_digits == 0) || ('0' <= kbinput->key && kbinput->key <= '9' - && word_digits > 0)) { - int word_kbinput; + && byte_digits > 0)) { + int byte_kbinput; - word_digits++; - word_kbinput = get_word_kbinput(kbinput->key + byte_digits++; + byte_kbinput = get_byte_kbinput(kbinput->key #ifndef NANO_SMALL , FALSE #endif ); - if (word_kbinput != ERR) { - /* If we've read in a complete word - * sequence, reset the word sequence + if (byte_kbinput != ERR) { + /* If we've read in a complete byte + * sequence, reset the byte sequence * counter and the escape counter, - * and put back the corresponding word + * and put back the corresponding byte * value. */ - word_digits = 0; + byte_digits = 0; escapes = 0; - unget_kbinput(word_kbinput, FALSE, + unget_kbinput(byte_kbinput, FALSE, FALSE); } } else { /* Reset the escape counter. */ escapes = 0; - if (word_digits == 0) + if (byte_digits == 0) /* Two escapes followed by a non-decimal * digit or a decimal digit that would - * create a word sequence greater than - * 6XXXX, and we're not in the middle of - * a word sequence: control character + * create a byte sequence greater than + * 2XX, and we're not in the middle of a + * byte sequence: control character * sequence mode. Interpret the control * sequence and save the corresponding * control character as the result. */ @@ -697,7 +697,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key * sequence, reset the word sequence * counter and save the character we got * as the result. */ - word_digits = 0; + byte_digits = 0; retval = kbinput->key; } } @@ -715,7 +715,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key retval = kbinput->key; #ifdef DEBUG - fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, word_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, word_digits, retval); + fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval); #endif /* Return the result. */ @@ -1250,98 +1250,174 @@ int get_escape_seq_abcd(int kbinput) } } -/* Translate a word sequence: turn a five-digit decimal number from - * 00000 to 65535 into its corresponding word value. */ -int get_word_kbinput(int kbinput +/* Translate a byte sequence: turn a three-digit decimal number from + * 000 to 255 into its corresponding byte value. */ +int get_byte_kbinput(int kbinput #ifndef NANO_SMALL , bool reset #endif ) { - static int word_digits = 0, word_kbinput = 0; + static int byte_digits = 0, byte_kbinput = 0; int retval = ERR; #ifndef NANO_SMALL if (reset) { - word_digits = 0; - word_kbinput = 0; + byte_digits = 0; + byte_kbinput = 0; return ERR; } #endif - /* Increment the word digit counter. */ - word_digits++; + /* Increment the byte digit counter. */ + byte_digits++; - switch (word_digits) { + switch (byte_digits) { case 1: - /* One digit: reset the word sequence holder and add the - * digit we got to the 10000's position of the word sequence + /* One digit: reset the byte sequence holder and add the + * digit we got to the 100's position of the byte sequence * holder. */ - word_kbinput = 0; - if ('0' <= kbinput && kbinput <= '6') - word_kbinput += (kbinput - '0') * 10000; + byte_kbinput = 0; + if ('0' <= kbinput && kbinput <= '2') + byte_kbinput += (kbinput - '0') * 100; else /* If the character we got isn't a decimal digit, or if - * it is and it would put the word sequence out of word + * it is and it would put the byte sequence out of byte * range, save it as the result. */ retval = kbinput; break; case 2: - /* Two digits: add the digit we got to the 1000's position - * of the word sequence holder. */ + /* Two digits: add the digit we got to the 10's position of + * the byte sequence holder. */ if (('0' <= kbinput && kbinput <= '5') || - (word_kbinput < 60000 && '6' <= kbinput && + (byte_kbinput < 200 && '6' <= kbinput && kbinput <= '9')) - word_kbinput += (kbinput - '0') * 1000; + byte_kbinput += (kbinput - '0') * 10; else /* If the character we got isn't a decimal digit, or if - * it is and it would put the word sequence out of word + * it is and it would put the byte sequence out of byte * range, save it as the result. */ retval = kbinput; break; case 3: - /* Three digits: add the digit we got to the 100's position - * of the word sequence holder. */ + /* Three digits: add the digit we got to the 1's position of + * the byte sequence holder, and save the corresponding word + * value as the result. */ if (('0' <= kbinput && kbinput <= '5') || - (word_kbinput < 65000 && '6' <= kbinput && - kbinput <= '9')) - word_kbinput += (kbinput - '0') * 100; - else + (byte_kbinput < 250 && '6' <= kbinput && + kbinput <= '9')) { + byte_kbinput += (kbinput - '0'); + retval = byte_kbinput; + } else /* If the character we got isn't a decimal digit, or if * it is and it would put the word sequence out of word * range, save it as the result. */ retval = kbinput; break; - case 4: - /* Four digits: add the digit we got to the 10's position of + default: + /* More than three digits: save the character we got as the + * result. */ + retval = kbinput; + break; + } + + /* If we have a result, reset the byte digit counter and the byte + * sequence holder. */ + if (retval != ERR) { + byte_digits = 0; + byte_kbinput = 0; + } + +#ifdef DEBUG + fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte_kbinput = %d, retval = %d\n", kbinput, byte_digits, byte_kbinput, retval); +#endif + + return retval; +} + +/* Translate a word sequence: turn a four-digit hexadecimal number from + * 0000 to ffff (case-insensitive) into its corresponding word value. */ +int get_word_kbinput(int kbinput +#ifndef NANO_SMALL + , bool reset +#endif + ) +{ + static int word_digits = 0, word_kbinput = 0; + int retval = ERR; + +#ifndef NANO_SMALL + if (reset) { + word_digits = 0; + word_kbinput = 0; + return ERR; + } +#endif + + /* Increment the word digit counter. */ + word_digits++; + + switch (word_digits) { + case 1: + /* One digit: reset the word sequence holder and add the + * digit we got to the 4096's position of the word sequence + * holder. */ + word_kbinput = 0; + if ('0' <= kbinput && kbinput <= '9') + word_kbinput += (kbinput - '0') * 4096; + else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f') + word_kbinput += (tolower(kbinput) + 10 - 'a') * 4096; + else + /* If the character we got isn't a hexadecimal digit, or + * if it is and it would put the word sequence out of + * word range, save it as the result. */ + retval = kbinput; + break; + case 2: + /* Two digits: add the digit we got to the 256's position of * the word sequence holder. */ - if (('0' <= kbinput && kbinput <= '3') || - (word_kbinput < 65500 && '4' <= kbinput && - kbinput <= '9')) - word_kbinput += (kbinput - '0') * 10; + if ('0' <= kbinput && kbinput <= '9') + word_kbinput += (kbinput - '0') * 256; + else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f') + word_kbinput += (tolower(kbinput) + 10 - 'a') * 256; else - /* If the character we got isn't a decimal digit, or if - * it is and it would put the word sequence out of word - * range, save it as the result. */ + /* If the character we got isn't a hexadecimal digit, or + * if it is and it would put the word sequence out of + * word range, save it as the result. */ retval = kbinput; break; - case 5: - /* Five digits: add the digit we got to the 1's position of + case 3: + /* Three digits: add the digit we got to the 16's position + * of the word sequence holder. */ + if ('0' <= kbinput && kbinput <= '9') + word_kbinput += (kbinput - '0') * 16; + else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f') + word_kbinput += (tolower(kbinput) + 10 - 'a') * 16; + else + /* If the character we got isn't a hexadecimal digit, or + * if it is and it would put the word sequence out of + * word range, save it as the result. */ + retval = kbinput; + break; + case 4: + /* Four digits: add the digit we got to the 1's position of * the word sequence holder, and save the corresponding word * value as the result. */ - if (('0' <= kbinput && kbinput <= '5') || - (word_kbinput < 65530 && '6' <= kbinput && - kbinput <= '9')) { + if ('0' <= kbinput && kbinput <= '9') { word_kbinput += (kbinput - '0'); retval = word_kbinput; + } else if ('a' <= tolower(kbinput) && + tolower(kbinput) <= 'f') { + word_kbinput += (tolower(kbinput) + 10 - 'a'); + retval = word_kbinput; } else - /* If the character we got isn't a decimal digit, or if - * it is and it would put the word sequence out of word - * range, save it as the result. */ + /* If the character we got isn't a hexadecimal digit, or + * if it is and it would put the word sequence out of + * word range, save it as the result. */ retval = kbinput; break; default: - /* More than three digits: save the character we got as the + /* More than four digits: save the character we got as the * result. */ retval = kbinput; break; @@ -1444,15 +1520,15 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len) /* Read in the first keystroke. */ while ((kbinput = get_input(win, 1)) == NULL); - /* Check whether the first keystroke is a decimal digit. */ + /* Check whether the first keystroke is a hexadecimal digit. */ word = get_word_kbinput(kbinput->key #ifndef NANO_SMALL , FALSE #endif ); - /* If the first keystroke isn't a decimal digit, put back the first - * keystroke. */ + /* If the first keystroke isn't a hexadecimal digit, put back the + * first keystroke. */ if (word != ERR) unget_input(kbinput, 1); /* Otherwise, read in keystrokes until we have a complete word