add multibyte character support to help_line_len(), so that UTF-8 help

text is wrapped properly


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2393 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
David Lawrence Ramsey 2005-03-18 21:29:33 +00:00
parent d456bfa10d
commit 9bd56204ee
5 changed files with 116 additions and 110 deletions

View File

@ -99,12 +99,12 @@ CVS code -
control_mbrep(), control_wrep(), mbwidth(), mb_cur_max(),
make_mbchar(), mbstrlen(), mbstrnlen(), mbstrcasecmp(),
mbstrncasecmp(), mbstrcasestr(), and mbrevstrcasestr();
changes to help_init(), is_byte() (moved to chars.c),
is_blank_char() (moved to chars.c), is_cntrl_char() (moved to
chars.c), nstricmp() (renamed nstrcasecmp() and moved to
chars.c), nstrnicmp() (renamed nstrncasecmp() and moved to
chars.c), nstristr() (renamed nstrcasestr() and moved to
chars.c), revstrstr() (moved to chars.c), revstristr()
changes to help_init(), break_line(), is_byte() (moved to
chars.c), is_blank_char() (moved to chars.c), is_cntrl_char()
(moved to chars.c), nstricmp() (renamed nstrcasecmp() and
moved to chars.c), nstrnicmp() (renamed nstrncasecmp() and
moved to chars.c), nstristr() (renamed nstrcasestr() and moved
to chars.c), revstrstr() (moved to chars.c), revstristr()
(renamed revstrcasestr() and moved to chars.c), nstrnlen()
(moved to chars.c), parse_char() (renamed parse_mbchar() and
moved to chars.c), move_left() (renamed move_mbleft() and
@ -116,9 +116,9 @@ CVS code -
unget_input(), unget_kbinput(), get_input(), parse_kbinput(),
unparse_kbinput(), parse_verbatim_kbinput(),
do_statusbar_input(), do_statusbar_home(),
do_statusbar_verbatim_kbinput(), do_statusbar_output(), and
display_string(); removal of buffer_to_keys() and
keys_to_buffer(). (DLR)
do_statusbar_verbatim_kbinput(), do_statusbar_output(),
do_help(), help_line_len(), and display_string(); removal of
buffer_to_keys() and keys_to_buffer(). (DLR)
- Add -O/--morespace command line option, plus a corresponding
Meta-O toggle and a "morespace" rcfile option. When these are
used, the normally-unused blank line below the titlebar will
@ -188,7 +188,7 @@ CVS code -
make whitespace display mode work with multibyte characters,
and add a few related documentation updates. New function
make_mbstring(); changes to make_mbchar(), make_mbstring(),
do_help(), main(), parse_rcfile(), and display_string(). (DLR)
main(), parse_rcfile(), display_string(), and do_help(). (DLR)
- cut.c:
do_cut_text()
- If keep_cutbuffer is FALSE, only blow away the text in the

4
TODO
View File

@ -2,8 +2,8 @@ TODO file (? means the feature may be implemented, but not definitely)
-----------------------------------------------------------------------------
For version 1.4:
- UTF-8 support. [DONE except for edit window text wrapping, help window
text wrapping, and the NO_CONVERT flag.]
- UTF-8 support. [DONE except for edit window text wrapping and the
NO_CONVERT flag, which should allow editing UTF-8 as raw bytes.]
- Support for paragraph searches. [DONE]
- Support for justifying the entire file at once. [DONE]
- Support for filename searches in the file browser.

View File

@ -2323,6 +2323,86 @@ void do_spell(void)
}
#endif /* !DISABLE_SPELLER */
#if !defined(DISABLE_HELP) || !defined(DISABLE_JUSTIFY)
/* We are trying to break a chunk off line. We find the last blank such
* that the display length to there is at most goal + 1. If there is no
* such blank, and force is TRUE, then we find the first blank. Anyway,
* we then take the last blank in that group of blanks. The terminating
* '\0' counts as a blank, as does a '\n' if newline is TRUE. */
ssize_t break_line(const char *line, ssize_t goal, bool newline, bool
force)
{
ssize_t blank_loc = -1;
/* Current tentative return value. Index of the last blank we
* found with short enough display width. */
ssize_t cur_loc = 0;
/* Current index in line. */
int line_len;
assert(line != NULL);
while (*line != '\0' && goal >= 0) {
size_t pos = 0;
line_len = parse_mbchar(line, NULL, NULL, &pos);
if (is_blank_mbchar(line) || (newline && *line == '\n')) {
blank_loc = cur_loc;
if (newline && *line == '\n')
break;
}
goal -= pos;
line += line_len;
cur_loc += line_len;
}
if (goal >= 0)
/* In fact, the whole line displays shorter than goal. */
return cur_loc;
if (blank_loc == -1) {
/* No blank was found that was short enough. */
if (force) {
bool found_blank = FALSE;
while (*line != '\0') {
line_len = parse_mbchar(line, NULL, NULL, NULL);
if (is_blank_mbchar(line) ||
(newline && *line == '\n')) {
if (!found_blank)
found_blank = TRUE;
} else if (found_blank)
return cur_loc - line_len;
line += line_len;
cur_loc += line_len;
}
return -1;
}
}
/* Move to the last blank after blank_loc, if there is one. */
line -= cur_loc;
line += blank_loc;
line_len = parse_mbchar(line, NULL, NULL, NULL);
line += line_len;
while (*line != '\0' && (is_blank_mbchar(line) ||
(newline && *line == '\n'))) {
line_len = parse_mbchar(line, NULL, NULL, NULL);
line += line_len;
blank_loc += line_len;
}
return blank_loc;
}
#endif /* !DISABLE_HELP || !DISABLE_JUSTIFY */
#if !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
/* The "indentation" of a line is the whitespace between the quote part
* and the non-whitespace of the line. */
@ -2759,77 +2839,6 @@ filestruct *backup_lines(filestruct *first_line, size_t par_len, size_t
return first_line;
}
/* We are trying to break a chunk off line. We find the last blank such
* that the display length to there is at most goal + 1. If there is no
* such blank, and force is TRUE, then we find the first blank. Anyway,
* we then take the last blank in that group of blanks. The terminating
* '\0' counts as a blank. */
ssize_t break_line(const char *line, ssize_t goal, bool force)
{
ssize_t blank_loc = -1;
/* Current tentative return value. Index of the last blank we
* found with short enough display width. */
ssize_t cur_loc = 0;
/* Current index in line. */
int line_len;
assert(line != NULL);
while (*line != '\0' && goal >= 0) {
size_t pos = 0;
line_len = parse_mbchar(line, NULL, NULL, &pos);
if (is_blank_mbchar(line))
blank_loc = cur_loc;
goal -= pos;
line += line_len;
cur_loc += line_len;
}
if (goal >= 0)
/* In fact, the whole line displays shorter than goal. */
return cur_loc;
if (blank_loc == -1) {
/* No blank was found that was short enough. */
if (force) {
bool found_blank = FALSE;
while (*line != '\0') {
line_len = parse_mbchar(line, NULL, NULL, NULL);
if (is_blank_mbchar(line)) {
if (!found_blank)
found_blank = TRUE;
} else if (found_blank)
return cur_loc - line_len;
line += line_len;
cur_loc += line_len;
}
return -1;
}
}
/* Move to the last blank after blank_loc, if there is one. */
line -= cur_loc;
line += blank_loc;
line_len = parse_mbchar(line, NULL, NULL, NULL);
line += line_len;
while (*line != '\0' && is_blank_mbchar(line)) {
line_len = parse_mbchar(line, NULL, NULL, NULL);
line += line_len;
blank_loc += line_len;
}
return blank_loc;
}
/* Find the beginning of the current paragraph if we're in one, or the
* beginning of the next paragraph if we're not. Afterwards, save the
* quote length and paragraph length in *quote and *par. Return TRUE if
@ -3082,7 +3091,8 @@ void do_justify(bool full_justify)
/* If this line is too long, try to wrap it to the next line
* to make it short enough. */
break_pos = break_line(current->data + indent_len,
fill - strnlenpt(current->data, indent_len), TRUE);
fill - strnlenpt(current->data, indent_len), FALSE,
TRUE);
/* We can't break the line, or don't need to, so get out. */
if (break_pos == -1 || break_pos + indent_len == line_len)

