0
0
mirror of https://github.com/rkd77/elinks.git synced 2025-06-30 22:19:29 -04:00

Support for double-width glyphs in plain renderer

Removed duplicate code for UTF-8 in plain renderer. Modified plain renderer
to correctly displaying multi-width glyphs.
This commit is contained in:
Pavol Babincak 2006-02-08 01:49:56 +01:00 committed by Jonas Fonseca
parent c726080def
commit fc5f2389ed

View File

@ -175,12 +175,12 @@ get_uri_length(unsigned char *line, int length)
static int static int
print_document_link(struct plain_renderer *renderer, int lineno, print_document_link(struct plain_renderer *renderer, int lineno,
unsigned char *line, int line_pos, int width, unsigned char *line, int line_pos, int width,
int expanded, struct screen_char *pos) int expanded, struct screen_char *pos, int cells)
{ {
struct document *document = renderer->document; struct document *document = renderer->document;
unsigned char *start = &line[line_pos]; unsigned char *start = &line[line_pos];
int len = get_uri_length(start, width - line_pos); int len = get_uri_length(start, width - line_pos);
int screen_column = line_pos + expanded; int screen_column = cells + expanded;
struct link *new_link; struct link *new_link;
int link_end = line_pos + len; int link_end = line_pos + len;
unsigned char saved_char; unsigned char saved_char;
@ -235,9 +235,9 @@ add_document_line(struct plain_renderer *renderer,
struct screen_char saved_renderer_template = *template; struct screen_char saved_renderer_template = *template;
struct screen_char *pos, *startpos; struct screen_char *pos, *startpos;
#ifdef CONFIG_UTF_8 #ifdef CONFIG_UTF_8
unsigned char *end, *text;
int utf8 = document->options.utf8; int utf8 = document->options.utf8;
#endif /* CONFIG_UTF_8 */ #endif /* CONFIG_UTF_8 */
int cells = 0;
int lineno = renderer->lineno; int lineno = renderer->lineno;
int expanded = 0; int expanded = 0;
int width = line_width; int width = line_width;
@ -249,13 +249,31 @@ add_document_line(struct plain_renderer *renderer,
if (!line) return 0; if (!line) return 0;
/* Now expand tabs */ /* Now expand tabs */
for (line_pos = 0; line_pos < width; line_pos++) { for (line_pos = 0; line_pos < width;) {
unsigned char line_char = line[line_pos]; unsigned char line_char = line[line_pos];
int charlen = 1;
int cell = 1;
#ifdef CONFIG_UTF_8
unicode_val_T data;
if (utf8) {
unsigned char *line_char2 = &line[line_pos];
charlen = utf8charlen(&line_char);
data = utf_8_to_unicode(&line_char2, &line[width]);
if (data == UCS_NO_CHAR) {
line_pos += charlen;
continue;
}
cell = unicode_to_cell(data);
}
#endif /* CONFIG_UTF_8 */
if (line_char == ASCII_TAB if (line_char == ASCII_TAB
&& (line_pos + 1 == width && (line_pos + charlen == width
|| line[line_pos + 1] != ASCII_BS)) { || line[line_pos + charlen] != ASCII_BS)) {
int tab_width = 7 - ((line_pos + expanded) & 7); int tab_width = 7 - ((cells + expanded) & 7);
expanded += tab_width; expanded += tab_width;
} else if (line_char == ASCII_BS) { } else if (line_char == ASCII_BS) {
@ -276,32 +294,50 @@ add_document_line(struct plain_renderer *renderer,
expanded--; expanded--;
#endif #endif
} }
line_pos += charlen;
cells += cell;
} }
assert(expanded >= 0); assert(expanded >= 0);
#ifdef CONFIG_UTF_8
if (utf8) goto utf_8;
#endif /* CONFIG_UTF_8 */
startpos = pos = realloc_line(document, width + expanded, lineno); startpos = pos = realloc_line(document, width + expanded, lineno);
if (!pos) { if (!pos) {
mem_free(line); mem_free(line);
return 0; return 0;
} }
cells = 0;
expanded = 0; expanded = 0;
for (line_pos = 0; line_pos < width; line_pos++) { for (line_pos = 0; line_pos < width;) {
unsigned char line_char = line[line_pos]; unsigned char line_char = line[line_pos];
unsigned char next_char, prev_char; unsigned char next_char, prev_char;
int charlen = 1;
int cell = 1;
#ifdef CONFIG_UTF_8
unicode_val_T data;
if (utf8) {
unsigned char *line_char2 = &line[line_pos];
charlen = utf8charlen(&line_char);
data = utf_8_to_unicode(&line_char2, &line[width]);
if (data == UCS_NO_CHAR) {
line_pos += charlen;
continue;
}
cell = unicode_to_cell(data);
}
#endif /* CONFIG_UTF_8 */
prev_char = line_pos > 0 ? line[line_pos - 1] : '\0'; prev_char = line_pos > 0 ? line[line_pos - 1] : '\0';
next_char = (line_pos + 1 < width) ? line[line_pos + 1] next_char = (line_pos + charlen < width) ?
: '\0'; line[line_pos + charlen] : '\0';
/* Do not expand tabs that precede back-spaces; this saves the /* Do not expand tabs that precede back-spaces; this saves the
* back-space code some trouble. */ * back-space code some trouble. */
if (line_char == ASCII_TAB && next_char != ASCII_BS) { if (line_char == ASCII_TAB && next_char != ASCII_BS) {
int tab_width = 7 - ((line_pos + expanded) & 7); int tab_width = 7 - ((cells + expanded) & 7);
expanded += tab_width; expanded += tab_width;
@ -313,7 +349,7 @@ add_document_line(struct plain_renderer *renderer,
*template = saved_renderer_template; *template = saved_renderer_template;
} else if (line_char == ASCII_BS) { } else if (line_char == ASCII_BS) {
if (!(expanded + line_pos)) { if (!(expanded + cells)) {
/* We've backspaced to the start of the line */ /* We've backspaced to the start of the line */
continue; continue;
} }
@ -327,8 +363,8 @@ add_document_line(struct plain_renderer *renderer,
/* x^H_ becomes _^Hx */ /* x^H_ becomes _^Hx */
if (line_pos - 1 >= 0) if (line_pos - 1 >= 0)
line[line_pos - 1] = next_char; line[line_pos - 1] = next_char;
if (line_pos + 1 < width) if (line_pos + charlen < width)
line[line_pos + 1] = prev_char; line[line_pos + charlen] = prev_char;
/* Go back and reparse the swapped characters */ /* Go back and reparse the swapped characters */
if (line_pos - 2 >= 0) if (line_pos - 2 >= 0)
@ -388,161 +424,53 @@ add_document_line(struct plain_renderer *renderer,
line_pos, line_pos,
width, width,
expanded, expanded,
pos); pos, cells);
} }
if (added_chars) { if (added_chars) {
line_pos += added_chars - 1; line_pos += added_chars - 1;
pos += added_chars; pos += added_chars;
} else { } else {
#ifdef CONFIG_UTF_8
if (utf8) {
unsigned char *text = &line[line_pos];
unicode_val_T data =
utf_8_to_unicode(&text,
&line[width]);
if (data == UCS_NO_CHAR) {
line_pos += charlen;
continue;
}
template->data = (uint16_t)data;
copy_screen_chars(pos++, template, 1);
if (unicode_to_cell(data) == 2) {
template->data = UCS_NO_CHAR;
copy_screen_chars(pos++,
template, 1);
}
} else
#endif /* CONFIG_UTF_8 */
{
if (!isscreensafe(line_char)) if (!isscreensafe(line_char))
line_char = '.'; line_char = '.';
template->data = line_char; template->data = line_char;
copy_screen_chars(pos++, template, 1); copy_screen_chars(pos++, template, 1);
/* Detect copy of nul chars to screen, this /* Detect copy of nul chars to screen,
* should not occur. --Zas */ * this should not occur. --Zas */
assert(line_char); assert(line_char);
} }
*template = saved_renderer_template;
}
}
#ifdef CONFIG_UTF_8
goto end;
utf_8:
end = line + width;
startpos = pos = realloc_line(document, width + expanded, lineno);
if (!pos) {
mem_free(line);
return 0;
}
expanded = 0;
for (text = line; text < end; ) {
unsigned char line_char = *text;
unsigned char next_char, prev_char;
line_pos = text - line;
prev_char = text > line ? *(text - 1) : '\0';
next_char = (text + 1 < end) ? *(text + 1) : '\0';
/* Do not expand tabs that precede back-spaces; this saves the
* back-space code some trouble. */
if (line_char == ASCII_TAB && next_char != ASCII_BS) {
int tab_width = 7 - ((line_pos + expanded) & 7);
expanded += tab_width;
template->data = ' ';
do
copy_screen_chars(pos++, template, 1);
while (tab_width--);
*template = saved_renderer_template;
text++;
} else if (line_char == ASCII_BS) {
if (!(expanded + line_pos)) {
/* We've backspaced to the start of the line */
if (expanded > 0)
expanded--; /* Don't count it */
continue;
}
if (pos > startpos)
pos--; /* Backspace */
/* Handle x^H_ as _^Hx, but prevent an infinite loop
* swapping two underscores. */
if (next_char == '_' && prev_char != '_') {
/* x^H_ becomes _^Hx */
if (text - 1 >= line)
*(text - 1) = next_char;
if (text + 1 < end)
*(text + 1) = prev_char;
/* Go back and reparse the swapped characters */
if (text - 2 >= line)
text -= 2;
continue;
}
if (expanded - 2 >= 0) {
/* Don't count the backspace character or the
* deleted character when returning the line's
* width or when expanding tabs. */
expanded -= 2;
}
if (pos->data == '_' && next_char == '_') {
/* Is _^H_ an underlined underscore
* or an emboldened underscore? */
if (expanded + line_pos >= 0
&& pos - 1 >= startpos
&& (pos - 1)->attr) {
/* There is some preceding text,
* and it has an attribute; copy it */
template->attr |= (pos - 1)->attr;
} else {
/* Default to bold; seems more useful
* than underlining the underscore */
template->attr |= SCREEN_ATTR_BOLD;
}
} else if (pos->data == '_') {
/* Underline _^Hx */
template->attr |= SCREEN_ATTR_UNDERLINE;
} else if (pos->data == next_char) {
/* Embolden x^Hx */
template->attr |= SCREEN_ATTR_BOLD;
}
/* Handle _^Hx^Hx as both bold and underlined */
if (template->attr)
template->attr |= pos->attr;
text++;
} else {
int added_chars = 0;
if (document->options.plain_display_links
&& isalpha(line_char) && isalpha(next_char)) {
/* We only want to check for a URI if there are
* at least two consecutive alphabetic
* characters, or if we are at the very start of
* the line. It improves performance a bit.
* --Zas */
added_chars = print_document_link(renderer,
lineno, line,
line_pos,
width,
expanded,
pos);
}
if (added_chars) {
text += added_chars;
pos += added_chars;
} else {
unicode_val_T data = utf_8_to_unicode(&text, end);
if (data == UCS_NO_CHAR) text++;
template->data = (uint16_t)data;
copy_screen_chars(pos++, template, 1);
/* Detect copy of nul chars to screen, this
* should not occur. --Zas */
assert(line_char);
} }
*template = saved_renderer_template; *template = saved_renderer_template;
} }
line_pos += charlen;
cells += cell;
} }
end:
#endif /* CONFIG_UTF_8 */
mem_free(line); mem_free(line);
realloc_line(document, pos - startpos, lineno); realloc_line(document, pos - startpos, lineno);
@ -596,10 +524,11 @@ add_document_lines(struct plain_renderer *renderer)
int last_space = 0; int last_space = 0;
int tab_spaces = 0; int tab_spaces = 0;
int step = 0; int step = 0;
int doc_width = int_min(renderer->max_width, length); int cells = 0;
/* End of line detection: We handle \r, \r\n and \n types. */ /* End of line detection: We handle \r, \r\n and \n types. */
for (width = 0; width + tab_spaces < doc_width; width++) { for (width = 0; (width < length) &&
(cells < renderer->max_width);) {
if (source[width] == ASCII_CR) if (source[width] == ASCII_CR)
step++; step++;
if (source[width + step] == ASCII_LF) if (source[width + step] == ASCII_LF)
@ -618,6 +547,22 @@ add_document_lines(struct plain_renderer *renderer)
only_spaces = 0; only_spaces = 0;
was_spaces = 0; was_spaces = 0;
} }
#ifdef CONFIG_UTF_8
if (renderer->document->options.utf8) {
unsigned char *text = &source[width];
unicode_val_T data = utf_8_to_unicode(&text,
&source[length]);
if (data == UCS_NO_CHAR) return;
cells += unicode_to_cell(data);
width += utf8charlen(&source[width]);
} else
#endif /* CONFIG_UTF_8 */
{
cells++;
width++;
}
} }
if (only_spaces && step) { if (only_spaces && step) {
@ -645,6 +590,7 @@ add_document_lines(struct plain_renderer *renderer)
width -= was_spaces; width -= was_spaces;
step += was_spaces; step += was_spaces;
} }
if (!step && (width < length) && last_space) { if (!step && (width < length) && last_space) {
width = last_space; width = last_space;
step = 1; step = 1;