From 44a1aa9c87d72bd5020e68ef6e62f5a363a54b54 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sat, 14 Jan 2006 22:44:00 +0100 Subject: [PATCH 01/73] Witekfl's UTF-8 patch v5. --- src/bfu/button.c | 25 +++++ src/bfu/dialog.c | 12 ++- src/bfu/inpfield.c | 164 +++++++++++++++++++++++++++-- src/bfu/menu.c | 29 +++++ src/dialogs/options.c | 1 - src/document/dom/renderer.c | 40 +++++++ src/document/html/renderer.c | 103 +++++++++++++----- src/document/options.h | 1 + src/document/plain/renderer.c | 136 ++++++++++++++++++++++++ src/intl/charsets.c | 106 ++++++++++++++++++- src/intl/charsets.h | 4 + src/terminal/draw.c | 45 +++++++- src/terminal/draw.h | 6 +- src/terminal/event.c | 14 +-- src/terminal/screen.c | 90 +++++++--------- src/terminal/terminal.h | 3 + src/viewer/dump/dump.c | 92 +++++++++++++++- src/viewer/text/form.c | 169 ++++++++++++++++++++++++++--- src/viewer/text/form.h | 1 + src/viewer/text/link.c | 8 +- src/viewer/text/textarea.c | 193 ++++++++++++++++++++++++++++------ src/viewer/text/textarea.h | 16 +-- 22 files changed, 1099 insertions(+), 159 deletions(-) diff --git a/src/bfu/button.c b/src/bfu/button.c index 48afb3a6..5c1ff8a4 100644 --- a/src/bfu/button.c +++ b/src/bfu/button.c @@ -167,6 +167,31 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) attr = get_opt_bool("ui.dialogs.underline_button_shortcuts") ? SCREEN_ATTR_UNDERLINE : 0; + if (term->utf8) { + unsigned char *text2 = text; + unsigned char *end = text + + widget_data->widget->info.button.truetextlen; + int hk_state = 0; + int x1; + + for (x1 = 0; x1 - !!hk_state < len && *text2; x1++) { + uint16_t data; + + data = (uint16_t)utf_8_to_unicode(&text2, end); + if (!hk_state && (int)(text2 - text) == hk_pos + 1) { + hk_state = 1; + continue; + } + if (hk_state == 1) { + draw_char(term, x + x1 - 1, pos->y, data, attr, shortcut_color); + hk_state = 2; + } else { + draw_char(term, x + x1 - !!hk_state, pos->y, data, 0, color); + } + + } + len = x1 - !!hk_state; + } else if (hk_pos >= 0) { int right = widget_data->widget->info.button.truetextlen - hk_pos - 1; diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index 042a172c..554b9dbc 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -12,6 +12,7 @@ #include "bfu/dialog.h" #include "config/kbdbind.h" #include "config/options.h" +#include "intl/charsets.h" #include "intl/gettext/libintl.h" #include "terminal/draw.h" #include "main/timer.h" @@ -96,13 +97,18 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) title_color = get_bfu_color(term, "dialog.title"); if (title_color && box.width > 2) { unsigned char *title = dlg_data->dlg->title; - int titlelen = int_min(box.width - 2, strlen(title)); - int x = (box.width - titlelen) / 2 + box.x; + unsigned char *t2 = title; + int titlelen = strlen(title); + int len = term->utf8 ? strlen_utf8(&t2) : titlelen; +#if 1 + len = int_min(box.width - 2, len); +#endif + int x = (box.width - len) / 2 + box.x; int y = box.y - 1; draw_text(term, x - 1, y, " ", 1, 0, title_color); draw_text(term, x, y, title, titlelen, 0, title_color); - draw_text(term, x + titlelen, y, " ", 1, 0, title_color); + draw_text(term, x + len, y, " ", 1, 0, title_color); } } diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index 5c4359de..969a17aa 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -17,6 +17,7 @@ #include "bfu/msgbox.h" #include "bfu/text.h" #include "config/kbdbind.h" +#include "intl/charsets.h" #include "intl/gettext/libintl.h" #include "osdep/osdep.h" #include "session/session.h" @@ -101,6 +102,71 @@ check_nonempty(struct dialog_data *dlg_data, struct widget_data *widget_data) return EVENT_NOT_PROCESSED; } +#if 0 +void +dlg_format_field(struct terminal *term, + struct widget_data *widget_data, + int x, int *y, int w, int *rw, enum format_align align) +{ + static int max_label_width; + static int *prev_y; /* Assert the uniqueness of y */ /* TODO: get rid of this !! --Zas */ + unsigned char *label = widget_data->widget->text; + struct color_pair *text_color = NULL; + int label_width = 0; + int float_label = widget_data->widget->info.field.flags & (INPFIELD_FLOAT|INPFIELD_FLOAT2); + + if (label && *label && float_label) { + unsigned char *l2 = label; + int len = strlen(label); + + label_width = term->utf8 ? strlen_utf8(&l2) : len; + if (prev_y == y) { + int_lower_bound(&max_label_width, label_width); + } else { + max_label_width = label_width; + prev_y = y; + } + + /* Right align the floating label up against the + * input field */ + x += max_label_width - label_width; + w -= max_label_width - len; + } + + if (label && *label) { + if (term) text_color = get_bfu_color(term, "dialog.text"); + + dlg_format_text_do(term, label, x, y, w, rw, text_color, ALIGN_LEFT); + } + + /* XXX: We want the field and label on the same line if the terminal + * width allows it. */ + if (label && *label && float_label) { + if (widget_data->widget->info.field.flags & INPFIELD_FLOAT) { + (*y) -= INPUTFIELD_HEIGHT; + dlg_format_text_do(term, INPUTFIELD_FLOAT_SEPARATOR, + x + label_width, y, w, rw, + text_color, ALIGN_LEFT); + w -= INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; + x += INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; + } + + /* FIXME: Is 5 chars for input field enough? --jonas */ + if (label_width < w - 5) { + (*y) -= INPUTFIELD_HEIGHT; + w -= label_width; + x += label_width; + } + } + + if (rw) int_lower_bound(rw, int_min(w, DIALOG_MIN_WIDTH)); + + set_box(&widget_data->box, x, *y, w, INPUTFIELD_HEIGHT); + + (*y) += INPUTFIELD_HEIGHT; +} +#endif + void dlg_format_field(struct terminal *term, struct widget_data *widget_data, @@ -265,11 +331,30 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, struct terminal *term = dlg_data->win->term; struct color_pair *color; int sel = is_selected_widget(dlg_data, widget_data); + int len = 0, left = 0; - int_bounds(&widget_data->info.field.vpos, + if (term->utf8) { + unsigned char *t = widget_data->cdata; + unsigned char *t2 = t; + int p = widget_data->info.field.cpos; + unsigned char tmp = t[p]; + int x; + + t[p] = '\0'; + len = strlen_utf8(&t2); + int_bounds(&left, len - widget_data->box.width + 1, len); + int_lower_bound(&left, 0); + for (t2 = t, x = 0; x < left; x++) { + utf_8_to_unicode(&t2, &t[p]); + } + t[p] = tmp; + widget_data->info.field.vpos = (int)(t2 - t); + } else { + int_bounds(&widget_data->info.field.vpos, widget_data->info.field.cpos - widget_data->box.width + 1, widget_data->info.field.cpos); - int_lower_bound(&widget_data->info.field.vpos, 0); + int_lower_bound(&widget_data->info.field.vpos, 0); + } color = get_bfu_color(term, "dialog.field"); if (color) @@ -277,7 +362,8 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, color = get_bfu_color(term, "dialog.field-text"); if (color) { - int len = strlen(widget_data->cdata + widget_data->info.field.vpos); + unsigned char *text = widget_data->cdata + widget_data->info.field.vpos; + int len = strlen(text); int w = int_min(len, widget_data->box.width); if (!hide) { @@ -287,6 +373,9 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, } else { struct box box; + if (term->utf8) len = strlen_utf8(&text); + w = int_min(len, widget_data->box.width); + copy_box(&box, &widget_data->box); box.width = w; @@ -295,8 +384,14 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, } if (sel) { - int x = widget_data->box.x + widget_data->info.field.cpos - widget_data->info.field.vpos; + int x; + if (term->utf8) { + x = widget_data->box.x + len - left; + } else { + x = widget_data->box.x + widget_data->info.field.cpos - widget_data->info.field.vpos; + + } set_cursor(term, x, widget_data->box.y, 0); set_window_ptr(dlg_data->win, widget_data->box.x, widget_data->box.y); } @@ -435,13 +530,33 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) break; case ACT_EDIT_RIGHT: - if (widget_data->info.field.cpos < strlen(widget_data->cdata)) - widget_data->info.field.cpos++; + if (widget_data->info.field.cpos < strlen(widget_data->cdata)) { + if (term->utf8) { + unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; + unsigned char *end = strchr(next, '\0'); + + utf_8_to_unicode(&next, end); + widget_data->info.field.cpos = (int)(next - widget_data->cdata); + } else + widget_data->info.field.cpos++; + } goto display_field; case ACT_EDIT_LEFT: if (widget_data->info.field.cpos > 0) widget_data->info.field.cpos--; + if (widget_data->info.field.cpos && term->utf8) { + unsigned char *t = widget_data->cdata; + unsigned char *t2 = t; + int p = widget_data->info.field.cpos; + unsigned char tmp = t[p]; + + t[p] = '\0'; + strlen_utf8(&t2); + t[p] = tmp; + widget_data->info.field.cpos = (int)(t2 - t); + + } goto display_field; case ACT_EDIT_HOME: @@ -453,6 +568,19 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) goto display_field; case ACT_EDIT_BACKSPACE: + if (widget_data->info.field.cpos && term->utf8) { + unsigned char *t = widget_data->cdata; + unsigned char *t2 = t; + int p = widget_data->info.field.cpos - 1; + unsigned char tmp = t[p]; + + t[p] = '\0'; + strlen_utf8(&t2); + t[p] = tmp; + memmove(t2, &t[p + 1], strlen(&t[p + 1]) + 1); + widget_data->info.field.cpos = (int)(t2 - t); + goto display_field; + } if (widget_data->info.field.cpos) { memmove(widget_data->cdata + widget_data->info.field.cpos - 1, widget_data->cdata + widget_data->info.field.cpos, @@ -467,6 +595,15 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) if (widget_data->info.field.cpos >= cdata_len) goto display_field; + if (term->utf8) { + unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; + unsigned char *dest = next; + unsigned char *end = strchr(next, '\0'); + + utf_8_to_unicode(&next, end); + memmove(dest, next, strlen(next) + 1); + goto display_field; + } memmove(widget_data->cdata + widget_data->info.field.cpos, widget_data->cdata + widget_data->info.field.cpos + 1, cdata_len - widget_data->info.field.cpos + 1); @@ -548,7 +685,20 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) memmove(text + 1, text, textlen + 1); *text = get_kbd_key(ev); - + if (term->utf8) { + static unsigned char buf[7]; + unsigned char *t = buf; + static int i = 0; + unicode_val_T data; + + buf[i++] = *text; + buf[i] = '\0'; + data = utf_8_to_unicode(&t, buf + i); + if (i == 6) i = 0; + if (data == UCS_NO_CHAR) + return EVENT_PROCESSED; + else i = 0; + } goto display_field; } } diff --git a/src/bfu/menu.c b/src/bfu/menu.c index a7e1fb06..0b71a648 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -346,10 +346,12 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, struct color_pair *hk_color_sel = get_bfu_color(term, "menu.hotkey.selected"); enum screen_char_attr hk_attr = get_opt_bool("ui.dialogs.underline_hotkeys") ? SCREEN_ATTR_UNDERLINE : 0; + unsigned char *text2, *end; unsigned char c; int xbase = x + L_TEXT_SPACE; int w = width - (L_TEXT_SPACE + R_TEXT_SPACE); int hk_state = 0; + #ifdef CONFIG_DEBUG /* For redundant hotkeys highlighting. */ int double_hk = 0; @@ -366,6 +368,7 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, hk_color_sel = tmp; } + if (term->utf8) goto utf8; for (x = 0; x - !!hk_state < w && (c = text[x]); x++) { if (!hk_state && x == hotkey_pos - 1) { hk_state = 1; @@ -384,6 +387,32 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, draw_char(term, xbase + x - !!hk_state, y, c, 0, color); } } + return; +utf8: + end = strchr(text, '\0'); + text2 = text; + for (x = 0; x - !!hk_state < w && *text2; x++) { + unicode_val_T data; + + data = utf_8_to_unicode(&text2, end); + if (!hk_state && (int)(text2 - text) == hotkey_pos) { + hk_state = 1; + continue; + } + if (hk_state == 1) { +#ifdef CONFIG_DEBUG + draw_char(term, xbase + x - 1, y, data, hk_attr, + (double_hk ? hk_color_sel : hk_color)); +#else + draw_char(term, xbase + x - 1, y, data, hk_attr, hk_color); +#endif + hk_state = 2; + } else { + draw_char(term, xbase + x - !!hk_state, y, data, 0, color); + } + + } + } static inline void diff --git a/src/dialogs/options.c b/src/dialogs/options.c index 70836da3..906bc83f 100644 --- a/src/dialogs/options.c +++ b/src/dialogs/options.c @@ -59,7 +59,6 @@ charset_list(struct terminal *term, void *xxx, void *ses_) unsigned char *name = get_cp_name(i); if (!name) break; - if (is_cp_special(i)) continue; add_to_menu(&mi, name, NULL, ACT_MAIN_NONE, display_codepage, get_cp_mime_name(i), 0); diff --git a/src/document/dom/renderer.c b/src/document/dom/renderer.c index 0dfb3890..0461aacb 100644 --- a/src/document/dom/renderer.c +++ b/src/document/dom/renderer.c @@ -250,8 +250,11 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, struct document *document = renderer->document; struct conv_table *convert = renderer->convert_table; enum convert_string_mode mode = renderer->convert_mode; + int utf8 = document->options.utf8; + unsigned char *end, *text; int x; + assert(renderer && template && string && length); string = convert_string(convert, string, length, document->options.cp, @@ -265,6 +268,7 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, add_search_node(renderer, length); + if (utf8) goto utf_8; for (x = 0; x < length; x++, renderer->canvas_x++) { unsigned char data = string[x]; @@ -293,7 +297,42 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, copy_screen_chars(POS(renderer), template, 1); } + goto end; +utf_8: + end = string + length; + for (text = string; text < end; renderer->canvas_x++) { + unsigned char data = *text; + unicode_val_T d2; + /* This is mostly to be able to break out so the indentation + * level won't get to high. */ + switch (data) { + case ASCII_TAB: + { + int tab_width = 7 - (X(renderer) & 7); + int width = WIDTH(renderer, end - text + tab_width); + + template->data = ' '; + + if (!realloc_line(document, width, Y(renderer))) + break; + + /* Only loop over the expanded tab chars and let the + * ``main loop'' add the actual tab char. */ + for (; tab_width-- > 0; renderer->canvas_x++) + copy_screen_chars(POS(renderer), template, 1); + text++; + break; + } + default: + d2 = utf_8_to_unicode(&text, end); + if (d2 == UCS_NO_CHAR) text++; + template->data = (uint16_t)d2; + } + + copy_screen_chars(POS(renderer), template, 1); + } +end: mem_free(string); } @@ -989,6 +1028,7 @@ render_dom_document(struct cache_entry *cached, struct document *document, init_dom_renderer(&renderer, document, buffer, convert_table); document->bgcolor = document->options.default_bg; + document->options.utf8 = is_cp_special(document->options.cp); if (document->options.plain) parser_type = SGML_PARSER_STREAM; diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 63915faf..e9a8a5a4 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -23,6 +23,7 @@ #include "document/refresh.h" #include "document/renderer.h" #include "intl/charsets.h" +#include "osdep/types.h" #include "protocol/uri.h" #include "session/session.h" #include "terminal/color.h" @@ -404,7 +405,7 @@ get_format_screen_char(struct html_context *html_context, /* First possibly do the format change and then find out what coordinates * to use since sub- or superscript might change them */ -static inline void +static inline int set_hline(struct html_context *html_context, unsigned char *chars, int charslen, enum link_state link_state) { @@ -413,34 +414,83 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, link_state); int x = part->cx; int y = part->cy; + int x2 = x; + int len = charslen; + int utf8 = html_context->options->utf8; assert(part); - if_assert_failed return; + if_assert_failed return len; + + assert(charslen >= 0); if (realloc_spaces(part, x + charslen)) - return; + return len; if (part->document) { if (realloc_line(html_context, part->document, Y(y), X(x) + charslen - 1)) - return; + return len; + if (utf8) { + unsigned char *end; - for (; charslen > 0; charslen--, x++, chars++) { - if (*chars == NBSP_CHAR) { - schar->data = ' '; - part->spaces[x] = html_context->options->wrap_nbsp; - } else { - part->spaces[x] = (*chars == ' '); - schar->data = *chars; + for (end = chars + charslen; chars < end; x++) { + if (*chars == NBSP_CHAR) { + schar->data = ' '; + part->spaces[x] = html_context->options->wrap_nbsp; + chars++; + } else { + unicode_val_T data; + + part->spaces[x] = (*chars == ' '); + data = utf_8_to_unicode(&chars, end); + if (data == UCS_NO_CHAR) { + /* HR */ + unsigned char attr = schar->attr; + + schar->data = *chars++; + schar->attr = SCREEN_ATTR_FRAME; + copy_screen_chars(&POS(x, y), schar, 1); + schar->attr = attr; + continue; + } else { + schar->data = (uint16_t)data; + } + } + copy_screen_chars(&POS(x, y), schar, 1); + } + } else { + for (; charslen > 0; charslen--, x++, chars++) { + if (*chars == NBSP_CHAR) { + schar->data = ' '; + part->spaces[x] = html_context->options->wrap_nbsp; + } else { + part->spaces[x] = (*chars == ' '); + schar->data = *chars; + } + copy_screen_chars(&POS(x, y), schar, 1); } - copy_screen_chars(&POS(x, y), schar, 1); } + len = x - x2; } else { - for (; charslen > 0; charslen--, x++, chars++) { - part->spaces[x] = (*chars == ' '); + if (utf8) { + unsigned char *end; + + for (end = chars + charslen; chars < end; x++) { + unicode_val_T data; + + part->spaces[x] = (*chars == ' '); + data = utf_8_to_unicode(&chars, end); + if (data == UCS_NO_CHAR) chars++; + } + len = x - x2; + } else { + for (; charslen > 0; charslen--, x++, chars++) { + part->spaces[x] = (*chars == ' '); + } } } + return len; } static void @@ -1170,7 +1220,7 @@ done_link_state_info(void) static inline void process_link(struct html_context *html_context, enum link_state link_state, - unsigned char *chars, int charslen) + unsigned char *chars, int charslen, int utf8_len) { struct part *part = html_context->part; struct link *link; @@ -1222,6 +1272,7 @@ process_link(struct html_context *html_context, enum link_state link_state, if (x_offset) { charslen -= x_offset; chars += x_offset; + utf8_len -= x_offset; } link = new_link(html_context, chars, charslen); @@ -1236,14 +1287,14 @@ process_link(struct html_context *html_context, enum link_state link_state, } /* Add new canvas positions to the link. */ - if (realloc_points(link, link->npoints + charslen)) { + if (realloc_points(link, link->npoints + utf8_len)) { struct point *point = &link->points[link->npoints]; int x = X(part->cx) + x_offset; int y = Y(part->cy); - link->npoints += charslen; + link->npoints += utf8_len; - for (; charslen > 0; charslen--, point++, x++) { + for (; utf8_len > 0; utf8_len--, point++, x++) { point->x = x; point->y = y; } @@ -1295,6 +1346,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) enum link_state link_state; int update_after_subscript = renderer_context.subscript; struct part *part; + int utf8_len; assert(html_context); if_assert_failed return; @@ -1353,9 +1405,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) else if (html_context->options->links_numbering) put_link_number(html_context); } - - set_hline(html_context, chars, charslen, link_state); - + utf8_len = set_hline(html_context, chars, charslen, link_state); if (link_state != LINK_STATE_NONE) { #define is_drawing_subs_or_sups() \ @@ -1375,15 +1425,15 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) } #undef is_drawing_subs_or_sups - - process_link(html_context, link_state, chars, charslen); + process_link(html_context, link_state, chars, charslen, + utf8_len); } if (renderer_context.nowrap - && part->cx + charslen > overlap(par_format)) + && part->cx + utf8_len > overlap(par_format)) return; - part->cx += charslen; + part->cx += utf8_len; renderer_context.nobreak = 0; if (!(html_context->options->wrap || html_is_preformatted())) { @@ -1399,7 +1449,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) } assert(charslen > 0); - part->xa += charslen; + part->xa += utf8_len; int_lower_bound(&part->max_width, part->xa + par_format.leftmargin + par_format.rightmargin - (chars[charslen - 1] == ' ' @@ -1963,6 +2013,7 @@ render_html_document(struct cache_entry *cached, struct document *document, &document->cp, &document->cp_status, document->options.hard_assume); + html_context->options->utf8 = is_cp_special(document->options.cp); if (title.length) { document->title = convert_string(renderer_context.convert_table, diff --git a/src/document/options.h b/src/document/options.h index a540fd7f..db510b33 100644 --- a/src/document/options.h +++ b/src/document/options.h @@ -71,6 +71,7 @@ struct document_options { unsigned int plain:1; unsigned int wrap:1; + unsigned int utf8:1; /* XXX: Everything past this comment is specialy handled by compare_opt() */ unsigned char *framename; diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index bd4ffa49..f19af844 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -234,8 +234,10 @@ add_document_line(struct plain_renderer *renderer, struct screen_char *template = &renderer->template; struct screen_char saved_renderer_template = *template; struct screen_char *pos, *startpos; + unsigned char *end, *text; int lineno = renderer->lineno; int expanded = 0; + int utf8 = document->options.utf8; int width = line_width; int line_pos; @@ -276,6 +278,7 @@ add_document_line(struct plain_renderer *renderer, assert(expanded >= 0); + if (utf8) goto utf_8; startpos = pos = realloc_line(document, width + expanded, lineno); if (!pos) { mem_free(line); @@ -401,7 +404,139 @@ add_document_line(struct plain_renderer *renderer, *template = saved_renderer_template; } } + 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; + } + } +end: mem_free(line); realloc_line(document, pos - startpos, lineno); @@ -559,6 +694,7 @@ render_plain_document(struct cache_entry *cached, struct document *document, document->bgcolor = document->options.default_bg; document->width = 0; + document->options.utf8 = is_cp_special(document->options.cp); /* Setup the style */ init_template(&renderer.template, &document->options); diff --git a/src/intl/charsets.c b/src/intl/charsets.c index d25c558f..ca564d6a 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -140,6 +140,12 @@ u2cp_(unicode_val_T u, int to, int no_nbsp_hack) int s; if (u < 128) return strings[u]; + + to &= ~SYSTEM_CHARSET_FLAG; + + if (codepages[to].table == table_utf_8) + return encode_utf_8(u); + /* To mark non breaking spaces, we use a special char NBSP_CHAR. */ if (u == 0xa0) return no_nbsp_hack ? " " : NBSP_CHAR_STRING; if (u == 0xad) return ""; @@ -151,7 +157,6 @@ u2cp_(unicode_val_T u, int to, int no_nbsp_hack) return u2cp_(strange, to, no_nbsp_hack); } - to &= ~SYSTEM_CHARSET_FLAG; for (j = 0; codepages[to].table[j].c; j++) if (codepages[to].table[j].u == u) @@ -165,7 +170,7 @@ u2cp_(unicode_val_T u, int to, int no_nbsp_hack) static unsigned char utf_buffer[7]; -static unsigned char * +inline unsigned char * encode_utf_8(unicode_val_T u) { memset(utf_buffer, 0, 7); @@ -200,6 +205,91 @@ encode_utf_8(unicode_val_T u) return utf_buffer; } +inline int +strlen_utf8(unsigned char **str) +{ + unsigned char *s = *str; + unsigned char *end = strchr(s, '\0'); + int x; + int len; + + for (x = 0;; x++, s += len) { + if (*s < 0x80) len = 1; + else if (*s < 0xe0) len = 2; + else if (*s < 0xf0) len = 3; + else if (*s < 0xf8) len = 4; + else if (*s < 0xfc) len = 5; + else len = 6; + if (s + len > end) break; + } + *str = s; + return x; +} + +inline unicode_val_T +utf_8_to_unicode(unsigned char **string, unsigned char *end) +{ + unsigned char *str = *string; + unicode_val_T u; + int length; + + if (str[0] < 0x80) + length = 1; + else if (str[0] < 0xe0) + length = 2; + else if (str[0] < 0xf0) + length = 3; + else if (str[0] < 0xf8) + length = 4; + else if (str[0] < 0xfc) + length = 5; + else + length = 6; + + if (str + length > end) { + return UCS_NO_CHAR; + } + + switch (length) { + case 1: + u = str[0]; + break; + case 2: + u = (str[0] & 0x1f) << 6; + u += (str[1] & 0x3f); + break; + case 3: + u = (str[0] & 0x0f) << 12; + u += ((str[1] & 0x3f) << 6); + u += (str[2] & 0x3f); + break; + case 4: + u = (str[0] & 0x0f) << 18; + u += ((str[1] & 0x3f) << 12); + u += ((str[2] & 0x3f) << 6); + u += (str[3] & 0x3f); + break; + case 5: + u = (str[0] & 0x0f) << 24; + u += ((str[1] & 0x3f) << 18); + u += ((str[2] & 0x3f) << 12); + u += ((str[3] & 0x3f) << 6); + u += (str[4] & 0x3f); + break; + case 6: + default: + u = (str[0] & 0x01) << 30; + u += ((str[1] & 0x3f) << 24); + u += ((str[2] & 0x3f) << 18); + u += ((str[3] & 0x3f) << 12); + u += ((str[4] & 0x3f) << 6); + u += (str[5] & 0x3f); + break; + } + *string = str + length; + return u > 0xffff ? '*' : u; +} + /* This slow and ugly code is used by the terminal utf_8_io */ unsigned char * cp2utf_8(int from, int c) @@ -430,11 +520,16 @@ get_entity_string(const unsigned char *str, const int strlen, int encoding) static struct entity_cache entity_cache[ENTITY_CACHE_MAXLEN][ENTITY_CACHE_SIZE]; static unsigned int nb_entity_cache[ENTITY_CACHE_MAXLEN]; static int first_time = 1; - unsigned int slen; + unsigned int slen = 0; unsigned char *result = NULL; if (strlen <= 0) return NULL; + /* TODO: caching UTF-8 */ + encoding &= ~SYSTEM_CHARSET_FLAG; + if (codepages[encoding].table == table_utf_8) + goto skip; + if (first_time) { memset(&nb_entity_cache, 0, ENTITY_CACHE_MAXLEN * sizeof(unsigned int)); first_time = 0; @@ -488,7 +583,7 @@ get_entity_string(const unsigned char *str, const int strlen, int encoding) fprintf(stderr, "miss\n"); #endif } - +skip: if (*str == '#') { /* Numeric entity. */ int l = (int) strlen; unsigned char *st = (unsigned char *) str; @@ -540,6 +635,9 @@ get_entity_string(const unsigned char *str, const int strlen, int encoding) if (element) result = u2cp(element->c, encoding); } + if (codepages[encoding].table == table_utf_8) { + return result; + } end: /* Take care of potential buffer overflow. */ if (strlen < sizeof(entity_cache[slen][0].str)) { diff --git a/src/intl/charsets.h b/src/intl/charsets.h index b99d3e67..364c484d 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -53,6 +53,10 @@ unsigned char *get_cp_name(int); unsigned char *get_cp_mime_name(int); int is_cp_special(int); void free_conv_table(void); +inline unsigned char *encode_utf_8(unicode_val_T); +inline int strlen_utf8(unsigned char **); +inline unicode_val_T utf_8_to_unicode(unsigned char **, unsigned char *); + unsigned char *cp2utf_8(int, int); unsigned char *u2cp_(unicode_val_T, int, int no_nbsp_hack); diff --git a/src/terminal/draw.c b/src/terminal/draw.c index b691f23b..b44b8b9c 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -7,6 +7,7 @@ #include "elinks.h" #include "config/options.h" +#include "intl/charsets.h" #include "terminal/color.h" #include "terminal/draw.h" #include "terminal/screen.h" @@ -102,7 +103,7 @@ draw_char_color(struct terminal *term, int x, int y, struct color_pair *color) } void -draw_char_data(struct terminal *term, int x, int y, unsigned char data) +draw_char_data(struct terminal *term, int x, int y, uint16_t data) { struct screen_char *screen_char = get_char(term, x, y); @@ -200,7 +201,7 @@ draw_border(struct terminal *term, struct box *box, void draw_char(struct terminal *term, int x, int y, - unsigned char data, enum screen_char_attr attr, + uint16_t data, enum screen_char_attr attr, struct color_pair *color) { struct screen_char *screen_char = get_char(term, x, y); @@ -277,6 +278,41 @@ draw_shadow(struct terminal *term, struct box *box, draw_box(term, &dbox, ' ', 0, color); } +static void +draw_text_utf8(struct terminal *term, int x, int y, + unsigned char *text, int length, + enum screen_char_attr attr, struct color_pair *color) +{ + struct screen_char *start, *pos; + unsigned char *end = text + length; + unicode_val_T data; + + assert(text && length >= 0); + if_assert_failed return; + + if (length <= 0) return; + if (x >= term->width) return; + + data = utf_8_to_unicode(&text, end); + if (data == UCS_NO_CHAR) return; + start = get_char(term, x++, y); + start->data = (uint16_t)data; + if (color) { + start->attr = attr; + set_term_color(start, color, 0, + get_opt_int_tree(term->spec, "colors")); + } + + for (pos = start + 1; x < term->width; x++, pos++) { + data = utf_8_to_unicode(&text, end); + if (data == UCS_NO_CHAR) break; + if (color) copy_screen_chars(pos, start, 1); + pos->data = (uint16_t)data; + } + set_screen_dirty(term->screen, y, y); + +} + void draw_text(struct terminal *term, int x, int y, unsigned char *text, int length, @@ -288,6 +324,11 @@ draw_text(struct terminal *term, int x, int y, assert(text && length >= 0); if_assert_failed return; + if (term->utf8) { + draw_text_utf8(term, x, y, text, length, attr, color); + return; + } + if (length <= 0) return; pos = get_char(term, x, y); if (!pos) return; diff --git a/src/terminal/draw.h b/src/terminal/draw.h index fd9a6812..8b1e6f63 100644 --- a/src/terminal/draw.h +++ b/src/terminal/draw.h @@ -19,7 +19,7 @@ enum screen_char_attr { /* One position in the terminal screen's image. */ struct screen_char { /* Contains either character value or frame data. */ - unsigned char data; + uint16_t data; /* Attributes are screen_char_attr bits. */ unsigned char attr; @@ -202,7 +202,7 @@ void draw_char_color(struct terminal *term, int x, int y, struct color_pair *color); /* Sets the data of a screen position. */ -void draw_char_data(struct terminal *term, int x, int y, unsigned char data); +void draw_char_data(struct terminal *term, int x, int y, uint16_t data); /* Sets the data to @border and of a screen position. */ void draw_border_char(struct terminal *term, int x, int y, @@ -214,7 +214,7 @@ void draw_border_cross(struct terminal *, int x, int y, /* Draws a char. */ void draw_char(struct terminal *term, int x, int y, - unsigned char data, enum screen_char_attr attr, + uint16_t data, enum screen_char_attr attr, struct color_pair *color); /* Draws area defined by @box using the same colors and attributes. */ diff --git a/src/terminal/event.c b/src/terminal/event.c index 37e86b37..29c61d33 100644 --- a/src/terminal/event.c +++ b/src/terminal/event.c @@ -245,7 +245,6 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) case EVENT_KBD: { - int utf8_io = -1; int key = get_kbd_key(ev); reset_timer(); @@ -260,9 +259,7 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) } if (interlink->utf_8.len) { - utf8_io = get_opt_bool_tree(term->spec, "utf_8_io"); - - if ((key & 0xC0) == 0x80 && utf8_io) { + if ((key & 0xC0) == 0x80 && term->utf8) { interlink->utf_8.ucs <<= 6; interlink->utf_8.ucs |= key & 0x3F; if (! --interlink->utf_8.len) { @@ -280,15 +277,14 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) } } - if (key < 0x80 || key > 0xFF - || (utf8_io == -1 - ? !get_opt_bool_tree(term->spec, "utf_8_io") - : !utf8_io)) { + if (key < 0x80 || key > 0xFF || !term->utf8) { term_send_event(term, ev); break; - } else if ((key & 0xC0) == 0xC0 && (key & 0xFE) != 0xFE) { + } + + else if ((key & 0xC0) == 0xC0 && (key & 0xFE) != 0xFE) { unsigned int mask, cov = 0x80; int len = 0; diff --git a/src/terminal/screen.c b/src/terminal/screen.c index 1d44f595..a4ac73ba 100644 --- a/src/terminal/screen.c +++ b/src/terminal/screen.c @@ -30,6 +30,7 @@ unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ "; static unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla "; +#if 0 /* For UTF8 I/O */ static unsigned char frame_vt100_u[48] = { 177, 177, 177, 179, 180, 180, 180, 191, @@ -39,6 +40,7 @@ static unsigned char frame_vt100_u[48] = { 193, 194, 194, 192, 192, 218, 218, 197, 197, 217, 218, 177, 32, 32, 32, 32 }; +#endif static unsigned char frame_freebsd[48] = { 130, 138, 128, 153, 150, 150, 150, 140, @@ -78,6 +80,11 @@ static struct string m11_hack_frame_seqs[] = { /* begin border: */ TERM_STRING("\033[11m"), }; +static struct string utf8_linux_frame_seqs[] = { + /* end border: */ TERM_STRING("\033[10m\033%G"), + /* begin border: */ TERM_STRING("\033%@\033[11m"), +}; + static struct string vt100_frame_seqs[] = { /* end border: */ TERM_STRING("\x0f"), /* begin border: */ TERM_STRING("\x0e"), @@ -99,11 +106,6 @@ struct screen_driver { * uniquely identify the screen_driver. */ enum term_mode_type type; - /* Charsets when doing UTF8 I/O. */ - /* [0] is the common charset and [1] is the frame charset. - * Test wether to use UTF8 I/O using the use_utf8_io() macro. */ - int charsets[2]; - /* The frame translation table. May be NULL. */ unsigned char *frame; @@ -119,6 +121,9 @@ struct screen_driver { /* These are directly derived from the terminal options. */ unsigned int transparent:1; + /* UTF-8 I/O */ + unsigned int utf8:1; + /* The terminal._template_ name. */ unsigned char name[1]; /* XXX: Keep last! */ }; @@ -126,56 +131,56 @@ struct screen_driver { static struct screen_driver dumb_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_DUMB, - /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_dumb, /* frame_seqs: */ NULL, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, + /* utf-8: */ 0, }; static struct screen_driver vt100_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_VT100, - /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_vt100, /* frame_seqs: */ vt100_frame_seqs, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, + /* utf-8: */ 0, }; static struct screen_driver linux_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_LINUX, - /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ NULL, /* No restrict_852 */ /* frame_seqs: */ NULL, /* No m11_hack */ /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, + /* utf-8: */ 0, }; static struct screen_driver koi8_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_KOI8, - /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_koi, /* frame_seqs: */ NULL, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, + /* utf-8: */ 0, }; static struct screen_driver freebsd_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_FREEBSD, - /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_freebsd, /* frame_seqs: */ NULL, /* No m11_hack */ /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, + /* utf-8: */ 0, }; /* XXX: Keep in sync with enum term_mode_type. */ @@ -187,13 +192,14 @@ static struct screen_driver *screen_drivers[] = { /* TERM_FREEBSD: */ &freebsd_screen_driver, }; +#define use_utf8_io(driver) ((driver)->utf8) static INIT_LIST_HEAD(active_screen_drivers); static void update_screen_driver(struct screen_driver *driver, struct option *term_spec) { - int utf8_io = get_opt_bool_tree(term_spec, "utf_8_io"); + driver->utf8 = get_opt_bool_tree(term_spec, "utf_8_io"); driver->color_mode = get_opt_int_tree(term_spec, "colors"); driver->transparent = get_opt_bool_tree(term_spec, "transparency"); @@ -204,44 +210,22 @@ update_screen_driver(struct screen_driver *driver, struct option *term_spec) driver->underline = NULL; } - if (utf8_io) { - driver->charsets[0] = get_opt_codepage_tree(term_spec, "charset"); - if (driver->type == TERM_LINUX) { - if (get_opt_bool_tree(term_spec, "restrict_852")) - driver->frame = frame_restrict; + if (driver->type == TERM_LINUX) { + if (get_opt_bool_tree(term_spec, "restrict_852")) + driver->frame = frame_restrict; - driver->charsets[1] = get_cp_index("cp437"); + if (get_opt_bool_tree(term_spec, "m11_hack")) + driver->frame_seqs = m11_hack_frame_seqs; - } else if (driver->type == TERM_FREEBSD) { - driver->charsets[1] = get_cp_index("cp437"); + if (driver->utf8) + driver->frame_seqs = utf8_linux_frame_seqs; - } else if (driver->type == TERM_VT100) { - driver->frame = frame_vt100_u; - driver->charsets[1] = get_cp_index("cp437"); + } else if (driver->type == TERM_FREEBSD) { + if (get_opt_bool_tree(term_spec, "m11_hack")) + driver->frame_seqs = m11_hack_frame_seqs; - } else if (driver->type == TERM_KOI8) { - driver->charsets[1] = get_cp_index("koi8-r"); - - } else { - driver->charsets[1] = driver->charsets[0]; - } - - } else { - driver->charsets[0] = -1; - if (driver->type == TERM_LINUX) { - if (get_opt_bool_tree(term_spec, "restrict_852")) - driver->frame = frame_restrict; - - if (get_opt_bool_tree(term_spec, "m11_hack")) - driver->frame_seqs = m11_hack_frame_seqs; - - } else if (driver->type == TERM_FREEBSD) { - if (get_opt_bool_tree(term_spec, "m11_hack")) - driver->frame_seqs = m11_hack_frame_seqs; - - } else if (driver->type == TERM_VT100) { - driver->frame = frame_vt100; - } + } else if (driver->type == TERM_VT100) { + driver->frame = frame_vt100; } } @@ -281,6 +265,8 @@ add_screen_driver(enum term_mode_type type, struct terminal *term, int env_len) term->spec->change_hook = screen_driver_change_hook; + term->utf8 = use_utf8_io(driver); + return driver; } @@ -299,6 +285,7 @@ get_screen_driver(struct terminal *term) /* Some simple probably useless MRU ;) */ move_to_top_of_list(active_screen_drivers, driver); + term->utf8 = use_utf8_io(driver); return driver; } @@ -364,11 +351,10 @@ struct screen_state { #define compare_bg_color(a, b) (TERM_COLOR_BACKGROUND(a) == TERM_COLOR_BACKGROUND(b)) #define compare_fg_color(a, b) (TERM_COLOR_FOREGROUND(a) == TERM_COLOR_FOREGROUND(b)) -#define use_utf8_io(driver) ((driver)->charsets[0] != -1) static inline void add_char_data(struct string *screen, struct screen_driver *driver, - unsigned char data, unsigned char border) + unicode_val_T data, unsigned char border) { if (!isscreensafe(data)) { add_char_to_string(screen, ' '); @@ -379,13 +365,15 @@ add_char_data(struct string *screen, struct screen_driver *driver, data = driver->frame[data - 176]; if (use_utf8_io(driver)) { - int charset = driver->charsets[!!border]; - - add_to_string(screen, cp2utf_8(charset, data)); + if (border) + add_char_to_string(screen, (unsigned char)data); + else + if (data != UCS_NO_CHAR) + add_to_string(screen, encode_utf_8(data)); return; } - add_char_to_string(screen, data); + add_char_to_string(screen, (unsigned char)data); } /* Time critical section. */ diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index 0689f098..685afb0a 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -110,6 +110,9 @@ struct terminal { * work and even maintaining these structures ;-). */ unsigned int master:1; + /* Indicates whether UTF-8 I/O is used */ + unsigned int utf8:1; + /* The current tab number. */ int current_tab; diff --git a/src/viewer/dump/dump.c b/src/viewer/dump/dump.c index dc12ca5c..6a50fa04 100644 --- a/src/viewer/dump/dump.c +++ b/src/viewer/dump/dump.c @@ -26,6 +26,7 @@ #include "document/options.h" #include "document/renderer.h" #include "document/view.h" +#include "intl/charsets.h" #include "intl/gettext/libintl.h" #include "main/select.h" #include "main/main.h" @@ -322,6 +323,9 @@ add_document_to_string(struct string *string, struct document *document) assert(string && document); if_assert_failed return NULL; + if (is_cp_special(document->options.cp)) + goto utf_8; + for (y = 0; y < document->height; y++) { int white = 0; int x; @@ -354,7 +358,43 @@ add_document_to_string(struct string *string, struct document *document) add_char_to_string(string, '\n'); } + goto end; +utf_8: + for (y = 0; y < document->height; y++) { + struct screen_char *pos = document->data[y].chars; + int white = 0; + int x; + for (x = 0; x < document->data[y].length; x++) { + uint16_t data = pos->data; + unsigned int frame = (pos->attr & SCREEN_ATTR_FRAME); + + if (!isscreensafe(data)) { + white++; + continue; + } else if (frame && data >= 176 && data < 224) { + data = frame_dumb[data - 176]; + + if (data <= ' ') { + /* Count spaces. */ + white++; + } else { + /* Print spaces if any. */ + if (white) { + add_xchar_to_string(string, ' ', white); + white = 0; + } + if (frame) + add_char_to_string(string, data); + else + add_to_string(string, encode_utf_8(data)); + } + } + } + + add_char_to_string(string, '\n'); + } +end: return string; } @@ -382,6 +422,9 @@ dump_to_file(struct document *document, int fd) if (!buf) return -1; + if (is_cp_special(document->options.cp)) + goto utf_8; + for (y = 0; y < document->height; y++) { int white = 0; int x; @@ -418,13 +461,60 @@ dump_to_file(struct document *document, int fd) if (write_char('\n', fd, buf, &bptr)) goto fail; } + goto ref; +utf_8: + for (y = 0; y < document->height; y++) { + int white = 0; + int x; + + for (x = 0; x < document->data[y].length; x++) { + uint16_t c; + unsigned char attr = document->data[y].chars[x].attr; + + c = document->data[y].chars[x].data; + + if ((attr & SCREEN_ATTR_FRAME) + && c >= 176 && c < 224) + c = frame_dumb[c - 176]; + else { + unsigned char *utf8_buf = encode_utf_8(c); + + while (*utf8_buf) { + if (write_char(*utf8_buf++, + fd, buf, &bptr)) goto fail; + } + continue; + } + + if (c <= ' ') { + /* Count spaces. */ + white++; + continue; + } + + /* Print spaces if any. */ + while (white) { + if (write_char(' ', fd, buf, &bptr)) + goto fail; + white--; + } + + /* Print normal char. */ + if (write_char(c, fd, buf, &bptr)) + goto fail; + } + + /* Print end of line. */ + if (write_char('\n', fd, buf, &bptr)) + goto fail; + } if (hard_write(fd, buf, bptr) != bptr) { fail: mem_free(buf); return -1; } - +ref: if (document->nlinks && get_opt_bool("document.dump.references")) { int x; unsigned char *header = "\nReferences\n\n Visible links\n"; diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 90b809f1..3b3f499e 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -158,16 +158,22 @@ init_form_state(struct form_control *fc, struct form_state *fs) mem_free_set(&fs->value, NULL); switch (fc->type) { + unsigned char *text; + case FC_TEXT: case FC_PASSWORD: case FC_TEXTAREA: fs->value = stracpy(fc->default_value); fs->state = strlen(fc->default_value); + text = fs->value; + if (fc->type != FC_TEXTAREA) + fs->utf8_pos = strlen_utf8(&text); fs->vpos = 0; break; case FC_FILE: fs->value = stracpy(""); fs->state = 0; + fs->utf8_pos = 0; fs->vpos = 0; break; case FC_SELECT: @@ -330,12 +336,14 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, dy = box->y - vs->y; switch (fc->type) { unsigned char *s; + unsigned char *text, *end; int len; int i, x, y; case FC_TEXT: case FC_PASSWORD: case FC_FILE: + if (term->utf8) goto utf_8; int_bounds(&fs->vpos, fs->state - fc->size + 1, fs->state); if (!link->npoints) break; @@ -360,6 +368,36 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, draw_char_data(term, x, y, data); } break; +utf_8: + text = fs->value; + end = strchr(text, '\0'); + int_bounds(&fs->vpos, fs->utf8_pos - fc->size + 1, fs->utf8_pos); + if (!link->npoints) break; + + y = link->points[0].y + dy; + if (!row_is_in_box(box, y)) + break; + for (i = 0; i < fs->vpos; i++) { + utf_8_to_unicode(&text, end); + } + s = text; + len = strlen_utf8(&s); + x = link->points[0].x + dx; + + for (i = 0; i < fc->size; i++, x++) { + uint16_t data; + + if (!col_is_in_box(box, x)) continue; + + if (fs->value && i >= -fs->vpos && i < len) + data = fc->type != FC_PASSWORD + ? utf_8_to_unicode(&text, end) : '*'; + else + data = '_'; + + draw_char_data(term, x, y, data); + } + break; case FC_TEXTAREA: draw_textarea(term, fs, doc_view, link); break; @@ -378,6 +416,7 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, else /* XXX: when can this happen? --pasky */ s = ""; + if (term->utf8) goto utf_8_select; len = s ? strlen(s) : 0; for (i = 0; i < link->npoints; i++) { x = link->points[i].x + dx; @@ -386,6 +425,18 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, draw_char_data(term, x, y, i < len ? s[i] : '_'); } break; +utf_8_select: + text = s; + end = strchr(s, '\0'); + len = strlen_utf8(&text); + for (i = 0; i < link->npoints; i++) { + x = link->points[i].x + dx; + y = link->points[i].y + dy; + if (is_in_box(box, x, y)) + draw_char_data(term, x, y, i < len + ? utf_8_to_unicode(&s, end) : '_'); + } + break; case FC_SUBMIT: case FC_IMAGE: case FC_RESET: @@ -1195,6 +1246,7 @@ field_op(struct session *ses, struct document_view *doc_view, unsigned char *text; int length; enum frame_event_status status = FRAME_EVENT_REFRESH; + int utf8 = ses->tab->term->utf8; assert(ses && doc_view && link && ev); if_assert_failed return FRAME_EVENT_OK; @@ -1214,49 +1266,79 @@ field_op(struct session *ses, struct document_view *doc_view, switch (action_id) { case ACT_EDIT_LEFT: - fs->state = int_max(fs->state - 1, 0); + if (utf8) { + unsigned char *text = fs->value; + unsigned char *end = fs->value + fs->state - 1; + int old = fs->state; + + while (utf_8_to_unicode(&text, end) != UCS_NO_CHAR); + fs->state = (int)(text - fs->value); + if (old != fs->state) fs->utf8_pos--; + } else + fs->state = int_max(fs->state - 1, 0); break; case ACT_EDIT_RIGHT: - fs->state = int_min(fs->state + 1, strlen(fs->value)); + if (utf8) { + unsigned char *text = fs->value + fs->state; + unsigned char *end = strchr(text, '\0'); + int old = fs->state; + + utf_8_to_unicode(&text, end); + fs->state = (int)(text - fs->value); + if (old != fs->state) fs->utf8_pos++; + } else + fs->state = int_min(fs->state + 1, strlen(fs->value)); break; case ACT_EDIT_HOME: if (fc->type == FC_TEXTAREA) { - status = textarea_op_home(fs, fc); + status = textarea_op_home(fs, fc, utf8); } else { fs->state = 0; + fs->utf8_pos = 0; } break; case ACT_EDIT_UP: if (fc->type != FC_TEXTAREA) status = FRAME_EVENT_IGNORED; else - status = textarea_op_up(fs, fc); + status = textarea_op_up(fs, fc, utf8); break; case ACT_EDIT_DOWN: if (fc->type != FC_TEXTAREA) status = FRAME_EVENT_IGNORED; else - status = textarea_op_down(fs, fc); + status = textarea_op_down(fs, fc, utf8); break; case ACT_EDIT_END: if (fc->type == FC_TEXTAREA) { - status = textarea_op_end(fs, fc); + status = textarea_op_end(fs, fc, utf8); } else { fs->state = strlen(fs->value); + if (utf8) { + unsigned char *text = fs->value; + + fs->utf8_pos = strlen_utf8(&text); + } } break; case ACT_EDIT_BEGINNING_OF_BUFFER: if (fc->type == FC_TEXTAREA) { - status = textarea_op_bob(fs, fc); + status = textarea_op_bob(fs, fc, utf8); } else { fs->state = 0; + fs->utf8_pos = 0; } break; case ACT_EDIT_END_OF_BUFFER: if (fc->type == FC_TEXTAREA) { - status = textarea_op_eob(fs, fc); + status = textarea_op_eob(fs, fc, utf8); } else { fs->state = strlen(fs->value); + if (utf8) { + unsigned char *text = fs->value; + + fs->utf8_pos = strlen_utf8(&text); + } } break; case ACT_EDIT_OPEN_EXTERNAL: @@ -1274,6 +1356,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (!form_field_is_readonly(fc)) fs->value[0] = 0; fs->state = 0; + fs->utf8_pos = 0; break; case ACT_EDIT_PASTE_CLIPBOARD: if (form_field_is_readonly(fc)) break; @@ -1289,13 +1372,19 @@ field_op(struct session *ses, struct document_view *doc_view, fs->value = v; memmove(v, text, length + 1); fs->state = strlen(fs->value); + if (utf8 && fc->type != FC_TEXTAREA) { + unsigned char *text = fs->value; + + fs->utf8_pos = strlen_utf8(&text); + } + } } mem_free(text); break; case ACT_EDIT_ENTER: if (fc->type == FC_TEXTAREA) { - status = textarea_op_enter(fs, fc); + status = textarea_op_enter(fs, fc, utf8); break; } @@ -1320,7 +1409,19 @@ field_op(struct session *ses, struct document_view *doc_view, status = FRAME_EVENT_OK; break; } + if (utf8) { + int i; + unsigned char *text = fs->value; + unsigned char *end = fs->value + fs->state; + for (i = 0; i < fs->utf8_pos - 1; i++) + utf_8_to_unicode(&text, end); + length = strlen(end) + 1; + memmove(text, end, length); + fs->state = (int)(text - fs->value); + fs->utf8_pos--; + break; + } length = strlen(fs->value + fs->state) + 1; text = fs->value + fs->state; @@ -1338,7 +1439,18 @@ field_op(struct session *ses, struct document_view *doc_view, status = FRAME_EVENT_OK; break; } + if (utf8) { + unsigned char *end = fs->value + length; + unsigned char *text = fs->value + fs->state; + unsigned char *old = text; + utf_8_to_unicode(&text, end); + if (old != text) { + memmove(old, text, + (int)(end - text) + 1); + } + break; + } text = fs->value + fs->state; memmove(text, text + 1, length - fs->state); @@ -1368,6 +1480,11 @@ field_op(struct session *ses, struct document_view *doc_view, memmove(text, fs->value + fs->state, length); fs->state = (int) (text - fs->value); + if (utf8 && fc->type != FC_TEXTAREA) { + unsigned char *text = fs->value; + + fs->utf8_pos = strlen_utf8(&text); + } break; case ACT_EDIT_KILL_TO_EOL: if (form_field_is_readonly(fc)) { @@ -1421,13 +1538,41 @@ field_op(struct session *ses, struct document_view *doc_view, } if (form_field_is_readonly(fc) - || strlen(fs->value) >= fc->maxlength - || !insert_in_string(&fs->value, fs->state, "?", 1)) { + || strlen(fs->value) >= fc->maxlength) { status = FRAME_EVENT_OK; break; } + if (utf8) { + static unsigned char buf[7]; + static int i = 0; + unicode_val_T data; + unsigned char *t; - fs->value[fs->state++] = get_kbd_key(ev); + t = buf; + buf[i++] = get_kbd_key(ev); + buf[i] = 0; + data = utf_8_to_unicode(&t, buf + i); + if (data != UCS_NO_CHAR) { + if (!insert_in_string(&fs->value, fs->state, buf, i)) { + i = 0; + return FRAME_EVENT_OK; + } + fs->state += i; + fs->utf8_pos++; + i = 0; + break; + } + if (i == 6) { + i = 0; + return FRAME_EVENT_OK; + } else { + return FRAME_EVENT_OK; + } + } else { + if (!insert_in_string(&fs->value, fs->state, "?", 1)) + return FRAME_EVENT_OK; + fs->value[fs->state++] = get_kbd_key(ev); + } break; } diff --git a/src/viewer/text/form.h b/src/viewer/text/form.h index 1bf47982..fd034cfb 100644 --- a/src/viewer/text/form.h +++ b/src/viewer/text/form.h @@ -39,6 +39,7 @@ struct form_state { unsigned char *value; int state; + int utf8_pos; int vpos; int vypos; diff --git a/src/viewer/text/link.c b/src/viewer/text/link.c index d9a0617d..2fec2f42 100644 --- a/src/viewer/text/link.c +++ b/src/viewer/text/link.c @@ -112,6 +112,7 @@ get_link_cursor_offset(struct document_view *doc_view, struct link *link) { struct form_control *fc; struct form_state *fs; + int utf8 = doc_view->document->options.utf8; switch (link->type) { case LINK_CHECKBOX: @@ -123,12 +124,15 @@ get_link_cursor_offset(struct document_view *doc_view, struct link *link) case LINK_FIELD: fc = get_link_form_control(link); fs = find_form_state(doc_view, fc); - return fs ? fs->state - fs->vpos : 0; + if (utf8) { + return fs ? fs->utf8_pos - fs->vpos : 0; + } else + return fs ? fs->state - fs->vpos : 0; case LINK_AREA: fc = get_link_form_control(link); fs = find_form_state(doc_view, fc); - return fs ? area_cursor(fc, fs) : 0; + return fs ? area_cursor(fc, fs, utf8) : 0; case LINK_HYPERTEXT: case LINK_MAP: diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index 6d5b512e..e4ecdc9c 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -138,7 +138,7 @@ get_textarea_line_number(struct line_info *line, int cursor_position) /* Fixes up the vpos and vypos members of the form_state. Returns the * logical position in the textarea view. */ int -area_cursor(struct form_control *fc, struct form_state *fs) +area_cursor(struct form_control *fc, struct form_state *fs, int utf8) { struct line_info *line; int x, y; @@ -155,7 +155,15 @@ area_cursor(struct form_control *fc, struct form_state *fs) return 0; } - x = fs->state - line[y].start; + if (utf8) { + unsigned char *text = fs->value + line[y].start; + unsigned char tmp = fs->value[fs->state]; + + fs->value[fs->state] = '\0'; + x = strlen_utf8(&text); + fs->value[fs->state] = tmp; + } else + x = fs->state - line[y].start; mem_free(line); @@ -170,8 +178,8 @@ area_cursor(struct form_control *fc, struct form_state *fs) return y * fc->cols + x; } -void -draw_textarea(struct terminal *term, struct form_state *fs, +static void +draw_textarea_utf8(struct terminal *term, struct form_state *fs, struct document_view *doc_view, struct link *link) { struct line_info *line, *linex; @@ -192,7 +200,91 @@ draw_textarea(struct terminal *term, struct form_state *fs, vy = doc_view->vs->y; if (!link->npoints) return; - area_cursor(fc, fs); + area_cursor(fc, fs, 1); + linex = format_text(fs->value, fc->cols, fc->wrap, 0); + if (!linex) return; + line = linex; + sl = fs->vypos; + while (line->start != -1 && sl) sl--, line++; + + x = link->points[0].x + box->x - vx; + y = link->points[0].y + box->y - vy; + ye = y + fc->rows; + + for (; line->start != -1 && y < ye; line++, y++) { + int i; + unsigned char *text, *end; + + text = fs->value + line->start; + end = fs->value + line->end; + + for (i = 0; i < fs->vpos; i++) + utf_8_to_unicode(&text, end); + + if (!row_is_in_box(box, y)) continue; + + for (i = 0; i < fc->cols; i++) { + uint16_t data; + int xi = x + i; + + if (!col_is_in_box(box, xi)) + continue; + + if (i >= -fs->vpos + && text < end) + data = utf_8_to_unicode(&text, end); + else + data = '_'; + + draw_char_data(term, xi, y, data); + } + } + + for (; y < ye; y++) { + int i; + + if (!row_is_in_box(box, y)) continue; + + for (i = 0; i < fc->cols; i++) { + int xi = x + i; + + if (col_is_in_box(box, xi)) + draw_char_data(term, xi, y, '_'); + } + } + + mem_free(linex); +} + + +void +draw_textarea(struct terminal *term, struct form_state *fs, + struct document_view *doc_view, struct link *link) +{ + struct line_info *line, *linex; + struct form_control *fc; + struct box *box; + int vx, vy; + int sl, ye; + int x, y; + + assert(term && doc_view && doc_view->document && doc_view->vs && link); + if_assert_failed return; + + if (term->utf8) { + draw_textarea_utf8(term, fs, doc_view, link); + return; + } + fc = get_link_form_control(link); + assertm(fc, "link %d has no form control", (int) (link - doc_view->document->links)); + if_assert_failed return; + + box = &doc_view->box; + vx = doc_view->vs->x; + vy = doc_view->vs->y; + + if (!link->npoints) return; + area_cursor(fc, fs, 0); linex = format_text(fs->value, fc->cols, fc->wrap, 0); if (!linex) return; line = linex; @@ -448,8 +540,8 @@ menu_textarea_edit(struct terminal *term, void *xxx, void *ses_) } static enum frame_event_status -textarea_op(struct form_state *fs, struct form_control *fc, - int (*do_op)(struct form_state *, struct line_info *, int)) +textarea_op(struct form_state *fs, struct form_control *fc, int utf8, + int (*do_op)(struct form_state *, struct line_info *, int, int)) { struct line_info *line; int current, state; @@ -462,47 +554,87 @@ textarea_op(struct form_state *fs, struct form_control *fc, current = get_textarea_line_number(line, fs->state); state = fs->state; - if (do_op(fs, line, current)) { + if (do_op(fs, line, current, utf8)) { mem_free(line); return FRAME_EVENT_IGNORED; } mem_free(line); - return fs->state == state ? FRAME_EVENT_OK : FRAME_EVENT_REFRESH; } static int -do_op_home(struct form_state *fs, struct line_info *line, int current) +x_pos(struct form_state *fs, struct line_info *line, int current) +{ + unsigned char *text = fs->value + line[current].start; + unsigned char tmp = fs->value[fs->state]; + int len; + + fs->value[fs->state] = '\0'; + len = strlen_utf8(&text); + fs->value[fs->state] = tmp; + return len; +} + +static void +new_pos(struct form_state *fs, struct line_info *line, int current, int len) +{ + unsigned char *text = fs->value + line[current].start; + unsigned char *end = fs->value + line[current].end; + int i; + + for (i = 0; i < len; i++) { + unicode_val_T data = utf_8_to_unicode(&text, end); + + if (data == UCS_NO_CHAR) break; + } + fs->state = (int)(text - fs->value); +} + +static int +do_op_home(struct form_state *fs, struct line_info *line, int current, int utf8) { if (current != -1) fs->state = line[current].start; return 0; } static int -do_op_up(struct form_state *fs, struct line_info *line, int current) +do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) { if (current == -1) return 0; if (!current) return 1; + if (utf8) { + int len = x_pos(fs, line, current); + + new_pos(fs, line, current - 1, len); + return 0; + } + fs->state -= line[current].start - line[current-1].start; int_upper_bound(&fs->state, line[current-1].end); return 0; } static int -do_op_down(struct form_state *fs, struct line_info *line, int current) +do_op_down(struct form_state *fs, struct line_info *line, int current, int utf8) { if (current == -1) return 0; if (line[current+1].start == -1) return 1; + if (utf8) { + int len = x_pos(fs, line, current); + + new_pos(fs, line, current + 1, len); + return 0; + } fs->state += line[current+1].start - line[current].start; int_upper_bound(&fs->state, line[current+1].end); return 0; } static int -do_op_end(struct form_state *fs, struct line_info *line, int current) +do_op_end(struct form_state *fs, struct line_info *line, int current, int utf8) { if (current == -1) { fs->state = strlen(fs->value); @@ -517,7 +649,7 @@ do_op_end(struct form_state *fs, struct line_info *line, int current) } static int -do_op_bob(struct form_state *fs, struct line_info *line, int current) +do_op_bob(struct form_state *fs, struct line_info *line, int current, int utf8) { if (current == -1) return 0; @@ -527,7 +659,7 @@ do_op_bob(struct form_state *fs, struct line_info *line, int current) } static int -do_op_eob(struct form_state *fs, struct line_info *line, int current) +do_op_eob(struct form_state *fs, struct line_info *line, int current, int utf8) { if (current == -1) { fs->state = strlen(fs->value); @@ -544,35 +676,35 @@ do_op_eob(struct form_state *fs, struct line_info *line, int current) } enum frame_event_status -textarea_op_home(struct form_state *fs, struct form_control *fc) +textarea_op_home(struct form_state *fs, struct form_control *fc, int utf8) { - return textarea_op(fs, fc, do_op_home); + return textarea_op(fs, fc, utf8, do_op_home); } enum frame_event_status -textarea_op_up(struct form_state *fs, struct form_control *fc) +textarea_op_up(struct form_state *fs, struct form_control *fc, int utf8) { - return textarea_op(fs, fc, do_op_up); + return textarea_op(fs, fc, utf8, do_op_up); } enum frame_event_status -textarea_op_down(struct form_state *fs, struct form_control *fc) +textarea_op_down(struct form_state *fs, struct form_control *fc, int utf8) { - return textarea_op(fs, fc, do_op_down); + return textarea_op(fs, fc, utf8, do_op_down); } enum frame_event_status -textarea_op_end(struct form_state *fs, struct form_control *fc) +textarea_op_end(struct form_state *fs, struct form_control *fc, int utf8) { - return textarea_op(fs, fc, do_op_end); + return textarea_op(fs, fc, utf8, do_op_end); } /* Set the form state so the cursor is on the first line of the buffer. * Preserve the column if possible. */ enum frame_event_status -textarea_op_bob(struct form_state *fs, struct form_control *fc) +textarea_op_bob(struct form_state *fs, struct form_control *fc, int utf8) { - return textarea_op(fs, fc, do_op_bob); + return textarea_op(fs, fc, utf8, do_op_bob); } /* Set the form state so the cursor is on the last line of the buffer. Preserve @@ -580,13 +712,13 @@ textarea_op_bob(struct form_state *fs, struct form_control *fc) * then shifting the state by the delta of both lines start position bounding * the whole thing to the end of the last line. */ enum frame_event_status -textarea_op_eob(struct form_state *fs, struct form_control *fc) +textarea_op_eob(struct form_state *fs, struct form_control *fc, int utf8) { - return textarea_op(fs, fc, do_op_eob); + return textarea_op(fs, fc, utf8, do_op_eob); } enum frame_event_status -textarea_op_enter(struct form_state *fs, struct form_control *fc) +textarea_op_enter(struct form_state *fs, struct form_control *fc, int utf8) { assert(fs && fs->value && fc); if_assert_failed return FRAME_EVENT_OK; @@ -607,6 +739,7 @@ set_textarea(struct document_view *doc_view, int direction) struct form_control *fc; struct form_state *fs; struct link *link; + int utf8 = doc_view->document->options.utf8; assert(doc_view && doc_view->vs && doc_view->document); assert(direction == 1 || direction == -1); @@ -628,7 +761,7 @@ set_textarea(struct document_view *doc_view, int direction) /* Depending on which way we entered the textarea move cursor so that * it is available at end or start. */ if (direction == 1) - textarea_op_eob(fs, fc); + textarea_op_eob(fs, fc, utf8); else - textarea_op_bob(fs, fc); + textarea_op_bob(fs, fc, utf8); } diff --git a/src/viewer/text/textarea.h b/src/viewer/text/textarea.h index 03e67070..0a27f58f 100644 --- a/src/viewer/text/textarea.h +++ b/src/viewer/text/textarea.h @@ -13,7 +13,7 @@ struct link; struct session; struct terminal; -int area_cursor(struct form_control *fc, struct form_state *fs); +int area_cursor(struct form_control *fc, struct form_state *fs, int utf8); void draw_textarea(struct terminal *term, struct form_state *fs, struct document_view *doc_view, struct link *link); unsigned char *encode_textarea(struct submitted_value *sv); @@ -21,13 +21,13 @@ extern int textarea_editor; void textarea_edit(int, struct terminal *, struct form_state *, struct document_view *, struct link *); void menu_textarea_edit(struct terminal *term, void *xxx, void *ses_); -enum frame_event_status textarea_op_home(struct form_state *fs, struct form_control *fc); -enum frame_event_status textarea_op_up(struct form_state *fs, struct form_control *fc); -enum frame_event_status textarea_op_down(struct form_state *fs, struct form_control *fc); -enum frame_event_status textarea_op_end(struct form_state *fs, struct form_control *fc); -enum frame_event_status textarea_op_bob(struct form_state *fs, struct form_control *fc); -enum frame_event_status textarea_op_eob(struct form_state *fs, struct form_control *fc); -enum frame_event_status textarea_op_enter(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_home(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_up(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_down(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_end(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_bob(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_eob(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_enter(struct form_state *fs, struct form_control *fc, int utf8); void set_textarea(struct document_view *doc_view, int direction); From 259a64a7a702d45df311f224f23fcb8741a4ab4e Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Tue, 31 Jan 2006 00:12:05 +0100 Subject: [PATCH 02/73] Code cleanup. --- src/bfu/inpfield.c | 65 ---------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index 969a17aa..7f477a9b 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -102,71 +102,6 @@ check_nonempty(struct dialog_data *dlg_data, struct widget_data *widget_data) return EVENT_NOT_PROCESSED; } -#if 0 -void -dlg_format_field(struct terminal *term, - struct widget_data *widget_data, - int x, int *y, int w, int *rw, enum format_align align) -{ - static int max_label_width; - static int *prev_y; /* Assert the uniqueness of y */ /* TODO: get rid of this !! --Zas */ - unsigned char *label = widget_data->widget->text; - struct color_pair *text_color = NULL; - int label_width = 0; - int float_label = widget_data->widget->info.field.flags & (INPFIELD_FLOAT|INPFIELD_FLOAT2); - - if (label && *label && float_label) { - unsigned char *l2 = label; - int len = strlen(label); - - label_width = term->utf8 ? strlen_utf8(&l2) : len; - if (prev_y == y) { - int_lower_bound(&max_label_width, label_width); - } else { - max_label_width = label_width; - prev_y = y; - } - - /* Right align the floating label up against the - * input field */ - x += max_label_width - label_width; - w -= max_label_width - len; - } - - if (label && *label) { - if (term) text_color = get_bfu_color(term, "dialog.text"); - - dlg_format_text_do(term, label, x, y, w, rw, text_color, ALIGN_LEFT); - } - - /* XXX: We want the field and label on the same line if the terminal - * width allows it. */ - if (label && *label && float_label) { - if (widget_data->widget->info.field.flags & INPFIELD_FLOAT) { - (*y) -= INPUTFIELD_HEIGHT; - dlg_format_text_do(term, INPUTFIELD_FLOAT_SEPARATOR, - x + label_width, y, w, rw, - text_color, ALIGN_LEFT); - w -= INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; - x += INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; - } - - /* FIXME: Is 5 chars for input field enough? --jonas */ - if (label_width < w - 5) { - (*y) -= INPUTFIELD_HEIGHT; - w -= label_width; - x += label_width; - } - } - - if (rw) int_lower_bound(rw, int_min(w, DIALOG_MIN_WIDTH)); - - set_box(&widget_data->box, x, *y, w, INPUTFIELD_HEIGHT); - - (*y) += INPUTFIELD_HEIGHT; -} -#endif - void dlg_format_field(struct terminal *term, struct widget_data *widget_data, From 0bacd766e2e7174724bf76da44b52becb6881154 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Tue, 31 Jan 2006 01:09:49 +0100 Subject: [PATCH 03/73] Added UTF-8 char length lookup table Added lookup table to quick get number of bytes of UTF-8 character from first byte. --- src/intl/charsets.c | 44 ++++++++++++++++++++++++++------------------ src/intl/charsets.h | 1 + 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index ca564d6a..cae7b274 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -168,6 +168,21 @@ u2cp_(unicode_val_T u, int to, int no_nbsp_hack) return no_str; } + +/* Number of bytes utf8 character indexed by first byte. Illegal bytes are + * equal ones and handled different. */ +static char utf8char_len_tab[256] = +{ + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 5,5,5,5,6,6,1,1, +}; + static unsigned char utf_buffer[7]; inline unsigned char * @@ -205,6 +220,15 @@ encode_utf_8(unicode_val_T u) return utf_buffer; } +inline int utf8charlen(const unsigned char *p) +{ + int len; + if (p==NULL) + return 0; + len = utf8char_len_tab[*p]; + return len; +} + inline int strlen_utf8(unsigned char **str) { @@ -214,12 +238,7 @@ strlen_utf8(unsigned char **str) int len; for (x = 0;; x++, s += len) { - if (*s < 0x80) len = 1; - else if (*s < 0xe0) len = 2; - else if (*s < 0xf0) len = 3; - else if (*s < 0xf8) len = 4; - else if (*s < 0xfc) len = 5; - else len = 6; + len = utf8charlen(s); if (s + len > end) break; } *str = s; @@ -233,18 +252,7 @@ utf_8_to_unicode(unsigned char **string, unsigned char *end) unicode_val_T u; int length; - if (str[0] < 0x80) - length = 1; - else if (str[0] < 0xe0) - length = 2; - else if (str[0] < 0xf0) - length = 3; - else if (str[0] < 0xf8) - length = 4; - else if (str[0] < 0xfc) - length = 5; - else - length = 6; + length = utf8char_len_tab[str[0]]; if (str + length > end) { return UCS_NO_CHAR; diff --git a/src/intl/charsets.h b/src/intl/charsets.h index 364c484d..d57913a5 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -54,6 +54,7 @@ unsigned char *get_cp_mime_name(int); int is_cp_special(int); void free_conv_table(void); inline unsigned char *encode_utf_8(unicode_val_T); +inline int utf8charlen(const unsigned char *); inline int strlen_utf8(unsigned char **); inline unicode_val_T utf_8_to_unicode(unsigned char **, unsigned char *); From 585d69355a6f98cb31cbafd131a5525acae927e2 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Tue, 31 Jan 2006 01:26:27 +0100 Subject: [PATCH 04/73] Bug fix: hidden UTF-8 characters before end of input box Bug fix: when UTF-8 characters are entered into input box they are hidden before end of input box. --- src/bfu/inpfield.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index 7f477a9b..84874888 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -298,13 +298,20 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, color = get_bfu_color(term, "dialog.field-text"); if (color) { unsigned char *text = widget_data->cdata + widget_data->info.field.vpos; - int len = strlen(text); - int w = int_min(len, widget_data->box.width); + unsigned char *text2 = text; + int x, l, len, w; + + len = (term->utf8) ? strlen_utf8(&text2) : strlen(text); + w = int_min(len, widget_data->box.width); if (!hide) { + if (term->utf8) { + for (l = 0, x = 0; x < w; x++) + l += utf8charlen(text+l); + w = l; + } draw_text(term, widget_data->box.x, widget_data->box.y, - widget_data->cdata + widget_data->info.field.vpos, w, - 0, color); + text, w, 0, color); } else { struct box box; From 3ffa7cac9131bf4bdff380c01e1c1bcfd14daeba Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Thu, 2 Feb 2006 00:03:03 +0100 Subject: [PATCH 05/73] Bug fix: formating error in UTF-8 textarea When textarea contains UTF-8 characters they are not correctly wrapped. --- src/viewer/text/form.c | 3 +- src/viewer/text/textarea.c | 84 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 3b3f499e..530fe83e 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -166,8 +166,7 @@ init_form_state(struct form_control *fc, struct form_state *fs) fs->value = stracpy(fc->default_value); fs->state = strlen(fc->default_value); text = fs->value; - if (fc->type != FC_TEXTAREA) - fs->utf8_pos = strlen_utf8(&text); + fs->utf8_pos = strlen_utf8(&text); fs->vpos = 0; break; case FC_FILE: diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index e4ecdc9c..8dca3b00 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -47,6 +47,77 @@ struct line_info { #define realloc_line_info(info, size) \ mem_align_alloc(info, size, (size) + 3, 0xFF) +/* Allocates a line_info table describing the layout of the textarea buffer. + * + * @width is max width and the offset at which text will be wrapped + * @wrap controls how the wrapping of text is performed + * @format is non zero the @text will be modified to make it suitable for + * encoding it for form posting + */ +static struct line_info * +format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) +{ + struct line_info *line = NULL; + int line_number = 0; + int begin = 0; + int pos = 0; + int skip; + unsigned char *wrappos=NULL; + int char_cnt=0; /* Number of console chars on line */ + + assert(text); + if_assert_failed return NULL; + + /* Allocate the ending entries */ + if (!realloc_line_info(&line, 0)) + return NULL; + + while (text[pos]) { + + if (text[pos] == ' ') + wrappos = &text[pos]; + + if (text[pos] == '\n') { + skip = 1; + + } else if (wrap == FORM_WRAP_NONE || char_cnt < width) { + pos += utf8charlen(&text[pos]); + char_cnt++; + continue; + + } else { + if (wrappos) { + /* When formatting text for form submitting we + * have to apply the wrapping mode. */ + if (wrap == FORM_WRAP_HARD && format) + *wrappos = '\n'; + pos = wrappos - text; + } + skip = !!wrappos; + char_cnt = 0; + wrappos = NULL; + } + + if (!realloc_line_info(&line, line_number)) { + mem_free_if(line); + return NULL; + } + + line[line_number].start = begin; + line[line_number++].end = pos; + begin = pos += skip; + } + + /* Flush the last text before the loop ended */ + line[line_number].start = begin; + line[line_number++].end = pos; + + /* Add end marker */ + line[line_number].start = line[line_number].end = -1; + + return line; +} + /* Allocates a line_info table describing the layout of the textarea buffer. * * @width is max width and the offset at which text will be wrapped @@ -146,7 +217,10 @@ area_cursor(struct form_control *fc, struct form_state *fs, int utf8) assert(fc && fs); if_assert_failed return 0; - line = format_text(fs->value, fc->cols, fc->wrap, 0); + if (utf8) + line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); + else + line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return 0; y = get_textarea_line_number(line, fs->state); @@ -201,7 +275,7 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, if (!link->npoints) return; area_cursor(fc, fs, 1); - linex = format_text(fs->value, fc->cols, fc->wrap, 0); + linex = format_textutf8(fs->value, fc->cols, fc->wrap, 0); if (!linex) return; line = linex; sl = fs->vypos; @@ -349,6 +423,7 @@ encode_textarea(struct submitted_value *sv) /* We need to reformat text now if it has to be wrapped hard, just * before encoding it. */ + /* TODO: Do we need here UTF-8 format or not? --scrool */ blabla = format_text(sv->value, fc->cols, fc->wrap, 1); mem_free_if(blabla); @@ -549,7 +624,10 @@ textarea_op(struct form_state *fs, struct form_control *fc, int utf8, assert(fs && fs->value && fc); if_assert_failed return FRAME_EVENT_OK; - line = format_text(fs->value, fc->cols, fc->wrap, 0); + if (utf8) + line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); + else + line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return FRAME_EVENT_OK; current = get_textarea_line_number(line, fs->state); From f9d67aeb73f76640b9e986530986072c5a4a97bd Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Fri, 3 Feb 2006 00:27:01 +0100 Subject: [PATCH 06/73] Added configure option --enable-utf-8 For enabling better UTF-8 support by Witek and Scrool. --- Makefile.config.in | 1 + configure.in | 4 ++ src/bfu/button.c | 2 + src/bfu/dialog.c | 11 ++- src/bfu/inpfield.c | 44 +++++++++--- src/bfu/menu.c | 12 ++-- src/dialogs/options.c | 3 + src/document/dom/renderer.c | 8 +++ src/document/html/renderer.c | 93 ++++++++++++++++++++++++- src/document/options.h | 2 + src/document/plain/renderer.c | 10 ++- src/intl/charsets.c | 44 ++++++++---- src/intl/charsets.h | 2 + src/terminal/draw.c | 15 ++++ src/terminal/draw.h | 14 ++++ src/terminal/event.c | 26 +++++-- src/terminal/screen.c | 106 +++++++++++++++++++++++++++- src/terminal/terminal.h | 2 + src/viewer/dump/dump.c | 10 +++ src/viewer/text/form.c | 80 ++++++++++++++++++++- src/viewer/text/form.h | 2 + src/viewer/text/link.c | 8 +++ src/viewer/text/textarea.c | 126 +++++++++++++++++++++++++++++++++- src/viewer/text/textarea.h | 14 ++++ 24 files changed, 591 insertions(+), 48 deletions(-) diff --git a/Makefile.config.in b/Makefile.config.in index f5145e9c..2282dfc2 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -155,6 +155,7 @@ CONFIG_SPIDERMONKEY = @CONFIG_SPIDERMONKEY@ CONFIG_SSL = @CONFIG_SSL@ CONFIG_SYSMOUSE = @CONFIG_SYSMOUSE@ CONFIG_URI_REWRITE = @CONFIG_URI_REWRITE@ +CONFIG_UTF_8 = @CONFIG_UTF_8@ CONFIG_XBEL_BOOKMARKS = @CONFIG_XBEL_BOOKMARKS@ CONFIG_XMLTO = @CONFIG_XMLTO@ diff --git a/configure.in b/configure.in index b87f00a7..6e95ac71 100644 --- a/configure.in +++ b/configure.in @@ -1257,6 +1257,10 @@ EL_ARG_ENABLE(CONFIG_OWN_LIBC, own-libc, [Own libc stubs], EL_ARG_ENABLE(CONFIG_SMALL, small, [Small binary], [ --enable-small reduce binary size as far as possible (but see the bottom of doc/small.txt!)]) +EL_ARG_ENABLE(CONFIG_UTF_8, utf-8, [UTF-8], + [ --enable-utf-8 enable UTF-8 support]) + + AC_ARG_ENABLE(weehoofooboomookerchoo, [ Also check out the features.conf file for more information about features! diff --git a/src/bfu/button.c b/src/bfu/button.c index 5c1ff8a4..8cccbc39 100644 --- a/src/bfu/button.c +++ b/src/bfu/button.c @@ -167,6 +167,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) attr = get_opt_bool("ui.dialogs.underline_button_shortcuts") ? SCREEN_ATTR_UNDERLINE : 0; +#ifdef CONFIG_UTF_8 if (term->utf8) { unsigned char *text2 = text; unsigned char *end = text @@ -192,6 +193,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) } len = x1 - !!hk_state; } else +#endif /* CONFIG_UTF_8 */ if (hk_pos >= 0) { int right = widget_data->widget->info.button.truetextlen - hk_pos - 1; diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index 554b9dbc..e585ac57 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -97,18 +97,25 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) title_color = get_bfu_color(term, "dialog.title"); if (title_color && box.width > 2) { unsigned char *title = dlg_data->dlg->title; +#ifdef CONFIG_UTF_8 unsigned char *t2 = title; int titlelen = strlen(title); int len = term->utf8 ? strlen_utf8(&t2) : titlelen; -#if 1 len = int_min(box.width - 2, len); -#endif int x = (box.width - len) / 2 + box.x; +#else + int titlelen = int_min(box.width - 2, strlen(title)); + int x = (box.width - titlelen) / 2 + box.x; +#endif /* CONFIG_UTF_8 */ int y = box.y - 1; draw_text(term, x - 1, y, " ", 1, 0, title_color); draw_text(term, x, y, title, titlelen, 0, title_color); +#ifdef CONFIG_UTF_8 draw_text(term, x + len, y, " ", 1, 0, title_color); +#else + draw_text(term, x + titlelen, y, " ", 1, 0, title_color); +#endif /* CONFIG_UTF_8 */ } } diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index 84874888..e907119d 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -266,8 +266,11 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, struct terminal *term = dlg_data->win->term; struct color_pair *color; int sel = is_selected_widget(dlg_data, widget_data); +#ifdef CONFIG_UTF_8 int len = 0, left = 0; +#endif /* CONFIG_UTF_8 */ +#ifdef CONFIG_UTF_8 if (term->utf8) { unsigned char *t = widget_data->cdata; unsigned char *t2 = t; @@ -284,7 +287,9 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, } t[p] = tmp; widget_data->info.field.vpos = (int)(t2 - t); - } else { + } else +#endif /* CONFIG_UTF_8 */ + { int_bounds(&widget_data->info.field.vpos, widget_data->info.field.cpos - widget_data->box.width + 1, widget_data->info.field.cpos); @@ -298,26 +303,34 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, color = get_bfu_color(term, "dialog.field-text"); if (color) { unsigned char *text = widget_data->cdata + widget_data->info.field.vpos; +#ifdef CONFIG_UTF_8 unsigned char *text2 = text; - int x, l, len, w; +#endif /* CONFIG_UTF_8 */ + int len, w; - len = (term->utf8) ? strlen_utf8(&text2) : strlen(text); +#ifdef CONFIG_UTF_8 + if (term->utf8) + len = strlen_utf8(&text2); + else +#endif /* CONFIG_UTF_8 */ + len = strlen(text); w = int_min(len, widget_data->box.width); if (!hide) { +#ifdef CONFIG_UTF_8 + int x; if (term->utf8) { + int l; for (l = 0, x = 0; x < w; x++) l += utf8charlen(text+l); w = l; } +#endif /* CONFIG_UTF_8 */ draw_text(term, widget_data->box.x, widget_data->box.y, text, w, 0, color); } else { struct box box; - if (term->utf8) len = strlen_utf8(&text); - w = int_min(len, widget_data->box.width); - copy_box(&box, &widget_data->box); box.width = w; @@ -328,12 +341,13 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, if (sel) { int x; - if (term->utf8) { +#ifdef CONFIG_UTF_8 + if (term->utf8) x = widget_data->box.x + len - left; - } else { + else +#endif /* CONFIG_UTF_8 */ x = widget_data->box.x + widget_data->info.field.cpos - widget_data->info.field.vpos; - } set_cursor(term, x, widget_data->box.y, 0); set_window_ptr(dlg_data->win, widget_data->box.x, widget_data->box.y); } @@ -473,6 +487,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) case ACT_EDIT_RIGHT: if (widget_data->info.field.cpos < strlen(widget_data->cdata)) { +#ifdef CONFIG_UTF_8 if (term->utf8) { unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; unsigned char *end = strchr(next, '\0'); @@ -480,13 +495,17 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) utf_8_to_unicode(&next, end); widget_data->info.field.cpos = (int)(next - widget_data->cdata); } else +#endif /* CONFIG_UTF_8 */ + { widget_data->info.field.cpos++; + } } goto display_field; case ACT_EDIT_LEFT: if (widget_data->info.field.cpos > 0) widget_data->info.field.cpos--; +#ifdef CONFIG_UTF_8 if (widget_data->info.field.cpos && term->utf8) { unsigned char *t = widget_data->cdata; unsigned char *t2 = t; @@ -499,6 +518,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) widget_data->info.field.cpos = (int)(t2 - t); } +#endif /* CONFIG_UTF_8 */ goto display_field; case ACT_EDIT_HOME: @@ -510,6 +530,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) goto display_field; case ACT_EDIT_BACKSPACE: +#ifdef CONFIG_UTF_8 if (widget_data->info.field.cpos && term->utf8) { unsigned char *t = widget_data->cdata; unsigned char *t2 = t; @@ -523,6 +544,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) widget_data->info.field.cpos = (int)(t2 - t); goto display_field; } +#endif /* CONFIG_UTF_8 */ if (widget_data->info.field.cpos) { memmove(widget_data->cdata + widget_data->info.field.cpos - 1, widget_data->cdata + widget_data->info.field.cpos, @@ -537,6 +559,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) if (widget_data->info.field.cpos >= cdata_len) goto display_field; +#ifdef CONFIG_UTF_8 if (term->utf8) { unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; unsigned char *dest = next; @@ -546,6 +569,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) memmove(dest, next, strlen(next) + 1); goto display_field; } +#endif /* CONFIG_UTF_8 */ memmove(widget_data->cdata + widget_data->info.field.cpos, widget_data->cdata + widget_data->info.field.cpos + 1, cdata_len - widget_data->info.field.cpos + 1); @@ -627,6 +651,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) memmove(text + 1, text, textlen + 1); *text = get_kbd_key(ev); +#ifdef CONFIG_UTF_8 if (term->utf8) { static unsigned char buf[7]; unsigned char *t = buf; @@ -641,6 +666,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) return EVENT_PROCESSED; else i = 0; } +#endif /* CONFIG_UTF_8 */ goto display_field; } } diff --git a/src/bfu/menu.c b/src/bfu/menu.c index 0b71a648..addf8575 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -346,7 +346,6 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, struct color_pair *hk_color_sel = get_bfu_color(term, "menu.hotkey.selected"); enum screen_char_attr hk_attr = get_opt_bool("ui.dialogs.underline_hotkeys") ? SCREEN_ATTR_UNDERLINE : 0; - unsigned char *text2, *end; unsigned char c; int xbase = x + L_TEXT_SPACE; int w = width - (L_TEXT_SPACE + R_TEXT_SPACE); @@ -368,7 +367,10 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, hk_color_sel = tmp; } +#ifdef CONFIG_UTF_8 if (term->utf8) goto utf8; +#endif /* CONFIG_UTF_8 */ + for (x = 0; x - !!hk_state < w && (c = text[x]); x++) { if (!hk_state && x == hotkey_pos - 1) { hk_state = 1; @@ -381,13 +383,15 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, (double_hk ? hk_color_sel : hk_color)); #else draw_char(term, xbase + x - 1, y, c, hk_attr, hk_color); -#endif +#endif /* CONFIG_DEBUG */ hk_state = 2; } else { draw_char(term, xbase + x - !!hk_state, y, c, 0, color); } } return; +#ifdef CONFIG_UTF_8 + unsigned char *text2, *end; utf8: end = strchr(text, '\0'); text2 = text; @@ -405,14 +409,14 @@ utf8: (double_hk ? hk_color_sel : hk_color)); #else draw_char(term, xbase + x - 1, y, data, hk_attr, hk_color); -#endif +#endif /* CONFIG_DEBUG */ hk_state = 2; } else { draw_char(term, xbase + x - !!hk_state, y, data, 0, color); } } - +#endif /* CONFIG_UTF_8 */ } static inline void diff --git a/src/dialogs/options.c b/src/dialogs/options.c index 906bc83f..31b59b4c 100644 --- a/src/dialogs/options.c +++ b/src/dialogs/options.c @@ -59,6 +59,9 @@ charset_list(struct terminal *term, void *xxx, void *ses_) unsigned char *name = get_cp_name(i); if (!name) break; +#ifndef CONFIG_UTF_8 + if (is_cp_special(i)) continue; +#endif /* CONFIG_UTF_8 */ add_to_menu(&mi, name, NULL, ACT_MAIN_NONE, display_codepage, get_cp_mime_name(i), 0); diff --git a/src/document/dom/renderer.c b/src/document/dom/renderer.c index 0461aacb..e70df10f 100644 --- a/src/document/dom/renderer.c +++ b/src/document/dom/renderer.c @@ -250,8 +250,10 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, struct document *document = renderer->document; struct conv_table *convert = renderer->convert_table; enum convert_string_mode mode = renderer->convert_mode; +#ifdef CONFIG_UTF_8 int utf8 = document->options.utf8; unsigned char *end, *text; +#endif /* CONFIG_UTF_8 */ int x; @@ -268,7 +270,9 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, add_search_node(renderer, length); +#ifdef CONFIG_UTF_8 if (utf8) goto utf_8; +#endif /* CONFIG_UTF_8 */ for (x = 0; x < length; x++, renderer->canvas_x++) { unsigned char data = string[x]; @@ -297,6 +301,7 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, copy_screen_chars(POS(renderer), template, 1); } +#ifdef CONFIG_UTF_8 goto end; utf_8: end = string + length; @@ -333,6 +338,7 @@ utf_8: copy_screen_chars(POS(renderer), template, 1); } end: +#endif /* CONFIG_UTF_8 */ mem_free(string); } @@ -1028,7 +1034,9 @@ render_dom_document(struct cache_entry *cached, struct document *document, init_dom_renderer(&renderer, document, buffer, convert_table); document->bgcolor = document->options.default_bg; +#ifdef CONFIG_UTF_8 document->options.utf8 = is_cp_special(document->options.cp); +#endif /* CONFIG_UTF_8 */ if (document->options.plain) parser_type = SGML_PARSER_STREAM; diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index e9a8a5a4..41a79657 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -403,6 +403,7 @@ get_format_screen_char(struct html_context *html_context, return &schar_cache; } +#ifdef CONFIG_UTF_8 /* First possibly do the format change and then find out what coordinates * to use since sub- or superscript might change them */ static inline int @@ -492,6 +493,48 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, } return len; } +#else + +/* First possibly do the format change and then find out what coordinates + * to use since sub- or superscript might change them */ +static inline void +set_hline(struct html_context *html_context, unsigned char *chars, int charslen, + enum link_state link_state) +{ + struct part *part = html_context->part; + struct screen_char *schar = get_format_screen_char(html_context, + link_state); + int x = part->cx; + int y = part->cy; + + assert(part); + if_assert_failed return; + + if (realloc_spaces(part, x + charslen)) + return; + + if (part->document) { + if (realloc_line(html_context, part->document, + Y(y), X(x) + charslen - 1)) + return; + + for (; charslen > 0; charslen--, x++, chars++) { + if (*chars == NBSP_CHAR) { + schar->data = ' '; + part->spaces[x] = html_context->options->wrap_nbsp; + } else { + part->spaces[x] = (*chars == ' '); + schar->data = *chars; + } + copy_screen_chars(&POS(x, y), schar, 1); + } + } else { + for (; charslen > 0; charslen--, x++, chars++) { + part->spaces[x] = (*chars == ' '); + } + } +} +#endif /* CONFIG_UTF_8 */ static void move_links(struct html_context *html_context, int xf, int yf, int xt, int yt) @@ -1218,9 +1261,15 @@ done_link_state_info(void) sizeof(renderer_context.link_state_info)); } +#ifdef CONFIG_UTF_8 static inline void process_link(struct html_context *html_context, enum link_state link_state, unsigned char *chars, int charslen, int utf8_len) +#else +static inline void +process_link(struct html_context *html_context, enum link_state link_state, + unsigned char *chars, int charslen) +#endif /* CONFIG_UTF_8 */ { struct part *part = html_context->part; struct link *link; @@ -1272,7 +1321,9 @@ process_link(struct html_context *html_context, enum link_state link_state, if (x_offset) { charslen -= x_offset; chars += x_offset; +#ifdef CONFIG_UTF_8 utf8_len -= x_offset; +#endif /* CONFIG_UTF_8 */ } link = new_link(html_context, chars, charslen); @@ -1287,14 +1338,24 @@ process_link(struct html_context *html_context, enum link_state link_state, } /* Add new canvas positions to the link. */ - if (realloc_points(link, link->npoints + utf8_len)) { +#ifdef CONFIG_UTF_8 + if (realloc_points(link, link->npoints + utf8_len)) +#else + if (realloc_points(link, link->npoints + charslen)) +#endif /* CONFIG_UTF_8 */ + { struct point *point = &link->points[link->npoints]; int x = X(part->cx) + x_offset; int y = Y(part->cy); +#ifdef CONFIG_UTF_8 link->npoints += utf8_len; - for (; utf8_len > 0; utf8_len--, point++, x++) { + for (; utf8_len > 0; utf8_len--, point++, x++) +#else + for (; charslen > 0; charslen--, point++, x++) +#endif /* CONFIG_UTF_8 */ + { point->x = x; point->y = y; } @@ -1346,7 +1407,9 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) enum link_state link_state; int update_after_subscript = renderer_context.subscript; struct part *part; +#ifdef CONFIG_UTF_8 int utf8_len; +#endif /* CONFIG_UTF_8 */ assert(html_context); if_assert_failed return; @@ -1405,7 +1468,11 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) else if (html_context->options->links_numbering) put_link_number(html_context); } - utf8_len = set_hline(html_context, chars, charslen, link_state); +#ifdef CONFIG_UTF_8 + utf8_len = +#endif /* CONFIG_UTF_8 */ + set_hline(html_context, chars, charslen, link_state); + if (link_state != LINK_STATE_NONE) { #define is_drawing_subs_or_sups() \ @@ -1425,15 +1492,29 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) } #undef is_drawing_subs_or_sups + +#ifdef CONFIG_UTF_8 process_link(html_context, link_state, chars, charslen, utf8_len); +#else + process_link(html_context, link_state, chars, charslen); +#endif /* CONFIG_UTF_8 */ } +#ifdef CONFIG_UTF_8 if (renderer_context.nowrap && part->cx + utf8_len > overlap(par_format)) return; part->cx += utf8_len; +#else + if (renderer_context.nowrap + && part->cx + charslen > overlap(par_format)) + return; + + part->cx += charslen; +#endif /* CONFIG_UTF_8 */ + renderer_context.nobreak = 0; if (!(html_context->options->wrap || html_is_preformatted())) { @@ -1449,7 +1530,11 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) } assert(charslen > 0); +#ifdef CONFIG_UTF_8 part->xa += utf8_len; +#else + part->xa += charslen; +#endif /* CONFIG_UTF_8 */ int_lower_bound(&part->max_width, part->xa + par_format.leftmargin + par_format.rightmargin - (chars[charslen - 1] == ' ' @@ -2013,7 +2098,9 @@ render_html_document(struct cache_entry *cached, struct document *document, &document->cp, &document->cp_status, document->options.hard_assume); +#ifdef CONFIG_UTF_8 html_context->options->utf8 = is_cp_special(document->options.cp); +#endif /* CONFIG_UTF_8 */ if (title.length) { document->title = convert_string(renderer_context.convert_table, diff --git a/src/document/options.h b/src/document/options.h index db510b33..d2a33bfe 100644 --- a/src/document/options.h +++ b/src/document/options.h @@ -71,7 +71,9 @@ struct document_options { unsigned int plain:1; unsigned int wrap:1; +#ifdef CONFIG_UTF_8 unsigned int utf8:1; +#endif /* CONFIG_UTF_8 */ /* XXX: Everything past this comment is specialy handled by compare_opt() */ unsigned char *framename; diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index f19af844..d238efc0 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -234,10 +234,12 @@ add_document_line(struct plain_renderer *renderer, struct screen_char *template = &renderer->template; struct screen_char saved_renderer_template = *template; struct screen_char *pos, *startpos; +#ifdef CONFIG_UTF_8 unsigned char *end, *text; + int utf8 = document->options.utf8; +#endif /* CONFIG_UTF_8 */ int lineno = renderer->lineno; int expanded = 0; - int utf8 = document->options.utf8; int width = line_width; int line_pos; @@ -278,7 +280,9 @@ add_document_line(struct plain_renderer *renderer, assert(expanded >= 0); +#ifdef CONFIG_UTF_8 if (utf8) goto utf_8; +#endif /* CONFIG_UTF_8 */ startpos = pos = realloc_line(document, width + expanded, lineno); if (!pos) { mem_free(line); @@ -404,6 +408,7 @@ add_document_line(struct plain_renderer *renderer, *template = saved_renderer_template; } } +#ifdef CONFIG_UTF_8 goto end; utf_8: end = line + width; @@ -537,6 +542,7 @@ utf_8: } } end: +#endif /* CONFIG_UTF_8 */ mem_free(line); realloc_line(document, pos - startpos, lineno); @@ -694,7 +700,9 @@ render_plain_document(struct cache_entry *cached, struct document *document, document->bgcolor = document->options.default_bg; document->width = 0; +#ifdef CONFIG_UTF_8 document->options.utf8 = is_cp_special(document->options.cp); +#endif /* CONFIG_UTF_8 */ /* Setup the style */ init_template(&renderer.template, &document->options); diff --git a/src/intl/charsets.c b/src/intl/charsets.c index cae7b274..9a224399 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -143,8 +143,10 @@ u2cp_(unicode_val_T u, int to, int no_nbsp_hack) to &= ~SYSTEM_CHARSET_FLAG; +#ifdef CONFIG_UTF_8 if (codepages[to].table == table_utf_8) return encode_utf_8(u); +#endif /* CONFIG_UTF_8 */ /* To mark non breaking spaces, we use a special char NBSP_CHAR. */ if (u == 0xa0) return no_nbsp_hack ? " " : NBSP_CHAR_STRING; @@ -168,25 +170,15 @@ u2cp_(unicode_val_T u, int to, int no_nbsp_hack) return no_str; } - -/* Number of bytes utf8 character indexed by first byte. Illegal bytes are - * equal ones and handled different. */ -static char utf8char_len_tab[256] = -{ - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 5,5,5,5,6,6,1,1, -}; - static unsigned char utf_buffer[7]; +#ifdef CONFIG_UTF_8 inline unsigned char * encode_utf_8(unicode_val_T u) +#else +static unsigned char * +encode_utf_8(unicode_val_T u) +#endif /* CONFIG_UTF_8 */ { memset(utf_buffer, 0, 7); @@ -220,6 +212,21 @@ encode_utf_8(unicode_val_T u) return utf_buffer; } +#ifdef CONFIG_UTF_8 +/* Number of bytes utf8 character indexed by first byte. Illegal bytes are + * equal ones and handled different. */ +static char utf8char_len_tab[256] = +{ + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 5,5,5,5,6,6,1,1, +}; + inline int utf8charlen(const unsigned char *p) { int len; @@ -297,6 +304,7 @@ utf_8_to_unicode(unsigned char **string, unsigned char *end) *string = str + length; return u > 0xffff ? '*' : u; } +#endif /* CONFIG_UTF_8 */ /* This slow and ugly code is used by the terminal utf_8_io */ unsigned char * @@ -533,10 +541,12 @@ get_entity_string(const unsigned char *str, const int strlen, int encoding) if (strlen <= 0) return NULL; +#ifdef CONFIG_UTF_8 /* TODO: caching UTF-8 */ encoding &= ~SYSTEM_CHARSET_FLAG; if (codepages[encoding].table == table_utf_8) goto skip; +#endif /* CONFIG_UTF_8 */ if (first_time) { memset(&nb_entity_cache, 0, ENTITY_CACHE_MAXLEN * sizeof(unsigned int)); @@ -591,7 +601,9 @@ get_entity_string(const unsigned char *str, const int strlen, int encoding) fprintf(stderr, "miss\n"); #endif } +#ifdef CONFIG_UTF_8 skip: +#endif /* CONFIG_UTF_8 */ if (*str == '#') { /* Numeric entity. */ int l = (int) strlen; unsigned char *st = (unsigned char *) str; @@ -643,9 +655,11 @@ skip: if (element) result = u2cp(element->c, encoding); } +#ifdef CONFIG_UTF_8 if (codepages[encoding].table == table_utf_8) { return result; } +#endif /* CONFIG_UTF_8 */ end: /* Take care of potential buffer overflow. */ if (strlen < sizeof(entity_cache[slen][0].str)) { diff --git a/src/intl/charsets.h b/src/intl/charsets.h index d57913a5..f237e8f9 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -53,10 +53,12 @@ unsigned char *get_cp_name(int); unsigned char *get_cp_mime_name(int); int is_cp_special(int); void free_conv_table(void); +#ifdef CONFIG_UTF_8 inline unsigned char *encode_utf_8(unicode_val_T); inline int utf8charlen(const unsigned char *); inline int strlen_utf8(unsigned char **); inline unicode_val_T utf_8_to_unicode(unsigned char **, unsigned char *); +#endif /* CONFIG_UTF_8 */ unsigned char *cp2utf_8(int, int); diff --git a/src/terminal/draw.c b/src/terminal/draw.c index b44b8b9c..5f94ab18 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -103,7 +103,11 @@ draw_char_color(struct terminal *term, int x, int y, struct color_pair *color) } void +#ifdef CONFIG_UTF_8 draw_char_data(struct terminal *term, int x, int y, uint16_t data) +#else +draw_char_data(struct terminal *term, int x, int y, unsigned char data) +#endif /* CONFIG_UTF_8 */ { struct screen_char *screen_char = get_char(term, x, y); @@ -199,10 +203,17 @@ draw_border(struct terminal *term, struct box *box, set_screen_dirty(term->screen, borderbox.y, borderbox.y + borderbox.height); } +#ifdef CONFIG_UTF_8 void draw_char(struct terminal *term, int x, int y, uint16_t data, enum screen_char_attr attr, struct color_pair *color) +#else +void +draw_char(struct terminal *term, int x, int y, + unsigned char data, enum screen_char_attr attr, + struct color_pair *color) +#endif /* CONFIG_UTF_8 */ { struct screen_char *screen_char = get_char(term, x, y); @@ -278,6 +289,7 @@ draw_shadow(struct terminal *term, struct box *box, draw_box(term, &dbox, ' ', 0, color); } +#ifdef CONFIG_UTF_8 static void draw_text_utf8(struct terminal *term, int x, int y, unsigned char *text, int length, @@ -312,6 +324,7 @@ draw_text_utf8(struct terminal *term, int x, int y, set_screen_dirty(term->screen, y, y); } +#endif /* CONFIG_UTF_8 */ void draw_text(struct terminal *term, int x, int y, @@ -324,10 +337,12 @@ draw_text(struct terminal *term, int x, int y, assert(text && length >= 0); if_assert_failed return; +#ifdef CONFIG_UTF_8 if (term->utf8) { draw_text_utf8(term, x, y, text, length, attr, color); return; } +#endif /* CONFIG_UTF_8 */ if (length <= 0) return; pos = get_char(term, x, y); diff --git a/src/terminal/draw.h b/src/terminal/draw.h index 8b1e6f63..4d7307e7 100644 --- a/src/terminal/draw.h +++ b/src/terminal/draw.h @@ -19,7 +19,11 @@ enum screen_char_attr { /* One position in the terminal screen's image. */ struct screen_char { /* Contains either character value or frame data. */ +#ifdef CONFIG_UTF_8 uint16_t data; +#else + unsigned char data; +#endif /* CONFIG_UTF_8 */ /* Attributes are screen_char_attr bits. */ unsigned char attr; @@ -202,7 +206,11 @@ void draw_char_color(struct terminal *term, int x, int y, struct color_pair *color); /* Sets the data of a screen position. */ +#ifdef CONFIG_UTF_8 void draw_char_data(struct terminal *term, int x, int y, uint16_t data); +#else +void draw_char_data(struct terminal *term, int x, int y, unsigned char data); +#endif /* CONFIG_UTF_8 */ /* Sets the data to @border and of a screen position. */ void draw_border_char(struct terminal *term, int x, int y, @@ -213,9 +221,15 @@ void draw_border_cross(struct terminal *, int x, int y, enum border_cross_direction, struct color_pair *color); /* Draws a char. */ +#ifdef CONFIG_UTF_8 void draw_char(struct terminal *term, int x, int y, uint16_t data, enum screen_char_attr attr, struct color_pair *color); +#else +void draw_char(struct terminal *term, int x, int y, + unsigned char data, enum screen_char_attr attr, + struct color_pair *color); +#endif /* CONFIG_UTF_8 */ /* Draws area defined by @box using the same colors and attributes. */ void draw_box(struct terminal *term, struct box *box, diff --git a/src/terminal/event.c b/src/terminal/event.c index 29c61d33..07c32ee0 100644 --- a/src/terminal/event.c +++ b/src/terminal/event.c @@ -245,6 +245,9 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) case EVENT_KBD: { +#ifndef CONFIG_UTF_8 + int utf8_io = -1; +#endif /* CONFIG_UTF_8 */ int key = get_kbd_key(ev); reset_timer(); @@ -259,7 +262,13 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) } if (interlink->utf_8.len) { - if ((key & 0xC0) == 0x80 && term->utf8) { +#ifdef CONFIG_UTF_8 + if ((key & 0xC0) == 0x80 && term->utf8) +#else + utf8_io = get_opt_bool_tree(term->spec, "utf_8_io"); + if ((key & 0xC0) == 0x80 && utf8_io) +#endif /* CONFIG_UTF_8 */ + { interlink->utf_8.ucs <<= 6; interlink->utf_8.ucs |= key & 0x3F; if (! --interlink->utf_8.len) { @@ -277,14 +286,19 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) } } - if (key < 0x80 || key > 0xFF || !term->utf8) { - +#ifdef CONFIG_UTF_8 + if (key < 0x80 || key > 0xFF || !term->utf8) +#else + if (key < 0x80 || key > 0xFF + || (utf8_io == -1 + ? !get_opt_bool_tree(term->spec, "utf_8_io") + : !utf8_io)) +#endif /* CONFIG_UTF_8 */ + { term_send_event(term, ev); break; - } - - else if ((key & 0xC0) == 0xC0 && (key & 0xFE) != 0xFE) { + } else if ((key & 0xC0) == 0xC0 && (key & 0xFE) != 0xFE) { unsigned int mask, cov = 0x80; int len = 0; diff --git a/src/terminal/screen.c b/src/terminal/screen.c index a4ac73ba..dcf86861 100644 --- a/src/terminal/screen.c +++ b/src/terminal/screen.c @@ -30,7 +30,7 @@ unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ "; static unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla "; -#if 0 +#ifndef CONFIG_UTF_8 /* For UTF8 I/O */ static unsigned char frame_vt100_u[48] = { 177, 177, 177, 179, 180, 180, 180, 191, @@ -40,7 +40,7 @@ static unsigned char frame_vt100_u[48] = { 193, 194, 194, 192, 192, 218, 218, 197, 197, 217, 218, 177, 32, 32, 32, 32 }; -#endif +#endif /* CONFIG_UTF_8 */ static unsigned char frame_freebsd[48] = { 130, 138, 128, 153, 150, 150, 150, 140, @@ -80,10 +80,12 @@ static struct string m11_hack_frame_seqs[] = { /* begin border: */ TERM_STRING("\033[11m"), }; +#ifdef CONFIG_UTF_8 static struct string utf8_linux_frame_seqs[] = { /* end border: */ TERM_STRING("\033[10m\033%G"), /* begin border: */ TERM_STRING("\033%@\033[11m"), }; +#endif /* CONFIG_UTF_8 */ static struct string vt100_frame_seqs[] = { /* end border: */ TERM_STRING("\x0f"), @@ -106,6 +108,13 @@ struct screen_driver { * uniquely identify the screen_driver. */ enum term_mode_type type; +#ifndef CONFIG_UTF_8 + /* Charsets when doing UTF8 I/O. */ + /* [0] is the common charset and [1] is the frame charset. + * Test wether to use UTF8 I/O using the use_utf8_io() macro. */ + int charsets[2]; +#endif /* CONFIG_UTF_8 */ + /* The frame translation table. May be NULL. */ unsigned char *frame; @@ -121,8 +130,10 @@ struct screen_driver { /* These are directly derived from the terminal options. */ unsigned int transparent:1; +#ifdef CONFIG_UTF_8 /* UTF-8 I/O */ unsigned int utf8:1; +#endif /* CONFIG_UTF_8 */ /* The terminal._template_ name. */ unsigned char name[1]; /* XXX: Keep last! */ @@ -131,56 +142,81 @@ struct screen_driver { static struct screen_driver dumb_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_DUMB, +#ifndef CONFIG_UTF_8 + /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ +#endif /* CONFIG_UTF_8 */ /* frame: */ frame_dumb, /* frame_seqs: */ NULL, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, +#ifdef CONFIG_UTF_8 /* utf-8: */ 0, +#endif /* CONFIG_UTF_8 */ }; static struct screen_driver vt100_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_VT100, +#ifndef CONFIG_UTF_8 + /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ +#endif /* CONFIG_UTF_8 */ /* frame: */ frame_vt100, /* frame_seqs: */ vt100_frame_seqs, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, +#ifdef CONFIG_UTF_8 /* utf-8: */ 0, +#endif /* CONFIG_UTF_8 */ }; static struct screen_driver linux_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_LINUX, +#ifndef CONFIG_UTF_8 + /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ +#endif /* CONFIG_UTF_8 */ /* frame: */ NULL, /* No restrict_852 */ /* frame_seqs: */ NULL, /* No m11_hack */ /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, +#ifdef CONFIG_UTF_8 /* utf-8: */ 0, +#endif /* CONFIG_UTF_8 */ }; static struct screen_driver koi8_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_KOI8, +#ifndef CONFIG_UTF_8 + /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ +#endif /* CONFIG_UTF_8 */ /* frame: */ frame_koi, /* frame_seqs: */ NULL, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, +#ifdef CONFIG_UTF_8 /* utf-8: */ 0, +#endif /* CONFIG_UTF_8 */ }; static struct screen_driver freebsd_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_FREEBSD, +#ifndef CONFIG_UTF_8 + /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ +#endif /* CONFIG_UTF_8 */ /* frame: */ frame_freebsd, /* frame_seqs: */ NULL, /* No m11_hack */ /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1, +#ifdef CONFIG_UTF_8 /* utf-8: */ 0, +#endif /* CONFIG_UTF_8 */ }; /* XXX: Keep in sync with enum term_mode_type. */ @@ -192,14 +228,22 @@ static struct screen_driver *screen_drivers[] = { /* TERM_FREEBSD: */ &freebsd_screen_driver, }; +#ifdef CONFIG_UTF_8 #define use_utf8_io(driver) ((driver)->utf8) +#else +#define use_utf8_io(driver) ((driver)->charsets[0] != -1) +#endif /* CONFIG_UTF_8 */ static INIT_LIST_HEAD(active_screen_drivers); static void update_screen_driver(struct screen_driver *driver, struct option *term_spec) { +#ifdef CONFIG_UTF_8 driver->utf8 = get_opt_bool_tree(term_spec, "utf_8_io"); +#else + int utf8_io = get_opt_bool_tree(term_spec, "utf_8_io"); +#endif /* CONFIG_UTF_8 */ driver->color_mode = get_opt_int_tree(term_spec, "colors"); driver->transparent = get_opt_bool_tree(term_spec, "transparency"); @@ -210,6 +254,7 @@ update_screen_driver(struct screen_driver *driver, struct option *term_spec) driver->underline = NULL; } +#ifdef CONFIG_UTF_8 if (driver->type == TERM_LINUX) { if (get_opt_bool_tree(term_spec, "restrict_852")) driver->frame = frame_restrict; @@ -227,6 +272,46 @@ update_screen_driver(struct screen_driver *driver, struct option *term_spec) } else if (driver->type == TERM_VT100) { driver->frame = frame_vt100; } +#else + if (utf8_io) { + driver->charsets[0] = get_opt_codepage_tree(term_spec, "charset"); + if (driver->type == TERM_LINUX) { + if (get_opt_bool_tree(term_spec, "restrict_852")) + driver->frame = frame_restrict; + + driver->charsets[1] = get_cp_index("cp437"); + + } else if (driver->type == TERM_FREEBSD) { + driver->charsets[1] = get_cp_index("cp437"); + + } else if (driver->type == TERM_VT100) { + driver->frame = frame_vt100_u; + driver->charsets[1] = get_cp_index("cp437"); + + } else if (driver->type == TERM_KOI8) { + driver->charsets[1] = get_cp_index("koi8-r"); + + } else { + driver->charsets[1] = driver->charsets[0]; + } + + } else { + driver->charsets[0] = -1; + if (driver->type == TERM_LINUX) { + if (get_opt_bool_tree(term_spec, "restrict_852")) + driver->frame = frame_restrict; + + if (get_opt_bool_tree(term_spec, "m11_hack")) + driver->frame_seqs = m11_hack_frame_seqs; + + } else if (driver->type == TERM_FREEBSD) { + if (get_opt_bool_tree(term_spec, "m11_hack")) + driver->frame_seqs = m11_hack_frame_seqs; + } else if (driver->type == TERM_VT100) { + driver->frame = frame_vt100; + } + } +#endif /* CONFIG_UTF_8 */ } static int @@ -265,7 +350,9 @@ add_screen_driver(enum term_mode_type type, struct terminal *term, int env_len) term->spec->change_hook = screen_driver_change_hook; +#ifdef CONFIG_UTF_8 term->utf8 = use_utf8_io(driver); +#endif /* CONFIG_UTF_8 */ return driver; } @@ -285,7 +372,9 @@ get_screen_driver(struct terminal *term) /* Some simple probably useless MRU ;) */ move_to_top_of_list(active_screen_drivers, driver); +#ifdef CONFIG_UTF_8 term->utf8 = use_utf8_io(driver); +#endif /* CONFIG_UTF_8 */ return driver; } @@ -351,10 +440,15 @@ struct screen_state { #define compare_bg_color(a, b) (TERM_COLOR_BACKGROUND(a) == TERM_COLOR_BACKGROUND(b)) #define compare_fg_color(a, b) (TERM_COLOR_FOREGROUND(a) == TERM_COLOR_FOREGROUND(b)) - +#ifdef CONFIG_UTF_8 static inline void add_char_data(struct string *screen, struct screen_driver *driver, unicode_val_T data, unsigned char border) +#else +static inline void +add_char_data(struct string *screen, struct screen_driver *driver, + unsigned char data, unsigned char border) +#endif /* CONFIG_UTF_8 */ { if (!isscreensafe(data)) { add_char_to_string(screen, ' '); @@ -365,11 +459,17 @@ add_char_data(struct string *screen, struct screen_driver *driver, data = driver->frame[data - 176]; if (use_utf8_io(driver)) { +#ifdef CONFIG_UTF_8 if (border) add_char_to_string(screen, (unsigned char)data); else if (data != UCS_NO_CHAR) add_to_string(screen, encode_utf_8(data)); +#else + int charset = driver->charsets[!!border]; + + add_to_string(screen, cp2utf_8(charset, data)); +#endif /* CONFIG_UTF_8 */ return; } diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index 685afb0a..80a5ad8f 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -110,8 +110,10 @@ struct terminal { * work and even maintaining these structures ;-). */ unsigned int master:1; +#ifdef CONFIG_UTF_8 /* Indicates whether UTF-8 I/O is used */ unsigned int utf8:1; +#endif /* CONFIG_UTF_8 */ /* The current tab number. */ int current_tab; diff --git a/src/viewer/dump/dump.c b/src/viewer/dump/dump.c index 6a50fa04..dcfb7f3e 100644 --- a/src/viewer/dump/dump.c +++ b/src/viewer/dump/dump.c @@ -323,8 +323,10 @@ add_document_to_string(struct string *string, struct document *document) assert(string && document); if_assert_failed return NULL; +#ifdef CONFIG_UTF_8 if (is_cp_special(document->options.cp)) goto utf_8; +#endif /* CONFIG_UTF_8 */ for (y = 0; y < document->height; y++) { int white = 0; @@ -358,6 +360,7 @@ add_document_to_string(struct string *string, struct document *document) add_char_to_string(string, '\n'); } +#ifdef CONFIG_UTF_8 goto end; utf_8: for (y = 0; y < document->height; y++) { @@ -395,6 +398,7 @@ utf_8: add_char_to_string(string, '\n'); } end: +#endif /* CONFIG_UTF_8 */ return string; } @@ -422,8 +426,10 @@ dump_to_file(struct document *document, int fd) if (!buf) return -1; +#ifdef CONFIG_UTF_8 if (is_cp_special(document->options.cp)) goto utf_8; +#endif /* CONFIG_UTF_8 */ for (y = 0; y < document->height; y++) { int white = 0; @@ -461,6 +467,7 @@ dump_to_file(struct document *document, int fd) if (write_char('\n', fd, buf, &bptr)) goto fail; } +#ifdef CONFIG_UTF_8 goto ref; utf_8: for (y = 0; y < document->height; y++) { @@ -508,13 +515,16 @@ utf_8: if (write_char('\n', fd, buf, &bptr)) goto fail; } +#endif /* CONFIG_UTF_8 */ if (hard_write(fd, buf, bptr) != bptr) { fail: mem_free(buf); return -1; } +#ifdef CONFIG_UTF_8 ref: +#endif /* CONFIG_UTF_8 */ if (document->nlinks && get_opt_bool("document.dump.references")) { int x; unsigned char *header = "\nReferences\n\n Visible links\n"; diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 530fe83e..814b3f35 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -158,21 +158,27 @@ init_form_state(struct form_control *fc, struct form_state *fs) mem_free_set(&fs->value, NULL); switch (fc->type) { +#ifdef CONFIG_UTF_8 unsigned char *text; +#endif /* CONFIG_UTF_8 */ case FC_TEXT: case FC_PASSWORD: case FC_TEXTAREA: fs->value = stracpy(fc->default_value); fs->state = strlen(fc->default_value); +#ifdef CONFIG_UTF_8 text = fs->value; fs->utf8_pos = strlen_utf8(&text); +#endif /* CONFIG_UTF_8 */ fs->vpos = 0; break; case FC_FILE: fs->value = stracpy(""); fs->state = 0; +#ifdef CONFIG_UTF_8 fs->utf8_pos = 0; +#endif /* CONFIG_UTF_8 */ fs->vpos = 0; break; case FC_SELECT: @@ -335,14 +341,18 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, dy = box->y - vs->y; switch (fc->type) { unsigned char *s; +#ifdef CONFIG_UTF_8 unsigned char *text, *end; +#endif /* CONFIG_UTF_8 */ int len; int i, x, y; case FC_TEXT: case FC_PASSWORD: case FC_FILE: +#ifdef CONFIG_UTF_8 if (term->utf8) goto utf_8; +#endif /* CONFIG_UTF_8 */ int_bounds(&fs->vpos, fs->state - fc->size + 1, fs->state); if (!link->npoints) break; @@ -367,6 +377,7 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, draw_char_data(term, x, y, data); } break; +#ifdef CONFIG_UTF_8 utf_8: text = fs->value; end = strchr(text, '\0'); @@ -397,6 +408,7 @@ utf_8: draw_char_data(term, x, y, data); } break; +#endif /* CONFIG_UTF_8 */ case FC_TEXTAREA: draw_textarea(term, fs, doc_view, link); break; @@ -415,7 +427,9 @@ utf_8: else /* XXX: when can this happen? --pasky */ s = ""; +#ifdef CONFIG_UTF_8 if (term->utf8) goto utf_8_select; +#endif /* CONFIG_UTF_8 */ len = s ? strlen(s) : 0; for (i = 0; i < link->npoints; i++) { x = link->points[i].x + dx; @@ -424,6 +438,7 @@ utf_8: draw_char_data(term, x, y, i < len ? s[i] : '_'); } break; +#ifdef CONFIG_UTF_8 utf_8_select: text = s; end = strchr(s, '\0'); @@ -436,6 +451,7 @@ utf_8_select: ? utf_8_to_unicode(&s, end) : '_'); } break; +#endif /* CONFIG_UTF_8 */ case FC_SUBMIT: case FC_IMAGE: case FC_RESET: @@ -1245,7 +1261,9 @@ field_op(struct session *ses, struct document_view *doc_view, unsigned char *text; int length; enum frame_event_status status = FRAME_EVENT_REFRESH; +#ifdef CONFIG_UTF_8 int utf8 = ses->tab->term->utf8; +#endif /* CONFIG_UTF_8 */ assert(ses && doc_view && link && ev); if_assert_failed return FRAME_EVENT_OK; @@ -1265,6 +1283,7 @@ field_op(struct session *ses, struct document_view *doc_view, switch (action_id) { case ACT_EDIT_LEFT: +#ifdef CONFIG_UTF_8 if (utf8) { unsigned char *text = fs->value; unsigned char *end = fs->value + fs->state - 1; @@ -1274,9 +1293,11 @@ field_op(struct session *ses, struct document_view *doc_view, fs->state = (int)(text - fs->value); if (old != fs->state) fs->utf8_pos--; } else +#endif /* CONFIG_UTF_8 */ fs->state = int_max(fs->state - 1, 0); break; case ACT_EDIT_RIGHT: +#ifdef CONFIG_UTF_8 if (utf8) { unsigned char *text = fs->value + fs->state; unsigned char *end = strchr(text, '\0'); @@ -1286,58 +1307,91 @@ field_op(struct session *ses, struct document_view *doc_view, fs->state = (int)(text - fs->value); if (old != fs->state) fs->utf8_pos++; } else +#endif /* CONFIG_UTF_8 */ fs->state = int_min(fs->state + 1, strlen(fs->value)); break; case ACT_EDIT_HOME: if (fc->type == FC_TEXTAREA) { +#ifdef CONFIG_UTF_8 status = textarea_op_home(fs, fc, utf8); +#else + status = textarea_op_home(fs, fc); +#endif /* CONFIG_UTF_8 */ } else { fs->state = 0; +#ifdef CONFIG_UTF_8 fs->utf8_pos = 0; +#endif /* CONFIG_UTF_8 */ } break; case ACT_EDIT_UP: if (fc->type != FC_TEXTAREA) status = FRAME_EVENT_IGNORED; else +#ifdef CONFIG_UTF_8 status = textarea_op_up(fs, fc, utf8); +#else + status = textarea_op_up(fs, fc); +#endif /* CONFIG_UTF_8 */ break; case ACT_EDIT_DOWN: if (fc->type != FC_TEXTAREA) status = FRAME_EVENT_IGNORED; else +#ifdef CONFIG_UTF_8 status = textarea_op_down(fs, fc, utf8); +#else + status = textarea_op_down(fs, fc); +#endif /* CONFIG_UTF_8 */ break; case ACT_EDIT_END: if (fc->type == FC_TEXTAREA) { +#ifdef CONFIG_UTF_8 status = textarea_op_end(fs, fc, utf8); +#else + status = textarea_op_end(fs, fc); +#endif /* CONFIG_UTF_8 */ } else { fs->state = strlen(fs->value); +#ifdef CONFIG_UTF_8 if (utf8) { unsigned char *text = fs->value; fs->utf8_pos = strlen_utf8(&text); } +#endif /* CONFIG_UTF_8 */ } break; case ACT_EDIT_BEGINNING_OF_BUFFER: if (fc->type == FC_TEXTAREA) { +#ifdef CONFIG_UTF_8 status = textarea_op_bob(fs, fc, utf8); +#else + status = textarea_op_bob(fs, fc); +#endif /* CONFIG_UTF_8 */ } else { fs->state = 0; +#ifdef CONFIG_UTF_8 fs->utf8_pos = 0; +#endif /* CONFIG_UTF_8 */ } break; case ACT_EDIT_END_OF_BUFFER: if (fc->type == FC_TEXTAREA) { +#ifdef CONFIG_UTF_8 status = textarea_op_eob(fs, fc, utf8); +#else + status = textarea_op_eob(fs, fc); +#endif /* CONFIG_UTF_8 */ } else { fs->state = strlen(fs->value); +#ifdef CONFIG_UTF_8 if (utf8) { unsigned char *text = fs->value; fs->utf8_pos = strlen_utf8(&text); } +#endif /* CONFIG_UTF_8 */ } break; case ACT_EDIT_OPEN_EXTERNAL: @@ -1355,7 +1409,9 @@ field_op(struct session *ses, struct document_view *doc_view, if (!form_field_is_readonly(fc)) fs->value[0] = 0; fs->state = 0; +#ifdef CONFIG_UTF_8 fs->utf8_pos = 0; +#endif /* CONFIG_UTF_8 */ break; case ACT_EDIT_PASTE_CLIPBOARD: if (form_field_is_readonly(fc)) break; @@ -1371,19 +1427,24 @@ field_op(struct session *ses, struct document_view *doc_view, fs->value = v; memmove(v, text, length + 1); fs->state = strlen(fs->value); +#ifdef CONFIG_UTF_8 if (utf8 && fc->type != FC_TEXTAREA) { unsigned char *text = fs->value; fs->utf8_pos = strlen_utf8(&text); } - +#endif /* CONFIG_UTF_8 */ } } mem_free(text); break; case ACT_EDIT_ENTER: if (fc->type == FC_TEXTAREA) { +#ifdef CONFIG_UTF_8 status = textarea_op_enter(fs, fc, utf8); +#else + status = textarea_op_enter(fs, fc); +#endif /* CONFIG_UTF_8 */ break; } @@ -1408,6 +1469,7 @@ field_op(struct session *ses, struct document_view *doc_view, status = FRAME_EVENT_OK; break; } +#ifdef CONFIG_UTF_8 if (utf8) { int i; unsigned char *text = fs->value; @@ -1421,6 +1483,7 @@ field_op(struct session *ses, struct document_view *doc_view, fs->utf8_pos--; break; } +#endif /* CONFIG_UTF_8 */ length = strlen(fs->value + fs->state) + 1; text = fs->value + fs->state; @@ -1438,6 +1501,7 @@ field_op(struct session *ses, struct document_view *doc_view, status = FRAME_EVENT_OK; break; } +#ifdef CONFIG_UTF_8 if (utf8) { unsigned char *end = fs->value + length; unsigned char *text = fs->value + fs->state; @@ -1450,6 +1514,7 @@ field_op(struct session *ses, struct document_view *doc_view, } break; } +#endif /* CONFIG_UTF_8 */ text = fs->value + fs->state; memmove(text, text + 1, length - fs->state); @@ -1479,11 +1544,13 @@ field_op(struct session *ses, struct document_view *doc_view, memmove(text, fs->value + fs->state, length); fs->state = (int) (text - fs->value); +#ifdef CONFIG_UTF_8 if (utf8 && fc->type != FC_TEXTAREA) { unsigned char *text = fs->value; fs->utf8_pos = strlen_utf8(&text); } +#endif /* CONFIG_UTF_8 */ break; case ACT_EDIT_KILL_TO_EOL: if (form_field_is_readonly(fc)) { @@ -1537,10 +1604,16 @@ field_op(struct session *ses, struct document_view *doc_view, } if (form_field_is_readonly(fc) - || strlen(fs->value) >= fc->maxlength) { + || strlen(fs->value) >= fc->maxlength +#ifndef CONFIG_UTF_8 + || !insert_in_string(&fs->value, fs->state, "?", 1) +#endif /* CONFIG_UTF_8 */ + ) + { status = FRAME_EVENT_OK; break; } +#ifdef CONFIG_UTF_8 if (utf8) { static unsigned char buf[7]; static int i = 0; @@ -1572,6 +1645,9 @@ field_op(struct session *ses, struct document_view *doc_view, return FRAME_EVENT_OK; fs->value[fs->state++] = get_kbd_key(ev); } +#else + fs->value[fs->state++] = get_kbd_key(ev); +#endif /* CONFIG_UTF_8 */ break; } diff --git a/src/viewer/text/form.h b/src/viewer/text/form.h index fd034cfb..0f9658c3 100644 --- a/src/viewer/text/form.h +++ b/src/viewer/text/form.h @@ -39,7 +39,9 @@ struct form_state { unsigned char *value; int state; +#ifdef CONFIG_UTF_8 int utf8_pos; +#endif /* CONFIG_UTF_8 */ int vpos; int vypos; diff --git a/src/viewer/text/link.c b/src/viewer/text/link.c index 2fec2f42..68890689 100644 --- a/src/viewer/text/link.c +++ b/src/viewer/text/link.c @@ -112,7 +112,9 @@ get_link_cursor_offset(struct document_view *doc_view, struct link *link) { struct form_control *fc; struct form_state *fs; +#ifdef CONFIG_UTF_8 int utf8 = doc_view->document->options.utf8; +#endif /* CONFIG_UTF_8 */ switch (link->type) { case LINK_CHECKBOX: @@ -124,15 +126,21 @@ get_link_cursor_offset(struct document_view *doc_view, struct link *link) case LINK_FIELD: fc = get_link_form_control(link); fs = find_form_state(doc_view, fc); +#ifdef CONFIG_UTF_8 if (utf8) { return fs ? fs->utf8_pos - fs->vpos : 0; } else +#endif /* CONFIG_UTF_8 */ return fs ? fs->state - fs->vpos : 0; case LINK_AREA: fc = get_link_form_control(link); fs = find_form_state(doc_view, fc); +#ifdef CONFIG_UTF_8 return fs ? area_cursor(fc, fs, utf8) : 0; +#else + return fs ? area_cursor(fc, fs) : 0; +#endif /* CONFIG_UTF_8 */ case LINK_HYPERTEXT: case LINK_MAP: diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index 8dca3b00..ab5920ec 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -47,6 +47,7 @@ struct line_info { #define realloc_line_info(info, size) \ mem_align_alloc(info, size, (size) + 3, 0xFF) +#ifdef CONFIG_UTF_8 /* Allocates a line_info table describing the layout of the textarea buffer. * * @width is max width and the offset at which text will be wrapped @@ -117,6 +118,7 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) return line; } +#endif /* CONFIG_UTF_8 */ /* Allocates a line_info table describing the layout of the textarea buffer. * @@ -209,7 +211,11 @@ get_textarea_line_number(struct line_info *line, int cursor_position) /* Fixes up the vpos and vypos members of the form_state. Returns the * logical position in the textarea view. */ int +#ifdef CONFIG_UTF_8 area_cursor(struct form_control *fc, struct form_state *fs, int utf8) +#else +area_cursor(struct form_control *fc, struct form_state *fs) +#endif /* CONFIG_UTF_8 */ { struct line_info *line; int x, y; @@ -217,9 +223,11 @@ area_cursor(struct form_control *fc, struct form_state *fs, int utf8) assert(fc && fs); if_assert_failed return 0; +#ifdef CONFIG_UTF_8 if (utf8) line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); else +#endif /* CONFIG_UTF_8 */ line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return 0; @@ -228,7 +236,7 @@ area_cursor(struct form_control *fc, struct form_state *fs, int utf8) mem_free(line); return 0; } - +#ifdef CONFIG_UTF_8 if (utf8) { unsigned char *text = fs->value + line[y].start; unsigned char tmp = fs->value[fs->state]; @@ -237,6 +245,7 @@ area_cursor(struct form_control *fc, struct form_state *fs, int utf8) x = strlen_utf8(&text); fs->value[fs->state] = tmp; } else +#endif /* CONFIG_UTF_8 */ x = fs->state - line[y].start; mem_free(line); @@ -252,6 +261,7 @@ area_cursor(struct form_control *fc, struct form_state *fs, int utf8) return y * fc->cols + x; } +#ifdef CONFIG_UTF_8 static void draw_textarea_utf8(struct terminal *term, struct form_state *fs, struct document_view *doc_view, struct link *link) @@ -329,7 +339,7 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, mem_free(linex); } - +#endif /* CONFIG_UTF_8 */ void draw_textarea(struct terminal *term, struct form_state *fs, @@ -345,10 +355,12 @@ draw_textarea(struct terminal *term, struct form_state *fs, assert(term && doc_view && doc_view->document && doc_view->vs && link); if_assert_failed return; +#ifdef CONFIG_UTF_8 if (term->utf8) { draw_textarea_utf8(term, fs, doc_view, link); return; } +#endif /* CONFIG_UTF_8 */ fc = get_link_form_control(link); assertm(fc, "link %d has no form control", (int) (link - doc_view->document->links)); if_assert_failed return; @@ -358,7 +370,11 @@ draw_textarea(struct terminal *term, struct form_state *fs, vy = doc_view->vs->y; if (!link->npoints) return; +#ifdef CONFIG_UTF_8 area_cursor(fc, fs, 0); +#else + area_cursor(fc, fs); +#endif /* CONFIG_UTF_8 */ linex = format_text(fs->value, fc->cols, fc->wrap, 0); if (!linex) return; line = linex; @@ -615,8 +631,13 @@ menu_textarea_edit(struct terminal *term, void *xxx, void *ses_) } static enum frame_event_status +#ifdef CONFIG_UTF_8 textarea_op(struct form_state *fs, struct form_control *fc, int utf8, int (*do_op)(struct form_state *, struct line_info *, int, int)) +#else +textarea_op(struct form_state *fs, struct form_control *fc, + int (*do_op)(struct form_state *, struct line_info *, int)) +#endif /* CONFIG_UTF_8 */ { struct line_info *line; int current, state; @@ -624,15 +645,22 @@ textarea_op(struct form_state *fs, struct form_control *fc, int utf8, assert(fs && fs->value && fc); if_assert_failed return FRAME_EVENT_OK; +#ifdef CONFIG_UTF_8 if (utf8) line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); else +#endif /* CONFIG_UTF_8 */ line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return FRAME_EVENT_OK; current = get_textarea_line_number(line, fs->state); state = fs->state; - if (do_op(fs, line, current, utf8)) { +#ifdef CONFIG_UTF_8 + if (do_op(fs, line, current, utf8)) +#else + if (do_op(fs, line, current)) +#endif /* CONFIG_UTF_8 */ +{ mem_free(line); return FRAME_EVENT_IGNORED; } @@ -641,6 +669,7 @@ textarea_op(struct form_state *fs, struct form_control *fc, int utf8, return fs->state == state ? FRAME_EVENT_OK : FRAME_EVENT_REFRESH; } +#ifdef CONFIG_UTF_8 static int x_pos(struct form_state *fs, struct line_info *line, int current) { @@ -668,26 +697,37 @@ new_pos(struct form_state *fs, struct line_info *line, int current, int len) } fs->state = (int)(text - fs->value); } +#endif /* CONFIG_UTF_8 */ static int +#ifdef CONFIG_UTF_8 do_op_home(struct form_state *fs, struct line_info *line, int current, int utf8) +#else +do_op_home(struct form_state *fs, struct line_info *line, int current) +#endif /* CONFIG_UTF_8 */ { if (current != -1) fs->state = line[current].start; return 0; } static int +#ifdef CONFIG_UTF_8 do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) +#else +do_op_up(struct form_state *fs, struct line_info *line, int current) +#endif /* CONFIG_UTF_8 */ { if (current == -1) return 0; if (!current) return 1; +#ifdef CONFIG_UTF_8 if (utf8) { int len = x_pos(fs, line, current); new_pos(fs, line, current - 1, len); return 0; } +#endif /* CONFIG_UTF_8 */ fs->state -= line[current].start - line[current-1].start; int_upper_bound(&fs->state, line[current-1].end); @@ -695,24 +735,35 @@ do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) } static int +#ifdef CONFIG_UTF_8 do_op_down(struct form_state *fs, struct line_info *line, int current, int utf8) +#else +do_op_down(struct form_state *fs, struct line_info *line, int current) +#endif /* CONFIG_UTF_8 */ { if (current == -1) return 0; if (line[current+1].start == -1) return 1; +#ifdef CONFIG_UTF_8 if (utf8) { int len = x_pos(fs, line, current); new_pos(fs, line, current + 1, len); return 0; } +#endif /* CONFIG_UTF_8 */ + fs->state += line[current+1].start - line[current].start; int_upper_bound(&fs->state, line[current+1].end); return 0; } static int +#ifdef CONFIG_UTF_8 do_op_end(struct form_state *fs, struct line_info *line, int current, int utf8) +#else +do_op_end(struct form_state *fs, struct line_info *line, int current) +#endif /* CONFIG_UTF_8 */ { if (current == -1) { fs->state = strlen(fs->value); @@ -727,7 +778,11 @@ do_op_end(struct form_state *fs, struct line_info *line, int current, int utf8) } static int +#ifdef CONFIG_UTF_8 do_op_bob(struct form_state *fs, struct line_info *line, int current, int utf8) +#else +do_op_bob(struct form_state *fs, struct line_info *line, int current) +#endif /* CONFIG_UTF_8 */ { if (current == -1) return 0; @@ -737,7 +792,11 @@ do_op_bob(struct form_state *fs, struct line_info *line, int current, int utf8) } static int +#ifdef CONFIG_UTF_8 do_op_eob(struct form_state *fs, struct line_info *line, int current, int utf8) +#else +do_op_eob(struct form_state *fs, struct line_info *line, int current) +#endif /* CONFIG_UTF_8 */ { if (current == -1) { fs->state = strlen(fs->value); @@ -753,50 +812,102 @@ do_op_eob(struct form_state *fs, struct line_info *line, int current, int utf8) return 0; } +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_home(struct form_state *fs, struct form_control *fc, int utf8) { return textarea_op(fs, fc, utf8, do_op_home); } +#else +enum frame_event_status +textarea_op_home(struct form_state *fs, struct form_control *fc) +{ + return textarea_op(fs, fc, do_op_home); +} +#endif /* CONFIG_UTF_8 */ +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_up(struct form_state *fs, struct form_control *fc, int utf8) { return textarea_op(fs, fc, utf8, do_op_up); } +#else +enum frame_event_status +textarea_op_up(struct form_state *fs, struct form_control *fc) +{ + return textarea_op(fs, fc, do_op_up); +} +#endif /* CONFIG_UTF_8 */ +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_down(struct form_state *fs, struct form_control *fc, int utf8) { return textarea_op(fs, fc, utf8, do_op_down); } +#else +enum frame_event_status +textarea_op_down(struct form_state *fs, struct form_control *fc) +{ + return textarea_op(fs, fc, do_op_down); +} +#endif /* CONFIG_UTF_8 */ +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_end(struct form_state *fs, struct form_control *fc, int utf8) { return textarea_op(fs, fc, utf8, do_op_end); } +#else +enum frame_event_status +textarea_op_end(struct form_state *fs, struct form_control *fc) +{ + return textarea_op(fs, fc, do_op_end); +} +#endif /* CONFIG_UTF_8 */ /* Set the form state so the cursor is on the first line of the buffer. * Preserve the column if possible. */ +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_bob(struct form_state *fs, struct form_control *fc, int utf8) { return textarea_op(fs, fc, utf8, do_op_bob); } +#else +enum frame_event_status +textarea_op_bob(struct form_state *fs, struct form_control *fc) +{ + return textarea_op(fs, fc, do_op_bob); +} +#endif /* CONFIG_UTF_8 */ /* Set the form state so the cursor is on the last line of the buffer. Preserve * the column if possible. This is done by getting current and last line and * then shifting the state by the delta of both lines start position bounding * the whole thing to the end of the last line. */ +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_eob(struct form_state *fs, struct form_control *fc, int utf8) { return textarea_op(fs, fc, utf8, do_op_eob); } +#else +enum frame_event_status +textarea_op_eob(struct form_state *fs, struct form_control *fc) +{ + return textarea_op(fs, fc, do_op_eob); +} +#endif /* CONFIG_UTF_8 */ enum frame_event_status +#ifdef CONFIG_UTF_8 textarea_op_enter(struct form_state *fs, struct form_control *fc, int utf8) +#else +textarea_op_enter(struct form_state *fs, struct form_control *fc) +#endif /* CONFIG_UTF_8 */ { assert(fs && fs->value && fc); if_assert_failed return FRAME_EVENT_OK; @@ -817,7 +928,9 @@ set_textarea(struct document_view *doc_view, int direction) struct form_control *fc; struct form_state *fs; struct link *link; +#ifdef CONFIG_UTF_8 int utf8 = doc_view->document->options.utf8; +#endif /* CONFIG_UTF_8 */ assert(doc_view && doc_view->vs && doc_view->document); assert(direction == 1 || direction == -1); @@ -838,8 +951,15 @@ set_textarea(struct document_view *doc_view, int direction) /* Depending on which way we entered the textarea move cursor so that * it is available at end or start. */ +#ifdef CONFIG_UTF_8 if (direction == 1) textarea_op_eob(fs, fc, utf8); else textarea_op_bob(fs, fc, utf8); +#else + if (direction == 1) + textarea_op_eob(fs, fc); + else + textarea_op_bob(fs, fc); +#endif /* CONFIG_UTF_8 */ } diff --git a/src/viewer/text/textarea.h b/src/viewer/text/textarea.h index 0a27f58f..462aa3e6 100644 --- a/src/viewer/text/textarea.h +++ b/src/viewer/text/textarea.h @@ -13,7 +13,11 @@ struct link; struct session; struct terminal; +#ifdef CONFIG_UTF_8 int area_cursor(struct form_control *fc, struct form_state *fs, int utf8); +#else +int area_cursor(struct form_control *fc, struct form_state *fs); +#endif /* CONFIG_UTF_8 */ void draw_textarea(struct terminal *term, struct form_state *fs, struct document_view *doc_view, struct link *link); unsigned char *encode_textarea(struct submitted_value *sv); @@ -21,6 +25,7 @@ extern int textarea_editor; void textarea_edit(int, struct terminal *, struct form_state *, struct document_view *, struct link *); void menu_textarea_edit(struct terminal *term, void *xxx, void *ses_); +#ifdef CONFIG_UTF_8 enum frame_event_status textarea_op_home(struct form_state *fs, struct form_control *fc, int utf8); enum frame_event_status textarea_op_up(struct form_state *fs, struct form_control *fc, int utf8); enum frame_event_status textarea_op_down(struct form_state *fs, struct form_control *fc, int utf8); @@ -28,6 +33,15 @@ enum frame_event_status textarea_op_end(struct form_state *fs, struct form_contr enum frame_event_status textarea_op_bob(struct form_state *fs, struct form_control *fc, int utf8); enum frame_event_status textarea_op_eob(struct form_state *fs, struct form_control *fc, int utf8); enum frame_event_status textarea_op_enter(struct form_state *fs, struct form_control *fc, int utf8); +#else +enum frame_event_status textarea_op_home(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_up(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_down(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_end(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_bob(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_eob(struct form_state *fs, struct form_control *fc); +enum frame_event_status textarea_op_enter(struct form_state *fs, struct form_control *fc); +#endif /* CONFIG_UTF_8 */ void set_textarea(struct document_view *doc_view, int direction); From 81778bc5d7927f0d0d3cfa862245204363a10bff Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 4 Feb 2006 02:18:00 +0100 Subject: [PATCH 07/73] Correct computing of cursor position in UTF-8 textarea. --- src/viewer/text/form.c | 6 +++--- src/viewer/text/textarea.c | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 814b3f35..82228c9b 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -1634,12 +1634,12 @@ field_op(struct session *ses, struct document_view *doc_view, i = 0; break; } + if (i == 6) { i = 0; - return FRAME_EVENT_OK; - } else { - return FRAME_EVENT_OK; } + return FRAME_EVENT_OK; + } else { if (!insert_in_string(&fs->value, fs->state, "?", 1)) return FRAME_EVENT_OK; diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index ab5920ec..bffe0e9f 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -95,9 +95,9 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) pos = wrappos - text; } skip = !!wrappos; - char_cnt = 0; - wrappos = NULL; } + char_cnt = 0; + wrappos = NULL; if (!realloc_line_info(&line, line_number)) { mem_free_if(line); @@ -238,10 +238,13 @@ area_cursor(struct form_control *fc, struct form_state *fs) } #ifdef CONFIG_UTF_8 if (utf8) { - unsigned char *text = fs->value + line[y].start; + unsigned char *text = fs->value; unsigned char tmp = fs->value[fs->state]; fs->value[fs->state] = '\0'; + fs->utf8_pos = strlen_utf8(&text); + + text = fs->value + line[y].start; x = strlen_utf8(&text); fs->value[fs->state] = tmp; } else From c726080def2d11ff322cfa3155ebdb89b94a14de Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Wed, 8 Feb 2006 01:42:39 +0100 Subject: [PATCH 08/73] Double-width glyph support in terminal draw Added unicode_to_cell detect double-width glyphs. Modified terminal draw to correctly accept double-width glyphs. --- src/intl/charsets.c | 32 ++++++++++++++++++++++++++++++++ src/intl/charsets.h | 1 + src/terminal/draw.c | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index 9a224399..da3b27b5 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -252,6 +252,38 @@ strlen_utf8(unsigned char **str) return x; } + +/* + * Find out number of standard terminal collumns needed for displaying symbol + * (glyph) which represents Unicode character c. + * TODO: Use wcwidth when it is available. + * + * @return 2 for double-width glyph, 1 for others. + * TODO: May be extended to return 0 for zero-width glyphs + * (like composing, maybe unprintable too). + */ +inline int +unicode_to_cell(unicode_val_T c) +{ + if (c >= 0x1100 + && (c <= 0x115f /* Hangul Jamo */ + || c == 0x2329 + || c == 0x232a + || (c >= 0x2e80 && c <= 0xa4cf + && c != 0x303f) /* CJK ... Yi */ + || (c >= 0xac00 && c <= 0xd7a3) /* Hangul Syllables */ + || (c >= 0xf900 && c <= 0xfaff) /* CJK Compatibility + Ideographs */ + || (c >= 0xfe30 && c <= 0xfe6f) /* CJK Compatibility Forms */ + || (c >= 0xff00 && c <= 0xff60) /* Fullwidth Forms */ + || (c >= 0xffe0 && c <= 0xffe6) + || (c >= 0x20000 && c <= 0x2fffd) + || (c >= 0x30000 && c <= 0x3fffd))) + return 2; + + return 1; +} + inline unicode_val_T utf_8_to_unicode(unsigned char **string, unsigned char *end) { diff --git a/src/intl/charsets.h b/src/intl/charsets.h index f237e8f9..fbccb3bb 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -56,6 +56,7 @@ void free_conv_table(void); #ifdef CONFIG_UTF_8 inline unsigned char *encode_utf_8(unicode_val_T); inline int utf8charlen(const unsigned char *); +inline int unicode_to_cell(unicode_val_T); inline int strlen_utf8(unsigned char **); inline unicode_val_T utf_8_to_unicode(unsigned char **, unsigned char *); #endif /* CONFIG_UTF_8 */ diff --git a/src/terminal/draw.c b/src/terminal/draw.c index 5f94ab18..34c83d33 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -114,6 +114,26 @@ draw_char_data(struct terminal *term, int x, int y, unsigned char data) if (!screen_char) return; screen_char->data = data; + +#ifdef CONFIG_UTF_8 + if (unicode_to_cell(data) == 2) { + +#ifdef CONFIG_DEBUG + /* Detect attempt to draw double-width char on the last + * collumn of terminal. */ + if (x+1 > term->width) + INTERNAL("Attempt to draw double-width glyph on " + "last collumn!!"); +#endif /* CONFIG_DEBUG */ + + screen_char = get_char(term, x+1, y); + + if (!screen_char) return; + + screen_char->data = UCS_NO_CHAR; + } +#endif /* CONFIG_UTF_8 */ + set_screen_dirty(term->screen, y, y); } @@ -315,7 +335,25 @@ draw_text_utf8(struct terminal *term, int x, int y, get_opt_int_tree(term->spec, "colors")); } - for (pos = start + 1; x < term->width; x++, pos++) { + pos = start + 1; + + if (unicode_to_cell(data) == 2) { + +#ifdef CONFIG_DEBUG + /* Detect attempt to draw double-width char on the last + * collumn of terminal. */ + if (x+1 > term->width) + INTERNAL("Attempt to draw double-width character on " + "last collumn!!"); +#endif /* CONFIG_DEBUG */ + + pos->data = UCS_NO_CHAR; + if (color) copy_screen_chars(pos, start, 1); + x++; + pos++; + } + + for (; x < term->width; x++, pos++) { data = utf_8_to_unicode(&text, end); if (data == UCS_NO_CHAR) break; if (color) copy_screen_chars(pos, start, 1); From fc5f2389edb15941149ab6bc7feaaabe8a87e4e1 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Wed, 8 Feb 2006 01:49:56 +0100 Subject: [PATCH 09/73] 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. --- src/document/plain/renderer.c | 260 ++++++++++++++-------------------- 1 file changed, 103 insertions(+), 157 deletions(-) diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index d238efc0..9421de9b 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -175,12 +175,12 @@ get_uri_length(unsigned char *line, int length) static int print_document_link(struct plain_renderer *renderer, int lineno, 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; unsigned char *start = &line[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; int link_end = line_pos + len; 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 *pos, *startpos; #ifdef CONFIG_UTF_8 - unsigned char *end, *text; int utf8 = document->options.utf8; #endif /* CONFIG_UTF_8 */ + int cells = 0; int lineno = renderer->lineno; int expanded = 0; int width = line_width; @@ -249,13 +249,31 @@ add_document_line(struct plain_renderer *renderer, if (!line) return 0; /* 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]; + 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 - && (line_pos + 1 == width - || line[line_pos + 1] != ASCII_BS)) { - int tab_width = 7 - ((line_pos + expanded) & 7); + && (line_pos + charlen == width + || line[line_pos + charlen] != ASCII_BS)) { + int tab_width = 7 - ((cells + expanded) & 7); expanded += tab_width; } else if (line_char == ASCII_BS) { @@ -276,32 +294,50 @@ add_document_line(struct plain_renderer *renderer, expanded--; #endif } + line_pos += charlen; + cells += cell; } assert(expanded >= 0); -#ifdef CONFIG_UTF_8 - if (utf8) goto utf_8; -#endif /* CONFIG_UTF_8 */ startpos = pos = realloc_line(document, width + expanded, lineno); if (!pos) { mem_free(line); return 0; } + cells = 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 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'; - next_char = (line_pos + 1 < width) ? line[line_pos + 1] - : '\0'; + next_char = (line_pos + charlen < width) ? + line[line_pos + charlen] : '\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); + int tab_width = 7 - ((cells + expanded) & 7); expanded += tab_width; @@ -313,7 +349,7 @@ add_document_line(struct plain_renderer *renderer, *template = saved_renderer_template; } else if (line_char == ASCII_BS) { - if (!(expanded + line_pos)) { + if (!(expanded + cells)) { /* We've backspaced to the start of the line */ continue; } @@ -327,8 +363,8 @@ add_document_line(struct plain_renderer *renderer, /* x^H_ becomes _^Hx */ if (line_pos - 1 >= 0) line[line_pos - 1] = next_char; - if (line_pos + 1 < width) - line[line_pos + 1] = prev_char; + if (line_pos + charlen < width) + line[line_pos + charlen] = prev_char; /* Go back and reparse the swapped characters */ if (line_pos - 2 >= 0) @@ -388,161 +424,53 @@ add_document_line(struct plain_renderer *renderer, line_pos, width, expanded, - pos); + pos, cells); } if (added_chars) { line_pos += added_chars - 1; pos += added_chars; } else { - if (!isscreensafe(line_char)) - line_char = '.'; - template->data = line_char; - 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; - } - } #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; - } + if (utf8) { + unsigned char *text = &line[line_pos]; + unicode_val_T data = + utf_8_to_unicode(&text, + &line[width]); - expanded = 0; - for (text = line; text < end; ) { - unsigned char line_char = *text; - unsigned char next_char, prev_char; + if (data == UCS_NO_CHAR) { + line_pos += charlen; + continue; + } - line_pos = text - line; - prev_char = text > line ? *(text - 1) : '\0'; - next_char = (text + 1 < end) ? *(text + 1) : '\0'; + template->data = (uint16_t)data; + copy_screen_chars(pos++, template, 1); - /* 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); + 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)) + line_char = '.'; + template->data = line_char; + copy_screen_chars(pos++, template, 1); - 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; + /* Detect copy of nul chars to screen, + * this should not occur. --Zas */ + assert(line_char); } - - } 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; } + + line_pos += charlen; + cells += cell; } -end: -#endif /* CONFIG_UTF_8 */ mem_free(line); realloc_line(document, pos - startpos, lineno); @@ -596,10 +524,11 @@ add_document_lines(struct plain_renderer *renderer) int last_space = 0; int tab_spaces = 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. */ - for (width = 0; width + tab_spaces < doc_width; width++) { + for (width = 0; (width < length) && + (cells < renderer->max_width);) { if (source[width] == ASCII_CR) step++; if (source[width + step] == ASCII_LF) @@ -618,6 +547,22 @@ add_document_lines(struct plain_renderer *renderer) only_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) { @@ -645,6 +590,7 @@ add_document_lines(struct plain_renderer *renderer) width -= was_spaces; step += was_spaces; } + if (!step && (width < length) && last_space) { width = last_space; step = 1; From 556143762977182209a00c0e9109eaef72cfde73 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Wed, 8 Feb 2006 03:23:21 +0100 Subject: [PATCH 10/73] Added UTF-8 to ELinks version. --- src/main/version.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/version.c b/src/main/version.c index de13b74d..05ff3ed4 100644 --- a/src/main/version.c +++ b/src/main/version.c @@ -115,6 +115,9 @@ get_dyn_full_version(struct terminal *term, int more) #endif #ifndef CONFIG_MOUSE comma, _("No mouse", term), +#endif +#ifdef CONFIG_UTF_8 + comma, "UTF-8", #endif comma, NULL From f4a430e4801259dbfd768750c41042464e60da36 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Wed, 8 Feb 2006 22:03:40 +0100 Subject: [PATCH 11/73] Support for double-width glyphs in DOM renderer Removed duplicate code for UTF-8 in DOM renderer. Modified DOM renderer to correctly displaying multi-width glyphs. --- src/document/dom/renderer.c | 61 +++++++++++++------------------------ 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/src/document/dom/renderer.c b/src/document/dom/renderer.c index e70df10f..e1565aa2 100644 --- a/src/document/dom/renderer.c +++ b/src/document/dom/renderer.c @@ -250,11 +250,11 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, struct document *document = renderer->document; struct conv_table *convert = renderer->convert_table; enum convert_string_mode mode = renderer->convert_mode; + int x, charlen; #ifdef CONFIG_UTF_8 int utf8 = document->options.utf8; - unsigned char *end, *text; + unsigned char *end; #endif /* CONFIG_UTF_8 */ - int x; assert(renderer && template && string && length); @@ -271,14 +271,14 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, add_search_node(renderer, length); #ifdef CONFIG_UTF_8 - if (utf8) goto utf_8; + end = string + length; #endif /* CONFIG_UTF_8 */ - for (x = 0; x < length; x++, renderer->canvas_x++) { - unsigned char data = string[x]; + for (x = 0, charlen = 1; x < length;x += charlen, renderer->canvas_x++) { + unsigned char *text = &string[x]; /* This is mostly to be able to break out so the indentation * level won't get to high. */ - switch (data) { + switch (*text) { case ASCII_TAB: { int tab_width = 7 - (X(renderer) & 7); @@ -293,52 +293,33 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, * ``main loop'' add the actual tab char. */ for (; tab_width-- > 0; renderer->canvas_x++) copy_screen_chars(POS(renderer), template, 1); + charlen = 1; break; } default: - template->data = isscreensafe(data) ? data : '.'; - } - - copy_screen_chars(POS(renderer), template, 1); - } #ifdef CONFIG_UTF_8 - goto end; -utf_8: - end = string + length; - for (text = string; text < end; renderer->canvas_x++) { - unsigned char data = *text; - unicode_val_T d2; + if (utf8) { + unicode_val_T data; + charlen = utf8charlen(text); + data = utf_8_to_unicode(&text, end); - /* This is mostly to be able to break out so the indentation - * level won't get to high. */ - switch (data) { - case ASCII_TAB: - { - int tab_width = 7 - (X(renderer) & 7); - int width = WIDTH(renderer, end - text + tab_width); + template->data = (uint16_t)data; - template->data = ' '; + if (unicode_to_cell(data) == 2) { + copy_screen_chars(POS(renderer), + template, 1); - if (!realloc_line(document, width, Y(renderer))) - break; + X(renderer)++; + template->data = UCS_NO_CHAR; + } - /* Only loop over the expanded tab chars and let the - * ``main loop'' add the actual tab char. */ - for (; tab_width-- > 0; renderer->canvas_x++) - copy_screen_chars(POS(renderer), template, 1); - text++; - break; - } - default: - d2 = utf_8_to_unicode(&text, end); - if (d2 == UCS_NO_CHAR) text++; - template->data = (uint16_t)d2; + } else +#endif /* CONFIG_UTF_8 */ + template->data = isscreensafe(*text) ? *text:'.'; } copy_screen_chars(POS(renderer), template, 1); } -end: -#endif /* CONFIG_UTF_8 */ mem_free(string); } From 79d4d74a22b12aafc3ac38469c515590a0d86806 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 5 Mar 2006 00:10:33 +0100 Subject: [PATCH 12/73] Added functions for manipulating with UTF-8 strings. --- src/intl/charsets.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ src/intl/charsets.h | 3 ++ 2 files changed, 86 insertions(+) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index da3b27b5..085b2d4f 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -252,6 +252,89 @@ strlen_utf8(unsigned char **str) return x; } +/* Count number of standard terminal cells needed for displaying UTF-8 + * character. */ +int +utf8_char2cells(unsigned char *utf8_char, unsigned char *end) +{ + unicode_val_T u; + + if (end == NULL) + end = strchr(utf8_char, '\0'); + + if(!utf8_char || !end) + return -1; + + u = utf_8_to_unicode(&utf8_char, end); + + return unicode_to_cell(u); +} + +/* Count number of standard terminal cells needed for displaying string + * with UTF-8 characters. */ +int +utf8_ptr2cells(unsigned char *string, unsigned char *end) +{ + int charlen, cell, cells = 0; + + if (end == NULL) + end = strchr(string, '\0'); + + if(!string || !end) + return -1; + + do { + charlen = utf8charlen(string); + if (string + charlen > end) + break; + + cell = utf8_char2cells(string, end); + if (cell < 0) + return -1; + + cells += cell; + string += charlen; + } while (1); + + return cells; +} + +/* + * Count number of bytes from begining of the string needed for displaying + * specified number of cells. + */ +int +utf8_cells2bytes(unsigned char *string, int max_cells, unsigned char *end) +{ + unsigned int bytes = 0, cells = 0; + + assert(max_cells>=0); + + if (end == NULL) + end = strchr(string, '\0'); + + if(!string || !end) + return -1; + + do { + int cell = utf8_char2cells(&string[bytes], end); + if (cell < 0) + return -1; + + cells += cell; + if (cells > max_cells) + break; + + bytes += utf8charlen(&string[bytes]); + + if (string + bytes > end) { + bytes = end - string; + break; + } + } while(1); + + return bytes; +} /* * Find out number of standard terminal collumns needed for displaying symbol diff --git a/src/intl/charsets.h b/src/intl/charsets.h index fbccb3bb..5a26d43a 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -56,6 +56,9 @@ void free_conv_table(void); #ifdef CONFIG_UTF_8 inline unsigned char *encode_utf_8(unicode_val_T); inline int utf8charlen(const unsigned char *); +int utf8_char2cells(unsigned char *, unsigned char *); +int utf8_ptr2cells(unsigned char *, unsigned char *); +int utf8_cells2bytes(unsigned char *, int, unsigned char *); inline int unicode_to_cell(unicode_val_T); inline int strlen_utf8(unsigned char **); inline unicode_val_T utf_8_to_unicode(unsigned char **, unsigned char *); From b356da18506775e640ee3dc5e51cfa7ebbf6daf4 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 5 Mar 2006 00:37:10 +0100 Subject: [PATCH 13/73] Added better support for displaying double-width UTF-8 chars. --- src/terminal/draw.c | 48 ++++++++++++++++++++++++++++-------------- src/terminal/screen.c | 49 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/src/terminal/draw.c b/src/terminal/draw.c index 34c83d33..c11836f7 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -327,37 +327,53 @@ draw_text_utf8(struct terminal *term, int x, int y, data = utf_8_to_unicode(&text, end); if (data == UCS_NO_CHAR) return; - start = get_char(term, x++, y); - start->data = (uint16_t)data; + start = get_char(term, x, y); if (color) { start->attr = attr; set_term_color(start, color, 0, get_opt_int_tree(term->spec, "colors")); } - pos = start + 1; + pos = start; if (unicode_to_cell(data) == 2) { + /* Is there enough room for whole double-width char? */ + if (x + 1 < term->width) { + pos->data = data; + pos++; + x++; -#ifdef CONFIG_DEBUG - /* Detect attempt to draw double-width char on the last - * collumn of terminal. */ - if (x+1 > term->width) - INTERNAL("Attempt to draw double-width character on " - "last collumn!!"); -#endif /* CONFIG_DEBUG */ - - pos->data = UCS_NO_CHAR; - if (color) copy_screen_chars(pos, start, 1); - x++; - pos++; + pos->data = UCS_NO_CHAR; + pos->attr = 0; + } else { + pos->data = (unicode_val_T)' '; + } + } else { + pos->data = data; } + pos++; + x++; for (; x < term->width; x++, pos++) { data = utf_8_to_unicode(&text, end); if (data == UCS_NO_CHAR) break; if (color) copy_screen_chars(pos, start, 1); - pos->data = (uint16_t)data; + + if (unicode_to_cell(data) == 2) { + /* Is there enough room for whole double-width char? */ + if (x + 1 < term->width) { + pos->data = data; + + x++; + pos++; + pos->data = UCS_NO_CHAR; + pos->attr = 0; + } else { + pos->data = (unicode_val_T)' '; + } + } else { + pos->data = data; + } } set_screen_dirty(term->screen, y, y); diff --git a/src/terminal/screen.c b/src/terminal/screen.c index dcf86861..c5e74035 100644 --- a/src/terminal/screen.c +++ b/src/terminal/screen.c @@ -450,7 +450,12 @@ add_char_data(struct string *screen, struct screen_driver *driver, unsigned char data, unsigned char border) #endif /* CONFIG_UTF_8 */ { - if (!isscreensafe(data)) { + if ( +#ifdef CONFIG_UTF_8 + !use_utf8_io(driver) && +#endif /* CONFIG_UTF_8 */ + !isscreensafe(data) + ) { add_char_to_string(screen, ' '); return; } @@ -485,17 +490,32 @@ add_char16(struct string *screen, struct screen_driver *driver, unsigned char underline = (ch->attr & SCREEN_ATTR_UNDERLINE); unsigned char bold = (ch->attr & SCREEN_ATTR_BOLD); - if (border != state->border && driver->frame_seqs) { + if ( +#ifdef CONFIG_UTF_8 + (!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && +#endif /* CONFIG_UTF_8 */ + border != state->border && driver->frame_seqs + ) { state->border = border; add_term_string(screen, driver->frame_seqs[!!border]); } - if (underline != state->underline && driver->underline) { + if ( +#ifdef CONFIG_UTF_8 + (!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && +#endif /* CONFIG_UTF_8 */ + underline != state->underline && driver->underline + ) { state->underline = underline; add_term_string(screen, driver->underline[!!underline]); } - if (bold != state->bold) { + if ( +#ifdef CONFIG_UTF_8 + (!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && +#endif /* CONFIG_UTF_8 */ + bold != state->bold + ) { state->bold = bold; if (bold) { add_bytes_to_string(screen, "\033[1m", 4); @@ -505,7 +525,12 @@ add_char16(struct string *screen, struct screen_driver *driver, } } - if (!compare_color(ch->color, state->color)) { + if ( +#ifdef CONFIG_UTF_8 + (!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && +#endif /* CONFIG_UTF_8 */ + !compare_color(ch->color, state->color) + ) { copy_color(state->color, ch->color); add_bytes_to_string(screen, "\033[0", 3); @@ -607,7 +632,12 @@ add_char256(struct string *screen, struct screen_driver *driver, { unsigned char attr_delta = (ch->attr ^ state->attr); - if (attr_delta) { + if ( +#ifdef CONFIG_UTF_8 + (!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && +#endif /* CONFIG_UTF_8 */ + attr_delta + ) { if ((attr_delta & SCREEN_ATTR_FRAME) && driver->frame_seqs) { state->border = !!(ch->attr & SCREEN_ATTR_FRAME); add_term_string(screen, driver->frame_seqs[state->border]); @@ -630,7 +660,12 @@ add_char256(struct string *screen, struct screen_driver *driver, state->attr = ch->attr; } - if (!compare_color(ch->color, state->color)) { + if ( +#ifdef CONFIG_UTF_8 + (!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && +#endif /* CONFIG_UTF_8 */ + !compare_color(ch->color, state->color) + ) { copy_color(state->color, ch->color); add_foreground_color(screen, color256_seqs, ch); From e0886dd842db7758d019e68a245ead5d6843f43d Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 5 Mar 2006 01:15:26 +0100 Subject: [PATCH 14/73] Bug fix: menu with UTF-8 items was unneeded wider. Also deal with double-width UTF-8 characters. --- src/bfu/menu.c | 93 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/src/bfu/menu.c b/src/bfu/menu.c index addf8575..b967ece5 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -186,7 +186,14 @@ get_menuitem_text_width(struct terminal *term, struct menu_item *mi) if (!text[0]) return 0; - return L_TEXT_SPACE + strlen(text) - !!mi->hotkey_pos + R_TEXT_SPACE; +#ifdef CONFIG_UTF_8 + if (term->utf8) + return L_TEXT_SPACE + utf8_ptr2cells(text, NULL) + - !!mi->hotkey_pos + R_TEXT_SPACE; + else +#endif /* CONFIG_UTF_8 */ + return L_TEXT_SPACE + strlen(text) + - !!mi->hotkey_pos + R_TEXT_SPACE; } /* Get desired width for right text in menu item, accounting spacing. */ @@ -321,17 +328,31 @@ select_item: int_bounds(&menu->first, 0, menu->size - height); } +/* width - number of standard terminal cells to be displayed (text + whitespace + * separators). For double-width glyph width == 2. + * len - length of text in bytes */ static inline void draw_menu_left_text(struct terminal *term, unsigned char *text, int len, int x, int y, int width, struct color_pair *color) { int w = width - (L_TEXT_SPACE + R_TEXT_SPACE); + int max_len; if (w <= 0) return; if (len < 0) len = strlen(text); if (!len) return; - if (len > w) len = w; + +#ifdef CONFIG_UTF_8 + if (term->utf8) { + max_len = utf8_cells2bytes(text, w, NULL); + if (max_len <= 0) + return; + } else +#endif /* CONFIG_UTF_8 */ + max_len = w; + + if (len > max_len) len = max_len; draw_text(term, x + L_TEXT_SPACE, y, text, len, 0, color); } @@ -404,15 +425,52 @@ utf8: continue; } if (hk_state == 1) { + if (unicode_to_cell(data) == 2) { + if (x < w) { #ifdef CONFIG_DEBUG - draw_char(term, xbase + x - 1, y, data, hk_attr, - (double_hk ? hk_color_sel : hk_color)); + draw_char(term, xbase + x - 1, y, + data, hk_attr, + (double_hk ? hk_color_sel + : hk_color)); #else - draw_char(term, xbase + x - 1, y, data, hk_attr, hk_color); + draw_char(term, xbase + x - 1, y, + data, hk_attr, hk_color); #endif /* CONFIG_DEBUG */ + x++; + draw_char(term, xbase + x - 1, y, + UCS_NO_CHAR, 0, color); + } else { + draw_char(term, xbase + x - 1, y, + ' ', 0, color); + } + } else { +#ifdef CONFIG_DEBUG + draw_char(term, xbase + x - 1, y, + data, hk_attr, + (double_hk ? hk_color_sel + : hk_color)); +#else + draw_char(term, xbase + x - 1, y, + data, hk_attr, hk_color); +#endif /* CONFIG_DEBUG */ + } hk_state = 2; } else { - draw_char(term, xbase + x - !!hk_state, y, data, 0, color); + if (unicode_to_cell(data) == 2) { + if (x - !!hk_state + 1 < w) { + draw_char(term, xbase + x - !!hk_state, + y, data, 0, color); + x++; + draw_char(term, xbase + x - !!hk_state, + y, UCS_NO_CHAR, 0, color); + } else { + draw_char(term, xbase + x - !!hk_state, + y, ' ', 0, color); + } + } else { + draw_char(term, xbase + x - !!hk_state, + y, data, 0, color); + } } } @@ -971,18 +1029,33 @@ display_mainmenu(struct terminal *term, struct menu *menu) int l = mi->hotkey_pos; int textlen; int selected = (i == menu->selected); + int screencnt; if (mi_text_translate(mi)) text = _(text, term); textlen = strlen(text) - !!l; +#ifdef CONFIG_UTF_8 + if (term->utf8) + screencnt = utf8_ptr2cells(text, NULL) - !!l; + else +#endif /* CONFIG_UTF_8 */ + screencnt = textlen; if (selected) { color = selected_color; box.x = p; - box.width = L_MAINTEXT_SPACE + L_TEXT_SPACE - + textlen - + R_TEXT_SPACE + R_MAINTEXT_SPACE; +#ifdef CONFIG_UTF_8 + if (term->utf8) + box.width = L_MAINTEXT_SPACE + L_TEXT_SPACE + + screencnt + + R_TEXT_SPACE + R_MAINTEXT_SPACE; + else +#endif /* CONFIG_UTF_8 */ + box.width = L_MAINTEXT_SPACE + L_TEXT_SPACE + + textlen + + R_TEXT_SPACE + R_MAINTEXT_SPACE; + draw_box(term, &box, ' ', 0, color); set_cursor(term, p, 0, 1); set_window_ptr(menu->win, p, 1); @@ -1000,7 +1073,7 @@ display_mainmenu(struct terminal *term, struct menu *menu) color); } - p += textlen; + p += screencnt; if (p >= term->width - R_MAINMENU_SPACE) break; From 33c0943ce420142213a4a6032ca1e0497263bf8f Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 5 Mar 2006 01:54:17 +0100 Subject: [PATCH 15/73] Modified titlebar for correctly displaying UTF-8 page titles. --- src/dialogs/status.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/dialogs/status.c b/src/dialogs/status.c index 0eaa948a..ac3f5b0f 100644 --- a/src/dialogs/status.c +++ b/src/dialogs/status.c @@ -412,11 +412,25 @@ display_title_bar(struct session *ses, struct terminal *term) if (document->title) { int maxlen = int_max(term->width - 4 - buflen, 0); - int titlelen = int_min(strlen(document->title), maxlen); + int titlelen, titlewidth; + +#ifdef CONFIG_UTF_8 + if (term->utf8) { + titlewidth = utf8_ptr2cells(document->title, NULL); + titlewidth = int_min(titlewidth, maxlen); + + titlelen = utf8_cells2bytes(document->title, + titlewidth, NULL); + } else +#endif /* CONFIG_UTF_8 */ + { + titlewidth = int_min(strlen(document->title), maxlen); + titlelen = titlewidth; + } add_bytes_to_string(&title, document->title, titlelen); - if (titlelen == maxlen) + if (titlewidth == maxlen) add_bytes_to_string(&title, "...", 3); } @@ -424,7 +438,16 @@ display_title_bar(struct session *ses, struct terminal *term) add_bytes_to_string(&title, buf, buflen); if (title.length) { - int x = int_max(term->width - 1 - title.length, 0); + int x; +#ifdef CONFIG_UTF_8 + if (term->utf8) { + x = int_max(term->width - 1 + - utf8_ptr2cells(title.source, + title.source + + title.length), 0); + } else +#endif /* CONFIG_UTF_8 */ + x = int_max(term->width - 1 - title.length, 0); draw_text(term, x, 0, title.source, title.length, 0, get_bfu_color(term, "title.title-text")); From f3a063f1ed28ddaa17bdfc66e3c10c8699bd489b Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 6 Mar 2006 05:05:18 +0100 Subject: [PATCH 16/73] Corrected support for double-width UTF-8 chars in titles of dialogs. --- src/bfu/dialog.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index e585ac57..672106da 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -97,25 +97,33 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) title_color = get_bfu_color(term, "dialog.title"); if (title_color && box.width > 2) { unsigned char *title = dlg_data->dlg->title; -#ifdef CONFIG_UTF_8 - unsigned char *t2 = title; int titlelen = strlen(title); - int len = term->utf8 ? strlen_utf8(&t2) : titlelen; - len = int_min(box.width - 2, len); - int x = (box.width - len) / 2 + box.x; -#else - int titlelen = int_min(box.width - 2, strlen(title)); - int x = (box.width - titlelen) / 2 + box.x; + int titlecells = titlelen; + int x, y; +#ifdef CONFIG_UTF_8 + if (term->utf8) + titlecells = utf8_ptr2cells(title, + &title[titlelen]); #endif /* CONFIG_UTF_8 */ - int y = box.y - 1; + + titlecells = int_min(box.width - 2, titlecells); + +#ifdef CONFIG_UTF_8 + if (term->utf8) { + titlelen = utf8_cells2bytes(title, + titlecells, + NULL); + } +#endif /* CONFIG_UTF_8 */ + + x = (box.width - titlecells) / 2 + box.x; + y = box.y - 1; + draw_text(term, x - 1, y, " ", 1, 0, title_color); draw_text(term, x, y, title, titlelen, 0, title_color); -#ifdef CONFIG_UTF_8 - draw_text(term, x + len, y, " ", 1, 0, title_color); -#else - draw_text(term, x + titlelen, y, " ", 1, 0, title_color); -#endif /* CONFIG_UTF_8 */ + draw_text(term, x + titlecells, y, " ", 1, 0, + title_color); } } @@ -579,7 +587,13 @@ generic_dialog_layouter(struct dialog_data *dlg_data) struct terminal *term = dlg_data->win->term; int w = dialog_max_width(term); int height = dialog_max_height(term); - int rw = int_min(w, strlen(dlg_data->dlg->title)); + int rw; +#ifdef CONFIG_UTF_8 + if (term->utf8) + rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL)); + else +#endif /* CONFIG_UTF_8 */ + rw = int_min(w, strlen(dlg_data->dlg->title)); int y = dlg_data->dlg->layout.padding_top ? 0 : -1; int x = 0; From 38db20b7768df5e4c10e7bb8f6d002cdae3927a7 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 6 Mar 2006 06:01:12 +0100 Subject: [PATCH 17/73] Added format_only parameter for distinguish between formating. Preparation for using struct terminal in formating functions. By now distinguish between formating widgets and formating widgets with displaying was done with term == NULL and term != NULL. I hope I'am not wrong. --- src/bfu/button.c | 7 ++++--- src/bfu/button.h | 2 +- src/bfu/checkbox.c | 4 ++-- src/bfu/checkbox.h | 2 +- src/bfu/dialog.c | 23 ++++++++++++++--------- src/bfu/group.c | 18 +++++++++--------- src/bfu/group.h | 2 +- src/bfu/inpfield.c | 10 +++++----- src/bfu/inpfield.h | 2 +- src/bfu/listbox.c | 2 +- src/bfu/listbox.h | 2 +- src/bfu/text.c | 15 +++++++++------ src/bfu/text.h | 4 ++-- src/dialogs/download.c | 18 +++++++++--------- 14 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/bfu/button.c b/src/bfu/button.c index 8cccbc39..519b9eb8 100644 --- a/src/bfu/button.c +++ b/src/bfu/button.c @@ -88,7 +88,7 @@ buttons_width(struct widget_data *widget_data, int n, while (n--) { int minw = (widget_data++)->widget->info.button.textlen - + BUTTON_HSPACING + BUTTON_LR_LEN; + + BUTTON_HSPACING + BUTTON_LR_LEN; maxw += minw; if (minwidth) int_lower_bound(minwidth, minw); @@ -100,7 +100,7 @@ buttons_width(struct widget_data *widget_data, int n, void dlg_format_buttons(struct terminal *term, struct widget_data *widget_data, int n, - int x, int *y, int w, int *rw, enum format_align align) + int x, int *y, int w, int *rw, enum format_align align, int format_only) { int i1 = 0; @@ -120,7 +120,7 @@ dlg_format_buttons(struct terminal *term, buttons_width(widget_data1, i2 - i1, NULL, &mw); if (rw) int_bounds(rw, mw, w); - if (term) { + if (!format_only) { int i; int p = x + (align == ALIGN_CENTER ? (w - mw) / 2 : 0); @@ -190,6 +190,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) draw_char(term, x + x1 - !!hk_state, pos->y, data, 0, color); } + } len = x1 - !!hk_state; } else diff --git a/src/bfu/button.h b/src/bfu/button.h index 973a3ec7..90dba05f 100644 --- a/src/bfu/button.h +++ b/src/bfu/button.h @@ -48,6 +48,6 @@ void add_dlg_button_do(struct dialog *dlg, unsigned char *text, int flags, widge #endif extern struct widget_ops button_ops; -void dlg_format_buttons(struct terminal *, struct widget_data *, int, int, int *, int, int *, enum format_align); +void dlg_format_buttons(struct terminal *, struct widget_data *, int, int, int *, int, int *, enum format_align, int); #endif diff --git a/src/bfu/checkbox.c b/src/bfu/checkbox.c index c38f15ec..8fa6c636 100644 --- a/src/bfu/checkbox.c +++ b/src/bfu/checkbox.c @@ -39,7 +39,7 @@ void dlg_format_checkbox(struct terminal *term, struct widget_data *widget_data, int x, int *y, int w, int *rw, - enum format_align align) + enum format_align align, int format_only) { unsigned char *text = widget_data->widget->text; @@ -52,7 +52,7 @@ dlg_format_checkbox(struct terminal *term, dlg_format_text_do(term, text, x + CHECKBOX_LS, y, w - CHECKBOX_LS, rw, get_bfu_color(term, "dialog.checkbox-label"), - align); + align, format_only); if (rw) *rw += CHECKBOX_LS; } } diff --git a/src/bfu/checkbox.h b/src/bfu/checkbox.h index 5d2ce5dc..627be572 100644 --- a/src/bfu/checkbox.h +++ b/src/bfu/checkbox.h @@ -33,7 +33,7 @@ void dlg_format_checkbox(struct terminal *term, struct widget_data *widget_data, int x, int *y, int w, int *rw, - enum format_align align); + enum format_align align, int format_only); #define widget_has_group(widget_data) ((widget_data)->widget->type == WIDGET_CHECKBOX \ ? (widget_data)->widget->info.checkbox.gid : -1) diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index 672106da..db63eeb8 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -520,7 +520,7 @@ clear_dialog(struct dialog_data *dlg_data, struct widget_data *xxx) static void format_widgets(struct terminal *term, struct dialog_data *dlg_data, - int x, int *y, int w, int h, int *rw) + int x, int *y, int w, int h, int *rw, int format_only) { struct widget_data *wdata = dlg_data->widgets_data; int widgets = dlg_data->number_of_widgets; @@ -530,15 +530,18 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, switch (wdata->widget->type) { case WIDGET_FIELD_PASS: case WIDGET_FIELD: - dlg_format_field(term, wdata, x, y, w, rw, ALIGN_LEFT); + dlg_format_field(term, wdata, x, y, w, rw, ALIGN_LEFT, + format_only); break; case WIDGET_LISTBOX: - dlg_format_listbox(term, wdata, x, y, w, h, rw, ALIGN_LEFT); + dlg_format_listbox(term, wdata, x, y, w, h, rw, + ALIGN_LEFT, format_only); break; case WIDGET_TEXT: - dlg_format_text(term, wdata, x, y, w, rw, h); + dlg_format_text(term, wdata, x, y, w, rw, h, + format_only); break; case WIDGET_CHECKBOX: @@ -556,14 +559,16 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, break; } - dlg_format_group(term, wdata, size, x, y, w, rw); + dlg_format_group(term, wdata, size, x, y, w, rw, + format_only); wdata += size - 1; } else { /* No horizontal space between checkboxes belonging to * the same group. */ - dlg_format_checkbox(term, wdata, x, y, w, rw, ALIGN_LEFT); + dlg_format_checkbox(term, wdata, x, y, w, rw, + ALIGN_LEFT, format_only); if (widgets > 1 && group == widget_has_group(&wdata[1])) (*y)--; @@ -575,7 +580,7 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, * of the dialog. */ case WIDGET_BUTTON: dlg_format_buttons(term, wdata, widgets, - x, y, w, rw, ALIGN_CENTER); + x, y, w, rw, ALIGN_CENTER, format_only); return; } } @@ -597,7 +602,7 @@ generic_dialog_layouter(struct dialog_data *dlg_data) int y = dlg_data->dlg->layout.padding_top ? 0 : -1; int x = 0; - format_widgets(NULL, dlg_data, x, &y, w, height, &rw); + format_widgets(term, dlg_data, x, &y, w, height, &rw, 1); /* Update the width to respond to the required minimum width */ if (dlg_data->dlg->layout.fit_datalen) { @@ -612,7 +617,7 @@ generic_dialog_layouter(struct dialog_data *dlg_data) y = dlg_data->box.y + DIALOG_TB + dlg_data->dlg->layout.padding_top; x = dlg_data->box.x + DIALOG_LB; - format_widgets(term, dlg_data, x, &y, w, height, NULL); + format_widgets(term, dlg_data, x, &y, w, height, NULL, 0); } diff --git a/src/bfu/group.c b/src/bfu/group.c index 28eb20c8..8a815da2 100644 --- a/src/bfu/group.c +++ b/src/bfu/group.c @@ -19,7 +19,7 @@ void dlg_format_group(struct terminal *term, struct widget_data *widget_data, - int n, int x, int *y, int w, int *rw) + int n, int x, int *y, int w, int *rw, int format_only) { int space_between_widgets = 1; int line_width = 0; @@ -56,7 +56,7 @@ dlg_format_group(struct terminal *term, xpos = x + line_width; - if (term) { + if (!format_only) { if (widget_data->widget->type == WIDGET_CHECKBOX) { /* Draw text at right of checkbox. */ if (label_length) @@ -72,7 +72,6 @@ dlg_format_group(struct terminal *term, draw_text(term, xpos, *y, text, label_length, 0, color); - set_box(&widget_data->box, xpos + label_padding + label_length, *y, width, 1); @@ -97,12 +96,13 @@ group_layouter(struct dialog_data *dlg_data) int y = 0; int n = dlg_data->number_of_widgets - 2; - dlg_format_group(NULL, dlg_data->widgets_data, n, - 0, &y, w, &rw); + + dlg_format_group(term, dlg_data->widgets_data, n, + 0, &y, w, &rw, 1); y++; - dlg_format_buttons(NULL, dlg_data->widgets_data + n, 2, 0, &y, w, - &rw, ALIGN_CENTER); + dlg_format_buttons(term, dlg_data->widgets_data + n, 2, 0, &y, w, + &rw, ALIGN_CENTER, 1); w = rw; @@ -110,9 +110,9 @@ group_layouter(struct dialog_data *dlg_data) y = dlg_data->box.y + DIALOG_TB + 1; dlg_format_group(term, dlg_data->widgets_data, n, - dlg_data->box.x + DIALOG_LB, &y, w, NULL); + dlg_data->box.x + DIALOG_LB, &y, w, NULL, 0); y++; dlg_format_buttons(term, dlg_data->widgets_data + n, 2, - dlg_data->box.x + DIALOG_LB, &y, w, &rw, ALIGN_CENTER); + dlg_data->box.x + DIALOG_LB, &y, w, &rw, ALIGN_CENTER, 0); } diff --git a/src/bfu/group.h b/src/bfu/group.h index 040a7e83..0de645d0 100644 --- a/src/bfu/group.h +++ b/src/bfu/group.h @@ -7,7 +7,7 @@ struct widget_data; void dlg_format_group(struct terminal *term, struct widget_data *widget_data, - int n, int x, int *y, int w, int *rw); + int n, int x, int *y, int w, int *rw, int format_only); void group_layouter(struct dialog_data *); diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index e907119d..be68ee66 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -105,7 +105,7 @@ check_nonempty(struct dialog_data *dlg_data, struct widget_data *widget_data) void dlg_format_field(struct terminal *term, struct widget_data *widget_data, - int x, int *y, int w, int *rw, enum format_align align) + int x, int *y, int w, int *rw, enum format_align align, int format_only) { static int max_label_width; static int *prev_y; /* Assert the uniqueness of y */ /* TODO: get rid of this !! --Zas */ @@ -130,9 +130,9 @@ dlg_format_field(struct terminal *term, } if (label && *label) { - if (term) text_color = get_bfu_color(term, "dialog.text"); + if (!format_only) text_color = get_bfu_color(term, "dialog.text"); - dlg_format_text_do(term, label, x, y, w, rw, text_color, ALIGN_LEFT); + dlg_format_text_do(term, label, x, y, w, rw, text_color, ALIGN_LEFT, format_only); } /* XXX: We want the field and label on the same line if the terminal @@ -142,7 +142,7 @@ dlg_format_field(struct terminal *term, (*y) -= INPUTFIELD_HEIGHT; dlg_format_text_do(term, INPUTFIELD_FLOAT_SEPARATOR, x + label_width, y, w, rw, - text_color, ALIGN_LEFT); + text_color, ALIGN_LEFT, format_only); w -= INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; x += INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; } @@ -722,7 +722,7 @@ input_line_layouter(struct dialog_data *dlg_data) - ses->status.show_tabs_bar; dlg_format_field(win->term, dlg_data->widgets_data, 0, - &y, win->term->width, NULL, ALIGN_LEFT); + &y, win->term->width, NULL, ALIGN_LEFT, 0); } static widget_handler_status_T diff --git a/src/bfu/inpfield.h b/src/bfu/inpfield.h index c1db3397..5bd47da4 100644 --- a/src/bfu/inpfield.h +++ b/src/bfu/inpfield.h @@ -62,7 +62,7 @@ extern struct widget_ops field_pass_ops; widget_handler_status_T check_number(struct dialog_data *, struct widget_data *); widget_handler_status_T check_nonempty(struct dialog_data *, struct widget_data *); -void dlg_format_field(struct terminal *, struct widget_data *, int, int *, int, int *, enum format_align); +void dlg_format_field(struct terminal *, struct widget_data *, int, int *, int, int *, enum format_align, int format_only); void input_field(struct terminal *, struct memory_list *, int, unsigned char *, unsigned char *, unsigned char *, unsigned char *, void *, diff --git a/src/bfu/listbox.c b/src/bfu/listbox.c index 6ee74394..89e2400b 100644 --- a/src/bfu/listbox.c +++ b/src/bfu/listbox.c @@ -43,7 +43,7 @@ get_listbox_widget_data(struct widget_data *widget_data) void dlg_format_listbox(struct terminal *term, struct widget_data *widget_data, int x, int *y, int w, int max_height, int *rw, - enum format_align align) + enum format_align align, int format_only) { int min, optimal_h, height; diff --git a/src/bfu/listbox.h b/src/bfu/listbox.h index 3edfd358..2cea9b76 100644 --- a/src/bfu/listbox.h +++ b/src/bfu/listbox.h @@ -133,7 +133,7 @@ struct listbox_item { extern struct widget_ops listbox_ops; -void dlg_format_listbox(struct terminal *, struct widget_data *, int, int *, int, int, int *, enum format_align); +void dlg_format_listbox(struct terminal *, struct widget_data *, int, int *, int, int, int *, enum format_align, int format_only); struct listbox_item *traverse_listbox_items_list(struct listbox_item *, struct listbox_data *, int, int, int (*)(struct listbox_item *, void *, int *), void *); diff --git a/src/bfu/text.c b/src/bfu/text.c index e4e9d438..14360387 100644 --- a/src/bfu/text.c +++ b/src/bfu/text.c @@ -36,7 +36,7 @@ add_dlg_text(struct dialog *dlg, unsigned char *text, /* Returns length of substring (from start of @text) before a split. */ static inline int -split_line(unsigned char *text, int max_width) +split_line(unsigned char *text, int max_width, int *cells) { unsigned char *split = text; @@ -65,6 +65,7 @@ split_line(unsigned char *text, int max_width) split++; break; } +#endif /* CONFIG_UTF_8 */ /* If no way to do a clean split, just return * requested maximal width. */ @@ -134,7 +135,8 @@ split_lines(struct widget_data *widget_data, int max_width) void dlg_format_text_do(struct terminal *term, unsigned char *text, int x, int *y, int width, int *real_width, - struct color_pair *color, enum format_align align) + struct color_pair *color, enum format_align align, + int format_only) { int line_width; int firstline = 1; @@ -158,7 +160,7 @@ dlg_format_text_do(struct terminal *term, unsigned char *text, } if (real_width) int_lower_bound(real_width, line_width); - if (!term || !line_width) continue; + if (format_only || !line_width) continue; /* Calculate the number of chars to indent */ if (align == ALIGN_CENTER) @@ -176,7 +178,8 @@ dlg_format_text_do(struct terminal *term, unsigned char *text, void dlg_format_text(struct terminal *term, struct widget_data *widget_data, - int x, int *y, int width, int *real_width, int max_height) + int x, int *y, int width, int *real_width, int max_height, + int format_only) { unsigned char *text = widget_data->widget->text; unsigned char saved = 0; @@ -246,7 +249,7 @@ dlg_format_text(struct terminal *term, struct widget_data *widget_data, dlg_format_text_do(term, text, x, y, width, real_width, get_bfu_color(term, "dialog.text"), - widget_data->widget->info.text.align); + widget_data->widget->info.text.align, format_only); if (widget_data->widget->info.text.is_label) (*y)--; @@ -333,7 +336,7 @@ format_and_display_text(struct widget_data *widget_data, dlg_format_text(term, widget_data, widget_data->box.x, &y, widget_data->box.width, NULL, - height); + height, 0); display_text(dlg_data, widget_data); redraw_from_window(dlg_data->win); diff --git a/src/bfu/text.h b/src/bfu/text.h index 5c96b98a..408c7ce3 100644 --- a/src/bfu/text.h +++ b/src/bfu/text.h @@ -47,11 +47,11 @@ void add_dlg_text(struct dialog *dlg, unsigned char *text, extern struct widget_ops text_ops; void dlg_format_text_do(struct terminal *term, unsigned char *text, int x, int *y, int w, int *rw, - struct color_pair *scolor, enum format_align align); + struct color_pair *scolor, enum format_align align, int format_only); void dlg_format_text(struct terminal *term, struct widget_data *widget_data, - int x, int *y, int dlg_width, int *real_width, int height); + int x, int *y, int dlg_width, int *real_width, int height, int format_only); #define text_is_scrollable(widget_data) \ ((widget_data)->widget->info.text.is_scrollable \ diff --git a/src/dialogs/download.c b/src/dialogs/download.c index 8a0d1ffd..cd375d94 100644 --- a/src/dialogs/download.c +++ b/src/dialogs/download.c @@ -152,8 +152,8 @@ download_dialog_layouter(struct dialog_data *dlg_data) int_lower_bound(&w, DOWN_DLG_MIN); } - dlg_format_text_do(NULL, url, 0, &y, w, &rw, - dialog_text_color, ALIGN_LEFT); + dlg_format_text_do(term, url, 0, &y, w, &rw, + dialog_text_color, ALIGN_LEFT, 1); y++; if (show_meter) y += 2; @@ -161,13 +161,13 @@ download_dialog_layouter(struct dialog_data *dlg_data) #if CONFIG_BITTORRENT if (bittorrent) y += 2; #endif - dlg_format_text_do(NULL, msg, 0, &y, w, &rw, - dialog_text_color, ALIGN_LEFT); + dlg_format_text_do(term, msg, 0, &y, w, &rw, + dialog_text_color, ALIGN_LEFT, 1); y++; - dlg_format_buttons(NULL, dlg_data->widgets_data, + dlg_format_buttons(term, dlg_data->widgets_data, dlg_data->number_of_widgets, 0, &y, w, - &rw, ALIGN_CENTER); + &rw, ALIGN_CENTER, 1); draw_dialog(dlg_data, w, y); @@ -186,7 +186,7 @@ download_dialog_layouter(struct dialog_data *dlg_data) y = dlg_data->box.y + DIALOG_TB + 1; x = dlg_data->box.x + DIALOG_LB; dlg_format_text_do(term, url, x, &y, w, NULL, - dialog_text_color, ALIGN_LEFT); + dialog_text_color, ALIGN_LEFT, 0); if (show_meter) { y++; @@ -203,12 +203,12 @@ download_dialog_layouter(struct dialog_data *dlg_data) #endif y++; dlg_format_text_do(term, msg, x, &y, w, NULL, - dialog_text_color, ALIGN_LEFT); + dialog_text_color, ALIGN_LEFT, 0); y++; dlg_format_buttons(term, dlg_data->widgets_data, dlg_data->number_of_widgets, x, &y, w, - NULL, ALIGN_CENTER); + NULL, ALIGN_CENTER, 0); mem_free(url); mem_free(msg); From dfe029bc275797b43e31273a16b2c7b549d00b65 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 6 Mar 2006 06:09:58 +0100 Subject: [PATCH 18/73] Added support for correctly displaying double-width UTF-8 chars in buttons. With UTF-8 support in terminal enabled it is possible to use double-width UTF-8 strings as margins of buttons. Although they are displayed wrong when UTF-8 support in terminal is disabled. --- src/bfu/button.c | 135 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 27 deletions(-) diff --git a/src/bfu/button.c b/src/bfu/button.c index 519b9eb8..5cb7ba02 100644 --- a/src/bfu/button.c +++ b/src/bfu/button.c @@ -77,17 +77,34 @@ add_dlg_button_do(struct dialog *dlg, unsigned char *text, int flags, } } +#ifdef CONFIG_UTF_8 +static void +buttons_width(struct widget_data *widget_data, int n, + int *minwidth, int *maxwidth, int utf8) +#else static void buttons_width(struct widget_data *widget_data, int n, int *minwidth, int *maxwidth) +#endif /* CONFIG_UTF_8 */ { int maxw = -BUTTON_HSPACING; +#ifdef CONFIG_UTF_8 + int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + + utf8_ptr2cells(BUTTON_RIGHT, NULL); +#endif /* CONFIG_UTF_8 */ assert(n > 0); if_assert_failed return; while (n--) { - int minw = (widget_data++)->widget->info.button.textlen + int minw; +#ifdef CONFIG_UTF_8 + if (utf8) + minw = utf8_ptr2cells((widget_data++)->widget->text, NULL) + + BUTTON_HSPACING + button_lr_len; + else +#endif /* CONFIG_UTF_8 */ + minw = (widget_data++)->widget->info.button.textlen + BUTTON_HSPACING + BUTTON_LR_LEN; maxw += minw; @@ -111,24 +128,45 @@ dlg_format_buttons(struct terminal *term, while (i2 < n) { mw = 0; +#ifdef CONFIG_UTF_8 + buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw, + term->utf8); +#else buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw); +#endif /* CONFIG_UTF_8 */ if (mw <= w) i2++; else break; } mw = 0; +#ifdef CONFIG_UTF_8 + buttons_width(widget_data1, i2 - i1, NULL, &mw, term->utf8); +#else buttons_width(widget_data1, i2 - i1, NULL, &mw); +#endif /* CONFIG_UTF_8 */ if (rw) int_bounds(rw, mw, w); if (!format_only) { int i; int p = x + (align == ALIGN_CENTER ? (w - mw) / 2 : 0); +#ifdef CONFIG_UTF_8 + int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + + utf8_ptr2cells(BUTTON_RIGHT, NULL); +#endif /* CONFIG_UTF_8 */ for (i = i1; i < i2; i++) { - set_box(&widget_data[i].box, - p, *y, - widget_data[i].widget->info.button.textlen - + BUTTON_LR_LEN, BUTTON_HEIGHT); +#ifdef CONFIG_UTF_8 + if (term->utf8) + set_box(&widget_data[i].box, + p, *y, + utf8_ptr2cells(widget_data[i].widget->text, NULL) + + button_lr_len, BUTTON_HEIGHT); + else +#endif /* CONFIG_UTF_8 */ + set_box(&widget_data[i].box, + p, *y, + widget_data[i].widget->info.button.textlen + + BUTTON_LR_LEN, BUTTON_HEIGHT); p += widget_data[i].box.width + BUTTON_HSPACING; } @@ -145,8 +183,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) struct terminal *term = dlg_data->win->term; struct color_pair *color, *shortcut_color; struct box *pos = &widget_data->box; - int len = widget_data->box.width - BUTTON_LR_LEN; - int x = pos->x + BUTTON_LEFT_LEN; + int len, x; int sel = is_selected_widget(dlg_data, widget_data); if (sel) { @@ -158,6 +195,23 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) } if (!color || !shortcut_color) return EVENT_PROCESSED; +#ifdef CONFIG_UTF_8 + if (term->utf8) { + int button_left_len = utf8_ptr2cells(BUTTON_LEFT, NULL); + int button_right_len = utf8_ptr2cells(BUTTON_RIGHT, NULL); + + x = pos->x + button_left_len; + len = widget_data->box.width - + (button_left_len + button_right_len); + + } else +#endif /* CONFIG_UTF_8 */ + { + x = pos->x + BUTTON_LEFT_LEN; + len = widget_data->box.width - BUTTON_LR_LEN; + } + + draw_text(term, pos->x, pos->y, BUTTON_LEFT, BUTTON_LEFT_LEN, 0, color); if (len > 0) { unsigned char *text = widget_data->widget->text; @@ -169,30 +223,48 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) #ifdef CONFIG_UTF_8 if (term->utf8) { - unsigned char *text2 = text; - unsigned char *end = text - + widget_data->widget->info.button.truetextlen; - int hk_state = 0; - int x1; + if (hk_pos >= 0) { + int hk_bytes = utf8charlen(&text[hk_pos+1]); + int cells_to_hk = utf8_ptr2cells(text, + &text[hk_pos]); + int right = widget_data->widget->info.button.truetextlen + - hk_pos + - hk_bytes; - for (x1 = 0; x1 - !!hk_state < len && *text2; x1++) { - uint16_t data; + int hk_cells = utf8_char2cells(&text[hk_pos + + 1], + NULL); - data = (uint16_t)utf_8_to_unicode(&text2, end); - if (!hk_state && (int)(text2 - text) == hk_pos + 1) { - hk_state = 1; - continue; - } - if (hk_state == 1) { - draw_char(term, x + x1 - 1, pos->y, data, attr, shortcut_color); - hk_state = 2; - } else { - draw_char(term, x + x1 - !!hk_state, pos->y, data, 0, color); - } + if (hk_pos) + draw_text(term, x, pos->y, + text, hk_pos, 0, color); + draw_text(term, x + cells_to_hk, pos->y, + &text[hk_pos + 1], hk_bytes, + attr, shortcut_color); + if (right > 1) + draw_text(term, x+cells_to_hk+hk_cells, + pos->y, + &text[hk_pos + hk_bytes + 1], + right - 1, 0, color); + + } else { + int hk_width = utf8_char2cells(text, NULL); + int hk_len = utf8charlen(text); + int len_to_display = + utf8_cells2bytes(&text[hk_len], + len - hk_width, + NULL); + + draw_text(term, x, pos->y, + text, hk_len, + attr, shortcut_color); + + draw_text(term, x + hk_width, pos->y, + &text[hk_len], len_to_display, + 0, color); } - len = x1 - !!hk_state; } else #endif /* CONFIG_UTF_8 */ if (hk_pos >= 0) { @@ -213,8 +285,17 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) draw_text(term, x + 1, pos->y, &text[1], len - 1, 0, color); } } - draw_text(term, x + len, pos->y, BUTTON_RIGHT, BUTTON_RIGHT_LEN, 0, color); +#ifdef CONFIG_UTF_8 + if (term->utf8) { + int text_cells = utf8_ptr2cells(widget_data->widget->text, NULL); + int hk = (widget_data->widget->info.button.hotkey_pos >= 0); + draw_text(term, x + text_cells - hk, pos->y, + BUTTON_RIGHT, BUTTON_RIGHT_LEN, 0, color); + } else +#endif /* CONFIG_UTF_8 */ + draw_text(term, x + len, pos->y, BUTTON_RIGHT, + BUTTON_RIGHT_LEN, 0, color); if (sel) { set_cursor(term, x, pos->y, 1); set_window_ptr(dlg_data->win, pos->x, pos->y); From 10303bb94a129ef97491bf4a9a9b2031f9c99a54 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 6 Mar 2006 06:18:47 +0100 Subject: [PATCH 19/73] Added support for UTF-8 (including double-width) texts in dialogs. --- src/bfu/text.c | 115 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 18 deletions(-) diff --git a/src/bfu/text.c b/src/bfu/text.c index 14360387..6fc52126 100644 --- a/src/bfu/text.c +++ b/src/bfu/text.c @@ -19,6 +19,7 @@ #include "terminal/terminal.h" #include "util/color.h" +/* FIXME: For UTF-8 strings we need better function than isspace. */ #define is_unsplitable(pos) (*(pos) && *(pos) != '\n' && !isspace(*(pos))) void @@ -35,49 +36,103 @@ add_dlg_text(struct dialog *dlg, unsigned char *text, } /* Returns length of substring (from start of @text) before a split. */ +#ifdef CONFIG_UTF_8 +static inline int +split_line(unsigned char *text, int max_width, int *cells, int utf8) +#else static inline int split_line(unsigned char *text, int max_width, int *cells) +#endif /* CONFIG_UTF_8 */ { unsigned char *split = text; + int cells_save = *cells; if (max_width <= 0) return 0; while (*split && *split != '\n') { - unsigned char *next_split = split + 1; + unsigned char *next_split; +#ifdef CONFIG_UTF_8 + if (utf8) { + unsigned char *next_char_begin = split + + utf8charlen(split); - while (is_unsplitable(next_split)) - next_split++; + next_split = split; - if (next_split - text > max_width) { + *cells += utf8_char2cells(split, NULL); + while (*next_split && next_split != next_char_begin) + next_split++; + + next_char_begin = next_split; + while (is_unsplitable(next_split)) + { + if (next_split < next_char_begin) { + next_split++; + continue; + } + *cells += utf8_char2cells(next_split, NULL); + next_char_begin += utf8charlen(next_split); + } + } else +#endif /* CONFIG_UTF_8 */ + { + next_split = split + 1; + + while (is_unsplitable(next_split)) + next_split++; + *cells = next_split - text; + } + + if (*cells > max_width) { /* Force a split if no position was found yet, * meaning there's no splittable substring under * requested width. */ if (split == text) { - split = &text[max_width]; +#ifdef CONFIG_UTF_8 + if (utf8) { + int m_bytes = utf8_cells2bytes(text, + max_width, + NULL); + split = &text[m_bytes]; + } else +#endif /* CONFIG_UTF_8 */ + split = &text[max_width]; - /* Give preference to split on a punctuation - * if any. Note that most of the time - * punctuation char is followed by a space so - * this rule will not match often. - * We match dash and quotes too. */ + + /* FIXME: Function ispunct won't work correctly + * with UTF-8 characters. We need some similar + * function for UTF-8 characters. */ +#ifndef CONFIG_UTF_8 + /* Give preference to split on a + * punctuation if any. Note that most + * of the time punctuation char is + * followed by a space so this rule + * will not match often. We match dash + * and quotes too. */ + cells_save--; while (--split != text) { + cells_save--; if (!ispunct(*split)) continue; split++; + cells_save++; break; } #endif /* CONFIG_UTF_8 */ /* If no way to do a clean split, just return * requested maximal width. */ - if (split == text) + if (split == text) { + *cells = max_width; return max_width; + } } break; } + cells_save = *cells; split = next_split; } + *cells = cells_save; return split - text; } @@ -87,8 +142,13 @@ split_line(unsigned char *text, int max_width, int *cells) #define realloc_lines(x, o, n) mem_align_alloc(x, o, n, LINES_GRANULARITY) /* Find the start of each line with the current max width */ +#ifdef CONFIG_UTF_8 +static unsigned char ** +split_lines(struct widget_data *widget_data, int max_width, int utf8) +#else static unsigned char ** split_lines(struct widget_data *widget_data, int max_width) +#endif /* CONFIG_UTF_8 */ { unsigned char *text = widget_data->widget->text; unsigned char **lines = (unsigned char **) widget_data->cdata; @@ -101,19 +161,27 @@ split_lines(struct widget_data *widget_data, int max_width) while (*text) { int width; + int cells = 0; /* Skip first leading \n or space. */ if (isspace(*text)) text++; if (!*text) break; - width = split_line(text, max_width); +#ifdef CONFIG_UTF_8 + width = split_line(text, max_width, &cells, utf8); +#else + width = split_line(text, max_width, &cells); +#endif /* split_line() may return 0. */ if (width < 1) { width = 1; /* Infinite loop prevention. */ } + if (cells < 1) { + cells = 1; /* Infinite loop prevention. */ + } - int_lower_bound(&widget_data->box.width, width); + int_lower_bound(&widget_data->box.width, cells); if (!realloc_lines(&lines, line, line + 1)) break; @@ -143,6 +211,7 @@ dlg_format_text_do(struct terminal *term, unsigned char *text, for (; *text; text += line_width, (*y)++) { int shift; + int cells = 0; /* Skip first leading \n or space. */ if (!firstline && isspace(*text)) @@ -151,7 +220,11 @@ dlg_format_text_do(struct terminal *term, unsigned char *text, firstline = 0; if (!*text) break; - line_width = split_line(text, width); +#ifdef CONFIG_UTF_8 + line_width = split_line(text, width, &cells, term->utf8); +#else + line_width = split_line(text, width, &cells); +#endif /* CONFIG_UTF_8 */ /* split_line() may return 0. */ if (line_width < 1) { @@ -159,18 +232,18 @@ dlg_format_text_do(struct terminal *term, unsigned char *text, continue; } - if (real_width) int_lower_bound(real_width, line_width); + if (real_width) int_lower_bound(real_width, cells); if (format_only || !line_width) continue; /* Calculate the number of chars to indent */ if (align == ALIGN_CENTER) - shift = (width - line_width) / 2; + shift = (width - cells) / 2; else if (align == ALIGN_RIGHT) - shift = width - line_width; + shift = width - cells; else shift = 0; - assert(line_width <= width && shift < width); + assert(cells <= width && shift < width); draw_text(term, x + shift, *y, text, line_width, 0, color); } @@ -205,9 +278,15 @@ dlg_format_text(struct terminal *term, struct widget_data *widget_data, /* Ensure that the current split is valid but don't * split if we don't have to */ +#ifdef CONFIG_UTF_8 + if (widget_data->box.width != width + && !split_lines(widget_data, width, term->utf8)) + return; +#else if (widget_data->box.width != width && !split_lines(widget_data, width)) return; +#endif lines = (unsigned char **) widget_data->cdata; From 509fe2cf0dc28b4129a0dce622fa88f0beb9ff5c Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 6 Mar 2006 15:15:30 +0100 Subject: [PATCH 20/73] Added support for double-width UTF-8 checkboxes and listbox in dialogs. --- src/bfu/group.c | 84 +++++++++++++++++++++++++++++++++++++++-------- src/bfu/listbox.c | 9 ++++- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/bfu/group.c b/src/bfu/group.c index 8a815da2..75f40487 100644 --- a/src/bfu/group.c +++ b/src/bfu/group.c @@ -16,6 +16,9 @@ #include "terminal/terminal.h" #include "util/color.h" +/* Same as in src/bfu/checkbox.c */ +#define CHECKBOX_LEN 3 /* "[X]" or "(X)" */ + void dlg_format_group(struct terminal *term, struct widget_data *widget_data, @@ -33,13 +36,31 @@ dlg_format_group(struct terminal *term, int widget_width; int width; unsigned char *text = widget_data->widget->text; - int label_length = (text && *text) ? strlen(text) : 0; - int label_padding = (label_length > 0); + int label_length; + int label_padding; + +#ifdef CONFIG_UTF_8 + if (term->utf8) { + if (text && *text) + label_length = utf8_ptr2cells(text, NULL); + else + label_length = 0; + } else +#endif /* CONFIG_UTF_8 */ + label_length = (text && *text) ? strlen(text) : 0; + + label_padding = (label_length > 0); if (widget_data->widget->type == WIDGET_CHECKBOX) { - width = 3; + width = CHECKBOX_LEN; } else if (widget_is_textfield(widget_data)) { - width = widget_data->widget->datalen; +#ifdef CONFIG_UTF_8 + if (term->utf8) { + width = utf8_ptr2cells(widget_data->widget->data, + NULL); + } else +#endif /* CONFIG_UTF_8 */ + width = widget_data->widget->datalen; } else { /* TODO: handle all widget types. */ widget_data++; @@ -59,19 +80,50 @@ dlg_format_group(struct terminal *term, if (!format_only) { if (widget_data->widget->type == WIDGET_CHECKBOX) { /* Draw text at right of checkbox. */ - if (label_length) - draw_text(term, xpos + width + label_padding, *y, - text, label_length, - 0, color); + if (label_length) { +#ifdef CONFIG_UTF_8 + if (term->utf8) { + int lb = utf8_cells2bytes( + text, + label_length, + NULL); + draw_text(term, xpos + width + + label_padding, + *y, text, lb, 0, + color); + } else +#endif /* CONFIG_UTF_8 */ + { + draw_text(term, xpos + width + + label_padding, + *y, text, + label_length, 0, + color); + } + } set_box(&widget_data->box, xpos, *y, width, 1); } else if (widget_is_textfield(widget_data)) { /* Draw label at left of widget. */ - if (label_length) - draw_text(term, xpos, *y, - text, label_length, - 0, color); + if (label_length) { +#ifdef CONFIG_UTF_8 + if (term->utf8) { + int lb = utf8_cells2bytes( + text, + label_length, + NULL); + draw_text(term, xpos, *y, + text, lb, 0, color); + } else +#endif /* CONFIG_UTF_8 */ + { + draw_text(term, xpos, *y, + text, label_length, + 0, color); + } + } + set_box(&widget_data->box, xpos + label_padding + label_length, *y, width, 1); @@ -92,10 +144,16 @@ group_layouter(struct dialog_data *dlg_data) { struct terminal *term = dlg_data->win->term; int w = dialog_max_width(term); - int rw = int_min(w, strlen(dlg_data->dlg->title)); + int rw; int y = 0; int n = dlg_data->number_of_widgets - 2; +#ifdef CONFIG_UTF_8 + if (term->utf8) + rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL)); + else +#endif /* CONFIG_UTF_8 */ + rw = int_min(w, strlen(dlg_data->dlg->title)); dlg_format_group(term, dlg_data->widgets_data, n, 0, &y, w, &rw, 1); diff --git a/src/bfu/listbox.c b/src/bfu/listbox.c index 89e2400b..59015a1a 100644 --- a/src/bfu/listbox.c +++ b/src/bfu/listbox.c @@ -453,6 +453,7 @@ display_listbox_item(struct listbox_item *item, void *data_, int *offset) } else { unsigned char *text; struct listbox_ops *ops = data->box->ops; + int len_bytes; assert(ops && ops->get_info); @@ -461,8 +462,14 @@ display_listbox_item(struct listbox_item *item, void *data_, int *offset) len = strlen(text); int_upper_bound(&len, int_max(0, data->widget_data->box.width - depth * 5)); +#ifdef CONFIG_UTF_8 + if (data->term->utf8) + len_bytes = utf8_cells2bytes(text, len, NULL); + else +#endif /* CONFIG_UTF_8 */ + len_bytes = len; - draw_text(data->term, x, y, text, len, 0, text_color); + draw_text(data->term, x, y, text, len_bytes, 0, text_color); mem_free(text); } From 7d4dedcb8da728a836d4ebde3a77cbc7eeeca0a8 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Tue, 7 Mar 2006 00:38:41 +0100 Subject: [PATCH 21/73] Bug fix: dialog window opened with ELinks start wasn't right encoded. term->utf8 should be set before computing anything to be written on screen. But probably this is not the right place. --- src/terminal/event.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/terminal/event.c b/src/terminal/event.c index 07c32ee0..cf8a25f5 100644 --- a/src/terminal/event.c +++ b/src/terminal/event.c @@ -162,6 +162,12 @@ check_terminal_name(struct terminal *term, struct terminal_info *info) object_unlock(term->spec); term->spec = get_opt_rec(config_options, name); object_lock(term->spec); +#ifdef CONFIG_UTF_8 + /* Probably not best place for set this. But now we finally have + * term->spec and term->utf8 should be set before decode session info. + * --Scrool */ + term->utf8 = get_opt_bool_tree(term->spec, "utf_8_io"); +#endif /* CONFIG_UTF_8 */ } #ifdef CONFIG_MOUSE From 8b9d06c9771ee882a0b1049adf4081beda0e9aee Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 13 Mar 2006 01:54:34 +0100 Subject: [PATCH 22/73] Convert link titles to correct codepage before displaying it on screen. Don't replace UTF-8 bytes with '*'. Probably there is need to do better check what will be displayed. Also get_current_link_title is no longer pretty and trivial. (o: --- src/dialogs/download.c | 16 +++++++++++++-- src/dialogs/menu.c | 7 ++++++- src/dialogs/status.c | 7 ------- src/document/renderer.c | 10 ++++++++-- src/protocol/bittorrent/dialogs.c | 14 +++++++++++-- src/protocol/gopher/gopher.c | 4 ++++ src/session/download.c | 7 ++++++- src/session/session.c | 7 ++++++- src/viewer/text/link.c | 33 ++++++++++++++++++++++++++++--- src/viewer/text/link.h | 1 + 10 files changed, 87 insertions(+), 19 deletions(-) diff --git a/src/dialogs/download.c b/src/dialogs/download.c index cd375d94..722c2af5 100644 --- a/src/dialogs/download.c +++ b/src/dialogs/download.c @@ -145,7 +145,12 @@ download_dialog_layouter(struct dialog_data *dlg_data) mem_free(msg); return; } - decode_uri_for_display(url); +#ifdef CONFIG_UTF_8 + if (term->utf8) + decode_uri(url); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_for_display(url); url_len = strlen(url); if (show_meter) { @@ -296,7 +301,14 @@ get_file_download_text(struct listbox_item *item, struct terminal *term) unsigned char *uristring; uristring = get_uri_string(file_download->uri, URI_PUBLIC); - if (uristring) decode_uri_for_display(uristring); + if (uristring) { +#ifdef CONFIG_UTF_8 + if (term->utf8) + decode_uri(uristring); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_for_display(uristring); + } return uristring; } diff --git a/src/dialogs/menu.c b/src/dialogs/menu.c index 5eff89c3..b23c58a0 100644 --- a/src/dialogs/menu.c +++ b/src/dialogs/menu.c @@ -578,7 +578,12 @@ query_file(struct session *ses, struct uri *uri, void *data, add_mime_filename_to_string(&def, uri); /* Remove the %-ugliness for display */ - decode_uri_string_for_display(&def); +#ifdef CONFIG_UTF_8 + if (ses->tab->term->utf8) + decode_uri_string(&def); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_string_for_display(&def); if (interactive) { input_dialog(ses->tab->term, NULL, diff --git a/src/dialogs/status.c b/src/dialogs/status.c index ac3f5b0f..24424931 100644 --- a/src/dialogs/status.c +++ b/src/dialogs/status.c @@ -142,15 +142,8 @@ get_current_link_info_and_title(struct session *ses, link_title = get_current_link_title(doc_view); if (link_title) { - unsigned char *src; - assert(*link_title); - /* Remove illicit chars. */ - for (src = link_title; *src; src++) - if (!isprint(*src) || iscntrl(*src)) - *src = '*'; - ret = straconcat(link_info, " - ", link_title, NULL); mem_free(link_info); mem_free(link_title); diff --git a/src/document/renderer.c b/src/document/renderer.c index 2af18ed6..54035de0 100644 --- a/src/document/renderer.c +++ b/src/document/renderer.c @@ -345,8 +345,14 @@ render_document(struct view_state *vs, struct document_view *doc_view, } document->title = get_uri_string(document->uri, components); - if (document->title) - decode_uri_for_display(document->title); + if (document->title) { +#ifdef CONFIG_UTF_8 + if (doc_view->document->options.utf8) + decode_uri(document->title); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_for_display(document->title); + } } #ifdef CONFIG_CSS diff --git a/src/protocol/bittorrent/dialogs.c b/src/protocol/bittorrent/dialogs.c index 688a4727..7a29ddb8 100644 --- a/src/protocol/bittorrent/dialogs.c +++ b/src/protocol/bittorrent/dialogs.c @@ -574,7 +574,12 @@ bittorrent_message_dialog(struct session *ses, void *data) uristring = get_uri_string(message->uri, URI_PUBLIC); if (uristring) { - decode_uri_for_display(uristring); +#ifdef CONFIG_UTF_8 + if (ses->tab->term->utf8) + decode_uri(uristring); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_for_display(uristring); add_format_to_string(&string, _("Unable to retrieve %s", ses->tab->term), uristring); @@ -719,7 +724,12 @@ bittorrent_query_callback(void *data, enum connection_state state, /* Let's make the filename pretty for display & save */ /* TODO: The filename can be the empty string here. See bug 396. */ - decode_uri_string_for_display(&filename); +#ifdef CONFIG_UTF_8 + if (term->utf8) + decode_uri_string(&filename); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_string_for_display(&filename); } add_format_to_string(&msg, diff --git a/src/protocol/gopher/gopher.c b/src/protocol/gopher/gopher.c index 2ba57657..12b779e6 100644 --- a/src/protocol/gopher/gopher.c +++ b/src/protocol/gopher/gopher.c @@ -649,6 +649,10 @@ init_gopher_index_cache_entry(struct connection *conn) return S_OUT_OF_MEM; where = get_uri_string(conn->uri, URI_PUBLIC); + + /* TODO: Use different function when using UTF-8 + * in terminal (decode_uri_for_display replaces + * bytes of UTF-8 characters width '*'). */ if (where) decode_uri_for_display(where); add_format_to_string(&buffer, diff --git a/src/session/download.c b/src/session/download.c index 3ab40e13..058e710f 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -1048,7 +1048,12 @@ do_type_query(struct type_query *type_query, unsigned char *ct, struct mime_hand /* Let's make the filename pretty for display & save */ /* TODO: The filename can be the empty string here. See bug 396. */ - decode_uri_string_for_display(&filename); +#ifdef CONFIG_UTF_8 + if (term->utf8) + decode_uri_string(&filename); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_string_for_display(&filename); } text = get_dialog_offset(dlg, TYPE_QUERY_WIDGETS_COUNT); diff --git a/src/session/session.c b/src/session/session.c index d79b80f4..797cfd23 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -268,7 +268,12 @@ print_error_dialog(struct session *ses, enum connection_state state, uristring = uri ? get_uri_string(uri, URI_PUBLIC) : NULL; if (uristring) { - decode_uri_for_display(uristring); +#ifdef CONFIG_UTF_8 + if (ses->tab->term->utf8) + decode_uri(uristring); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_for_display(uristring); add_format_to_string(&msg, _("Unable to retrieve %s", ses->tab->term), uristring); diff --git a/src/viewer/text/link.c b/src/viewer/text/link.c index 68890689..a678ceaf 100644 --- a/src/viewer/text/link.c +++ b/src/viewer/text/link.c @@ -1347,7 +1347,7 @@ end: do_menu(term, mi, ses, 1); } -/* Return current link's title. Pretty trivial. */ +/* Return current link's title. */ unsigned char * get_current_link_title(struct document_view *doc_view) { @@ -1361,7 +1361,29 @@ get_current_link_title(struct document_view *doc_view) link = get_current_link(doc_view); - return (link && link->title && *link->title) ? stracpy(link->title) : NULL; + if (link && link->title && *link->title) { + unsigned char *link_title, *src; + struct conv_table *convert_table; + + convert_table = get_translation_table(doc_view->document->cp, + doc_view->document->options.cp); + + link_title = convert_string(convert_table, link->title, + strlen(link->title), + doc_view->document->options.cp, + CSM_DEFAULT, NULL, NULL, NULL); + /* Remove illicit chars. */ +#ifdef CONFIG_UTF_8 + if (link_title && !doc_view->document->options.utf8) +#endif /* CONFIG_UTF_8 */ + for (src = link_title; *src; src++) + if (!isprint(*src) || iscntrl(*src)) + *src = '*'; + + return link_title; + } + + return NULL; } unsigned char * @@ -1406,7 +1428,12 @@ get_current_link_info(struct session *ses, struct document_view *doc_view) add_char_to_string(&str, ')'); } - decode_uri_string_for_display(&str); +#ifdef CONFIG_UTF_8 + if (term->utf8) + decode_uri_string(&str); + else +#endif /* CONFIG_UTF_8 */ + decode_uri_string_for_display(&str); return str.source; } diff --git a/src/viewer/text/link.h b/src/viewer/text/link.h index 6014be88..39f43167 100644 --- a/src/viewer/text/link.h +++ b/src/viewer/text/link.h @@ -11,6 +11,7 @@ struct session; struct term_event; struct terminal; struct uri; +struct conv_table; void set_link(struct document_view *doc_view); void free_link(struct document_view *doc_view); From 129bd2f44410c602da5fc8374083dec390d99e3e Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Fri, 7 Apr 2006 22:06:17 +0200 Subject: [PATCH 23/73] Added function utf8_ptr2chars for counting number of characters in string. --- src/intl/charsets.c | 24 ++++++++++++++++++++++++ src/intl/charsets.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index 085b2d4f..52c9dfd0 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -299,6 +299,30 @@ utf8_ptr2cells(unsigned char *string, unsigned char *end) return cells; } +/* Count number of characters in string. */ +int +utf8_ptr2chars(unsigned char *string, unsigned char *end) +{ + int charlen, chars = 0; + + if (end == NULL) + end = strchr(string, '\0'); + + if(!string || !end) + return -1; + + do { + charlen = utf8charlen(string); + if (string + charlen > end) + break; + + chars++; + string += charlen; + } while (1); + + return chars; +} + /* * Count number of bytes from begining of the string needed for displaying * specified number of cells. diff --git a/src/intl/charsets.h b/src/intl/charsets.h index 5a26d43a..2b5380b3 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -58,6 +58,7 @@ inline unsigned char *encode_utf_8(unicode_val_T); inline int utf8charlen(const unsigned char *); int utf8_char2cells(unsigned char *, unsigned char *); int utf8_ptr2cells(unsigned char *, unsigned char *); +int utf8_ptr2chars(unsigned char *, unsigned char *); int utf8_cells2bytes(unsigned char *, int, unsigned char *); inline int unicode_to_cell(unicode_val_T); inline int strlen_utf8(unsigned char **); From 662ffb903cd1c22bb2d330d00056ed51fd29f2e9 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 8 Apr 2006 00:16:10 +0200 Subject: [PATCH 24/73] Modified inpfield to be able to work with double-width UTF-8 chars. Note: there is ugly hack in ACT_EDIT_BACKSPACE where last byte of UTF-8 character is removed and then moving to left until complete UTF-8 character is found. --- src/bfu/inpfield.c | 76 ++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index be68ee66..4ff4c029 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -273,20 +273,12 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, #ifdef CONFIG_UTF_8 if (term->utf8) { unsigned char *t = widget_data->cdata; - unsigned char *t2 = t; int p = widget_data->info.field.cpos; - unsigned char tmp = t[p]; - int x; - t[p] = '\0'; - len = strlen_utf8(&t2); + len = utf8_ptr2cells(t, &t[p]); int_bounds(&left, len - widget_data->box.width + 1, len); int_lower_bound(&left, 0); - for (t2 = t, x = 0; x < left; x++) { - utf_8_to_unicode(&t2, &t[p]); - } - t[p] = tmp; - widget_data->info.field.vpos = (int)(t2 - t); + widget_data->info.field.vpos = utf8_cells2bytes(t, left, NULL); } else #endif /* CONFIG_UTF_8 */ { @@ -303,14 +295,13 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, color = get_bfu_color(term, "dialog.field-text"); if (color) { unsigned char *text = widget_data->cdata + widget_data->info.field.vpos; -#ifdef CONFIG_UTF_8 - unsigned char *text2 = text; -#endif /* CONFIG_UTF_8 */ int len, w; #ifdef CONFIG_UTF_8 - if (term->utf8) - len = strlen_utf8(&text2); + if (term->utf8 && !hide) + len = utf8_ptr2cells(text, NULL); + else if (term->utf8) + len = utf8_ptr2chars(text, NULL); else #endif /* CONFIG_UTF_8 */ len = strlen(text); @@ -318,13 +309,8 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, if (!hide) { #ifdef CONFIG_UTF_8 - int x; - if (term->utf8) { - int l; - for (l = 0, x = 0; x < w; x++) - l += utf8charlen(text+l); - w = l; - } + if (term->utf8) + w = utf8_cells2bytes(text, w, NULL); #endif /* CONFIG_UTF_8 */ draw_text(term, widget_data->box.x, widget_data->box.y, text, w, 0, color); @@ -532,16 +518,29 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) case ACT_EDIT_BACKSPACE: #ifdef CONFIG_UTF_8 if (widget_data->info.field.cpos && term->utf8) { - unsigned char *t = widget_data->cdata; - unsigned char *t2 = t; - int p = widget_data->info.field.cpos - 1; - unsigned char tmp = t[p]; + /* XXX: stolen from src/viewer/text/form.c */ + /* FIXME: This isn't nice. We remove last byte + * from UTF-8 character to detect + * character before it. */ + unsigned char *text = widget_data->cdata; + unsigned char *end = widget_data->cdata + widget_data->info.field.cpos - 1; + unicode_val_T data; + int old = widget_data->info.field.cpos; - t[p] = '\0'; - strlen_utf8(&t2); - t[p] = tmp; - memmove(t2, &t[p + 1], strlen(&t[p + 1]) + 1); - widget_data->info.field.cpos = (int)(t2 - t); + while(1) { + data = utf_8_to_unicode(&text, end); + if (data == UCS_NO_CHAR) + break; + } + + widget_data->info.field.cpos = (int)(text - widget_data->cdata); + if (old != widget_data->info.field.cpos) { + int length; + + text = widget_data->cdata; + length = strlen(text + old) + 1; + memmove(text + widget_data->info.field.cpos, text + old, length); + } goto display_field; } #endif /* CONFIG_UTF_8 */ @@ -561,12 +560,15 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) #ifdef CONFIG_UTF_8 if (term->utf8) { - unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; - unsigned char *dest = next; - unsigned char *end = strchr(next, '\0'); - - utf_8_to_unicode(&next, end); - memmove(dest, next, strlen(next) + 1); + unsigned char *end = widget_data->cdata + cdata_len; + unsigned char *text = widget_data->cdata + widget_data->info.field.cpos; + unsigned char *old = text; + + utf_8_to_unicode(&text, end); + if (old != text) { + memmove(old, text, + (int)(end - text) + 1); + } goto display_field; } #endif /* CONFIG_UTF_8 */ From 3c019606b20ed9366b8a324ead5ee57c26c4bf37 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 8 Apr 2006 00:37:25 +0200 Subject: [PATCH 25/73] Correct split on punctuation in BFU text. When CONFIG_UTF_8 is defined but utf8 isn't used. --- src/bfu/text.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/bfu/text.c b/src/bfu/text.c index 6fc52126..f3ba6236 100644 --- a/src/bfu/text.c +++ b/src/bfu/text.c @@ -101,22 +101,25 @@ split_line(unsigned char *text, int max_width, int *cells) /* FIXME: Function ispunct won't work correctly * with UTF-8 characters. We need some similar * function for UTF-8 characters. */ -#ifndef CONFIG_UTF_8 - /* Give preference to split on a - * punctuation if any. Note that most - * of the time punctuation char is - * followed by a space so this rule - * will not match often. We match dash - * and quotes too. */ - cells_save--; - while (--split != text) { - cells_save--; - if (!ispunct(*split)) continue; - split++; - cells_save++; - break; - } +#ifdef CONFIG_UTF_8 + if (!utf8) #endif /* CONFIG_UTF_8 */ + { + /* Give preference to split on a + * punctuation if any. Note that most + * of the time punctuation char is + * followed by a space so this rule + * will not match often. We match dash + * and quotes too. */ + cells_save--; + while (--split != text) { + cells_save--; + if (!ispunct(*split)) continue; + split++; + cells_save++; + break; + } + } /* If no way to do a clean split, just return * requested maximal width. */ From b0e2840f0d7a62bb4ea96436247ecbe252830f5e Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 8 Apr 2006 00:42:41 +0200 Subject: [PATCH 26/73] When double-width character in mainmenu is on last collumn don't show it. --- src/bfu/menu.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/bfu/menu.c b/src/bfu/menu.c index b967ece5..2fefb7ff 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -426,7 +426,7 @@ utf8: } if (hk_state == 1) { if (unicode_to_cell(data) == 2) { - if (x < w) { + if (x < w && xbase + x < term->width) { #ifdef CONFIG_DEBUG draw_char(term, xbase + x - 1, y, data, hk_attr, @@ -438,10 +438,10 @@ utf8: #endif /* CONFIG_DEBUG */ x++; draw_char(term, xbase + x - 1, y, - UCS_NO_CHAR, 0, color); + UCS_NO_CHAR, 0, hk_color); } else { draw_char(term, xbase + x - 1, y, - ' ', 0, color); + ' ', 0, hk_color); } } else { #ifdef CONFIG_DEBUG @@ -457,7 +457,8 @@ utf8: hk_state = 2; } else { if (unicode_to_cell(data) == 2) { - if (x - !!hk_state + 1 < w) { + if (x - !!hk_state + 1 < w && + xbase + x - !!hk_state + 1 < term->width) { draw_char(term, xbase + x - !!hk_state, y, data, 0, color); x++; @@ -1084,6 +1085,18 @@ display_mainmenu(struct terminal *term, struct menu *menu) menu->last = i - 1; int_lower_bound(&menu->last, menu->first); if (menu->last < menu->size - 1) { + struct screen_char *schar; + + schar = get_char(term, term->width - R_MAINMENU_SPACE, 0); + /* Is second cell of double-width char on the place where + * first char of the R_MAINMENU_SPACE will be displayed? */ + if (schar->data == UCS_NO_CHAR) { + /* Replace double-width char with ' '. */ + schar++; + draw_char_data(term, term->width - R_MAINMENU_SPACE - 1, + 0, ' '); + } + set_box(&box, term->width - R_MAINMENU_SPACE, 0, R_MAINMENU_SPACE, 1); From 20331ffd74964cf23a8d76a9aa544647b77a288c Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 9 Apr 2006 16:52:23 +0200 Subject: [PATCH 27/73] Use unicode_val_T instead of uint16_t for unicode data. --- src/terminal/draw.c | 4 ++-- src/terminal/draw.h | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/terminal/draw.c b/src/terminal/draw.c index c11836f7..e50d9d29 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -104,7 +104,7 @@ draw_char_color(struct terminal *term, int x, int y, struct color_pair *color) void #ifdef CONFIG_UTF_8 -draw_char_data(struct terminal *term, int x, int y, uint16_t data) +draw_char_data(struct terminal *term, int x, int y, unicode_val_T data) #else draw_char_data(struct terminal *term, int x, int y, unsigned char data) #endif /* CONFIG_UTF_8 */ @@ -226,7 +226,7 @@ draw_border(struct terminal *term, struct box *box, #ifdef CONFIG_UTF_8 void draw_char(struct terminal *term, int x, int y, - uint16_t data, enum screen_char_attr attr, + unicode_val_T data, enum screen_char_attr attr, struct color_pair *color) #else void diff --git a/src/terminal/draw.h b/src/terminal/draw.h index 4d7307e7..77e34679 100644 --- a/src/terminal/draw.h +++ b/src/terminal/draw.h @@ -1,6 +1,8 @@ #ifndef EL__TERMINAL_DRAW_H #define EL__TERMINAL_DRAW_H +#include "intl/charsets.h" /* unicode_val_T */ + struct color_pair; struct box; struct terminal; @@ -20,7 +22,7 @@ enum screen_char_attr { struct screen_char { /* Contains either character value or frame data. */ #ifdef CONFIG_UTF_8 - uint16_t data; + unicode_val_T data; #else unsigned char data; #endif /* CONFIG_UTF_8 */ @@ -207,7 +209,7 @@ void draw_char_color(struct terminal *term, int x, int y, /* Sets the data of a screen position. */ #ifdef CONFIG_UTF_8 -void draw_char_data(struct terminal *term, int x, int y, uint16_t data); +void draw_char_data(struct terminal *term, int x, int y, unicode_val_T data); #else void draw_char_data(struct terminal *term, int x, int y, unsigned char data); #endif /* CONFIG_UTF_8 */ @@ -223,7 +225,7 @@ void draw_border_cross(struct terminal *, int x, int y, /* Draws a char. */ #ifdef CONFIG_UTF_8 void draw_char(struct terminal *term, int x, int y, - uint16_t data, enum screen_char_attr attr, + unicode_val_T data, enum screen_char_attr attr, struct color_pair *color); #else void draw_char(struct terminal *term, int x, int y, From 69a1c40fbdd3c91ce9f2fc0824f90fc3cfcefcd2 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 9 Apr 2006 16:58:00 +0200 Subject: [PATCH 28/73] Replace double-width chars in html renderer with ' ' if there isn't space. Instead of double-width chars use ' ' in html renderer if there isn't enought room for it. --- src/terminal/draw.c | 54 +++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/terminal/draw.c b/src/terminal/draw.c index e50d9d29..aa03e237 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -116,22 +116,15 @@ draw_char_data(struct terminal *term, int x, int y, unsigned char data) screen_char->data = data; #ifdef CONFIG_UTF_8 - if (unicode_to_cell(data) == 2) { - #ifdef CONFIG_DEBUG - /* Detect attempt to draw double-width char on the last - * collumn of terminal. */ - if (x+1 > term->width) - INTERNAL("Attempt to draw double-width glyph on " - "last collumn!!"); + /* Detect attempt to draw double-width char on the last + * collumn of terminal. */ + if (unicode_to_cell(data) == 2 && x + 1 > term->width) + INTERNAL("Attempt to draw double-width glyph on last collumn!"); #endif /* CONFIG_DEBUG */ - screen_char = get_char(term, x+1, y); - - if (!screen_char) return; - - screen_char->data = UCS_NO_CHAR; - } + if (data == UCS_NO_CHAR) + screen_char->attr = 0; #endif /* CONFIG_UTF_8 */ set_screen_dirty(term->screen, y, y); @@ -152,7 +145,37 @@ draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line) size = int_min(l, term->width - x); if (size == 0) return; - copy_screen_chars(screen_char, line, size); +#ifdef CONFIG_UTF_8 + if (term->utf8) { + struct screen_char *sc; + + if (line->data == UCS_NO_CHAR && x == 0) { + sc = line; + unicode_val_T data_save = sc->data; + + sc->data = ' '; + copy_screen_chars(screen_char, line, 1); + sc->data = data_save; + size--; + line++; + screen_char++; + + } + /* Instead of displaying double-width character at last collumn + * display only space. */ + if (size - 1 > 0 && unicode_to_cell(line[size - 1].data) == 2) { + sc = &line[size - 1]; + unicode_val_T data_save = sc->data; + + sc->data = ' '; + copy_screen_chars(screen_char, line, size); + sc->data = data_save; + } else { + copy_screen_chars(screen_char, line, size); + } + } else +#endif + copy_screen_chars(screen_char, line, size); set_screen_dirty(term->screen, y, y); } @@ -334,6 +357,9 @@ draw_text_utf8(struct terminal *term, int x, int y, get_opt_int_tree(term->spec, "colors")); } + if (start->data == UCS_NO_CHAR && x - 1 > 0) + draw_char_data(term, x - 1, y, ' '); + pos = start; if (unicode_to_cell(data) == 2) { From c8a6a4c44d73cc7b1c857be578256f9a581d5b13 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 9 Apr 2006 16:59:27 +0200 Subject: [PATCH 29/73] Fix broken double-width chars when displaying menu or dialog. --- src/bfu/dialog.c | 8 +++++ src/bfu/menu.c | 8 +++++ src/terminal/draw.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ src/terminal/draw.h | 5 ++++ 4 files changed, 92 insertions(+) diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index db63eeb8..67be711b 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -639,7 +639,15 @@ draw_dialog(struct dialog_data *dlg_data, int width, int height) /* Draw shadow */ draw_shadow(term, &dlg_data->box, get_bfu_color(term, "dialog.shadow"), 2, 1); +#ifdef CONFIG_UTF_8 + if (term->utf8) + fix_dwchar_around_box(term, &dlg_data->box, 0, 2, 1); +#endif /* CONFIG_UTF_8 */ } +#ifdef CONFIG_UTF_8 + else if(term->utf8) + fix_dwchar_around_box(term, &dlg_data->box, 0, 0, 0); +#endif /* CONFIG_UTF_8 */ } static void diff --git a/src/bfu/menu.c b/src/bfu/menu.c index 2fefb7ff..ad64712d 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -518,7 +518,15 @@ display_menu(struct terminal *term, struct menu *menu) /* Draw shadow */ draw_shadow(term, &menu->box, get_bfu_color(term, "dialog.shadow"), 2, 1); +#ifdef CONFIG_UTF_8 + if (term->utf8) + fix_dwchar_around_box(term, &box, 1, 2, 1); +#endif /* CONFIG_UTF_8 */ } +#ifdef CONFIG_UTF_8 + else if(term->utf8) + fix_dwchar_around_box(term, &box, 1, 0, 0); +#endif /* CONFIG_UTF_8 */ menu_height = box.height; box.height = 1; diff --git a/src/terminal/draw.c b/src/terminal/draw.c index aa03e237..f539f961 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -246,6 +246,77 @@ draw_border(struct terminal *term, struct box *box, set_screen_dirty(term->screen, borderbox.y, borderbox.y + borderbox.height); } +#ifdef CONFIG_UTF_8 +/* Checks cells left and right to the box for broken double-width chars. + * Replace it with ' '. + * 1+---+3 + * 1|box|##4 + * 1| |##4 + * 1| |##4 + * 1+---+##4 + * 2#####4 + * 1,2,3,4 - needs to be checked, # - shadow , +,-,| - border + */ +void +fix_dwchar_around_box(struct terminal *term, struct box *box, int border, + int shadow_width, int shadow_height) +{ + struct screen_char *schar; + int height, x, y; + + if (!term->utf8) + return; + + /* 1 */ + x = box->x - border - 1; + if (x > 0) { + y = box->y - border; + height = box->height + 2 * border; + + schar = get_char(term, x, y); + for (;height--; schar += term->width) + if (unicode_to_cell(schar->data) == 2) + schar->data = ' '; + } + + /* 2 */ + x = box->x - border + shadow_width - 1; + if (x > 0 && x < term->width) { + y = box->y + border + box->height; + height = shadow_height; + + schar = get_char(term, x, y); + for (;height--; schar += term->width) + if (unicode_to_cell(schar->data) == 2) + schar->data = ' '; + } + + /* 3 */ + x = box->x + box->width + border; + if (x < term->width) { + y = box->y - border; + height = shadow_height; + + schar = get_char(term, x, y); + for (;height--; schar += term->width) + if (schar->data == UCS_NO_CHAR) + schar->data = ' '; + } + + /* 4 */ + x = box->x + box->width + border + shadow_width; + if (x < term->width) { + y = box->y - border + shadow_height; + height = box->height + 2 * border; + + schar = get_char(term, x, y); + for (;height--; schar += term->width) + if (schar->data == UCS_NO_CHAR) + schar->data = ' '; + } +} +#endif + #ifdef CONFIG_UTF_8 void draw_char(struct terminal *term, int x, int y, diff --git a/src/terminal/draw.h b/src/terminal/draw.h index 77e34679..2598cd90 100644 --- a/src/terminal/draw.h +++ b/src/terminal/draw.h @@ -246,6 +246,11 @@ void draw_shadow(struct terminal *term, struct box *box, void draw_border(struct terminal *term, struct box *box, struct color_pair *color, int width); +#ifdef CONFIG_UTF_8 +void fix_dwchar_around_box(struct terminal *term, struct box *box, int border, + int shadow_width, int shadow_height); +#endif /* CONFIG_UTF_8 */ + /* Draws @length chars from @text. */ void draw_text(struct terminal *term, int x, int y, unsigned char *text, int length, From 161ccf9eaebc3c877c4486a3367bdf07a1f08b60 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 9 Apr 2006 17:04:47 +0200 Subject: [PATCH 30/73] Use unicode_val_T instead of uint16_t for unicode data + cell count fix. --- src/document/dom/renderer.c | 2 +- src/document/plain/renderer.c | 5 +++-- src/viewer/dump/dump.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/document/dom/renderer.c b/src/document/dom/renderer.c index e1565aa2..74cb6b6f 100644 --- a/src/document/dom/renderer.c +++ b/src/document/dom/renderer.c @@ -303,7 +303,7 @@ render_dom_line(struct dom_renderer *renderer, struct screen_char *template, charlen = utf8charlen(text); data = utf_8_to_unicode(&text, end); - template->data = (uint16_t)data; + template->data = (unicode_val_T)data; if (unicode_to_cell(data) == 2) { copy_screen_chars(POS(renderer), diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index 9421de9b..d0a5a703 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -443,13 +443,14 @@ add_document_line(struct plain_renderer *renderer, continue; } - template->data = (uint16_t)data; + template->data = (unicode_val_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); + template, 1); + cell++; } } else #endif /* CONFIG_UTF_8 */ diff --git a/src/viewer/dump/dump.c b/src/viewer/dump/dump.c index dcfb7f3e..534fe42e 100644 --- a/src/viewer/dump/dump.c +++ b/src/viewer/dump/dump.c @@ -369,7 +369,7 @@ utf_8: int x; for (x = 0; x < document->data[y].length; x++) { - uint16_t data = pos->data; + unicode_val_T data = pos->data; unsigned int frame = (pos->attr & SCREEN_ATTR_FRAME); if (!isscreensafe(data)) { @@ -475,7 +475,7 @@ utf_8: int x; for (x = 0; x < document->data[y].length; x++) { - uint16_t c; + unicode_val_T c; unsigned char attr = document->data[y].chars[x].attr; c = document->data[y].chars[x].data; From dd05c89d49c0741a8a503672576a00b8014b982b Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 9 Apr 2006 19:07:43 +0200 Subject: [PATCH 31/73] Replaced utf8_len with cells. --- src/document/html/renderer.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 41a79657..f7b3f374 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -1264,7 +1264,7 @@ done_link_state_info(void) #ifdef CONFIG_UTF_8 static inline void process_link(struct html_context *html_context, enum link_state link_state, - unsigned char *chars, int charslen, int utf8_len) + unsigned char *chars, int charslen, int cells) #else static inline void process_link(struct html_context *html_context, enum link_state link_state, @@ -1322,7 +1322,7 @@ process_link(struct html_context *html_context, enum link_state link_state, charslen -= x_offset; chars += x_offset; #ifdef CONFIG_UTF_8 - utf8_len -= x_offset; + cells -= x_offset; #endif /* CONFIG_UTF_8 */ } @@ -1339,7 +1339,7 @@ process_link(struct html_context *html_context, enum link_state link_state, /* Add new canvas positions to the link. */ #ifdef CONFIG_UTF_8 - if (realloc_points(link, link->npoints + utf8_len)) + if (realloc_points(link, link->npoints + cells)) #else if (realloc_points(link, link->npoints + charslen)) #endif /* CONFIG_UTF_8 */ @@ -1349,9 +1349,9 @@ process_link(struct html_context *html_context, enum link_state link_state, int y = Y(part->cy); #ifdef CONFIG_UTF_8 - link->npoints += utf8_len; + link->npoints += cells; - for (; utf8_len > 0; utf8_len--, point++, x++) + for (; cells > 0; cells--, point++, x++) #else for (; charslen > 0; charslen--, point++, x++) #endif /* CONFIG_UTF_8 */ @@ -1408,7 +1408,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) int update_after_subscript = renderer_context.subscript; struct part *part; #ifdef CONFIG_UTF_8 - int utf8_len; + int cells; #endif /* CONFIG_UTF_8 */ assert(html_context); @@ -1469,7 +1469,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) put_link_number(html_context); } #ifdef CONFIG_UTF_8 - utf8_len = + cells = #endif /* CONFIG_UTF_8 */ set_hline(html_context, chars, charslen, link_state); @@ -1495,7 +1495,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) #ifdef CONFIG_UTF_8 process_link(html_context, link_state, chars, charslen, - utf8_len); + cells); #else process_link(html_context, link_state, chars, charslen); #endif /* CONFIG_UTF_8 */ @@ -1503,10 +1503,10 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) #ifdef CONFIG_UTF_8 if (renderer_context.nowrap - && part->cx + utf8_len > overlap(par_format)) + && part->cx + cells > overlap(par_format)) return; - part->cx += utf8_len; + part->cx += cells; #else if (renderer_context.nowrap && part->cx + charslen > overlap(par_format)) @@ -1531,7 +1531,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) assert(charslen > 0); #ifdef CONFIG_UTF_8 - part->xa += utf8_len; + part->xa += cells; #else part->xa += charslen; #endif /* CONFIG_UTF_8 */ From 7951d7bf22ad7d8f0dda291906d6eb85e0261c5c Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sun, 9 Apr 2006 19:17:16 +0200 Subject: [PATCH 32/73] Added: split line after any double-width character in html renderer. Note: there are ugly bug (feature?) - when there isn't enought room for whole double-width char two double-chars are displayed. Can be seen on table with double-width chars reduced as much as possible. --- src/document/html/renderer.c | 109 ++++++++++++++++++++++++++++++----- src/document/html/renderer.h | 4 ++ 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index f7b3f374..c93e6ce4 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -210,6 +210,10 @@ realloc_spaces(struct part *part, int length) if (!ALIGN_SPACES(&part->spaces, part->spaces_len, length)) return -1; +#ifdef CONFIG_UTF_8 + if (!ALIGN_SPACES(&part->char_width, part->spaces_len, length)) + return -1; +#endif part->spaces_len = length; @@ -438,6 +442,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, if (*chars == NBSP_CHAR) { schar->data = ' '; part->spaces[x] = html_context->options->wrap_nbsp; + part->char_width[x] = 1; chars++; } else { unicode_val_T data; @@ -452,15 +457,27 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, schar->attr = SCREEN_ATTR_FRAME; copy_screen_chars(&POS(x, y), schar, 1); schar->attr = attr; + part->char_width[x] = 0; continue; } else { - schar->data = (uint16_t)data; + if (unicode_to_cell(data) == 2) { + schar->data = (unicode_val_T)data; + part->char_width[x] = 2; + copy_screen_chars(&POS(x++, y), schar, 1); + schar->data = UCS_NO_CHAR; + part->spaces[x] = 0; + part->char_width[x] = 0; + } else { + part->char_width[x] = unicode_to_cell(data); + schar->data = (unicode_val_T)data; + } } } copy_screen_chars(&POS(x, y), schar, 1); } } else { for (; charslen > 0; charslen--, x++, chars++) { + part->char_width[x] = 1; if (*chars == NBSP_CHAR) { schar->data = ' '; part->spaces[x] = html_context->options->wrap_nbsp; @@ -482,12 +499,23 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, part->spaces[x] = (*chars == ' '); data = utf_8_to_unicode(&chars, end); - if (data == UCS_NO_CHAR) chars++; + part->char_width[x] = unicode_to_cell(data); + if (part->char_width[x] == 2) { + x++; + part->spaces[x] = 0; + part->char_width[x] = 0; + } + if (data == UCS_NO_CHAR) { + chars++; + part->char_width[x] = 0; + x++; + } } len = x - x2; } else { for (; charslen > 0; charslen--, x++, chars++) { part->spaces[x] = (*chars == ' '); + part->char_width[x] = 1; } } } @@ -766,29 +794,53 @@ split_line_at(struct html_context *html_context, int width) if (part->document) { assert(part->document->data); if_assert_failed return 0; - assertm(POS(width, part->cy).data == ' ', - "bad split: %c", POS(width, part->cy).data); - move_chars(html_context, width + 1, part->cy, par_format.leftmargin, part->cy + 1); - del_chars(html_context, width, part->cy); +#ifdef CONFIG_UTF_8 + if (html_context->options->utf8 + && width < part->spaces_len && part->char_width[width] == 2) { + move_chars(html_context, width, part->cy, par_format.leftmargin, part->cy + 1); + del_chars(html_context, width, part->cy); + } else +#endif + { + assertm(POS(width, part->cy).data == ' ', + "bad split: %c", POS(width, part->cy).data); + move_chars(html_context, width + 1, part->cy, par_format.leftmargin, part->cy + 1); + del_chars(html_context, width, part->cy); + + } } - width++; /* Since we were using (x + 1) only later... */ +#ifdef CONFIG_UTF_8 + if (!(html_context->options->utf8 + && width < part->spaces_len + && part->char_width[width] == 2)) +#endif + width++; /* Since we were using (x + 1) only later... */ tmp = part->spaces_len - width; if (tmp > 0) { /* 0 is possible and I'm paranoid ... --Zas */ memmove(part->spaces, part->spaces + width, tmp); +#ifdef CONFIG_UTF_8 + memmove(part->char_width, part->char_width + width, tmp); +#endif } assert(tmp >= 0); if_assert_failed tmp = 0; memset(part->spaces + tmp, 0, width); +#ifdef CONFIG_UTF_8 + memset(part->char_width + tmp, 0, width); +#endif if (par_format.leftmargin > 0) { tmp = part->spaces_len - par_format.leftmargin; assertm(tmp > 0, "part->spaces_len - par_format.leftmargin == %d", tmp); /* So tmp is zero, memmove() should survive that. Don't recover. */ memmove(part->spaces + par_format.leftmargin, part->spaces, tmp); +#ifdef CONFIG_UTF_8 + memmove(part->char_width + par_format.leftmargin, part->char_width, tmp); +#endif } part->cy++; @@ -826,13 +878,38 @@ split_line(struct html_context *html_context) assert(part); if_assert_failed return 0; - for (x = overlap(par_format); x >= par_format.leftmargin; x--) - if (x < part->spaces_len && part->spaces[x]) - return split_line_at(html_context, x); +#ifdef CONFIG_UTF_8 + if (html_context->options->utf8) { + for (x = overlap(par_format); x >= par_format.leftmargin; x--) { - for (x = par_format.leftmargin; x < part->cx ; x++) - if (x < part->spaces_len && part->spaces[x]) - return split_line_at(html_context, x); + if (x < part->spaces_len && (part->spaces[x] + || (part->char_width[x] == 2 + /* Ugly hack. If we haven't place for + * double-width characters we print two + * double-width characters. */ + && x != par_format.leftmargin))) + return split_line_at(html_context, x); + } + + for (x = par_format.leftmargin; x < part->cx ; x++) { + if (x < part->spaces_len && (part->spaces[x] + || (part->char_width[x] == 2 + /* We want to break line after _second_ + * double-width character. */ + && x > par_format.leftmargin))) + return split_line_at(html_context, x); + } + } else +#endif + { + for (x = overlap(par_format); x >= par_format.leftmargin; x--) + if (x < part->spaces_len && part->spaces[x]) + return split_line_at(html_context, x); + + for (x = par_format.leftmargin; x < part->cx ; x++) + if (x < part->spaces_len && part->spaces[x]) + return split_line_at(html_context, x); + } /* Make sure that we count the right margin to the total * actual box width. */ @@ -1593,6 +1670,9 @@ end: part->cx = -1; part->xa = 0; memset(part->spaces, 0, part->spaces_len); +#ifdef CONFIG_UTF_8 + memset(part->char_width, 0, part->spaces_len); +#endif } static void @@ -2014,6 +2094,9 @@ format_html_part(struct html_context *html_context, done_link_state_info(); mem_free_if(part->spaces); +#ifdef CONFIG_UTF_8 + mem_free_if(part->char_width); +#endif if (document) { struct node *node = document->nodes.next; diff --git a/src/document/html/renderer.h b/src/document/html/renderer.h index 37f98350..ebba5cdf 100644 --- a/src/document/html/renderer.h +++ b/src/document/html/renderer.h @@ -23,6 +23,10 @@ struct part { unsigned char *spaces; int spaces_len; +#ifdef CONFIG_UTF_8 + unsigned char *char_width; +#endif + struct box box; From 9d1008c523a56e27c0f568de1a63a649d01a006e Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Mon, 1 May 2006 22:58:51 +0200 Subject: [PATCH 33/73] Added utf8_prevchar for moving throught UTF-8 string to left. --- src/intl/charsets.c | 18 ++++++++++++++++++ src/intl/charsets.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index 52c9dfd0..35c6ce8d 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -252,6 +252,24 @@ strlen_utf8(unsigned char **str) return x; } +#define utf8_issingle(p) (((p) & 0x80) == 0) +#define utf8_islead(p) (utf8_issingle(p) || ((p) & 0xc0) == 0xc0) + +/* Start from @current and move back to @pos char. This pointer return. The + * most left pointer is @start. */ +inline unsigned char * +utf8_prevchar(unsigned char *current, int pos, unsigned char *start) +{ + if (current == NULL || start == NULL || pos < 0) + return NULL; + while (pos > 0 && current != start) { + current--; + if (utf8_islead(*current)) + pos--; + } + return current; +} + /* Count number of standard terminal cells needed for displaying UTF-8 * character. */ int diff --git a/src/intl/charsets.h b/src/intl/charsets.h index 2b5380b3..04e6a0f6 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -55,6 +55,7 @@ int is_cp_special(int); void free_conv_table(void); #ifdef CONFIG_UTF_8 inline unsigned char *encode_utf_8(unicode_val_T); +inline unsigned char *utf8_prevchar(unsigned char *, int, unsigned char *); inline int utf8charlen(const unsigned char *); int utf8_char2cells(unsigned char *, unsigned char *); int utf8_ptr2cells(unsigned char *, unsigned char *); From f515f14e08a9e74beedd90b31bacc04d0f3c7214 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 6 May 2006 20:50:59 +0200 Subject: [PATCH 34/73] Renamed variables utf8_pos to state_cell and char_cnt to chars_cells. --- src/viewer/text/form.c | 30 +++++++++++++++--------------- src/viewer/text/form.h | 2 +- src/viewer/text/link.c | 2 +- src/viewer/text/textarea.c | 10 +++++----- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 82228c9b..326947d9 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -169,7 +169,7 @@ init_form_state(struct form_control *fc, struct form_state *fs) fs->state = strlen(fc->default_value); #ifdef CONFIG_UTF_8 text = fs->value; - fs->utf8_pos = strlen_utf8(&text); + fs->state_cell = strlen_utf8(&text); #endif /* CONFIG_UTF_8 */ fs->vpos = 0; break; @@ -177,7 +177,7 @@ init_form_state(struct form_control *fc, struct form_state *fs) fs->value = stracpy(""); fs->state = 0; #ifdef CONFIG_UTF_8 - fs->utf8_pos = 0; + fs->state_cell = 0; #endif /* CONFIG_UTF_8 */ fs->vpos = 0; break; @@ -381,7 +381,7 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, utf_8: text = fs->value; end = strchr(text, '\0'); - int_bounds(&fs->vpos, fs->utf8_pos - fc->size + 1, fs->utf8_pos); + int_bounds(&fs->vpos, fs->state_cell - fc->size + 1, fs->state_cell); if (!link->npoints) break; y = link->points[0].y + dy; @@ -1291,7 +1291,7 @@ field_op(struct session *ses, struct document_view *doc_view, while (utf_8_to_unicode(&text, end) != UCS_NO_CHAR); fs->state = (int)(text - fs->value); - if (old != fs->state) fs->utf8_pos--; + if (old != fs->state) fs->state_cell--; } else #endif /* CONFIG_UTF_8 */ fs->state = int_max(fs->state - 1, 0); @@ -1305,7 +1305,7 @@ field_op(struct session *ses, struct document_view *doc_view, utf_8_to_unicode(&text, end); fs->state = (int)(text - fs->value); - if (old != fs->state) fs->utf8_pos++; + if (old != fs->state) fs->state_cell++; } else #endif /* CONFIG_UTF_8 */ fs->state = int_min(fs->state + 1, strlen(fs->value)); @@ -1320,7 +1320,7 @@ field_op(struct session *ses, struct document_view *doc_view, } else { fs->state = 0; #ifdef CONFIG_UTF_8 - fs->utf8_pos = 0; + fs->state_cell = 0; #endif /* CONFIG_UTF_8 */ } break; @@ -1357,7 +1357,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8) { unsigned char *text = fs->value; - fs->utf8_pos = strlen_utf8(&text); + fs->state_cell = strlen_utf8(&text); } #endif /* CONFIG_UTF_8 */ } @@ -1372,7 +1372,7 @@ field_op(struct session *ses, struct document_view *doc_view, } else { fs->state = 0; #ifdef CONFIG_UTF_8 - fs->utf8_pos = 0; + fs->state_cell = 0; #endif /* CONFIG_UTF_8 */ } break; @@ -1389,7 +1389,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8) { unsigned char *text = fs->value; - fs->utf8_pos = strlen_utf8(&text); + fs->state_cell = strlen_utf8(&text); } #endif /* CONFIG_UTF_8 */ } @@ -1410,7 +1410,7 @@ field_op(struct session *ses, struct document_view *doc_view, fs->value[0] = 0; fs->state = 0; #ifdef CONFIG_UTF_8 - fs->utf8_pos = 0; + fs->state_cell = 0; #endif /* CONFIG_UTF_8 */ break; case ACT_EDIT_PASTE_CLIPBOARD: @@ -1431,7 +1431,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8 && fc->type != FC_TEXTAREA) { unsigned char *text = fs->value; - fs->utf8_pos = strlen_utf8(&text); + fs->state_cell = strlen_utf8(&text); } #endif /* CONFIG_UTF_8 */ } @@ -1475,12 +1475,12 @@ field_op(struct session *ses, struct document_view *doc_view, unsigned char *text = fs->value; unsigned char *end = fs->value + fs->state; - for (i = 0; i < fs->utf8_pos - 1; i++) + for (i = 0; i < fs->state_cell - 1; i++) utf_8_to_unicode(&text, end); length = strlen(end) + 1; memmove(text, end, length); fs->state = (int)(text - fs->value); - fs->utf8_pos--; + fs->state_cell--; break; } #endif /* CONFIG_UTF_8 */ @@ -1548,7 +1548,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8 && fc->type != FC_TEXTAREA) { unsigned char *text = fs->value; - fs->utf8_pos = strlen_utf8(&text); + fs->state_cell = strlen_utf8(&text); } #endif /* CONFIG_UTF_8 */ break; @@ -1630,7 +1630,7 @@ field_op(struct session *ses, struct document_view *doc_view, return FRAME_EVENT_OK; } fs->state += i; - fs->utf8_pos++; + fs->state_cell++; i = 0; break; } diff --git a/src/viewer/text/form.h b/src/viewer/text/form.h index 0f9658c3..b813d77a 100644 --- a/src/viewer/text/form.h +++ b/src/viewer/text/form.h @@ -40,7 +40,7 @@ struct form_state { unsigned char *value; int state; #ifdef CONFIG_UTF_8 - int utf8_pos; + int state_cell; #endif /* CONFIG_UTF_8 */ int vpos; int vypos; diff --git a/src/viewer/text/link.c b/src/viewer/text/link.c index a678ceaf..8bdc97a1 100644 --- a/src/viewer/text/link.c +++ b/src/viewer/text/link.c @@ -128,7 +128,7 @@ get_link_cursor_offset(struct document_view *doc_view, struct link *link) fs = find_form_state(doc_view, fc); #ifdef CONFIG_UTF_8 if (utf8) { - return fs ? fs->utf8_pos - fs->vpos : 0; + return fs ? fs->state_cell - fs->vpos : 0; } else #endif /* CONFIG_UTF_8 */ return fs ? fs->state - fs->vpos : 0; diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index bffe0e9f..d2e255db 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -64,7 +64,7 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) int pos = 0; int skip; unsigned char *wrappos=NULL; - int char_cnt=0; /* Number of console chars on line */ + int chars_cells=0; /* Number of console chars on line */ assert(text); if_assert_failed return NULL; @@ -81,9 +81,9 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) if (text[pos] == '\n') { skip = 1; - } else if (wrap == FORM_WRAP_NONE || char_cnt < width) { + } else if (wrap == FORM_WRAP_NONE || chars_cells < width) { pos += utf8charlen(&text[pos]); - char_cnt++; + chars_cells++; continue; } else { @@ -96,7 +96,7 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) } skip = !!wrappos; } - char_cnt = 0; + chars_cells = 0; wrappos = NULL; if (!realloc_line_info(&line, line_number)) { @@ -242,7 +242,7 @@ area_cursor(struct form_control *fc, struct form_state *fs) unsigned char tmp = fs->value[fs->state]; fs->value[fs->state] = '\0'; - fs->utf8_pos = strlen_utf8(&text); + fs->state_cell = strlen_utf8(&text); text = fs->value + line[y].start; x = strlen_utf8(&text); From 546539b25e19e39d956c9f9f6f7ed0c282b0a27b Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 6 May 2006 21:10:16 +0200 Subject: [PATCH 35/73] Changed type uint16_t to unicode_val_T.Changed var x and xi to xbase and x. --- src/viewer/text/textarea.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index d2e255db..111ff1af 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -274,7 +274,7 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, struct box *box; int vx, vy; int sl, ye; - int x, y; + int x, xbase, y; assert(term && doc_view && doc_view->document && doc_view->vs && link); if_assert_failed return; @@ -294,7 +294,7 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, sl = fs->vypos; while (line->start != -1 && sl) sl--, line++; - x = link->points[0].x + box->x - vx; + xbase = link->points[0].x + box->x - vx; y = link->points[0].y + box->y - vy; ye = y + fc->rows; @@ -310,11 +310,10 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, if (!row_is_in_box(box, y)) continue; - for (i = 0; i < fc->cols; i++) { - uint16_t data; - int xi = x + i; + for (i = 0, x = xbase; i < fc->cols; i++, x++) { + unicode_val_T data; - if (!col_is_in_box(box, xi)) + if (!col_is_in_box(box, x)) continue; if (i >= -fs->vpos @@ -323,7 +322,7 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, else data = '_'; - draw_char_data(term, xi, y, data); + draw_char_data(term, x, y, data); } } @@ -332,11 +331,9 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, if (!row_is_in_box(box, y)) continue; - for (i = 0; i < fc->cols; i++) { - int xi = x + i; - - if (col_is_in_box(box, xi)) - draw_char_data(term, xi, y, '_'); + for (i = 0, x = xbase; i < fc->cols; i++, x++) { + if (col_is_in_box(box, x)) + draw_char_data(term, x, y, '_'); } } From bbd24d7bf40bfaa788641803994f53abef79f5d4 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 6 May 2006 21:23:12 +0200 Subject: [PATCH 36/73] Corrected computing cell count for html select in UTF-8. --- src/document/html/parser/forms.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/document/html/parser/forms.c b/src/document/html/parser/forms.c index dc2ddbfa..eb253c2a 100644 --- a/src/document/html/parser/forms.c +++ b/src/document/html/parser/forms.c @@ -492,7 +492,13 @@ end_parse: max_width = 0; for (i = 0; i < order; i++) { if (!labels[i]) continue; - int_lower_bound(&max_width, strlen(labels[i])); +#ifdef CONFIG_UTF_8 + if (html_context->options->utf8) + int_lower_bound(&max_width, + utf8_ptr2cells(labels[i], NULL)); + else +#endif /* CONFIG_UTF_8 */ + int_lower_bound(&max_width, strlen(labels[i])); } for (i = 0; i < max_width; i++) From aedc5459efc67c140fa377194f97906a1ce7ab62 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 6 May 2006 22:03:26 +0200 Subject: [PATCH 37/73] UTF-8 support for html form elements: text, password, select and file. Including double-width glyphs. Without support for textarea. --- src/viewer/text/form.c | 195 +++++++++++++++++++++++++---------------- 1 file changed, 120 insertions(+), 75 deletions(-) diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 326947d9..a73052d8 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -158,18 +158,16 @@ init_form_state(struct form_control *fc, struct form_state *fs) mem_free_set(&fs->value, NULL); switch (fc->type) { -#ifdef CONFIG_UTF_8 - unsigned char *text; -#endif /* CONFIG_UTF_8 */ - case FC_TEXT: case FC_PASSWORD: case FC_TEXTAREA: fs->value = stracpy(fc->default_value); fs->state = strlen(fc->default_value); #ifdef CONFIG_UTF_8 - text = fs->value; - fs->state_cell = strlen_utf8(&text); + if (fc->type == FC_TEXT) + fs->state_cell = utf8_ptr2cells(fs->value, NULL); + if (fc->type == FC_PASSWORD) + fs->state_cell = utf8_ptr2chars(fs->value, NULL); #endif /* CONFIG_UTF_8 */ fs->vpos = 0; break; @@ -350,18 +348,18 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, case FC_TEXT: case FC_PASSWORD: case FC_FILE: -#ifdef CONFIG_UTF_8 - if (term->utf8) goto utf_8; -#endif /* CONFIG_UTF_8 */ - int_bounds(&fs->vpos, fs->state - fc->size + 1, fs->state); if (!link->npoints) break; y = link->points[0].y + dy; if (!row_is_in_box(box, y)) break; - len = strlen(fs->value) - fs->vpos; x = link->points[0].x + dx; +#ifdef CONFIG_UTF_8 + if (term->utf8) goto utf_8; +#endif /* CONFIG_UTF_8 */ + int_bounds(&fs->vpos, fs->state - fc->size + 1, fs->state); + len = strlen(fs->value) - fs->vpos; for (i = 0; i < fc->size; i++, x++) { unsigned char data; @@ -379,32 +377,37 @@ draw_form_entry(struct terminal *term, struct document_view *doc_view, break; #ifdef CONFIG_UTF_8 utf_8: + end = NULL; /* Shut up the compiler. */ + int_bounds(&fs->vpos, fs->state_cell - fc->size + 1, fs->state_cell); + if (fc->type == FC_PASSWORD) + len = utf8_ptr2chars(fs->value + fs->vpos, NULL); + else + len = utf8_ptr2cells(fs->value + fs->vpos, NULL); text = fs->value; end = strchr(text, '\0'); - int_bounds(&fs->vpos, fs->state_cell - fc->size + 1, fs->state_cell); - if (!link->npoints) break; - - y = link->points[0].y + dy; - if (!row_is_in_box(box, y)) - break; - for (i = 0; i < fs->vpos; i++) { - utf_8_to_unicode(&text, end); - } - s = text; - len = strlen_utf8(&s); - x = link->points[0].x + dx; + for (i = 0; i < fc->size; i++, x++) { - uint16_t data; + unicode_val_T data; if (!col_is_in_box(box, x)) continue; - if (fs->value && i >= -fs->vpos && i < len) - data = fc->type != FC_PASSWORD - ? utf_8_to_unicode(&text, end) : '*'; - else + if (fs->value && i >= -fs->vpos && i < len) { + if (fc->type != FC_PASSWORD) + data = utf_8_to_unicode(&text, end); + else + data = '*'; + } else data = '_'; + if (unicode_to_cell(data) == 2) { + if (i + 1 < fc->size) { + draw_char_data(term, x++, y, data); + data = UCS_NO_CHAR; + i++; + } else + data = ' '; + } draw_char_data(term, x, y, data); } break; @@ -442,13 +445,29 @@ utf_8: utf_8_select: text = s; end = strchr(s, '\0'); - len = strlen_utf8(&text); + len = utf8_ptr2cells(text, end); for (i = 0; i < link->npoints; i++) { x = link->points[i].x + dx; y = link->points[i].y + dy; - if (is_in_box(box, x, y)) - draw_char_data(term, x, y, i < len - ? utf_8_to_unicode(&s, end) : '_'); + if (is_in_box(box, x, y)) { + unicode_val_T data; + if (i < len) { + int cell; + + data = utf_8_to_unicode(&s, end); + cell = unicode_to_cell(data); + if (i + 1 < len && cell == 2) { + draw_char_data(term, x++, y, data); + + data = UCS_NO_CHAR; + i++; + } else if (cell == 2) { + data = ' '; + } + } else + data = '_'; + draw_char_data(term, x, y, data); + } } break; #endif /* CONFIG_UTF_8 */ @@ -1285,13 +1304,18 @@ field_op(struct session *ses, struct document_view *doc_view, case ACT_EDIT_LEFT: #ifdef CONFIG_UTF_8 if (utf8) { - unsigned char *text = fs->value; - unsigned char *end = fs->value + fs->state - 1; - int old = fs->state; + int old_state = fs->state; + unsigned char *new_value; + + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); + fs->state = new_value - fs->value; - while (utf_8_to_unicode(&text, end) != UCS_NO_CHAR); - fs->state = (int)(text - fs->value); - if (old != fs->state) fs->state_cell--; + if (old_state != fs->state) { + if (fc->type == FC_PASSWORD) + fs->state_cell = int_max(fs->state_cell - 1, 0); + else + fs->state_cell = int_max(utf8_char2cells(new_value, NULL) - 1, 0); + } } else #endif /* CONFIG_UTF_8 */ fs->state = int_max(fs->state - 1, 0); @@ -1301,11 +1325,17 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8) { unsigned char *text = fs->value + fs->state; unsigned char *end = strchr(text, '\0'); - int old = fs->state; + int old_state = fs->state; + unicode_val_T data = utf_8_to_unicode(&text, end); - utf_8_to_unicode(&text, end); fs->state = (int)(text - fs->value); - if (old != fs->state) fs->state_cell++; + if (old_state != fs->state) { + if (fc->type == FC_PASSWORD) + fs->state_cell = int_min(fs->state_cell + 1, + utf8_ptr2cells(fs->value, NULL)); + else + fs->state_cell += unicode_to_cell(data); + } } else #endif /* CONFIG_UTF_8 */ fs->state = int_min(fs->state + 1, strlen(fs->value)); @@ -1354,11 +1384,12 @@ field_op(struct session *ses, struct document_view *doc_view, } else { fs->state = strlen(fs->value); #ifdef CONFIG_UTF_8 - if (utf8) { - unsigned char *text = fs->value; - - fs->state_cell = strlen_utf8(&text); - } + if (utf8 && fc->type != FC_PASSWORD) + fs->state_cell = utf8_ptr2cells(fs->value, + fs->value + fs->state); + else if(utf8) + fs->state_cell = utf8_ptr2chars(fs->value, + fs->value + fs->state); #endif /* CONFIG_UTF_8 */ } break; @@ -1386,11 +1417,13 @@ field_op(struct session *ses, struct document_view *doc_view, } else { fs->state = strlen(fs->value); #ifdef CONFIG_UTF_8 - if (utf8) { - unsigned char *text = fs->value; + if (utf8 && fc->type != FC_PASSWORD) + fs->state_cell = utf8_ptr2cells(fs->value, + fs->value + fs->state); + else if(utf8) + fs->state_cell = utf8_ptr2chars(fs->value, + fs->value + fs->state); - fs->state_cell = strlen_utf8(&text); - } #endif /* CONFIG_UTF_8 */ } break; @@ -1428,11 +1461,12 @@ field_op(struct session *ses, struct document_view *doc_view, memmove(v, text, length + 1); fs->state = strlen(fs->value); #ifdef CONFIG_UTF_8 - if (utf8 && fc->type != FC_TEXTAREA) { - unsigned char *text = fs->value; - - fs->state_cell = strlen_utf8(&text); - } + if(utf8 && fc->type == FC_PASSWORD) + fs->state_cell = utf8_ptr2chars(fs->value, + fs->value + fs->state); + else if (utf8) + fs->state_cell = utf8_ptr2cells(fs->value, + fs->value + fs->state); #endif /* CONFIG_UTF_8 */ } } @@ -1471,24 +1505,29 @@ field_op(struct session *ses, struct document_view *doc_view, } #ifdef CONFIG_UTF_8 if (utf8) { - int i; - unsigned char *text = fs->value; - unsigned char *end = fs->value + fs->state; + int old_state = fs->state; + unsigned char *new_value; + + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); + fs->state = new_value - fs->value; - for (i = 0; i < fs->state_cell - 1; i++) - utf_8_to_unicode(&text, end); - length = strlen(end) + 1; - memmove(text, end, length); - fs->state = (int)(text - fs->value); - fs->state_cell--; - break; - } + if (old_state != fs->state) { + if (fc->type == FC_PASSWORD) + fs->state_cell = int_max(fs->state_cell - 1, 0); + else + fs->state_cell -= utf8_char2cells(new_value, NULL); + length = strlen(fs->value + old_state) + 1; + memmove(new_value, fs->value + old_state, length); + } + } else #endif /* CONFIG_UTF_8 */ - length = strlen(fs->value + fs->state) + 1; - text = fs->value + fs->state; + { + length = strlen(fs->value + fs->state) + 1; + text = fs->value + fs->state; - memmove(text - 1, text, length); - fs->state--; + memmove(text - 1, text, length); + fs->state--; + } break; case ACT_EDIT_DELETE: if (form_field_is_readonly(fc)) { @@ -1545,10 +1584,13 @@ field_op(struct session *ses, struct document_view *doc_view, fs->state = (int) (text - fs->value); #ifdef CONFIG_UTF_8 - if (utf8 && fc->type != FC_TEXTAREA) { - unsigned char *text = fs->value; - - fs->state_cell = strlen_utf8(&text); + if (utf8) { + if(fc->type == FC_PASSWORD) + fs->state_cell = utf8_ptr2cells(fs->value, + fs->value + fs->state); + else + fs->state_cell = utf8_ptr2cells(fs->value, + fs->value + fs->state); } #endif /* CONFIG_UTF_8 */ break; @@ -1630,7 +1672,10 @@ field_op(struct session *ses, struct document_view *doc_view, return FRAME_EVENT_OK; } fs->state += i; - fs->state_cell++; + if (fc->type == FC_PASSWORD) + fs->state_cell++; + else + fs->state_cell += unicode_to_cell(data); i = 0; break; } From c0d20d8420ae2b68be7c13c2f18d78e7f60750e5 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 6 May 2006 22:36:48 +0200 Subject: [PATCH 38/73] UTF-8 support for html form textarea. Changed displaying of textarea. Including double-width glyph support. Note: textarea is now drawn with blank collumn at end of lines. It seems that this is more intuitive for users. It behaves similar as textareas in graphical interfaces. I hope it will hold your interest. +----+ +----+ +----+ |aaA | [right] |aaa_| [right] |aaa | |aaa | |aaa | |Aaa | |bb | |bb | |bb | +----+ +----+ +----+ +----+ +----+ +----+ |Aaa | [end] |aaa_| [c] |aaa | |aaa | |aaa | |Caa | |bb | |bb | |abb | +----+ +----+ +----+ A, _, C - cursor positions. [right] - right arrow [end] - ACT_END (End button) [c] - Letter c. Now this code: represents textarea with 3x3 positions for chars. Before this texteare behaved some kind of weirdly. That code above was rendered like this: +----+ |aaaa| |aabb| |_ | +----+ --- src/viewer/text/form.c | 33 ++- src/viewer/text/textarea.c | 411 +++++++++++++++++++++++++++++-------- src/viewer/text/textarea.h | 2 + 3 files changed, 349 insertions(+), 97 deletions(-) diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index a73052d8..a17f4e0b 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -168,6 +168,8 @@ init_form_state(struct form_control *fc, struct form_state *fs) fs->state_cell = utf8_ptr2cells(fs->value, NULL); if (fc->type == FC_PASSWORD) fs->state_cell = utf8_ptr2chars(fs->value, NULL); + if (fc->type == FC_TEXTAREA) + fs->state_cell = 0; #endif /* CONFIG_UTF_8 */ fs->vpos = 0; break; @@ -1303,6 +1305,10 @@ field_op(struct session *ses, struct document_view *doc_view, switch (action_id) { case ACT_EDIT_LEFT: #ifdef CONFIG_UTF_8 + if (fc->type == FC_TEXTAREA) { + status = textarea_op_left(fs, fc, utf8); + break; + } if (utf8) { int old_state = fs->state; unsigned char *new_value; @@ -1341,18 +1347,21 @@ field_op(struct session *ses, struct document_view *doc_view, fs->state = int_min(fs->state + 1, strlen(fs->value)); break; case ACT_EDIT_HOME: - if (fc->type == FC_TEXTAREA) { #ifdef CONFIG_UTF_8 + if (fc->type == FC_TEXTAREA) { status = textarea_op_home(fs, fc, utf8); -#else - status = textarea_op_home(fs, fc); -#endif /* CONFIG_UTF_8 */ } else { fs->state = 0; -#ifdef CONFIG_UTF_8 fs->state_cell = 0; -#endif /* CONFIG_UTF_8 */ } +#else + if (fc->type == FC_TEXTAREA) { + status = textarea_op_home(fs, fc); + } else { + fs->state = 0; + } + +#endif /* CONFIG_UTF_8 */ break; case ACT_EDIT_UP: if (fc->type != FC_TEXTAREA) @@ -1402,10 +1411,10 @@ field_op(struct session *ses, struct document_view *doc_view, #endif /* CONFIG_UTF_8 */ } else { fs->state = 0; + } #ifdef CONFIG_UTF_8 fs->state_cell = 0; #endif /* CONFIG_UTF_8 */ - } break; case ACT_EDIT_END_OF_BUFFER: if (fc->type == FC_TEXTAREA) { @@ -1464,6 +1473,8 @@ field_op(struct session *ses, struct document_view *doc_view, if(utf8 && fc->type == FC_PASSWORD) fs->state_cell = utf8_ptr2chars(fs->value, fs->value + fs->state); + else if (utf8 && fc->type == FC_TEXTAREA) + fs->state_cell = 0; else if (utf8) fs->state_cell = utf8_ptr2cells(fs->value, fs->value + fs->state); @@ -1512,7 +1523,9 @@ field_op(struct session *ses, struct document_view *doc_view, fs->state = new_value - fs->value; if (old_state != fs->state) { - if (fc->type == FC_PASSWORD) + if (fc->type == FC_TEXTAREA) + fs->state_cell = 0; + else if (fc->type == FC_PASSWORD) fs->state_cell = int_max(fs->state_cell - 1, 0); else fs->state_cell -= utf8_char2cells(new_value, NULL); @@ -1588,6 +1601,8 @@ field_op(struct session *ses, struct document_view *doc_view, if(fc->type == FC_PASSWORD) fs->state_cell = utf8_ptr2cells(fs->value, fs->value + fs->state); + else if (fc->type == FC_TEXTAREA) + fs->state_cell = 0; else fs->state_cell = utf8_ptr2cells(fs->value, fs->value + fs->state); @@ -1674,6 +1689,8 @@ field_op(struct session *ses, struct document_view *doc_view, fs->state += i; if (fc->type == FC_PASSWORD) fs->state_cell++; + else if (fc->type == FC_TEXTAREA) + fs->state_cell = 0; else fs->state_cell += unicode_to_cell(data); i = 0; diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index 111ff1af..cea578de 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -40,6 +40,11 @@ struct line_info { int start; int end; +#ifdef CONFIG_UTF_8 + int last_char_width; + int split_prev:1; + int split_next:1; +#endif /* CONFIG_UTF_8 */ }; /* We add two extra entries to the table so the ending info can be added @@ -74,6 +79,7 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) return NULL; while (text[pos]) { + int char_cells = utf8_char2cells(&text[pos], NULL); if (text[pos] == ' ') wrappos = &text[pos]; @@ -81,11 +87,11 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) if (text[pos] == '\n') { skip = 1; - } else if (wrap == FORM_WRAP_NONE || chars_cells < width) { + } else if (wrap == FORM_WRAP_NONE || chars_cells + char_cells < width) { pos += utf8charlen(&text[pos]); - chars_cells++; + chars_cells += char_cells; continue; - + } else { if (wrappos) { /* When formatting text for form submitting we @@ -96,19 +102,26 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) } skip = !!wrappos; } - chars_cells = 0; - wrappos = NULL; if (!realloc_line_info(&line, line_number)) { mem_free_if(line); return NULL; } + line[line_number].last_char_width = char_cells; + line[line_number].split_next = !skip; line[line_number].start = begin; line[line_number++].end = pos; + line[line_number].split_prev = !skip; + begin = pos += skip; + + chars_cells = 0; + wrappos = NULL; } + line[line_number].split_next = 0; + /* Flush the last text before the loop ended */ line[line_number].start = begin; line[line_number++].end = pos; @@ -116,6 +129,9 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) /* Add end marker */ line[line_number].start = line[line_number].end = -1; + line[line_number].split_next = line[line_number].split_prev = 0; + line[0].split_prev = 0; + return line; } #endif /* CONFIG_UTF_8 */ @@ -210,12 +226,9 @@ get_textarea_line_number(struct line_info *line, int cursor_position) /* Fixes up the vpos and vypos members of the form_state. Returns the * logical position in the textarea view. */ -int #ifdef CONFIG_UTF_8 +int area_cursor(struct form_control *fc, struct form_state *fs, int utf8) -#else -area_cursor(struct form_control *fc, struct form_state *fs) -#endif /* CONFIG_UTF_8 */ { struct line_info *line; int x, y; @@ -223,12 +236,59 @@ area_cursor(struct form_control *fc, struct form_state *fs) assert(fc && fs); if_assert_failed return 0; -#ifdef CONFIG_UTF_8 if (utf8) line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); else -#endif /* CONFIG_UTF_8 */ line = format_text(fs->value, fc->cols, fc->wrap, 0); + + if (!line) return 0; + + if (fs->state_cell) + y = get_textarea_line_number(line, fs->state_cell); + else + y = get_textarea_line_number(line, fs->state); + + if (y == -1) { + mem_free(line); + return 0; + } + + if (utf8) { + if (fs->state_cell) { + x = utf8_ptr2cells(fs->value + line[y].start, + fs->value + fs->state_cell); + x += line[y].last_char_width; + } else + x = utf8_ptr2cells(fs->value + line[y].start, + fs->value + fs->state); + } else { + x = fs->state - line[y].start; + if (fc->wrap && x == fc->cols) x--; + } + + mem_free(line); + + int_bounds(&fs->vpos, x - fc->cols + 1, x); + int_bounds(&fs->vypos, y - fc->rows + 1, y); + + x -= fs->vpos; + y -= fs->vypos; + + return y * fc->cols + x; +} + +#else + +int +area_cursor(struct form_control *fc, struct form_state *fs) +{ + struct line_info *line; + int x, y; + + assert(fc && fs); + if_assert_failed return 0; + + line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return 0; y = get_textarea_line_number(line, fs->state); @@ -236,20 +296,8 @@ area_cursor(struct form_control *fc, struct form_state *fs) mem_free(line); return 0; } -#ifdef CONFIG_UTF_8 - if (utf8) { - unsigned char *text = fs->value; - unsigned char tmp = fs->value[fs->state]; - fs->value[fs->state] = '\0'; - fs->state_cell = strlen_utf8(&text); - - text = fs->value + line[y].start; - x = strlen_utf8(&text); - fs->value[fs->state] = tmp; - } else -#endif /* CONFIG_UTF_8 */ - x = fs->state - line[y].start; + x = fs->state - line[y].start; mem_free(line); @@ -263,6 +311,7 @@ area_cursor(struct form_control *fc, struct form_state *fs) return y * fc->cols + x; } +#endif #ifdef CONFIG_UTF_8 static void @@ -305,8 +354,7 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, text = fs->value + line->start; end = fs->value + line->end; - for (i = 0; i < fs->vpos; i++) - utf_8_to_unicode(&text, end); + text += utf8_cells2bytes(text, fs->vpos, end); if (!row_is_in_box(box, y)) continue; @@ -316,10 +364,18 @@ draw_textarea_utf8(struct terminal *term, struct form_state *fs, if (!col_is_in_box(box, x)) continue; - if (i >= -fs->vpos - && text < end) + if (i >= -fs->vpos && text < end) { + int cell; + data = utf_8_to_unicode(&text, end); - else + cell = unicode_to_cell(data); + if (cell == 2) { + draw_char_data(term, x++, y, data); + i++; + data = UCS_NO_CHAR; + } + + } else data = '_'; draw_char_data(term, x, y, data); @@ -630,14 +686,42 @@ menu_textarea_edit(struct terminal *term, void *xxx, void *ses_) textarea_edit(0, term, fs, doc_view, link); } -static enum frame_event_status #ifdef CONFIG_UTF_8 +static enum frame_event_status textarea_op(struct form_state *fs, struct form_control *fc, int utf8, int (*do_op)(struct form_state *, struct line_info *, int, int)) +{ + struct line_info *line; + int current, state; + int state_cell; + + assert(fs && fs->value && fc); + if_assert_failed return FRAME_EVENT_OK; + + if (utf8) + line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); + else + line = format_text(fs->value, fc->cols, fc->wrap, 0); + if (!line) return FRAME_EVENT_OK; + + current = get_textarea_line_number(line, fs->state); + state = fs->state; + state_cell = fs->state_cell; + if (do_op(fs, line, current, utf8)) { + mem_free(line); + return FRAME_EVENT_IGNORED; + } + + mem_free(line); + return (fs->state == state && fs->state_cell == state_cell) + ? FRAME_EVENT_OK : FRAME_EVENT_REFRESH; +} + #else + +static enum frame_event_status textarea_op(struct form_state *fs, struct form_control *fc, int (*do_op)(struct form_state *, struct line_info *, int)) -#endif /* CONFIG_UTF_8 */ { struct line_info *line; int current, state; @@ -645,55 +729,35 @@ textarea_op(struct form_state *fs, struct form_control *fc, assert(fs && fs->value && fc); if_assert_failed return FRAME_EVENT_OK; -#ifdef CONFIG_UTF_8 - if (utf8) - line = format_textutf8(fs->value, fc->cols, fc->wrap, 0); - else -#endif /* CONFIG_UTF_8 */ - line = format_text(fs->value, fc->cols, fc->wrap, 0); + line = format_text(fs->value, fc->cols, fc->wrap, 0); if (!line) return FRAME_EVENT_OK; current = get_textarea_line_number(line, fs->state); state = fs->state; -#ifdef CONFIG_UTF_8 - if (do_op(fs, line, current, utf8)) -#else - if (do_op(fs, line, current)) -#endif /* CONFIG_UTF_8 */ -{ + if (do_op(fs, line, current)) { mem_free(line); return FRAME_EVENT_IGNORED; } mem_free(line); + return fs->state == state ? FRAME_EVENT_OK : FRAME_EVENT_REFRESH; } +#endif /* CONFIG_UTF_8 */ #ifdef CONFIG_UTF_8 -static int -x_pos(struct form_state *fs, struct line_info *line, int current) -{ - unsigned char *text = fs->value + line[current].start; - unsigned char tmp = fs->value[fs->state]; - int len; - - fs->value[fs->state] = '\0'; - len = strlen_utf8(&text); - fs->value[fs->state] = tmp; - return len; -} - -static void -new_pos(struct form_state *fs, struct line_info *line, int current, int len) +void +new_pos(struct form_state *fs, struct line_info *line, int current, int max_cells) { unsigned char *text = fs->value + line[current].start; unsigned char *end = fs->value + line[current].end; - int i; + int cells = 0; - for (i = 0; i < len; i++) { + while(cells < max_cells) { unicode_val_T data = utf_8_to_unicode(&text, end); if (data == UCS_NO_CHAR) break; + cells += unicode_to_cell(data); } fs->state = (int)(text - fs->value); } @@ -706,64 +770,157 @@ do_op_home(struct form_state *fs, struct line_info *line, int current, int utf8) do_op_home(struct form_state *fs, struct line_info *line, int current) #endif /* CONFIG_UTF_8 */ { - if (current != -1) fs->state = line[current].start; + if (current == -1) + return 0; +#ifdef CONFIG_UTF_8 + if (utf8) + fs->state = line[current - !!fs->state_cell].start; + else +#endif /* CONFIG_UTF_8 */ + fs->state = line[current].start; return 0; } -static int #ifdef CONFIG_UTF_8 +static int do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) +{ + if (current == -1) return 0; + + if (!(current - !!fs->state_cell)) return 1; + + if (!utf8) { + fs->state -= line[current].start - line[current-1].start; + int_upper_bound(&fs->state, line[current-1].end); + return 0; + } + + int old_state = fs->state; + if (fs->state_cell) { + int len = utf8_ptr2cells(fs->value + line[current - 1].start, + fs->value + fs->state_cell); + + new_pos(fs, line, current - 2, len + line[current - 1].last_char_width); + } else { + int len = utf8_ptr2cells(fs->value + line[current].start, + fs->value + fs->state); + + new_pos(fs, line, current - 1, len); + } + + if (old_state != fs->state ) { + if (fs->state_cell && fs->state == line[current - 1].start) { + unsigned char *new_value; + + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); + fs->state_cell = new_value - fs->value; + } else + fs->state_cell = 0; + } + + return 0; +} + #else + +static int do_op_up(struct form_state *fs, struct line_info *line, int current) -#endif /* CONFIG_UTF_8 */ { if (current == -1) return 0; if (!current) return 1; -#ifdef CONFIG_UTF_8 - if (utf8) { - int len = x_pos(fs, line, current); - - new_pos(fs, line, current - 1, len); - return 0; - } -#endif /* CONFIG_UTF_8 */ - fs->state -= line[current].start - line[current-1].start; int_upper_bound(&fs->state, line[current-1].end); return 0; } +#endif /* CONFIG_UTF_8 */ + +#ifdef CONFIG_UTF_8 +static int +do_op_down(struct form_state *fs, struct line_info *line, int current, int utf8) +{ + if (current == -1) return 0; + + if (line[current + 1 - !!fs->state_cell].start == -1) return 1; + + if (!utf8) { + fs->state += line[current+1].start - line[current].start; + int_upper_bound(&fs->state, line[current+1].end); + return 0; + } + + int old_state = fs->state; + if (fs->state_cell) { + int len = utf8_ptr2cells(fs->value + line[current - 1].start, + fs->value + fs->state_cell); + + new_pos(fs, line, current, len + line[current - 1].last_char_width); + } else { + int len = utf8_ptr2cells(fs->value + line[current].start, + fs->value + fs->state); + + new_pos(fs, line, current + 1, len); + } + if (old_state != fs->state ) { + if (fs->state_cell && fs->state == line[current+1].start) { + unsigned char *new_value; + + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); + fs->state_cell = new_value - fs->value; + } else + fs->state_cell = 0; + } + return 0; +} + +#else static int -#ifdef CONFIG_UTF_8 -do_op_down(struct form_state *fs, struct line_info *line, int current, int utf8) -#else do_op_down(struct form_state *fs, struct line_info *line, int current) -#endif /* CONFIG_UTF_8 */ { if (current == -1) return 0; if (line[current+1].start == -1) return 1; -#ifdef CONFIG_UTF_8 - if (utf8) { - int len = x_pos(fs, line, current); - - new_pos(fs, line, current + 1, len); - return 0; - } -#endif /* CONFIG_UTF_8 */ - fs->state += line[current+1].start - line[current].start; int_upper_bound(&fs->state, line[current+1].end); return 0; } +#endif /* CONFIG_UTF_8 */ + +#ifdef CONFIG_UTF_8 +static int +do_op_end(struct form_state *fs, struct line_info *line, int current, int utf8) +{ + if (current == -1) { + fs->state = strlen(fs->value); + return 0; + } + + if (!utf8) { + int wrap = line[current + 1].start == line[current].end; + + /* Don't jump to next line when wrapping. */ + fs->state = int_max(0, line[current].end - wrap); + return 0; + } + + current -= !!fs->state_cell; + fs->state = line[current].end; + if (line[current].split_next) { + unsigned char *new_value; + + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); + fs->state_cell = new_value - fs->value; + } else { + fs->state_cell = 0; + } + return 0; +} + +#else static int -#ifdef CONFIG_UTF_8 -do_op_end(struct form_state *fs, struct line_info *line, int current, int utf8) -#else do_op_end(struct form_state *fs, struct line_info *line, int current) -#endif /* CONFIG_UTF_8 */ { if (current == -1) { fs->state = strlen(fs->value); @@ -776,6 +933,7 @@ do_op_end(struct form_state *fs, struct line_info *line, int current) } return 0; } +#endif /* CONFIG_UTF_8 */ static int #ifdef CONFIG_UTF_8 @@ -921,6 +1079,81 @@ textarea_op_enter(struct form_state *fs, struct form_control *fc) return FRAME_EVENT_REFRESH; } +#ifdef CONFIG_UTF_8 +static int +do_op_left(struct form_state *fs, struct line_info *line, int current, int utf8) +{ + if (!utf8) { + fs->state = int_max(fs->state - 1, 0); + return 0; + } + + if (fs->state_cell) { + fs->state = fs->state_cell; + fs->state_cell = 0; + return 0; + } + + int old_state = fs->state; + int new_state; + unsigned char *new_value; + + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); + new_state = new_value - fs->value; + + if (old_state != new_state) { + if (old_state == line[current].start && line[current].split_prev) + fs->state_cell = new_state; + else + fs->state = new_state; + } + return 0; +} + +static int +do_op_right(struct form_state *fs, struct line_info *line, int current, int utf8) +{ + if (!utf8) { + /* TODO: zle */ + fs->state = int_min(fs->state + 1, strlen(fs->value)); + return 0; + } + + if (fs->state_cell) { + fs->state_cell = 0; + return 0; + } + + unsigned char *text = fs->value + fs->state; + unsigned char *end = strchr(text, '\0'); + int old_state = fs->state; + utf_8_to_unicode(&text, end); + + fs->state = text - fs->value; + + if (old_state != fs->state && line[current].split_next) { + fs->state_cell = (fs->state == line[current].end) ? old_state:0; + } else if (!line[current].split_next) { + fs->state_cell = 0; + } + + return 0; +} +#endif /* CONFIG_UTF_8 */ + +#ifdef CONFIG_UTF_8 +enum frame_event_status +textarea_op_left(struct form_state *fs, struct form_control *fc, int utf8) +{ + return textarea_op(fs, fc, utf8, do_op_left); +} + +enum frame_event_status +textarea_op_right(struct form_state *fs, struct form_control *fc, int utf8) +{ + return textarea_op(fs, fc, utf8, do_op_right); +} +#endif /* CONFIG_UTF_8 */ void set_textarea(struct document_view *doc_view, int direction) diff --git a/src/viewer/text/textarea.h b/src/viewer/text/textarea.h index 462aa3e6..f9508553 100644 --- a/src/viewer/text/textarea.h +++ b/src/viewer/text/textarea.h @@ -33,6 +33,8 @@ enum frame_event_status textarea_op_end(struct form_state *fs, struct form_contr enum frame_event_status textarea_op_bob(struct form_state *fs, struct form_control *fc, int utf8); enum frame_event_status textarea_op_eob(struct form_state *fs, struct form_control *fc, int utf8); enum frame_event_status textarea_op_enter(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_left(struct form_state *fs, struct form_control *fc, int utf8); +enum frame_event_status textarea_op_right(struct form_state *fs, struct form_control *fc, int utf8); #else enum frame_event_status textarea_op_home(struct form_state *fs, struct form_control *fc); enum frame_event_status textarea_op_up(struct form_state *fs, struct form_control *fc); From 31f2c28c069f3ef9a1fd2fcc495c16028b582887 Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Sat, 6 May 2006 18:10:37 +0200 Subject: [PATCH 39/73] Correction of b0e2840f0d. Do not correct main menu when utf-8 is not used. --- src/bfu/menu.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/bfu/menu.c b/src/bfu/menu.c index ad64712d..23720955 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -1093,17 +1093,21 @@ display_mainmenu(struct terminal *term, struct menu *menu) menu->last = i - 1; int_lower_bound(&menu->last, menu->first); if (menu->last < menu->size - 1) { - struct screen_char *schar; +#ifdef CONFIG_UTF_8 + if (term->utf8) { + struct screen_char *schar; - schar = get_char(term, term->width - R_MAINMENU_SPACE, 0); - /* Is second cell of double-width char on the place where - * first char of the R_MAINMENU_SPACE will be displayed? */ - if (schar->data == UCS_NO_CHAR) { - /* Replace double-width char with ' '. */ - schar++; - draw_char_data(term, term->width - R_MAINMENU_SPACE - 1, - 0, ' '); + schar = get_char(term, term->width - R_MAINMENU_SPACE, 0); + /* Is second cell of double-width char on the place where + * first char of the R_MAINMENU_SPACE will be displayed? */ + if (schar->data == UCS_NO_CHAR) { + /* Replace double-width char with ' '. */ + schar++; + draw_char_data(term, term->width - R_MAINMENU_SPACE - 1, + 0, ' '); + } } +#endif set_box(&box, term->width - R_MAINMENU_SPACE, 0, From 1adbce84295122e44e2464ff1263e831b56932ec Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 17 Jul 2006 22:14:45 +0200 Subject: [PATCH 40/73] unicode_val_T instead of unsigned char in struct search --- src/document/document.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/document/document.h b/src/document/document.h index 69024d34..d8a3a100 100644 --- a/src/document/document.h +++ b/src/document/document.h @@ -118,13 +118,19 @@ struct link { #define get_link_name(link) \ (!link_is_form(link) ? (link)->data.name : NULL) - +#ifdef CONFIG_UTF_8 +struct search { + int x, y; + signed int n; /* RAM is cheap nowadays */ + unicode_val_T c; +}; +#else struct search { int x, y; signed int n:24; /* This structure is size-critical */ unsigned char c; }; - +#endif struct document { OBJECT_HEAD(struct document); From 8052c74a036a6305997726f81aa7dd9e8c5e983d Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 00:28:13 +0200 Subject: [PATCH 41/73] Case sensitive searching works, but only in UTF-8 mode --- src/viewer/text/search.c | 79 ++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index 2d61b929..aa267d39 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -22,6 +22,7 @@ #include "config/kbdbind.h" #include "document/document.h" #include "document/view.h" +#include "intl/charsets.h" #include "intl/gettext/libintl.h" #include "main/event.h" #include "main/module.h" @@ -44,9 +45,15 @@ static INIT_INPUT_HISTORY(search_history); +#undef UCHAR +#ifdef CONFIG_UTF_8 +#define UCHAR unicode_val_T +#else +#define UCHAR unsigned char +#endif static inline void -add_srch_chr(struct document *document, unsigned char c, int x, int y, int nn) +add_srch_chr(struct document *document, UCHAR c, int x, int y, int nn) { assert(document); if_assert_failed return; @@ -146,7 +153,7 @@ get_srch(struct document *document) x++); for (; x < width; x++) { - unsigned char c = document->data[y].chars[x].data; + UCHAR c = document->data[y].chars[x].data; int count = 0; int xx; @@ -251,17 +258,17 @@ get_range(struct document *document, int y, int height, int l, /* Returns a string |doc| that is a copy of the text in the search nodes * from |s1| to |s1 + doclen - 1| with the space at the end of each line * converted to a new-line character (LF). */ -static unsigned char * +static UCHAR * get_search_region_from_search_nodes(struct search *s1, struct search *s2, int pattern_len, int *doclen) { - unsigned char *doc; + UCHAR *doc; int i; *doclen = s2 - s1 + pattern_len; if (!*doclen) return NULL; - doc = mem_alloc(*doclen + 1); + doc = mem_alloc((*doclen + 1) * sizeof(UCHAR)); if (!doc) { *doclen = -1; return NULL; @@ -315,8 +322,8 @@ static void search_for_pattern(struct regex_match_context *common_ctx, void *data, void (*match)(struct regex_match_context *, void *)) { - unsigned char *doc; - unsigned char *doctmp; + UCHAR *doc; + UCHAR *doctmp; int doclen; int regexec_flags = 0; regex_t regex; @@ -441,15 +448,31 @@ is_in_range_regex(struct document *document, int y, int height, } #endif /* HAVE_REGEX_H */ -/* Returns an allocated string which is a lowered copy of passed one. */ -static unsigned char * -lowered_string(unsigned char *text, int textlen) +static UCHAR * +memacpy_u(unsigned char *text, int textlen) { - unsigned char *ret; +#ifdef CONFIG_UTF_8 + UCHAR *mem = mem_alloc((textlen + 1) * sizeof(UCHAR)); + int i; - if (textlen < 0) textlen = strlen(text); + if (!mem) return NULL; + for (i = 0; i < textlen; i++) mem[i] = utf_8_to_unicode(&text, text + 7); + mem[textlen] = 0; + return mem; +#else + return memacpy(text, textlen); +#endif +} - ret = mem_calloc(1, textlen + 1); +/* Returns an allocated string which is a lowered copy of passed one. */ +static UCHAR * +lowered_string(UCHAR *text, int textlen) +{ + UCHAR *ret; + + if (textlen < 0) textlen = strlen_u(text); + + ret = mem_calloc(1, (textlen + 1) * sizeof(UCHAR)); if (ret && textlen) { do { ret[textlen] = tolower(text[textlen]); @@ -461,16 +484,16 @@ lowered_string(unsigned char *text, int textlen) static int is_in_range_plain(struct document *document, int y, int height, - unsigned char *text, int textlen, + unsigned *text, int textlen, int *min, int *max, struct search *s1, struct search *s2) { int yy = y + height; - unsigned char *txt; + UCHAR *txt; int found = 0; int case_sensitive = get_opt_bool("document.browse.search.case"); - txt = case_sensitive ? stracpy(text) : lowered_string(text, textlen); + txt = case_sensitive ? memacpy_u(text, textlen) : lowered_string(text, textlen); if (!txt) return -1; /* TODO: This is a great candidate for nice optimizations. Fresh CS @@ -513,6 +536,16 @@ srch_failed: return found; } +static int +strlen_u(unsigned char *text) +{ +#ifdef CONFIG_UTF_8 + return strlen_utf8(&text); +#else + return strlen(text); +#endif +} + static int is_in_range(struct document *document, int y, int height, unsigned char *text, int *min, int *max) @@ -524,7 +557,7 @@ is_in_range(struct document *document, int y, int height, if_assert_failed return -1; *min = INT_MAX, *max = 0; - textlen = strlen(text); + textlen = strlen_u(text); if (get_range(document, y, height, textlen, &s1, &s2)) return 0; @@ -545,14 +578,14 @@ static void get_searched_plain(struct document_view *doc_view, struct point **pt, int *pl, int l, struct search *s1, struct search *s2) { - unsigned char *txt; + UCHAR *txt; struct point *points = NULL; struct box *box; int xoffset, yoffset; int len = 0; int case_sensitive = get_opt_bool("document.browse.search.case"); - txt = case_sensitive ? stracpy(*doc_view->search_word) + txt = case_sensitive ? memacpy_u(*doc_view->search_word, l) : lowered_string(*doc_view->search_word, l); if (!txt) return; @@ -683,7 +716,7 @@ get_searched(struct document_view *doc_view, struct point **pt, int *pl) return; get_search_data(doc_view->document); - l = strlen(*doc_view->search_word); + l = strlen_u(*doc_view->search_word); if (get_range(doc_view->document, doc_view->vs->y, doc_view->box.height, l, &s1, &s2)) { *pt = NULL; @@ -1174,7 +1207,7 @@ fixup_typeahead_match(struct session *ses, struct document_view *doc_view) doc_view->box.height += 1; } -static inline unsigned char +static inline UCHAR get_document_char(struct document *document, int x, int y) { return (document->height > y && document->data[y].length > x) @@ -1189,14 +1222,14 @@ draw_typeahead_match(struct terminal *term, struct document_view *doc_view, int xoffset = doc_view->box.x - doc_view->vs->x; int yoffset = doc_view->box.y - doc_view->vs->y; struct link *link = get_current_link(doc_view); - unsigned char *text = get_link_typeahead_text(link); + UCHAR *text = get_link_typeahead_text(link); int end = offset + chars; int i, j; for (i = 0, j = 0; text[j] && i < end; i++, j++) { int x = link->points[i].x; int y = link->points[i].y; - unsigned char data = get_document_char(doc_view->document, x, y); + UCHAR data = get_document_char(doc_view->document, x, y); /* Text wrapping might remove space chars from the link * position array so try to align the matched typeahead text From 7dc2b5bf021e9f2a2679d27cb48e5fa23bf42e3f Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 00:44:08 +0200 Subject: [PATCH 42/73] Case insensitive search works but accented letters --- src/viewer/text/search.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index aa267d39..e200bed9 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -472,10 +472,10 @@ lowered_string(UCHAR *text, int textlen) if (textlen < 0) textlen = strlen_u(text); - ret = mem_calloc(1, (textlen + 1) * sizeof(UCHAR)); + ret = memacpy_u(text, textlen); if (ret && textlen) { do { - ret[textlen] = tolower(text[textlen]); + ret[textlen] = tolower(ret[textlen]); } while (textlen--); } From 02e098dc5aa0d30829091716a70ff2e49069b87d Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 12:31:30 +0200 Subject: [PATCH 43/73] Case insensitive search works with accented letters. UTF-8 character set is assummed for now --- src/viewer/text/search.c | 42 +++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index e200bed9..e916b7ba 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -9,6 +9,11 @@ #endif #include /* tolower(), isprint() */ + +#if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) +#include +#endif + #include /* FreeBSD needs this before regex.h */ #ifdef HAVE_REGEX_H #include @@ -464,9 +469,19 @@ memacpy_u(unsigned char *text, int textlen) #endif } +static int +strlen_u(unsigned char *text) +{ +#ifdef CONFIG_UTF_8 + return strlen_utf8(&text); +#else + return strlen(text); +#endif +} + /* Returns an allocated string which is a lowered copy of passed one. */ static UCHAR * -lowered_string(UCHAR *text, int textlen) +lowered_string(unsigned char *text, int textlen) { UCHAR *ret; @@ -475,7 +490,11 @@ lowered_string(UCHAR *text, int textlen) ret = memacpy_u(text, textlen); if (ret && textlen) { do { +#if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) + ret[textlen] = towlower(ret[textlen]); +#else ret[textlen] = tolower(ret[textlen]); +#endif } while (textlen--); } @@ -484,7 +503,7 @@ lowered_string(UCHAR *text, int textlen) static int is_in_range_plain(struct document *document, int y, int height, - unsigned *text, int textlen, + unsigned char *text, int textlen, int *min, int *max, struct search *s1, struct search *s2) { @@ -501,9 +520,11 @@ is_in_range_plain(struct document *document, int y, int height, * trivial, probably a starter; very fast as well) or Turbo-BM (or * maybe some other Boyer-Moore variant, I don't feel that strong in * this area), hmm? >:) --pasky */ - +#if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) +#define maybe_tolower(c) (case_sensitive ? (c) : towlower(c)) +#else #define maybe_tolower(c) (case_sensitive ? (c) : tolower(c)) - +#endif for (; s1 <= s2; s1++) { int i; @@ -536,15 +557,6 @@ srch_failed: return found; } -static int -strlen_u(unsigned char *text) -{ -#ifdef CONFIG_UTF_8 - return strlen_utf8(&text); -#else - return strlen(text); -#endif -} static int is_in_range(struct document *document, int y, int height, @@ -593,7 +605,11 @@ get_searched_plain(struct document_view *doc_view, struct point **pt, int *pl, xoffset = box->x - doc_view->vs->x; yoffset = box->y - doc_view->vs->y; +#if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) +#define maybe_tolower(c) (case_sensitive ? (c) : towlower(c)) +#else #define maybe_tolower(c) (case_sensitive ? (c) : tolower(c)) +#endif for (; s1 <= s2; s1++) { int i; From 681cfc4ae5a9ef0fee8ae447351b72b5eb3c82a4 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 17:39:02 +0200 Subject: [PATCH 44/73] Populate search function with utf8 indicating whether we really use UTF-8 --- src/viewer/text/search.c | 72 ++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index e916b7ba..6f70cb57 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -454,14 +454,23 @@ is_in_range_regex(struct document *document, int y, int height, #endif /* HAVE_REGEX_H */ static UCHAR * -memacpy_u(unsigned char *text, int textlen) +memacpy_u(unsigned char *text, int textlen, int utf8) { #ifdef CONFIG_UTF_8 UCHAR *mem = mem_alloc((textlen + 1) * sizeof(UCHAR)); - int i; if (!mem) return NULL; - for (i = 0; i < textlen; i++) mem[i] = utf_8_to_unicode(&text, text + 7); + if (utf8) { + int i; + + for (i = 0; i < textlen; i++) + mem[i] = utf_8_to_unicode(&text, text + 7); + } else { + int i; + + for (i = 0; i < textlen; i++) + mem[i] = text[i]; + } mem[textlen] = 0; return mem; #else @@ -470,28 +479,29 @@ memacpy_u(unsigned char *text, int textlen) } static int -strlen_u(unsigned char *text) +strlen_u(unsigned char *text, int utf8) { #ifdef CONFIG_UTF_8 - return strlen_utf8(&text); -#else - return strlen(text); + if (utf8) + return strlen_utf8(&text); #endif + return strlen(text); + } /* Returns an allocated string which is a lowered copy of passed one. */ static UCHAR * -lowered_string(unsigned char *text, int textlen) +lowered_string(unsigned char *text, int textlen, int utf8) { UCHAR *ret; - if (textlen < 0) textlen = strlen_u(text); + if (textlen < 0) textlen = strlen_u(text, utf8); - ret = memacpy_u(text, textlen); + ret = memacpy_u(text, textlen, utf8); if (ret && textlen) { do { #if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) - ret[textlen] = towlower(ret[textlen]); + ret[textlen] = utf8 ? towlower(ret[textlen]) : tolower(ret[textlen]); #else ret[textlen] = tolower(ret[textlen]); #endif @@ -505,14 +515,14 @@ static int is_in_range_plain(struct document *document, int y, int height, unsigned char *text, int textlen, int *min, int *max, - struct search *s1, struct search *s2) + struct search *s1, struct search *s2, int utf8) { int yy = y + height; UCHAR *txt; int found = 0; int case_sensitive = get_opt_bool("document.browse.search.case"); - txt = case_sensitive ? memacpy_u(text, textlen) : lowered_string(text, textlen); + txt = case_sensitive ? memacpy_u(text, textlen, utf8) : lowered_string(text, textlen, utf8); if (!txt) return -1; /* TODO: This is a great candidate for nice optimizations. Fresh CS @@ -521,7 +531,7 @@ is_in_range_plain(struct document *document, int y, int height, * maybe some other Boyer-Moore variant, I don't feel that strong in * this area), hmm? >:) --pasky */ #if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) -#define maybe_tolower(c) (case_sensitive ? (c) : towlower(c)) +#define maybe_tolower(c) (case_sensitive ? (c) : utf8 ? towlower(c) : tolower(c)) #else #define maybe_tolower(c) (case_sensitive ? (c) : tolower(c)) #endif @@ -564,12 +574,16 @@ is_in_range(struct document *document, int y, int height, { struct search *s1, *s2; int textlen; + int utf8 = 0; assert(document && text && min && max); if_assert_failed return -1; +#ifdef CONFIG_UTF_8 + utf8 = is_cp_special(document->options.cp); +#endif *min = INT_MAX, *max = 0; - textlen = strlen_u(text); + textlen = strlen_u(text, utf8); if (get_range(document, y, height, textlen, &s1, &s2)) return 0; @@ -580,7 +594,7 @@ is_in_range(struct document *document, int y, int height, min, max, s1, s2); #endif return is_in_range_plain(document, y, height, text, textlen, - min, max, s1, s2); + min, max, s1, s2, utf8); } #define realloc_points(pts, size) \ @@ -588,7 +602,7 @@ is_in_range(struct document *document, int y, int height, static void get_searched_plain(struct document_view *doc_view, struct point **pt, int *pl, - int l, struct search *s1, struct search *s2) + int l, struct search *s1, struct search *s2, int utf8) { UCHAR *txt; struct point *points = NULL; @@ -597,8 +611,8 @@ get_searched_plain(struct document_view *doc_view, struct point **pt, int *pl, int len = 0; int case_sensitive = get_opt_bool("document.browse.search.case"); - txt = case_sensitive ? memacpy_u(*doc_view->search_word, l) - : lowered_string(*doc_view->search_word, l); + txt = case_sensitive ? memacpy_u(*doc_view->search_word, l, utf8) + : lowered_string(*doc_view->search_word, l, utf8); if (!txt) return; box = &doc_view->box; @@ -606,7 +620,7 @@ get_searched_plain(struct document_view *doc_view, struct point **pt, int *pl, yoffset = box->y - doc_view->vs->y; #if defined(CONFIG_UTF_8) && defined(HAVE_WCTYPE_H) -#define maybe_tolower(c) (case_sensitive ? (c) : towlower(c)) +#define maybe_tolower(c) (case_sensitive ? (c) : utf8 ? towlower(c) : tolower(c)) #else #define maybe_tolower(c) (case_sensitive ? (c) : tolower(c)) #endif @@ -720,7 +734,7 @@ get_searched_regex(struct document_view *doc_view, struct point **pt, int *pl, #endif /* HAVE_REGEX_H */ static void -get_searched(struct document_view *doc_view, struct point **pt, int *pl) +get_searched(struct document_view *doc_view, struct point **pt, int *pl, int utf8) { struct search *s1, *s2; int l; @@ -732,7 +746,7 @@ get_searched(struct document_view *doc_view, struct point **pt, int *pl) return; get_search_data(doc_view->document); - l = strlen_u(*doc_view->search_word); + l = strlen_u(*doc_view->search_word, utf8); if (get_range(doc_view->document, doc_view->vs->y, doc_view->box.height, l, &s1, &s2)) { *pt = NULL; @@ -746,7 +760,7 @@ get_searched(struct document_view *doc_view, struct point **pt, int *pl) get_searched_regex(doc_view, pt, pl, l, s1, s2); else #endif - get_searched_plain(doc_view, pt, pl, l, s1, s2); + get_searched_plain(doc_view, pt, pl, l, s1, s2, utf8); } /* Highlighting of searched strings. */ @@ -755,6 +769,7 @@ draw_searched(struct terminal *term, struct document_view *doc_view) { struct point *pt = NULL; int len = 0; + int utf8 = 0; assert(term && doc_view); if_assert_failed return; @@ -762,7 +777,10 @@ draw_searched(struct terminal *term, struct document_view *doc_view) if (!has_search_word(doc_view)) return; - get_searched(doc_view, &pt, &len); +#ifdef CONFIG_UTF_8 + utf8 = is_cp_special(doc_view->document->options.cp); +#endif + get_searched(doc_view, &pt, &len, utf8); if (len) { int i; struct color_pair *color = get_bfu_color(term, "searched"); @@ -925,10 +943,14 @@ find_next_link_in_search(struct document_view *doc_view, int direction) struct point *pt = NULL; struct link *link; int len; + int utf8 = 0; +#ifdef CONFIG_UTF_8 + utf8 = is_cp_special(doc_view->document->options.cp); +#endif nt: link = &doc_view->document->links[doc_view->vs->current_link]; - get_searched(doc_view, &pt, &len); + get_searched(doc_view, &pt, &len, utf8); if (point_intersect(pt, len, link->points, link->npoints)) { mem_free(pt); return 0; From 44c74ac389f2f69b01f3257b898837cfd3641f28 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 17:51:03 +0200 Subject: [PATCH 45/73] Refactor is_cp_special to is_cp_utf8 --- src/dialogs/options.c | 2 +- src/document/dom/renderer.c | 2 +- src/document/html/renderer.c | 2 +- src/document/plain/renderer.c | 2 +- src/intl/charsets.c | 2 +- src/intl/charsets.h | 2 +- src/viewer/dump/dump.c | 4 ++-- src/viewer/text/search.c | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dialogs/options.c b/src/dialogs/options.c index 31b59b4c..27f59a08 100644 --- a/src/dialogs/options.c +++ b/src/dialogs/options.c @@ -60,7 +60,7 @@ charset_list(struct terminal *term, void *xxx, void *ses_) if (!name) break; #ifndef CONFIG_UTF_8 - if (is_cp_special(i)) continue; + if (is_cp_utf8(i)) continue; #endif /* CONFIG_UTF_8 */ add_to_menu(&mi, name, NULL, ACT_MAIN_NONE, diff --git a/src/document/dom/renderer.c b/src/document/dom/renderer.c index 74cb6b6f..c0b51fab 100644 --- a/src/document/dom/renderer.c +++ b/src/document/dom/renderer.c @@ -1016,7 +1016,7 @@ render_dom_document(struct cache_entry *cached, struct document *document, document->bgcolor = document->options.default_bg; #ifdef CONFIG_UTF_8 - document->options.utf8 = is_cp_special(document->options.cp); + document->options.utf8 = is_cp_utf8(document->options.cp); #endif /* CONFIG_UTF_8 */ if (document->options.plain) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index c93e6ce4..afd482c8 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -2182,7 +2182,7 @@ render_html_document(struct cache_entry *cached, struct document *document, &document->cp_status, document->options.hard_assume); #ifdef CONFIG_UTF_8 - html_context->options->utf8 = is_cp_special(document->options.cp); + html_context->options->utf8 = is_cp_utf8(document->options.cp); #endif /* CONFIG_UTF_8 */ if (title.length) { diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index d0a5a703..f8b0122c 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -648,7 +648,7 @@ render_plain_document(struct cache_entry *cached, struct document *document, document->bgcolor = document->options.default_bg; document->width = 0; #ifdef CONFIG_UTF_8 - document->options.utf8 = is_cp_special(document->options.cp); + document->options.utf8 = is_cp_utf8(document->options.cp); #endif /* CONFIG_UTF_8 */ /* Setup the style */ diff --git a/src/intl/charsets.c b/src/intl/charsets.c index 35c6ce8d..908b3c84 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -1142,7 +1142,7 @@ get_cp_mime_name(int cp_index) } int -is_cp_special(int cp_index) +is_cp_utf8(int cp_index) { cp_index &= ~SYSTEM_CHARSET_FLAG; return codepages[cp_index].table == table_utf_8; diff --git a/src/intl/charsets.h b/src/intl/charsets.h index 04e6a0f6..6198b4fb 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -51,7 +51,7 @@ unsigned char *convert_string(struct conv_table *convert_table, int get_cp_index(unsigned char *); unsigned char *get_cp_name(int); unsigned char *get_cp_mime_name(int); -int is_cp_special(int); +int is_cp_utf8(int); void free_conv_table(void); #ifdef CONFIG_UTF_8 inline unsigned char *encode_utf_8(unicode_val_T); diff --git a/src/viewer/dump/dump.c b/src/viewer/dump/dump.c index 534fe42e..587391d7 100644 --- a/src/viewer/dump/dump.c +++ b/src/viewer/dump/dump.c @@ -324,7 +324,7 @@ add_document_to_string(struct string *string, struct document *document) if_assert_failed return NULL; #ifdef CONFIG_UTF_8 - if (is_cp_special(document->options.cp)) + if (is_cp_utf8(document->options.cp)) goto utf_8; #endif /* CONFIG_UTF_8 */ @@ -427,7 +427,7 @@ dump_to_file(struct document *document, int fd) if (!buf) return -1; #ifdef CONFIG_UTF_8 - if (is_cp_special(document->options.cp)) + if (is_cp_utf8(document->options.cp)) goto utf_8; #endif /* CONFIG_UTF_8 */ diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index 6f70cb57..91f2908c 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -580,7 +580,7 @@ is_in_range(struct document *document, int y, int height, if_assert_failed return -1; #ifdef CONFIG_UTF_8 - utf8 = is_cp_special(document->options.cp); + utf8 = is_cp_utf8(document->options.cp); #endif *min = INT_MAX, *max = 0; textlen = strlen_u(text, utf8); @@ -778,7 +778,7 @@ draw_searched(struct terminal *term, struct document_view *doc_view) return; #ifdef CONFIG_UTF_8 - utf8 = is_cp_special(doc_view->document->options.cp); + utf8 = is_cp_utf8(doc_view->document->options.cp); #endif get_searched(doc_view, &pt, &len, utf8); if (len) { @@ -945,7 +945,7 @@ find_next_link_in_search(struct document_view *doc_view, int direction) int len; int utf8 = 0; #ifdef CONFIG_UTF_8 - utf8 = is_cp_special(doc_view->document->options.cp); + utf8 = is_cp_utf8(doc_view->document->options.cp); #endif nt: From b27667fcf7375cef903a0160567e68b9811f85b3 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 17:54:23 +0200 Subject: [PATCH 46/73] Use already known document->options.utf8 instead of is_cp_utf8 --- src/viewer/text/search.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index 91f2908c..b3fd3bcd 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -580,7 +580,7 @@ is_in_range(struct document *document, int y, int height, if_assert_failed return -1; #ifdef CONFIG_UTF_8 - utf8 = is_cp_utf8(document->options.cp); + utf8 = document->options.utf8; #endif *min = INT_MAX, *max = 0; textlen = strlen_u(text, utf8); @@ -778,7 +778,7 @@ draw_searched(struct terminal *term, struct document_view *doc_view) return; #ifdef CONFIG_UTF_8 - utf8 = is_cp_utf8(doc_view->document->options.cp); + utf8 = doc_view->document->options.utf8; #endif get_searched(doc_view, &pt, &len, utf8); if (len) { @@ -945,7 +945,7 @@ find_next_link_in_search(struct document_view *doc_view, int direction) int len; int utf8 = 0; #ifdef CONFIG_UTF_8 - utf8 = is_cp_utf8(doc_view->document->options.cp); + utf8 = doc_view->document->options.utf8; #endif nt: From 3126078f51d3edfecd1fa8e784779b86eb6383ee Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 18:06:43 +0200 Subject: [PATCH 47/73] Rexgexp works but the accented letters. It's all I can do --- src/viewer/text/search.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index b3fd3bcd..a018ec83 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -263,17 +263,17 @@ get_range(struct document *document, int y, int height, int l, /* Returns a string |doc| that is a copy of the text in the search nodes * from |s1| to |s1 + doclen - 1| with the space at the end of each line * converted to a new-line character (LF). */ -static UCHAR * +static unsigned char * get_search_region_from_search_nodes(struct search *s1, struct search *s2, int pattern_len, int *doclen) { - UCHAR *doc; + unsigned char *doc; int i; *doclen = s2 - s1 + pattern_len; if (!*doclen) return NULL; - doc = mem_alloc((*doclen + 1) * sizeof(UCHAR)); + doc = mem_alloc(*doclen + 1); if (!doc) { *doclen = -1; return NULL; @@ -327,8 +327,8 @@ static void search_for_pattern(struct regex_match_context *common_ctx, void *data, void (*match)(struct regex_match_context *, void *)) { - UCHAR *doc; - UCHAR *doctmp; + unsigned char *doc; + unsigned char *doctmp; int doclen; int regexec_flags = 0; regex_t regex; @@ -1260,7 +1260,7 @@ draw_typeahead_match(struct terminal *term, struct document_view *doc_view, int xoffset = doc_view->box.x - doc_view->vs->x; int yoffset = doc_view->box.y - doc_view->vs->y; struct link *link = get_current_link(doc_view); - UCHAR *text = get_link_typeahead_text(link); + unsigned char *text = get_link_typeahead_text(link); int end = offset + chars; int i, j; From c34a91a92f4601f0d207d6059a3c2ce43bd62a05 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 19:58:36 +0200 Subject: [PATCH 48/73] pl.po: fixed a misleading translation --- po/pl.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/pl.po b/po/pl.po index 4e4e1b8a..60f22aeb 100644 --- a/po/pl.po +++ b/po/pl.po @@ -2802,7 +2802,7 @@ msgstr "Rozr msgid "" "Whether the search should match the document text while maintaining\n" "case sensitivity." -msgstr "Czy zaznaczaæ tekst ró¿ni±cy siê wielko¶ci± liter od poszukiwanego?" +msgstr "Czy rozró¿niaæ wielko¶æ liter przy szukaniu." #: src/config/options.inc:393 msgid "Regular expressions" From 8c3f931ff01a7a526582fbb8839250321d1f8fad Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Jul 2006 20:33:34 +0200 Subject: [PATCH 49/73] Wide char could be bigger than 0xffff --- src/intl/charsets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index 908b3c84..fde3d030 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -459,7 +459,7 @@ utf_8_to_unicode(unsigned char **string, unsigned char *end) break; } *string = str + length; - return u > 0xffff ? '*' : u; + return u; } #endif /* CONFIG_UTF_8 */ From 70a46e12aaba3174198c94a5ef807ed8094f6e36 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Wed, 19 Jul 2006 19:11:03 +0200 Subject: [PATCH 50/73] Fixed the issue when assummed codepage is not UTF-8 --- configure.in | 1 + src/document/plain/renderer.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 6e95ac71..c6c55090 100644 --- a/configure.in +++ b/configure.in @@ -168,6 +168,7 @@ AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_HEADER_TIME +AC_CHECK_HEADERS(wctype.h) AC_CHECK_HEADERS(fcntl.h limits.h time.h unistd.h) AC_CHECK_HEADERS(sigaction.h) AC_CHECK_HEADERS(arpa/inet.h) diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index f8b0122c..b65321d8 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -518,7 +518,9 @@ add_document_lines(struct plain_renderer *renderer) int length = renderer->length; int was_empty_line = 0; int was_wrapped = 0; - +#ifdef CONFIG_UTF_8 + int utf8 = is_cp_utf8(renderer->document->cp); +#endif for (; length > 0; renderer->lineno++) { unsigned char *xsource; int width, added, only_spaces = 1, spaces = 0, was_spaces = 0; @@ -549,7 +551,7 @@ add_document_lines(struct plain_renderer *renderer) was_spaces = 0; } #ifdef CONFIG_UTF_8 - if (renderer->document->options.utf8) { + if (utf8) { unsigned char *text = &source[width]; unicode_val_T data = utf_8_to_unicode(&text, &source[length]); From b388b4afeaa95212d04c4ad65c1dcd882357ffc6 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Thu, 20 Jul 2006 02:03:25 +0200 Subject: [PATCH 51/73] Avoided rerendering --- src/document/options.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/document/options.h b/src/document/options.h index d2a33bfe..54a821ef 100644 --- a/src/document/options.h +++ b/src/document/options.h @@ -71,9 +71,6 @@ struct document_options { unsigned int plain:1; unsigned int wrap:1; -#ifdef CONFIG_UTF_8 - unsigned int utf8:1; -#endif /* CONFIG_UTF_8 */ /* XXX: Everything past this comment is specialy handled by compare_opt() */ unsigned char *framename; @@ -104,6 +101,9 @@ struct document_options { unsigned int no_cache:1; unsigned int gradual_rerendering:1; +#ifdef CONFIG_UTF_8 + unsigned int utf8:1; +#endif /* CONFIG_UTF_8 */ /* Active link coloring */ /* This is mostly here to make use of this option cache so link * drawing is faster. --jonas */ From 8a1ef2ada9d3c933cdecd1adef8d8e53bef33584 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Thu, 20 Jul 2006 02:05:56 +0200 Subject: [PATCH 52/73] That was missing, at least I think so --- src/document/html/renderer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index afd482c8..9d908cf3 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -1430,6 +1430,8 @@ process_link(struct html_context *html_context, enum link_state link_state, for (; cells > 0; cells--, point++, x++) #else + link->npoints += charslen; + for (; charslen > 0; charslen--, point++, x++) #endif /* CONFIG_UTF_8 */ { From 8fa3a4c88f7c9bc2463ea9e32fc29cab845e1184 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Thu, 20 Jul 2006 03:42:22 +0200 Subject: [PATCH 53/73] Use isscreensafe also for UTF-8 --- src/terminal/screen.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/terminal/screen.c b/src/terminal/screen.c index c5e74035..503f751d 100644 --- a/src/terminal/screen.c +++ b/src/terminal/screen.c @@ -450,12 +450,7 @@ add_char_data(struct string *screen, struct screen_driver *driver, unsigned char data, unsigned char border) #endif /* CONFIG_UTF_8 */ { - if ( -#ifdef CONFIG_UTF_8 - !use_utf8_io(driver) && -#endif /* CONFIG_UTF_8 */ - !isscreensafe(data) - ) { + if (!isscreensafe(data)) { add_char_to_string(screen, ' '); return; } From ecbc2271d1c20e0de6c0b3e164e7259f04630ff9 Mon Sep 17 00:00:00 2001 From: Miciah Dashiel Butler Masters Date: Fri, 21 Jul 2006 11:10:54 +0000 Subject: [PATCH 54/73] examine_element: drop html_stack parameter The stack is available via the html_context, which is passed to examine_element as of commit f42c86be70744e62af92282e4d64fc3066f6ba04. --- src/document/css/apply.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/document/css/apply.c b/src/document/css/apply.c index b419c878..8f9759c8 100644 --- a/src/document/css/apply.c +++ b/src/document/css/apply.c @@ -119,8 +119,7 @@ static css_applier_T css_appliers[CSS_PT_LAST] = { static void examine_element(struct html_context *html_context, struct css_selector *base, enum css_selector_type seltype, enum css_selector_relation rel, - struct list_head *selectors, struct html_element *element, - struct list_head *html_stack) + struct list_head *selectors, struct html_element *element) { struct css_selector *selector; unsigned char *code; @@ -138,7 +137,8 @@ examine_element(struct html_context *html_context, struct css_selector *base, dbginfo(sel, type, base); \ merge_css_selectors(base, sel); \ /* Ancestor matches? */ \ - if ((struct list_head *) element->next != html_stack) { \ + if ((struct list_head *) element->next \ + != &html_context->stack) { \ struct html_element *ancestor; \ /* This is less effective than doing reverse iterations, * first over sel->leaves and then over the HTML stack, @@ -147,21 +147,20 @@ examine_element(struct html_context *html_context, struct css_selector *base, * have to duplicate the whole examine_element(), so if * profiles won't show it really costs... */ \ for (ancestor = element->next; \ - (struct list_head *) ancestor != html_stack;\ + (struct list_head *) ancestor \ + != &html_context->stack;\ ancestor = ancestor->next) \ examine_element(html_context, base, \ CST_ELEMENT, CSR_ANCESTOR, \ - &sel->leaves, ancestor, \ - html_stack); \ + &sel->leaves, ancestor); \ examine_element(html_context, base, \ CST_ELEMENT, CSR_PARENT, \ - &sel->leaves, element->next, \ - html_stack); \ + &sel->leaves, element->next); \ } \ /* More specific matches? */ \ examine_element(html_context, base, type + 1, \ CSR_SPECIFITY, \ - &sel->leaves, element, html_stack); \ + &sel->leaves, element); \ } if (seltype <= CST_ELEMENT && element->namelen) { @@ -235,7 +234,7 @@ get_css_selector_for_element(struct html_context *html_context, #endif examine_element(html_context, selector, CST_ELEMENT, CSR_ROOT, - &css->selectors, element, html_stack); + &css->selectors, element); #ifdef DEBUG_CSS DBG("Element %.*s applied.", element->namelen, element->name); From 97e2bc9365390b9343e3a1c7b0e6584048d1235c Mon Sep 17 00:00:00 2001 From: Miciah Dashiel Butler Masters Date: Fri, 21 Jul 2006 11:15:30 +0000 Subject: [PATCH 55/73] Text type-ahead searching: don't follow current link on enter When the user presses enter during a text type-ahead search, simply cancel the search without additionally following the current link. Link type-ahead searching still will follow the active link on enter. --- src/viewer/text/search.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index 2d61b929..b3e2e8fa 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -1311,7 +1311,6 @@ text_typeahead_handler(struct input_line *line, int action_id) * clears the last search. */ search_for_do(ses, buffer, direction, 0); } - goto_current_link(ses, doc_view, 0); return INPUT_LINE_CANCEL; case ACT_EDIT_PREVIOUS_ITEM: From 1b653b97657370b3f0e5f5b4b39b9637e9547ae9 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Fri, 21 Jul 2006 13:21:21 +0200 Subject: [PATCH 56/73] Compilation fix --- src/document/html/renderer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index cad55f68..fea51b99 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -1524,6 +1524,8 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) set_hline(html_context, chars, charslen, link_state); if (link_state != LINK_STATE_NONE) { +#if 0 +/* This all code is from utf8 branch */ #define is_drawing_subs_or_sups() \ ((format.style.attr & AT_SUBSCRIPT \ && html_context->options->display_subs) \ @@ -1541,6 +1543,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) } #undef is_drawing_subs_or_sups +#endif #ifdef CONFIG_UTF_8 process_link(html_context, link_state, chars, charslen, From 098fb87065e2c69f4f9ef65d16901e336a72b789 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Fri, 21 Jul 2006 14:08:24 +0200 Subject: [PATCH 57/73] Expand $LOCALEDIR. Previously, it was ${prefix}/share/locale --- configure.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.in b/configure.in index 82566786..4f698800 100644 --- a/configure.in +++ b/configure.in @@ -1328,6 +1328,10 @@ AC_SUBST(CONFDIR) # Create LOCALEDIR #define for config.h LOCALEDIR=`eval echo "$datadir/locale"` +while echo "$LOCALEDIR" | grep "\\$" +do + LOCALEDIR=`eval echo "$LOCALEDIR"` +done > /dev/null 2> /dev/null AC_DEFINE_UNQUOTED(LOCALEDIR, "$LOCALEDIR", [Directory containing locales]) AC_SUBST(LOCALEDIR) From 1c04b45669fe0fd5de2340a6827f9470b68de4e8 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Fri, 21 Jul 2006 14:37:46 +0200 Subject: [PATCH 58/73] Show dots after UTF-8. Taken from Jonas's mail --- config/m4/features.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/m4/features.m4 b/config/m4/features.m4 index 8c22d92e..79e332a4 100644 --- a/config/m4/features.m4 +++ b/config/m4/features.m4 @@ -19,7 +19,7 @@ AC_DEFUN([EL_LOG_CONFIG], [msgdots2="`echo $about | sed 's/[0-9]/./g'`"] [msgdots1="`echo $msgdots2 | sed 's/[a-z]/./g'`"] [msgdots0="`echo $msgdots1 | sed 's/[A-Z]/./g'`"] - [msgdots="`echo $msgdots0 | sed 's/[_ ()]/./g'`"] + [msgdots="`echo $msgdots0 | sed 's/[-_ ()]/./g'`"] DOTS="................................" dots=`echo $DOTS | sed "s/$msgdots//"` From f5351fc0dc533f12119dd9cf5421cc2e3beed7b5 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Fri, 21 Jul 2006 22:10:18 +0200 Subject: [PATCH 59/73] Remember fragment of the splitted char and decode it next time. Idea by Jonas. Not tested at all. UCS_NO_CHAR is returned only for
or for UTF-8 char which is splitted by convert_string --- src/document/document.h | 4 +++ src/document/html/renderer.c | 55 ++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/document/document.h b/src/document/document.h index d8a3a100..466a9240 100644 --- a/src/document/document.h +++ b/src/document/document.h @@ -182,6 +182,10 @@ struct document { struct search **slines1; struct search **slines2; +#ifdef CONFIG_UTF_8 + unsigned char buf[7]; + unsigned char buf_length; +#endif unsigned int id; /* Used to check cache entries. */ int cp; diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index fea51b99..4322c456 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -408,30 +408,61 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, Y(y), X(x) + charslen - 1)) return len; if (utf8) { - unsigned char *end; + unsigned char *end = chars + charslen; + unicode_val_T data; - for (end = chars + charslen; chars < end; x++) { + if (part->document->buf_length) { + /* previous char was broken in the middle */ + int length = utf8charlen(part->document->buf); + unsigned char i; + unsigned char *buf_ptr = part->document->buf; + + for (i = part->document->buf_length; i < length && chars < end;) { + part->document->buf[i++] = *chars++; + } + part->document->buf_length = i; + part->document->buf[i] = '\0'; + data = utf_8_to_unicode(&buf_ptr, buf_ptr + i); + if (data != UCS_NO_CHAR) { + part->document->buf_length = 0; + goto good_char; + } else { + /* Still not full char */ + return len; + } + } + + for (; chars < end; x++) { if (*chars == NBSP_CHAR) { schar->data = ' '; part->spaces[x] = html_context->options->wrap_nbsp; part->char_width[x] = 1; chars++; } else { - unicode_val_T data; - part->spaces[x] = (*chars == ' '); data = utf_8_to_unicode(&chars, end); if (data == UCS_NO_CHAR) { - /* HR */ - unsigned char attr = schar->attr; + if (charslen == 1) { + /* HR */ + unsigned char attr = schar->attr; - schar->data = *chars++; - schar->attr = SCREEN_ATTR_FRAME; - copy_screen_chars(&POS(x, y), schar, 1); - schar->attr = attr; - part->char_width[x] = 0; - continue; + schar->data = *chars++; + schar->attr = SCREEN_ATTR_FRAME; + copy_screen_chars(&POS(x, y), schar, 1); + schar->attr = attr; + part->char_width[x] = 0; + continue; + } else { + unsigned char i; + /* broken char */ + for (i = 0; chars < end;i++) { + part->document->buf[i] = *chars++; + } + part->document->buf_length = i; + return x - x2; + } } else { +good_char: if (unicode_to_cell(data) == 2) { schar->data = (unicode_val_T)data; part->char_width[x] = 2; From 71e569c1291a18c7f3d624af438ae80ffb969314 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Sat, 22 Jul 2006 17:06:05 +0200 Subject: [PATCH 60/73] Move variable out of loop to fix uninitialized warning caused by goto label --- src/viewer/text/search.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/viewer/text/search.c b/src/viewer/text/search.c index ff796aa5..b8e7c40f 100644 --- a/src/viewer/text/search.c +++ b/src/viewer/text/search.c @@ -923,6 +923,11 @@ point_intersect(struct point *p1, int l1, struct point *p2, int l2) static int find_next_link_in_search(struct document_view *doc_view, int direction) { + int utf8 = 0; +#ifdef CONFIG_UTF_8 + utf8 = doc_view->document->options.utf8; +#endif + assert(doc_view && doc_view->vs); if_assert_failed return 0; @@ -943,10 +948,6 @@ find_next_link_in_search(struct document_view *doc_view, int direction) struct point *pt = NULL; struct link *link; int len; - int utf8 = 0; -#ifdef CONFIG_UTF_8 - utf8 = doc_view->document->options.utf8; -#endif nt: link = &doc_view->document->links[doc_view->vs->current_link]; From a3e0caca57e5615ddc09e0557a5632fd8a2335d7 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 23 Jul 2006 12:27:20 +0200 Subject: [PATCH 61/73] Return number of really processed chars. In that case 0 --- src/document/html/renderer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 4322c456..7d76d45a 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -401,12 +401,12 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, assert(charslen >= 0); if (realloc_spaces(part, x + charslen)) - return len; + return 0; if (part->document) { if (realloc_line(html_context, part->document, Y(y), X(x) + charslen - 1)) - return len; + return 0; if (utf8) { unsigned char *end = chars + charslen; unicode_val_T data; @@ -428,7 +428,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, goto good_char; } else { /* Still not full char */ - return len; + return 0; } } From 7cb91c32139dc72aad02b9f11c1aad40ccb172a4 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 23 Jul 2006 13:04:39 +0200 Subject: [PATCH 62/73] Decode the second char from double glyph. When that char is splitted by convert_string and that char is the beginning of double glyph too we have a problem. This is a rare case. Must we care about it? --- src/document/html/renderer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 7d76d45a..4f2a67a5 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -454,7 +454,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen, continue; } else { unsigned char i; - /* broken char */ +broken_char: /* broken char */ for (i = 0; chars < end;i++) { part->document->buf[i] = *chars++; } @@ -467,7 +467,9 @@ good_char: schar->data = (unicode_val_T)data; part->char_width[x] = 2; copy_screen_chars(&POS(x++, y), schar, 1); - schar->data = UCS_NO_CHAR; + data = utf_8_to_unicode(&chars, end); + if (data == UCS_NO_CHAR) goto broken_char; + schar->data = (unicode_val_T)data; part->spaces[x] = 0; part->char_width[x] = 0; } else { From 58b158871ce5f7189cba8d171efcf9a4d1ad1c72 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 23 Jul 2006 13:14:38 +0200 Subject: [PATCH 63/73] Decode the second char of double glyph. Still problems with a splitted char --- src/document/html/renderer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 4f2a67a5..20310b27 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -509,11 +509,11 @@ good_char: x++; part->spaces[x] = 0; part->char_width[x] = 0; + data = utf_8_to_unicode(&chars, end); } if (data == UCS_NO_CHAR) { - chars++; - part->char_width[x] = 0; - x++; + /* this is at the end only */ + return x - x2; } } len = x - x2; From 4263af97a9503e95da9d4ea678e6cb3b5a61663d Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 23 Jul 2006 15:23:19 +0200 Subject: [PATCH 64/73] The missing code, I suppose. Fixed moving right in textareas in UTF-8 mode. First move was by two cells. --- src/viewer/text/form.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 092c7ccf..40cb5bd2 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -1328,6 +1328,10 @@ field_op(struct session *ses, struct document_view *doc_view, break; case ACT_EDIT_RIGHT: #ifdef CONFIG_UTF_8 + if (fc->type == FC_TEXTAREA) { + status = textarea_op_right(fs, fc, utf8); + break; + } if (utf8) { unsigned char *text = fs->value + fs->state; unsigned char *end = strchr(text, '\0'); From 8b4daed14838e9ad00f10338c4628f0656d3bf4e Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 23 Jul 2006 16:35:53 +0200 Subject: [PATCH 65/73] Commented out the code causing infinite loop when viewing test/backspaces.txt. --- src/document/plain/renderer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index b65321d8..5d3adf6d 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -349,11 +349,12 @@ add_document_line(struct plain_renderer *renderer, *template = saved_renderer_template; } else if (line_char == ASCII_BS) { +#if 0 if (!(expanded + cells)) { /* We've backspaced to the start of the line */ continue; } - +#endif if (pos > startpos) pos--; /* Backspace */ From 29fb051fc9de70848f25333f26c99acb82aa4b66 Mon Sep 17 00:00:00 2001 From: Laurent MONIN Date: Mon, 24 Jul 2006 17:56:07 +0200 Subject: [PATCH 66/73] Compilation fix: move variables declarations to top. --- src/bfu/dialog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index 67be711b..d3a3ec89 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -592,15 +592,15 @@ generic_dialog_layouter(struct dialog_data *dlg_data) struct terminal *term = dlg_data->win->term; int w = dialog_max_width(term); int height = dialog_max_height(term); - int rw; + int x = 0, y, rw; + #ifdef CONFIG_UTF_8 if (term->utf8) rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL)); else #endif /* CONFIG_UTF_8 */ rw = int_min(w, strlen(dlg_data->dlg->title)); - int y = dlg_data->dlg->layout.padding_top ? 0 : -1; - int x = 0; + y = dlg_data->dlg->layout.padding_top ? 0 : -1; format_widgets(term, dlg_data, x, &y, w, height, &rw, 1); From 6c8f532692242f0a0f338217d27cc3e812b43257 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 24 Jul 2006 18:52:25 +0200 Subject: [PATCH 67/73] Fixes to the Python scripting by M. Levinson --- AUTHORS | 3 + contrib/python/README.Python | 13 ++--- src/scripting/python/core.c | 102 +++++++++++++++++++++++++++----- src/scripting/python/core.h | 2 + src/scripting/python/hooks.c | 110 +++++++++++++++++------------------ src/scripting/scripting.c | 7 ++- 6 files changed, 158 insertions(+), 79 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0b0444e7..a8fe034b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -331,6 +331,9 @@ Len Lattanzi M. K. Srikant Small fix in forms +M. Levinson + Python scripting fixes + Marco Bodrato Twinterm support diff --git a/contrib/python/README.Python b/contrib/python/README.Python index 9fde5abf..862b60aa 100644 --- a/contrib/python/README.Python +++ b/contrib/python/README.Python @@ -1,13 +1,8 @@ -If you want to use Python scripting with ELinks add ---with-python to the configure invocation copy hooks.py to ~/.elinks -When your Python installation is your own build, you could give prefix -to the configure, eg. ---with-python=/usr/local when Python binary is placed in /usr/local/bin, etc. +If you want to use Python scripting with ELinks, add --with-python to the +configure invocation and copy hooks.py to your ~/.elinks directory. -When 'configure' cannot find -lpython make symbolic link to the appropriate -library, eg. -# cd /usr/local/lib -# ln -s libpython2.4.so.1.0 libpython.so +If configure cannot find Python you can supply a path, e.g. +--with-python=/usr/local/bin if your Python binary is in /usr/local/bin, etc. For the present hooks.py is not very usable. You are welcome to make it better. Good Luck! diff --git a/src/scripting/python/core.c b/src/scripting/python/core.c index fda82188..83eb2c39 100644 --- a/src/scripting/python/core.c +++ b/src/scripting/python/core.c @@ -4,7 +4,6 @@ #include "config.h" #endif -#include "scripting/python/core.h" #include #include @@ -14,24 +13,91 @@ #include "config/home.h" #include "main/module.h" +#include "scripting/scripting.h" +#include "scripting/python/core.h" +#include "scripting/python/python.h" #include "util/env.h" #include "util/file.h" #include "util/string.h" -PyObject *pDict, *pModule; +PyObject *pDict = NULL, *pModule = NULL; + +/* Error reporting. */ + +void +alert_python_error(struct session *ses) +{ + unsigned char *msg = "(no traceback available)"; + PyObject *err_type = NULL, *err_value = NULL, *err_traceback = NULL; + PyObject *tb_module = NULL; + PyObject *tb_dict; + PyObject *format_function; + PyObject *msg_list = NULL; + PyObject *empty_string = NULL; + PyObject *join_method = NULL; + PyObject *msg_string = NULL; + unsigned char *temp; + + /* + * Retrieve the current error indicator and use the format_exception() + * function in Python's traceback module to produce an informative + * error message. It returns a list of Python string objects. + */ + PyErr_Fetch(&err_type, &err_value, &err_traceback); + PyErr_NormalizeException(&err_type, &err_value, &err_traceback); + if (!err_traceback) goto end; + + tb_module = PyImport_ImportModule("traceback"); + if (!tb_module) goto end; + + tb_dict = PyModule_GetDict(tb_module); + format_function = PyDict_GetItemString(tb_dict, "format_exception"); + if (!format_function || !PyCallable_Check(format_function)) goto end; + + msg_list = PyObject_CallFunction(format_function, "OOO", + err_type, err_value, err_traceback); + if (!msg_list) goto end; + + /* + * Use the join() method of an empty Python string to join the list + * of strings into one Python string containing the entire error + * message. Then get the contents of the Python string. + */ + empty_string = PyString_FromString(""); + if (!empty_string) goto end; + + join_method = PyObject_GetAttrString(empty_string, "join"); + if (!join_method || !PyCallable_Check(join_method)) goto end; + + msg_string = PyObject_CallFunction(join_method, "O", msg_list); + if (!msg_string) goto end; + + temp = (unsigned char *)PyString_AsString(msg_string); + if (temp) msg = temp; + +end: + report_scripting_error(&python_scripting_module, ses, msg); + + Py_XDECREF(err_type); + Py_XDECREF(err_value); + Py_XDECREF(err_traceback); + Py_XDECREF(tb_module); + Py_XDECREF(msg_list); + Py_XDECREF(empty_string); + Py_XDECREF(join_method); + Py_XDECREF(msg_string); + + /* In case another error occurred while reporting the original error: */ + PyErr_Clear(); +} void cleanup_python(struct module *module) { if (Py_IsInitialized()) { - if (pModule) { - Py_DECREF(pModule); - } - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + Py_XDECREF(pDict); + Py_XDECREF(pModule); Py_Finalize(); } } @@ -44,15 +110,25 @@ init_python(struct module *module) if (!python_path) return; env_set("PYTHONPATH", python_path, -1); mem_free(python_path); + + /* Treat warnings as errors so they can be caught and handled; + * otherwise they would be printed to stderr. + * + * NOTE: PySys_ResetWarnOptions() and PySys_AddWarnOption() have been + * available and stable for many years but they're not officially + * documented as part of Python's public API, so in theory these two + * functions might no longer be available in some hypothetical future + * version of Python. */ + PySys_ResetWarnOptions(); + PySys_AddWarnOption("error"); + Py_Initialize(); pModule = PyImport_ImportModule("hooks"); if (pModule) { pDict = PyModule_GetDict(pModule); + Py_INCREF(pDict); } else { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + alert_python_error(NULL); } } diff --git a/src/scripting/python/core.h b/src/scripting/python/core.h index 00b08dee..44503138 100644 --- a/src/scripting/python/core.h +++ b/src/scripting/python/core.h @@ -3,7 +3,9 @@ #define EL__SCRIPTING_PYTHON_CORE_H struct module; +struct session; +void alert_python_error(struct session *ses); void init_python(struct module *module); void cleanup_python(struct module *module); diff --git a/src/scripting/python/hooks.c b/src/scripting/python/hooks.c index 9f3d0952..af9b6186 100644 --- a/src/scripting/python/hooks.c +++ b/src/scripting/python/hooks.c @@ -32,29 +32,29 @@ do_script_hook_goto_url(struct session *ses, unsigned char **url) if (pFunc && PyCallable_Check(pFunc)) { PyObject *pValue; - unsigned char *str; + unsigned char *current_url; if (!ses || !have_location(ses)) { - str = NULL; + current_url = NULL; } else { - str = struri(cur_loc(ses)->vs.uri); + current_url = struri(cur_loc(ses)->vs.uri); } - pValue = PyObject_CallFunction(pFunc, "ss", *url, str); - if (pValue && (pValue != Py_None)) { - const unsigned char *res = PyString_AsString(pValue); + pValue = PyObject_CallFunction(pFunc, "ss", *url, current_url); + if (pValue) { + if (pValue != Py_None) { + const unsigned char *str; + unsigned char *new_url; - if (res) { - unsigned char *new_url = stracpy((unsigned char *)res); - - if (new_url) mem_free_set(url, new_url); + str = PyString_AsString(pValue); + if (str) { + new_url = stracpy((unsigned char *)str); + if (new_url) mem_free_set(url, new_url); + } } Py_DECREF(pValue); } else { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + alert_python_error(ses); } } } @@ -72,26 +72,26 @@ script_hook_goto_url(va_list ap, void *data) } static void -do_script_hook_follow_url(unsigned char **url) +do_script_hook_follow_url(struct session *ses, unsigned char **url) { PyObject *pFunc = PyDict_GetItemString(pDict, "follow_url_hook"); if (pFunc && PyCallable_Check(pFunc)) { PyObject *pValue = PyObject_CallFunction(pFunc, "s", *url); - if (pValue && (pValue != Py_None)) { - const unsigned char *str = PyString_AsString(pValue); - unsigned char *new_url; + if (pValue) { + if (pValue != Py_None) { + const unsigned char *str; + unsigned char *new_url; - if (str) { - new_url = stracpy((unsigned char *)str); - if (new_url) mem_free_set(url, new_url); + str = PyString_AsString(pValue); + if (str) { + new_url = stracpy((unsigned char *)str); + if (new_url) mem_free_set(url, new_url); + } } Py_DECREF(pValue); } else { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + alert_python_error(ses); } } } @@ -100,15 +100,17 @@ static enum evhook_status script_hook_follow_url(va_list ap, void *data) { unsigned char **url = va_arg(ap, unsigned char **); + struct session *ses = va_arg(ap, struct session *); if (pDict && *url) - do_script_hook_follow_url(url); + do_script_hook_follow_url(ses, url); return EVENT_HOOK_STATUS_NEXT; } static void -do_script_hook_pre_format_html(unsigned char *url, struct cache_entry *cached, +do_script_hook_pre_format_html(struct session *ses, unsigned char *url, + struct cache_entry *cached, struct fragment *fragment) { PyObject *pFunc = PyDict_GetItemString(pDict, "pre_format_html_hook"); @@ -118,21 +120,21 @@ do_script_hook_pre_format_html(unsigned char *url, struct cache_entry *cached, fragment->data, fragment->length); - if (pValue && (pValue != Py_None)) { - const unsigned char *str = PyString_AsString(pValue); + if (pValue) { + if (pValue != Py_None) { + const unsigned char *str; + int len; - if (str) { - int len = PyString_Size(pValue); /* strlen(str); */ - - add_fragment(cached, 0, str, len); - normalize_cache_entry(cached, len); + str = PyString_AsString(pValue); + if (str) { + len = PyString_Size(pValue); + add_fragment(cached, 0, str, len); + normalize_cache_entry(cached, len); + } } Py_DECREF(pValue); } else { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + alert_python_error(ses); } } } @@ -146,7 +148,7 @@ script_hook_pre_format_html(va_list ap, void *data) unsigned char *url = struri(cached->uri); if (pDict && ses && url && cached->length && *fragment->data) - do_script_hook_pre_format_html(url, cached, fragment); + do_script_hook_pre_format_html(ses, url, cached, fragment); return EVENT_HOOK_STATUS_NEXT; } @@ -159,20 +161,21 @@ do_script_hook_get_proxy(unsigned char **new_proxy_url, unsigned char *url) if (pFunc && PyCallable_Check(pFunc)) { PyObject *pValue = PyObject_CallFunction(pFunc, "s", url); - if (pValue && (pValue != Py_None)) { - const unsigned char *str = PyString_AsString(pValue); + if (pValue) { + if (pValue != Py_None) { + const unsigned char *str; + unsigned char *new_url; - if (str) { - unsigned char *new_url = stracpy((unsigned char *)str); - - if (new_url) mem_free_set(new_proxy_url, new_url); + str = PyString_AsString(pValue); + if (str) { + new_url = stracpy((unsigned char *)str); + if (new_url) mem_free_set(new_proxy_url, + new_url); + } } Py_DECREF(pValue); } else { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + alert_python_error(NULL); } } } @@ -198,14 +201,9 @@ do_script_hook_quit(void) PyObject *pValue = PyObject_CallFunction(pFunc, NULL); if (pValue) { - if (pValue != Py_None) { - Py_DECREF(pValue); - } + Py_DECREF(pValue); } else { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + alert_python_error(NULL); } } } diff --git a/src/scripting/scripting.c b/src/scripting/scripting.c index 4a3360c5..78ff5b9e 100644 --- a/src/scripting/scripting.c +++ b/src/scripting/scripting.c @@ -24,10 +24,14 @@ #include "scripting/ruby/ruby.h" #include "scripting/smjs/smjs.h" +#ifdef HAVE_UNISTD_H +#include +#endif + /* Error reporting. */ -#if defined(CONFIG_SCRIPTING_RUBY) || defined(CONFIG_SCRIPTING_SPIDERMONKEY) +#if defined(CONFIG_SCRIPTING_RUBY) || defined(CONFIG_SCRIPTING_SPIDERMONKEY) || defined(CONFIG_SCRIPTING_PYTHON) void report_scripting_error(struct module *module, struct session *ses, unsigned char *msg) @@ -38,6 +42,7 @@ report_scripting_error(struct module *module, struct session *ses, if (!ses) { if (list_empty(terminals)) { usrerror("[%s error] %s", module->name, msg); + sleep(3); return; } From a7a7984d898fe8f012ea4d00e9d3bfe1af8cb20e Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Tue, 25 Jul 2006 09:59:12 +0200 Subject: [PATCH 68/73] Merge with http://www.fi.muni.cz/~xbabinc/elinks/elinks-utf8.git/ without ucdata stuff. UTF-8 code cleanup. Added Pavol Babincak to the AUTHORS --- AUTHORS | 3 +++ features.conf | 21 +++++++++++++++++++++ src/bfu/dialog.c | 9 ++++----- src/bfu/text.c | 1 + src/intl/charsets.c | 25 ++++++++++--------------- src/terminal/draw.c | 6 +++--- src/terminal/event.c | 22 ++++++---------------- 7 files changed, 48 insertions(+), 39 deletions(-) diff --git a/AUTHORS b/AUTHORS index a8fe034b..f65085d4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -423,6 +423,9 @@ Omar Khayam Fix stdin reading on Mac OS X +Pavol Babincak + Improved UTF-8 support with double-width chars + Peder Stray Fix handling of key presses turning up as key prefixes diff --git a/features.conf b/features.conf index 199d159e..5ee749e4 100644 --- a/features.conf +++ b/features.conf @@ -601,6 +601,27 @@ CONFIG_OWN_LIBC=no CONFIG_SMALL=no +### Unicode UTF-8 support +# +# By enabling this option you get better Unicode support. At present only some +# parts of ELinks are influenced with this. It includes DOM, plain, HTML +# renderer and user interface. Beside normal Unicode characters there is +# support for double-width characters (like Japanese, etc.). +# +# Some features of Unicode are not handled at all. Combining characters is +# most visible absence. +# Some features are partially supported. Like line breaking between +# double-width characters. There is no other detection for determining when to +# break or not. +# +# Note: This UTF-8 support is experimental. +# +# Default: disabled + +CONFIG_UTF_8=no + + + ### Back-trace Printing # # Once upon a time, a disaster happens and ELinks crashes. That is a very sad diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index d3a3ec89..0d720132 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -100,20 +100,19 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) int titlelen = strlen(title); int titlecells = titlelen; int x, y; + #ifdef CONFIG_UTF_8 if (term->utf8) titlecells = utf8_ptr2cells(title, - &title[titlelen]); + &title[titlelen]); #endif /* CONFIG_UTF_8 */ titlecells = int_min(box.width - 2, titlecells); #ifdef CONFIG_UTF_8 - if (term->utf8) { - titlelen = utf8_cells2bytes(title, - titlecells, + if (term->utf8) + titlelen = utf8_cells2bytes(title, titlecells, NULL); - } #endif /* CONFIG_UTF_8 */ x = (box.width - titlecells) / 2 + box.x; diff --git a/src/bfu/text.c b/src/bfu/text.c index f3ba6236..19704052 100644 --- a/src/bfu/text.c +++ b/src/bfu/text.c @@ -51,6 +51,7 @@ split_line(unsigned char *text, int max_width, int *cells) while (*split && *split != '\n') { unsigned char *next_split; + #ifdef CONFIG_UTF_8 if (utf8) { unsigned char *next_char_begin = split diff --git a/src/intl/charsets.c b/src/intl/charsets.c index fde3d030..dd7b382f 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -215,8 +215,7 @@ encode_utf_8(unicode_val_T u) #ifdef CONFIG_UTF_8 /* Number of bytes utf8 character indexed by first byte. Illegal bytes are * equal ones and handled different. */ -static char utf8char_len_tab[256] = -{ +static char utf8char_len_tab[256] = { 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, @@ -229,11 +228,7 @@ static char utf8char_len_tab[256] = inline int utf8charlen(const unsigned char *p) { - int len; - if (p==NULL) - return 0; - len = utf8char_len_tab[*p]; - return len; + return p ? utf8char_len_tab[*p] : 0; } inline int @@ -260,14 +255,14 @@ strlen_utf8(unsigned char **str) inline unsigned char * utf8_prevchar(unsigned char *current, int pos, unsigned char *start) { - if (current == NULL || start == NULL || pos < 0) - return NULL; - while (pos > 0 && current != start) { - current--; - if (utf8_islead(*current)) - pos--; - } - return current; + if (current == NULL || start == NULL || pos < 0) + return NULL; + while (pos > 0 && current != start) { + current--; + if (utf8_islead(*current)) + pos--; + } + return current; } /* Count number of standard terminal cells needed for displaying UTF-8 diff --git a/src/terminal/draw.c b/src/terminal/draw.c index f539f961..000a9c23 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -118,9 +118,9 @@ draw_char_data(struct terminal *term, int x, int y, unsigned char data) #ifdef CONFIG_UTF_8 #ifdef CONFIG_DEBUG /* Detect attempt to draw double-width char on the last - * collumn of terminal. */ + * column of terminal. */ if (unicode_to_cell(data) == 2 && x + 1 > term->width) - INTERNAL("Attempt to draw double-width glyph on last collumn!"); + INTERNAL("Attempt to draw double-width glyph on last column!"); #endif /* CONFIG_DEBUG */ if (data == UCS_NO_CHAR) @@ -161,7 +161,7 @@ draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line) screen_char++; } - /* Instead of displaying double-width character at last collumn + /* Instead of displaying double-width character at last column * display only space. */ if (size - 1 > 0 && unicode_to_cell(line[size - 1].data) == 2) { sc = &line[size - 1]; diff --git a/src/terminal/event.c b/src/terminal/event.c index cf8a25f5..f70854a3 100644 --- a/src/terminal/event.c +++ b/src/terminal/event.c @@ -251,9 +251,7 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) case EVENT_KBD: { -#ifndef CONFIG_UTF_8 int utf8_io = -1; -#endif /* CONFIG_UTF_8 */ int key = get_kbd_key(ev); reset_timer(); @@ -267,14 +265,14 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) return 0; } - if (interlink->utf_8.len) { #ifdef CONFIG_UTF_8 - if ((key & 0xC0) == 0x80 && term->utf8) + utf8_io = !!term->utf8; #else - utf8_io = get_opt_bool_tree(term->spec, "utf_8_io"); - if ((key & 0xC0) == 0x80 && utf8_io) + utf8_io = get_opt_bool_tree(term->spec, "utf_8_io"); #endif /* CONFIG_UTF_8 */ - { + + if (interlink->utf_8.len) { + if ((key & 0xC0) == 0x80 && utf8_io) { interlink->utf_8.ucs <<= 6; interlink->utf_8.ucs |= key & 0x3F; if (! --interlink->utf_8.len) { @@ -292,15 +290,7 @@ handle_interlink_event(struct terminal *term, struct term_event *ev) } } -#ifdef CONFIG_UTF_8 - if (key < 0x80 || key > 0xFF || !term->utf8) -#else - if (key < 0x80 || key > 0xFF - || (utf8_io == -1 - ? !get_opt_bool_tree(term->spec, "utf_8_io") - : !utf8_io)) -#endif /* CONFIG_UTF_8 */ - { + if (key < 0x80 || key > 0xFF || !utf8_io) { term_send_event(term, ev); break; From d83068ec85f2d68bbd16d0569a91ccbb7c01a713 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Wed, 26 Jul 2006 21:27:57 +0200 Subject: [PATCH 69/73] Proper CFLAGS and LDFLAGS for the Python scripting backend. The patch by M. Levinson. I added DIR to the --with-python --- configure.in | 73 +- src/intl/gettext/plural.c | 1760 ++++++++++++++++++++++--------------- 2 files changed, 1065 insertions(+), 768 deletions(-) diff --git a/configure.in b/configure.in index 4f698800..480a0180 100644 --- a/configure.in +++ b/configure.in @@ -771,50 +771,32 @@ dnl Check for Python dnl =================================================================== enable_python="no"; -AC_ARG_WITH(python, [ --with-python=[prefix] enable Python support], - [ -if test "$withval" != no; then - # FIXME: If withval is a valid directory append it to PATH - # so that you can specify one of several Python installations. - if test "$withval" != yes; then - python_prefix="$withval" - else - python_prefix="" - fi - enable_python=yes - cat < /dev/null`" - if test -n "$python_prefix" && test -d "$python_prefix/lib"; then - PYTHON_LIBS="-L$python_prefix/lib $PYTHON_LIBS" - fi + + if test "$PYTHON" != no; then + cf_result="yes"; + + PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; print "-I%s -I%s" % (sysconfig.get_python_inc(), sysconfig.get_python_inc(plat_specific=True))'`" + PYTHON_LIBS="`$PYTHON -c 'from distutils import sysconfig; var = sysconfig.get_config_var; print "%s %s %s -L%s -lpython%s" % (var("LINKFORSHARED"), var("LIBS"), var("SYSLIBS"), var("LIBPL"), var("VERSION"))'`" LIBS="$PYTHON_LIBS $LIBS" - CFLAGS="$PYTHON_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $PYTHON_CFLAGS" AC_TRY_LINK([#include ], [Py_Initialize();], cf_result=yes, cf_result=no) @@ -823,17 +805,28 @@ if test "$enable_python" = "yes"; then EL_RESTORE_FLAGS else EL_CONFIG(CONFIG_SCRIPTING_PYTHON, [Python]) - - CFLAGS="$CFLAGS_X" AC_SUBST(PYTHON_LIBS) AC_SUBST(PYTHON_CFLAGS) + cat < - -#include "elinks.h" - #include "intl/gettext/gettextP.h" #define YYLEX_PARAM &((struct parse_args *) arg)->cp #define YYPARSE_PARAM arg + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #line 41 "plural.y" -typedef union { +typedef union YYSTYPE { unsigned long int num; enum operator op; struct expression *exp; } YYSTYPE; +/* Line 191 of yacc.c. */ +#line 142 "plural.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ #line 47 "plural.y" /* Prototypes for local functions. */ @@ -150,431 +234,693 @@ new_exp_3(enum operator op, struct expression *bexp, struct expression *tbranch, return new_exp (3, op, args); } -#include - -#ifndef __cplusplus -#ifndef __STDC__ -#define const -#endif -#endif +/* Line 214 of yacc.c. */ +#line 240 "plural.c" -#define YYFINAL 27 -#define YYFLAG -32768 -#define YYNTBASE 16 +#if ! defined (yyoverflow) || YYERROR_VERBOSE -#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18) +/* The parser invokes alloca or malloc; define the necessary symbols. */ -static const char yytranslate[] = { 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 10, 2, 2, 2, 2, 5, 2, 14, - 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 12, 2, 2, - 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 6, 7, 8, 9, - 11 -}; +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif -#if YYDEBUG != 0 -static const short yyprhs[] = { 0, - 0, 2, 8, 12, 16, 20, 24, 28, 32, 35, - 37, 39 -}; +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ -static const short yyrhs[] = { 17, - 0, 17, 3, 17, 12, 17, 0, 17, 4, 17, - 0, 17, 5, 17, 0, 17, 6, 17, 0, 17, - 7, 17, 0, 17, 8, 17, 0, 17, 9, 17, - 0, 10, 17, 0, 13, 0, 11, 0, 14, 17, - 15, 0 -}; + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) #endif -#if YYDEBUG != 0 -static const short yyrline[] = { 0, - 154, 162, 166, 170, 174, 178, 182, 186, 190, 194, - 198, 203 -}; -#endif - - -#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) - -static const char * const yytname[] = { "$","error","$undefined.","'?'","'|'", -"'&'","EQUOP2","CMPOP2","ADDOP2","MULOP2","'!'","NUMBER","':'","'n'","'('","')'", -"start","exp", NULL -}; -#endif - -static const short yyr1[] = { 0, - 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17 -}; - -static const short yyr2[] = { 0, - 1, 5, 3, 3, 3, 3, 3, 3, 2, 1, - 1, 3 -}; - -static const short yydefact[] = { 0, - 0, 11, 10, 0, 1, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 12, 0, 3, 4, 5, 6, - 7, 8, 0, 2, 0, 0, 0 -}; - -static const short yydefgoto[] = { 25, - 5 -}; - -static const short yypact[] = { -9, - -9,-32768,-32768, -9, 34,-32768, 11, -9, -9, -9, - -9, -9, -9, -9,-32768, 24, 39, 43, 16, 26, - -3,-32768, -9, 34, 21, 53,-32768 -}; - -static const short yypgoto[] = {-32768, - -1 -}; - - -#define YYLAST 53 - - -static const short yytable[] = { 6, - 1, 2, 7, 3, 4, 14, 16, 17, 18, 19, - 20, 21, 22, 8, 9, 10, 11, 12, 13, 14, - 26, 24, 12, 13, 14, 15, 8, 9, 10, 11, - 12, 13, 14, 13, 14, 23, 8, 9, 10, 11, - 12, 13, 14, 10, 11, 12, 13, 14, 11, 12, - 13, 14, 27 -}; - -static const short yycheck[] = { 1, - 10, 11, 4, 13, 14, 9, 8, 9, 10, 11, - 12, 13, 14, 3, 4, 5, 6, 7, 8, 9, - 0, 23, 7, 8, 9, 15, 3, 4, 5, 6, - 7, 8, 9, 8, 9, 12, 3, 4, 5, 6, - 7, 8, 9, 5, 6, 7, 8, 9, 6, 7, - 8, 9, 0 -}; -#define YYPURE 1 - -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/local/share/bison.simple" -/* This file comes from bison-1.28. */ - -/* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* This is the parser code that is written into each bison parser - when the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include -#endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ -#endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ - -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; #else -#define YYSTACK_ALLOC malloc + typedef short yysigned_char; #endif -/* Note: there must be only one dollar sign in this file. - It is replaced by the list of actions, each action - as one case of the switch. */ +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 9 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 54 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 16 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 3 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 13 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 27 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 262 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 10, 2, 2, 2, 2, 5, 2, + 14, 15, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, + 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 6, 7, + 8, 9, 11 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 5, 11, 15, 19, 23, 27, 31, + 35, 38, 40, 42 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 17, 0, -1, 18, -1, 18, 3, 18, 12, 18, + -1, 18, 4, 18, -1, 18, 5, 18, -1, 18, + 6, 18, -1, 18, 7, 18, -1, 18, 8, 18, + -1, 18, 9, 18, -1, 10, 18, -1, 13, -1, + 11, -1, 14, 18, 15, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned char yyrline[] = +{ + 0, 154, 154, 162, 166, 170, 174, 178, 182, 186, + 190, 194, 198, 203 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2", + "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'", + "$accept", "start", "exp", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 63, 124, 38, 258, 259, 260, 261, + 33, 262, 58, 110, 40, 41 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 16, 17, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 5, 3, 3, 3, 3, 3, 3, + 2, 1, 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 0, 12, 11, 0, 0, 2, 10, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 4, + 5, 6, 7, 8, 9, 0, 3 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 5, 6 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -10 +static const yysigned_char yypact[] = +{ + -9, -9, -10, -10, -9, 8, 36, -10, 13, -10, + -9, -9, -9, -9, -9, -9, -9, -10, 26, 41, + 45, 18, -2, 14, -10, -9, 36 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -10, -10, -1 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 7, 1, 2, 8, 3, 4, 15, 16, 9, 18, + 19, 20, 21, 22, 23, 24, 10, 11, 12, 13, + 14, 15, 16, 16, 26, 14, 15, 16, 17, 10, + 11, 12, 13, 14, 15, 16, 0, 0, 25, 10, + 11, 12, 13, 14, 15, 16, 12, 13, 14, 15, + 16, 13, 14, 15, 16 +}; + +static const yysigned_char yycheck[] = +{ + 1, 10, 11, 4, 13, 14, 8, 9, 0, 10, + 11, 12, 13, 14, 15, 16, 3, 4, 5, 6, + 7, 8, 9, 9, 25, 7, 8, 9, 15, 3, + 4, 5, 6, 7, 8, 9, -1, -1, 12, 3, + 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, + 9, 6, 7, 8, 9 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 10, 11, 13, 14, 17, 18, 18, 18, 0, + 3, 4, 5, 6, 7, 8, 9, 15, 18, 18, + 18, 18, 18, 18, 18, 12, 18 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 +#define YYEMPTY (-2) #define YYEOF 0 + #define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab +#define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. - This remains here temporarily to ease the - transition to the new meaning of YYERROR, for GCC. + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ + #define YYFAIL goto yyerrlab + #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(token, value) \ + +#define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ - { yychar = (token), yylval = (value); \ - yychar1 = YYTRANSLATE (yychar); \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ - { yyerror ("syntax error: cannot back up"); YYERROR; } \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 -#ifndef YYPURE -#define YYLEX yylex() +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; #endif -#ifdef YYPURE -#ifdef YYLSP_NEEDED +/* YYLEX -- calling `yylex' with the right arguments. */ + #ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +# define YYLEX yylex (&yylval, YYLEX_PARAM) #else -#define YYLEX yylex(&yylval, &yylloc) +# define YYLEX yylex (&yylval) #endif -#else /* not YYLSP_NEEDED */ -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, YYLEX_PARAM) + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) #else -#define YYLEX yylex(&yylval) +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; #endif -#endif /* not YYLSP_NEEDED */ +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; #endif +{ + int yyi; + unsigned int yylineno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylineno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} -/* If nonreentrant, generate the variables here */ +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) -#ifndef YYPURE +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ -int yychar; /* the lookahead symbol */ -YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ - -#ifdef YYLSP_NEEDED -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ -#endif - -int yynerrs; /* number of parse errors so far */ -#endif /* not YYPURE */ - -#if YYDEBUG != 0 -int yydebug; /* nonzero means print parse trace */ -/* Since this is uninitialized, it does not stop multiple parsers - from coexisting. */ -#endif - -/* YYINITDEPTH indicates the initial size of the parser's stacks */ +/* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH -#define YYINITDEPTH 200 +# define YYINITDEPTH 200 #endif -/* YYMAXDEPTH is the maximum size the stacks can grow to - (effective only if the built-in stack extension method is used). */ +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ #if YYMAXDEPTH == 0 -#undef YYMAXDEPTH +# undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH -#define YYMAXDEPTH 10000 +# define YYMAXDEPTH 10000 #endif + -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ -#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) -#else /* not GNU C or C++ */ -#ifndef __cplusplus +#if YYERROR_VERBOSE -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (to, from, count) - char *to; - char *from; - unsigned int count; +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif { - register char *f = from; - register char *t = to; - register int i = count; + register const char *yys = yystr; - while (i-- > 0) - *t++ = *f++; + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; } +# endif +# endif -#else /* __cplusplus */ - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (char *to, char *from, unsigned int count) +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif { - register char *t = to; - register char *f = from; - register int i = count; + register char *yyd = yydest; + register const char *yys = yysrc; - while (i-- > 0) - *t++ = *f++; + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; } +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ -#endif -#endif -#line 217 "/usr/local/share/bison.simple" -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ -#ifdef YYPARSE_PARAM -#ifdef __cplusplus -#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* not __cplusplus */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -#endif /* not __cplusplus */ -#else /* not YYPARSE_PARAM */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* not YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -#ifdef YYPARSE_PARAM -int yyparse (void *); +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) #else -int yyparse (void); +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; #endif -#endif - -int -yyparse(YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL { + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + /* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + register int yystate; register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; - int yyerrstatus; /* number of tokens to shift before error messages enabled */ - int yychar1 = 0; /* lookahead token as an internal (translated) token number */ - short yyssa[YYINITDEPTH]; /* the state stack */ - YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ - short *yyss = yyssa; /* refer to the stacks thru separate pointers */ - YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ -#ifdef YYLSP_NEEDED - YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else #define YYPOPSTACK (yyvsp--, yyssp--) -#endif - int yystacksize = YYINITDEPTH; - int yyfree_stacks = 0; + YYSIZE_T yystacksize = YYINITDEPTH; -#ifdef YYPURE - int yychar; - YYSTYPE yylval; - int yynerrs; -#ifdef YYLSP_NEEDED - YYLTYPE yylloc; -#endif -#endif + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; - YYSTYPE yyval; /* the variable used to return */ - /* semantic values from the action */ - /* routines */ + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ int yylen; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Starting parse\n"); -#endif + YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; @@ -586,110 +932,96 @@ yyparse(YYPARSE_PARAM_ARG) so that they stay on the same level as the state stack. The wasted elements are never initialized. */ - yyssp = yyss - 1; + yyssp = yyss; yyvsp = yyvs; -#ifdef YYLSP_NEEDED - yylsp = yyls; -#endif -/* Push a new state, which is found in yystate . */ -/* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. */ -yynewstate: + goto yysetstate; - *++yyssp = yystate; +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; - if (yyssp >= yyss + yystacksize - 1) + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) { - /* Give user a chance to reallocate the stack */ - /* Use copies of these so that the &'s don't force the real ones into memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; -#ifdef YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; -#endif - /* Get the current used size of the three stacks, in elements. */ - int size = yyssp - yyss + 1; + YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow - /* Each stack pointer address is followed by the size of - the data in use in that stack, in bytes. */ -#ifdef YYLSP_NEEDED - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yyls1, size * sizeof (*yylsp), - &yystacksize); -#else - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yystacksize); -#endif + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; - yyss = yyss1; yyvs = yyvs1; -#ifdef YYLSP_NEEDED - yyls = yyls1; -#endif + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } #else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - { - yyerror("parser stack overflow"); - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 2; - } + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) + if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); -#ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); -#endif + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif #endif /* no yyoverflow */ - yyssp = yyss + size - 1; - yyvsp = yyvs + size - 1; -#ifdef YYLSP_NEEDED - yylsp = yyls + size - 1; -#endif + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Stack size increased to %d\n", yystacksize); -#endif - if (yyssp >= yyss + yystacksize - 1) + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) YYABORT; } -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Entering state %d\n", yystate); -#endif + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; - yybackup: + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ @@ -698,429 +1030,400 @@ yynewstate: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYFLAG) + if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Reading a token: "); -#endif + YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } - /* Convert token to internal form (in yychar1) for indexing tables with */ - - if (yychar <= 0) /* This means end of input. */ + if (yychar <= YYEOF) { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Now at end of input.\n"); -#endif + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); } else { - yychar1 = YYTRANSLATE(yychar); - -#if YYDEBUG != 0 - if (yydebug) - { - fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise meaning - of a token, for further debugging info. */ -#ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -#endif - fprintf (stderr, ")\n"); - } -#endif + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; - yyn = yytable[yyn]; - - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ - - if (yyn < 0) + if (yyn <= 0) { - if (yyn == YYFLAG) + if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } - else if (yyn == 0) - goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); -#endif + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - /* count tokens shifted since error; after three, turn off error status. */ - if (yyerrstatus) yyerrstatus--; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; yystate = yyn; goto yynewstate; -/* Do the default action for the current state. */ -yydefault: +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; + goto yyreduce; -/* Do a reduction. yyn is the number of a rule to reduce with. */ + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ yyreduce: + /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; - if (yylen > 0) - yyval = yyvsp[1-yylen]; /* implement default value of the action */ -#if YYDEBUG != 0 - if (yydebug) + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) { - int i; - - fprintf (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) - fprintf (stderr, "%s ", yytname[yyrhs[i]]); - fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif - - - switch (yyn) { - -case 1: + case 2: #line 155 "plural.y" -{ + { if (yyvsp[0].exp == NULL) YYABORT; ((struct parse_args *) arg)->res = yyvsp[0].exp; - ; - break;} -case 2: + } + break; + + case 3: #line 163 "plural.y" -{ + { yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 3: + } + break; + + case 4: #line 167 "plural.y" -{ + { yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 4: + } + break; + + case 5: #line 171 "plural.y" -{ + { yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 5: + } + break; + + case 6: #line 175 "plural.y" -{ + { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 6: + } + break; + + case 7: #line 179 "plural.y" -{ + { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 7: + } + break; + + case 8: #line 183 "plural.y" -{ + { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 8: + } + break; + + case 9: #line 187 "plural.y" -{ + { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 9: + } + break; + + case 10: #line 191 "plural.y" -{ + { yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); - ; - break;} -case 10: + } + break; + + case 11: #line 195 "plural.y" -{ + { yyval.exp = new_exp_0 (var); - ; - break;} -case 11: + } + break; + + case 12: #line 199 "plural.y" -{ + { if ((yyval.exp = new_exp_0 (num)) != NULL) yyval.exp->val.num = yyvsp[0].num; - ; - break;} -case 12: + } + break; + + case 13: #line 204 "plural.y" -{ + { yyval.exp = yyvsp[-1].exp; - ; - break;} -} - /* the action file gets copied in in place of this dollarsign */ -#line 543 "/usr/local/share/bison.simple" + } + break; + + + } + +/* Line 991 of yacc.c. */ +#line 1214 "plural.c" yyvsp -= yylen; yyssp -= yylen; -#ifdef YYLSP_NEEDED - yylsp -= yylen; -#endif -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif + + YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; -#ifdef YYLSP_NEEDED - yylsp++; - if (yylen == 0) - { - yylsp->first_line = yylloc.first_line; - yylsp->first_column = yylloc.first_column; - yylsp->last_line = (yylsp-1)->last_line; - yylsp->last_column = (yylsp-1)->last_column; - yylsp->text = 0; - } - else - { - yylsp->last_line = (yylsp+yylen-1)->last_line; - yylsp->last_column = (yylsp+yylen-1)->last_column; - } -#endif - /* Now "shift" the result of the reduction. - Determine what state that goes to, - based on the state we popped back to - and the rule number reduced by. */ + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ yyn = yyr1[yyn]; - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else - yystate = yydefgoto[yyn - YYNTBASE]; + yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; -yyerrlab: /* here on detecting error */ - if (! yyerrstatus) - /* If not already recovering from an error, report this error. */ +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) { ++yynerrs; - -#ifdef YYERROR_VERBOSE +#if YYERROR_VERBOSE yyn = yypact[yystate]; - if (yyn > YYFLAG && yyn < YYLAST) + if (YYPACT_NINF < yyn && yyn < YYLAST) { - int size = 0; - char *msg; - int x, count; + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; - count = 0; - /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - size += strlen(yytname[x]) + 15, count++; - msg = (char *) malloc(size + 15); - if (msg != 0) + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("syntax error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) { - strcpy(msg, "parse error"); + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); - if (count < 5) + if (yycount < 5) { - count = 0; - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - strcat(msg, count == 0 ? ", expecting `" : " or `"); - strcat(msg, yytname[x]); - strcat(msg, "'"); - count++; + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; } } - yyerror(msg); - free(msg); + yyerror (yymsg); + YYSTACK_FREE (yymsg); } else - yyerror ("parse error; also virtual memory exceeded"); + yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ - yyerror("parse error"); + yyerror ("syntax error"); } - goto yyerrlab1; -yyerrlab1: /* here on error raised explicitly by an action */ + if (yyerrstatus == 3) { - /* if just tried and failed to reuse lookahead token after an error, discard it. */ + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ - /* return failure if at end of input */ + /* Return failure if at end of input. */ if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyss < yyssp) + { + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; + + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab2; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + + /* Suppress GCC warning that yyerrlab1 is unused when no action + invokes YYERROR. */ +#if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__) + /* but it's harmful in C++ code + * (gcc 3.2.1 complained about erroneous yylerrsp declaration) */ +# ifndef __cplusplus + __attribute__ ((__unused__)) +# endif +#endif + + + goto yyerrlab2; + + +/*---------------------------------------------------------------. +| yyerrlab2 -- pop states until the error token can be shifted. | +`---------------------------------------------------------------*/ +yyerrlab2: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) YYABORT; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); -#endif + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + yyvsp--; + yystate = *--yyssp; - yychar = YYEMPTY; + YY_STACK_PRINT (yyss, yyssp); } - /* Else will try to reuse lookahead token - after shifting the error token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ - - goto yyerrhandle; - -yyerrdefault: /* current state does not do anything special for the error token. */ - -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ - if (yyn) goto yydefault; -#endif - -yyerrpop: /* pop the current state because it cannot handle the error token */ - - if (yyssp == yyss) YYABORT; - yyvsp--; - yystate = *--yyssp; -#ifdef YYLSP_NEEDED - yylsp--; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "Error: state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - -yyerrhandle: - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; - - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; - - yyn = yytable[yyn]; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrpop; - if (yyn == YYFINAL) YYACCEPT; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting error token, "); -#endif + YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif + yystate = yyn; goto yynewstate; - yyacceptlab: - /* YYACCEPT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 0; - yyabortlab: - /* YYABORT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ #endif - } - return 1; + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; } + + #line 209 "plural.y" @@ -1298,3 +1601,4 @@ yyerror(const unsigned char *str) { /* Do nothing. We don't print error messages here. */ } + From e301f0c4ab5014c5cb90cb9ad30ae57af65aabd8 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Wed, 26 Jul 2006 21:31:01 +0200 Subject: [PATCH 70/73] Alignment of --with-gc --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 480a0180..cb2cd8e1 100644 --- a/configure.in +++ b/configure.in @@ -448,7 +448,7 @@ EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_IDN, idn, idna.h, idn, stringprep_check_versio if test "x{with_gc}" != xno; then EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GC, gc, gc.h, gc, GC_init, - [ --with-gc enable Boehm's garbage collector]) + [ --with-gc enable Boehm's garbage collector]) fi EL_ARG_ENABLE(CONFIG_LZMA, lzma, [lzma], From 3ff8422e76cc13538ba296b382631bc2de434316 Mon Sep 17 00:00:00 2001 From: Miciah Dashiel Butler Masters Date: Wed, 26 Jul 2006 21:28:40 +0000 Subject: [PATCH 71/73] Fix a crash with the download manager when CONFIG_UTF_8 is enabled In draw_file_download, pass get_file_download_text the terminal pointer instead of NULL. --- src/dialogs/download.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialogs/download.c b/src/dialogs/download.c index 1741e5e3..2eaefc78 100644 --- a/src/dialogs/download.c +++ b/src/dialogs/download.c @@ -381,7 +381,7 @@ draw_file_download(struct listbox_item *item, struct listbox_context *context, color = get_bfu_color(context->term, stylename); - text = get_file_download_text(item, NULL); + text = get_file_download_text(item, context->term); if (!text) return; length = strlen(text); From a897a957215fb7ec8ee66e9f17c7f9dc7b656c0d Mon Sep 17 00:00:00 2001 From: Laurent MONIN Date: Thu, 27 Jul 2006 09:49:49 +0200 Subject: [PATCH 72/73] Compilation fixes (CONFIG_UTF_8): move variables declarations at start of blocks. Old compilers do not support in-block declarations. --- src/bfu/menu.c | 5 ++++- src/terminal/draw.c | 10 ++++++---- src/viewer/text/textarea.c | 26 +++++++++++++++++--------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/bfu/menu.c b/src/bfu/menu.c index bb0b85fa..0b73fbc9 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -410,6 +410,9 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, int xbase = x + L_TEXT_SPACE; int w = width - (L_TEXT_SPACE + R_TEXT_SPACE); int hk_state = 0; +#ifdef CONFIG_UTF_8 + unsigned char *text2, *end; +#endif #ifdef CONFIG_DEBUG /* For redundant hotkeys highlighting. */ @@ -450,8 +453,8 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text, } } return; + #ifdef CONFIG_UTF_8 - unsigned char *text2, *end; utf8: end = strchr(text, '\0'); text2 = text; diff --git a/src/terminal/draw.c b/src/terminal/draw.c index 000a9c23..1e31b442 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -150,9 +150,10 @@ draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line) struct screen_char *sc; if (line->data == UCS_NO_CHAR && x == 0) { - sc = line; - unicode_val_T data_save = sc->data; + unicode_val_T data_save; + sc = line; + data_save = sc->data; sc->data = ' '; copy_screen_chars(screen_char, line, 1); sc->data = data_save; @@ -164,9 +165,10 @@ draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line) /* Instead of displaying double-width character at last column * display only space. */ if (size - 1 > 0 && unicode_to_cell(line[size - 1].data) == 2) { + unicode_val_T data_save; + sc = &line[size - 1]; - unicode_val_T data_save = sc->data; - + data_save = sc->data; sc->data = ' '; copy_screen_chars(screen_char, line, size); sc->data = data_save; diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index cea578de..b3096267 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -785,6 +785,8 @@ do_op_home(struct form_state *fs, struct line_info *line, int current) static int do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) { + int old_state; + if (current == -1) return 0; if (!(current - !!fs->state_cell)) return 1; @@ -795,7 +797,7 @@ do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) return 0; } - int old_state = fs->state; + old_state = fs->state; if (fs->state_cell) { int len = utf8_ptr2cells(fs->value + line[current - 1].start, fs->value + fs->state_cell); @@ -839,6 +841,8 @@ do_op_up(struct form_state *fs, struct line_info *line, int current) static int do_op_down(struct form_state *fs, struct line_info *line, int current, int utf8) { + int old_state; + if (current == -1) return 0; if (line[current + 1 - !!fs->state_cell].start == -1) return 1; @@ -849,7 +853,7 @@ do_op_down(struct form_state *fs, struct line_info *line, int current, int utf8) return 0; } - int old_state = fs->state; + old_state = fs->state; if (fs->state_cell) { int len = utf8_ptr2cells(fs->value + line[current - 1].start, fs->value + fs->state_cell); @@ -1083,6 +1087,10 @@ textarea_op_enter(struct form_state *fs, struct form_control *fc) static int do_op_left(struct form_state *fs, struct line_info *line, int current, int utf8) { + int old_state; + int new_state; + unsigned char *new_value; + if (!utf8) { fs->state = int_max(fs->state - 1, 0); return 0; @@ -1094,10 +1102,7 @@ do_op_left(struct form_state *fs, struct line_info *line, int current, int utf8) return 0; } - int old_state = fs->state; - int new_state; - unsigned char *new_value; - + old_state = fs->state; new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); new_state = new_value - fs->value; @@ -1113,6 +1118,9 @@ do_op_left(struct form_state *fs, struct line_info *line, int current, int utf8) static int do_op_right(struct form_state *fs, struct line_info *line, int current, int utf8) { + unsigned char *text, *end; + int old_state; + if (!utf8) { /* TODO: zle */ fs->state = int_min(fs->state + 1, strlen(fs->value)); @@ -1124,9 +1132,9 @@ do_op_right(struct form_state *fs, struct line_info *line, int current, int utf8 return 0; } - unsigned char *text = fs->value + fs->state; - unsigned char *end = strchr(text, '\0'); - int old_state = fs->state; + text = fs->value + fs->state; + end = strchr(text, '\0'); + old_state = fs->state; utf_8_to_unicode(&text, end); fs->state = text - fs->value; From 1136aefb71081811934d4c5080badb322561af95 Mon Sep 17 00:00:00 2001 From: Laurent MONIN Date: Thu, 27 Jul 2006 09:51:10 +0200 Subject: [PATCH 73/73] Trim trailing whitespaces. --- src/bfu/button.c | 32 ++++++++++++++++---------------- src/bfu/dialog.c | 2 +- src/bfu/group.c | 6 +++--- src/bfu/inpfield.c | 12 ++++++------ src/bfu/menu.c | 12 ++++++------ src/bfu/text.c | 6 +++--- src/bookmarks/dialogs.c | 2 +- src/config/options.c | 2 +- src/dialogs/status.c | 4 ++-- src/document/html/renderer.c | 2 +- src/document/plain/renderer.c | 6 +++--- src/intl/charsets.c | 12 ++++++------ src/intl/gettext/plural.c | 6 +++--- src/protocol/gopher/gopher.c | 2 +- src/terminal/draw.c | 12 ++++++------ src/terminal/draw.h | 2 +- src/terminal/screen.c | 2 +- src/viewer/text/form.c | 8 ++++---- src/viewer/text/textarea.c | 4 ++-- 19 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/bfu/button.c b/src/bfu/button.c index 5cb7ba02..327c73fa 100644 --- a/src/bfu/button.c +++ b/src/bfu/button.c @@ -89,7 +89,7 @@ buttons_width(struct widget_data *widget_data, int n, { int maxw = -BUTTON_HSPACING; #ifdef CONFIG_UTF_8 - int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + utf8_ptr2cells(BUTTON_RIGHT, NULL); #endif /* CONFIG_UTF_8 */ @@ -150,7 +150,7 @@ dlg_format_buttons(struct terminal *term, int i; int p = x + (align == ALIGN_CENTER ? (w - mw) / 2 : 0); #ifdef CONFIG_UTF_8 - int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + int button_lr_len = utf8_ptr2cells(BUTTON_LEFT, NULL) + utf8_ptr2cells(BUTTON_RIGHT, NULL); #endif /* CONFIG_UTF_8 */ @@ -201,9 +201,9 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) int button_right_len = utf8_ptr2cells(BUTTON_RIGHT, NULL); x = pos->x + button_left_len; - len = widget_data->box.width - + len = widget_data->box.width - (button_left_len + button_right_len); - + } else #endif /* CONFIG_UTF_8 */ { @@ -227,38 +227,38 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) int hk_bytes = utf8charlen(&text[hk_pos+1]); int cells_to_hk = utf8_ptr2cells(text, &text[hk_pos]); - int right = widget_data->widget->info.button.truetextlen - - hk_pos + int right = widget_data->widget->info.button.truetextlen + - hk_pos - hk_bytes; - int hk_cells = utf8_char2cells(&text[hk_pos + int hk_cells = utf8_char2cells(&text[hk_pos + 1], NULL); if (hk_pos) - draw_text(term, x, pos->y, + draw_text(term, x, pos->y, text, hk_pos, 0, color); draw_text(term, x + cells_to_hk, pos->y, - &text[hk_pos + 1], hk_bytes, + &text[hk_pos + 1], hk_bytes, attr, shortcut_color); if (right > 1) - draw_text(term, x+cells_to_hk+hk_cells, - pos->y, + draw_text(term, x+cells_to_hk+hk_cells, + pos->y, &text[hk_pos + hk_bytes + 1], right - 1, 0, color); } else { int hk_width = utf8_char2cells(text, NULL); int hk_len = utf8charlen(text); - int len_to_display = - utf8_cells2bytes(&text[hk_len], + int len_to_display = + utf8_cells2bytes(&text[hk_len], len - hk_width, NULL); - draw_text(term, x, pos->y, - text, hk_len, + draw_text(term, x, pos->y, + text, hk_len, attr, shortcut_color); draw_text(term, x + hk_width, pos->y, @@ -290,7 +290,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) int text_cells = utf8_ptr2cells(widget_data->widget->text, NULL); int hk = (widget_data->widget->info.button.hotkey_pos >= 0); - draw_text(term, x + text_cells - hk, pos->y, + draw_text(term, x + text_cells - hk, pos->y, BUTTON_RIGHT, BUTTON_RIGHT_LEN, 0, color); } else #endif /* CONFIG_UTF_8 */ diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index 0d720132..289f4b66 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -103,7 +103,7 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) #ifdef CONFIG_UTF_8 if (term->utf8) - titlecells = utf8_ptr2cells(title, + titlecells = utf8_ptr2cells(title, &title[titlelen]); #endif /* CONFIG_UTF_8 */ diff --git a/src/bfu/group.c b/src/bfu/group.c index 75f40487..38673867 100644 --- a/src/bfu/group.c +++ b/src/bfu/group.c @@ -113,13 +113,13 @@ dlg_format_group(struct terminal *term, text, label_length, NULL); - draw_text(term, xpos, *y, + draw_text(term, xpos, *y, text, lb, 0, color); } else #endif /* CONFIG_UTF_8 */ { - draw_text(term, xpos, *y, - text, label_length, + draw_text(term, xpos, *y, + text, label_length, 0, color); } } diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c index 23539da5..ff7c9c1e 100644 --- a/src/bfu/inpfield.c +++ b/src/bfu/inpfield.c @@ -279,8 +279,8 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, int_bounds(&left, len - widget_data->box.width + 1, len); int_lower_bound(&left, 0); widget_data->info.field.vpos = utf8_cells2bytes(t, left, NULL); - } else -#endif /* CONFIG_UTF_8 */ + } else +#endif /* CONFIG_UTF_8 */ { int_bounds(&widget_data->info.field.vpos, widget_data->info.field.cpos - widget_data->box.width + 1, @@ -330,7 +330,7 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, #ifdef CONFIG_UTF_8 if (term->utf8) x = widget_data->box.x + len - left; - else + else #endif /* CONFIG_UTF_8 */ x = widget_data->box.x + widget_data->info.field.cpos - widget_data->info.field.vpos; @@ -477,7 +477,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) if (term->utf8) { unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; unsigned char *end = strchr(next, '\0'); - + utf_8_to_unicode(&next, end); widget_data->info.field.cpos = (int)(next - widget_data->cdata); } else @@ -502,7 +502,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) strlen_utf8(&t2); t[p] = tmp; widget_data->info.field.cpos = (int)(t2 - t); - + } #endif /* CONFIG_UTF_8 */ goto display_field; @@ -696,7 +696,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data) unsigned char *t = buf; static int i = 0; unicode_val_T data; - + buf[i++] = *text; buf[i] = '\0'; data = utf_8_to_unicode(&t, buf + i); diff --git a/src/bfu/menu.c b/src/bfu/menu.c index 0b73fbc9..c80bf4c5 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -202,11 +202,11 @@ get_menuitem_text_width(struct terminal *term, struct menu_item *mi) #ifdef CONFIG_UTF_8 if (term->utf8) - return L_TEXT_SPACE + utf8_ptr2cells(text, NULL) + return L_TEXT_SPACE + utf8_ptr2cells(text, NULL) - !!mi->hotkey_pos + R_TEXT_SPACE; else #endif /* CONFIG_UTF_8 */ - return L_TEXT_SPACE + strlen(text) + return L_TEXT_SPACE + strlen(text) - !!mi->hotkey_pos + R_TEXT_SPACE; } @@ -385,7 +385,7 @@ draw_menu_left_text(struct terminal *term, unsigned char *text, int len, #ifdef CONFIG_UTF_8 if (term->utf8) { max_len = utf8_cells2bytes(text, w, NULL); - if (max_len <= 0) + if (max_len <= 0) return; } else #endif /* CONFIG_UTF_8 */ @@ -479,10 +479,10 @@ utf8: data, hk_attr, hk_color); #endif /* CONFIG_DEBUG */ x++; - draw_char(term, xbase + x - 1, y, + draw_char(term, xbase + x - 1, y, UCS_NO_CHAR, 0, hk_color); } else { - draw_char(term, xbase + x - 1, y, + draw_char(term, xbase + x - 1, y, ' ', 0, hk_color); } } else { @@ -1165,7 +1165,7 @@ display_mainmenu(struct terminal *term, struct menu *menu) if (menu->last < menu->size - 1) { #ifdef CONFIG_UTF_8 if (term->utf8) { - struct screen_char *schar; + struct screen_char *schar; schar = get_char(term, term->width - R_MAINMENU_SPACE, 0); /* Is second cell of double-width char on the place where diff --git a/src/bfu/text.c b/src/bfu/text.c index 19704052..9156e557 100644 --- a/src/bfu/text.c +++ b/src/bfu/text.c @@ -54,7 +54,7 @@ split_line(unsigned char *text, int max_width, int *cells) #ifdef CONFIG_UTF_8 if (utf8) { - unsigned char *next_char_begin = split + unsigned char *next_char_begin = split + utf8charlen(split); next_split = split; @@ -64,7 +64,7 @@ split_line(unsigned char *text, int max_width, int *cells) next_split++; next_char_begin = next_split; - while (is_unsplitable(next_split)) + while (is_unsplitable(next_split)) { if (next_split < next_char_begin) { next_split++; @@ -207,7 +207,7 @@ split_lines(struct widget_data *widget_data, int max_width) void dlg_format_text_do(struct terminal *term, unsigned char *text, int x, int *y, int width, int *real_width, - struct color_pair *color, enum format_align align, + struct color_pair *color, enum format_align align, int format_only) { int line_width; diff --git a/src/bookmarks/dialogs.c b/src/bookmarks/dialogs.c index f69bc395..ed17ecc7 100644 --- a/src/bookmarks/dialogs.c +++ b/src/bookmarks/dialogs.c @@ -377,7 +377,7 @@ do_move_bookmark(struct bookmark *dest, int insert_as_child, if (box2->top == bm->box_item) listbox_sel_move(widget_data, 1); } - + del_from_list(bm->box_item); del_from_list(bm); if (insert_as_child) { diff --git a/src/config/options.c b/src/config/options.c index 961dd661..d9854986 100644 --- a/src/config/options.c +++ b/src/config/options.c @@ -516,7 +516,7 @@ add_opt(struct option *tree, unsigned char *path, unsigned char *capt, return NULL; } } - + add_opt_rec(tree, path, option); return option; } diff --git a/src/dialogs/status.c b/src/dialogs/status.c index e9ecb6c7..9dff84a5 100644 --- a/src/dialogs/status.c +++ b/src/dialogs/status.c @@ -446,8 +446,8 @@ display_title_bar(struct session *ses, struct terminal *term) int x; #ifdef CONFIG_UTF_8 if (term->utf8) { - x = int_max(term->width - 1 - - utf8_ptr2cells(title.source, + x = int_max(term->width - 1 + - utf8_ptr2cells(title.source, title.source + title.length), 0); } else diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c index 20310b27..99d06a60 100644 --- a/src/document/html/renderer.c +++ b/src/document/html/renderer.c @@ -1552,7 +1552,7 @@ put_chars(struct html_context *html_context, unsigned char *chars, int charslen) put_link_number(html_context); } #ifdef CONFIG_UTF_8 - cells = + cells = #endif /* CONFIG_UTF_8 */ set_hline(html_context, chars, charslen, link_state); diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index 5d3adf6d..301f2796 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -325,13 +325,13 @@ add_document_line(struct plain_renderer *renderer, line_pos += charlen; continue; } - + cell = unicode_to_cell(data); } #endif /* CONFIG_UTF_8 */ prev_char = line_pos > 0 ? line[line_pos - 1] : '\0'; - next_char = (line_pos + charlen < width) ? + next_char = (line_pos + charlen < width) ? line[line_pos + charlen] : '\0'; /* Do not expand tabs that precede back-spaces; this saves the @@ -531,7 +531,7 @@ add_document_lines(struct plain_renderer *renderer) int cells = 0; /* End of line detection: We handle \r, \r\n and \n types. */ - for (width = 0; (width < length) && + for (width = 0; (width < length) && (cells < renderer->max_width);) { if (source[width] == ASCII_CR) step++; diff --git a/src/intl/charsets.c b/src/intl/charsets.c index dd7b382f..dd0ee5b5 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -298,7 +298,7 @@ utf8_ptr2cells(unsigned char *string, unsigned char *end) do { charlen = utf8charlen(string); - if (string + charlen > end) + if (string + charlen > end) break; cell = utf8_char2cells(string, end); @@ -326,7 +326,7 @@ utf8_ptr2chars(unsigned char *string, unsigned char *end) do { charlen = utf8charlen(string); - if (string + charlen > end) + if (string + charlen > end) break; chars++; @@ -373,7 +373,7 @@ utf8_cells2bytes(unsigned char *string, int max_cells, unsigned char *end) return bytes; } -/* +/* * Find out number of standard terminal collumns needed for displaying symbol * (glyph) which represents Unicode character c. * TODO: Use wcwidth when it is available. @@ -401,7 +401,7 @@ unicode_to_cell(unicode_val_T c) || (c >= 0x30000 && c <= 0x3fffd))) return 2; - return 1; + return 1; } inline unicode_val_T @@ -415,7 +415,7 @@ utf_8_to_unicode(unsigned char **string, unsigned char *end) if (str + length > end) { return UCS_NO_CHAR; - } + } switch (length) { case 1: @@ -443,7 +443,7 @@ utf_8_to_unicode(unsigned char **string, unsigned char *end) u += ((str[3] & 0x3f) << 6); u += (str[4] & 0x3f); break; - case 6: + case 6: default: u = (str[0] & 0x01) << 30; u += ((str[1] & 0x3f) << 24); diff --git a/src/intl/gettext/plural.c b/src/intl/gettext/plural.c index 19ce43df..62819f34 100644 --- a/src/intl/gettext/plural.c +++ b/src/intl/gettext/plural.c @@ -418,8 +418,8 @@ static const unsigned char yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2", - "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'", + "$end", "error", "$undefined", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2", + "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'", "$accept", "start", "exp", 0 }; #endif @@ -1336,7 +1336,7 @@ yyerrlab1: /* Suppress GCC warning that yyerrlab1 is unused when no action invokes YYERROR. */ #if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__) - /* but it's harmful in C++ code + /* but it's harmful in C++ code * (gcc 3.2.1 complained about erroneous yylerrsp declaration) */ # ifndef __cplusplus __attribute__ ((__unused__)) diff --git a/src/protocol/gopher/gopher.c b/src/protocol/gopher/gopher.c index 12b779e6..6df9968a 100644 --- a/src/protocol/gopher/gopher.c +++ b/src/protocol/gopher/gopher.c @@ -650,7 +650,7 @@ init_gopher_index_cache_entry(struct connection *conn) where = get_uri_string(conn->uri, URI_PUBLIC); - /* TODO: Use different function when using UTF-8 + /* TODO: Use different function when using UTF-8 * in terminal (decode_uri_for_display replaces * bytes of UTF-8 characters width '*'). */ if (where) decode_uri_for_display(where); diff --git a/src/terminal/draw.c b/src/terminal/draw.c index 1e31b442..774f166e 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -107,14 +107,14 @@ void draw_char_data(struct terminal *term, int x, int y, unicode_val_T data) #else draw_char_data(struct terminal *term, int x, int y, unsigned char data) -#endif /* CONFIG_UTF_8 */ +#endif /* CONFIG_UTF_8 */ { struct screen_char *screen_char = get_char(term, x, y); if (!screen_char) return; screen_char->data = data; - + #ifdef CONFIG_UTF_8 #ifdef CONFIG_DEBUG /* Detect attempt to draw double-width char on the last @@ -125,7 +125,7 @@ draw_char_data(struct terminal *term, int x, int y, unsigned char data) if (data == UCS_NO_CHAR) screen_char->attr = 0; -#endif /* CONFIG_UTF_8 */ +#endif /* CONFIG_UTF_8 */ set_screen_dirty(term->screen, y, y); } @@ -166,7 +166,7 @@ draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line) * display only space. */ if (size - 1 > 0 && unicode_to_cell(line[size - 1].data) == 2) { unicode_val_T data_save; - + sc = &line[size - 1]; data_save = sc->data; sc->data = ' '; @@ -263,7 +263,7 @@ void fix_dwchar_around_box(struct terminal *term, struct box *box, int border, int shadow_width, int shadow_height) { - struct screen_char *schar; + struct screen_char *schar; int height, x, y; if (!term->utf8) @@ -475,7 +475,7 @@ draw_text_utf8(struct terminal *term, int x, int y, } } set_screen_dirty(term->screen, y, y); - + } #endif /* CONFIG_UTF_8 */ diff --git a/src/terminal/draw.h b/src/terminal/draw.h index 2598cd90..fcb6be18 100644 --- a/src/terminal/draw.h +++ b/src/terminal/draw.h @@ -25,7 +25,7 @@ struct screen_char { unicode_val_T data; #else unsigned char data; -#endif /* CONFIG_UTF_8 */ +#endif /* CONFIG_UTF_8 */ /* Attributes are screen_char_attr bits. */ unsigned char attr; diff --git a/src/terminal/screen.c b/src/terminal/screen.c index dd9be931..47487c0e 100644 --- a/src/terminal/screen.c +++ b/src/terminal/screen.c @@ -464,7 +464,7 @@ add_char_data(struct string *screen, struct screen_driver *driver, #ifdef CONFIG_UTF_8 if (border) add_char_to_string(screen, (unsigned char)data); - else + else if (data != UCS_NO_CHAR) add_to_string(screen, encode_utf_8(data)); #else diff --git a/src/viewer/text/form.c b/src/viewer/text/form.c index 40cb5bd2..29b981bc 100644 --- a/src/viewer/text/form.c +++ b/src/viewer/text/form.c @@ -387,7 +387,7 @@ utf_8: len = utf8_ptr2cells(fs->value + fs->vpos, NULL); text = fs->value; end = strchr(text, '\0'); - + for (i = 0; i < fc->size; i++, x++) { unicode_val_T data; @@ -1312,7 +1312,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8) { int old_state = fs->state; unsigned char *new_value; - + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); fs->state = new_value - fs->value; @@ -1522,7 +1522,7 @@ field_op(struct session *ses, struct document_view *doc_view, if (utf8) { int old_state = fs->state; unsigned char *new_value; - + new_value = utf8_prevchar(fs->value + fs->state, 1, fs->value); fs->state = new_value - fs->value; @@ -1666,7 +1666,7 @@ field_op(struct session *ses, struct document_view *doc_view, while (fs->state > 0 && isspace(fs->value[fs->state - 1])) --fs->state; - while (fs->state > 0 + while (fs->state > 0 && !isspace(fs->value[fs->state - 1])) --fs->state; break; diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index b3096267..944c257f 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -117,7 +117,7 @@ format_textutf8(unsigned char *text, int width, enum form_wrap wrap, int format) begin = pos += skip; chars_cells = 0; - wrappos = NULL; + wrappos = NULL; } line[line_number].split_next = 0; @@ -786,7 +786,7 @@ static int do_op_up(struct form_state *fs, struct line_info *line, int current, int utf8) { int old_state; - + if (current == -1) return 0; if (!(current - !!fs->state_cell)) return 1;