View File

@ -413,6 +413,10 @@ const char *do_int_speller(const char *tempfile_name);
const char *do_alt_speller(char *tempfile_name);
void do_spell(void);
#endif
#if !defined(DISABLE_HELP) || !defined(DISABLE_JUSTIFY)
ssize_t break_line(const char *line, ssize_t goal, bool newline, bool
force);
#endif
#if !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
size_t indent_length(const char *line);
#endif
@ -431,7 +435,6 @@ void do_para_end(bool allow_update);
void do_para_end_void(void);
filestruct *backup_lines(filestruct *first_line, size_t par_len, size_t
quote_len);
ssize_t break_line(const char *line, ssize_t goal, bool force);
bool find_paragraph(size_t *const quote, size_t *const par);
void do_justify(bool full_justify);
void do_justify_void(void);
@ -680,7 +683,7 @@ void display_main_list(void);
void do_cursorpos(bool constant);
void do_cursorpos_void(void);
#ifndef DISABLE_HELP
int help_line_len(const char *ptr);
size_t help_line_len(const char *ptr);
void do_help(void);
#endif
void do_replace_highlight(bool highlight_flag, const char *word);

View File

@ -3826,31 +3826,26 @@ void do_cursorpos_void(void)
#ifndef DISABLE_HELP
/* Calculate the next line of help_text, starting at ptr. */
int help_line_len(const char *ptr)
size_t help_line_len(const char *ptr)
{
int j = 0;
int help_cols = (COLS > 80) ? COLS - 8 : 72;
while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
ptr++;
j++;
}
if (j == COLS - 5) {
/* Don't wrap at the first of two spaces following a period. */
if (*ptr == ' ' && *(ptr + 1) == ' ')
j++;
/* Don't print half a word if we've run out of space. */
while (*ptr != ' ' && j > 0) {
ptr--;
j--;
}
/* A word longer than (COLS - 5) chars just gets broken. */
if (j == 0)
j = COLS - 5;
}
/* Try to break the line at (COLS - 8) columns if we have more than
* 80 columns, and at 72 columns otherwise. */
size_t retval = break_line(ptr, help_cols, TRUE, TRUE);
size_t retval_save = retval;
assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
/* Get the length of the entire line up to a null or a newline. */
while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
retval += move_mbright(ptr + retval, 0);
return j;
/* If the entire line doesn't go more than 8 columns beyond where we
* tried to break it, we should display it as-is. Otherwise, we
* should display it only up to the break. */
if (strnlenpt(ptr, retval) > help_cols + 8)
retval = retval_save;
return retval;
}
/* Our dynamic, shortcut-list-compliant help function. */
@ -3944,8 +3939,6 @@ void do_help(void)
blank_edit();
}
assert(COLS > 5);
/* Calculate where in the text we should be, based on the
* page. */
for (i = 0; i < line; i++) {
@ -3955,7 +3948,7 @@ void do_help(void)
}
for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
int j = help_line_len(ptr);
size_t j = help_line_len(ptr);
mvwaddnstr(edit, i, 0, ptr, j);
ptr += j;