/** Checks cells left and right to the box for broken double-width chars. * Replace it with UCS_ORPHAN_CELL. * * @verbatim * 1+---+3 * 1|box|##4 * 1| |##4 * 1| |##4 * 1+---+##4 * 2#####4 * 1,2,3,4 - needs to be checked, # - shadow , +,-,| - border * @endverbatim */ 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_cp) 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 = UCS_ORPHAN_CELL; } /* 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 = UCS_ORPHAN_CELL; } /* 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 = UCS_ORPHAN_CELL; } /* 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 = UCS_ORPHAN_CELL; } }
draw_char_data(struct terminal *term, int x, int y, unsigned char data) #endif /* CONFIG_UTF8 */ { struct screen_char *screen_char = get_char(term, x, y); if (!screen_char) return; screen_char->data = data; #ifdef CONFIG_UTF8 #ifdef CONFIG_DEBUG /* Detect attempt to draw double-width char on the last * column of terminal. The unicode_to_cell(data) call is * in principle wrong if CONFIG_UTF8 is defined but the * charset of the terminal is not UTF-8, because @data * is then a byte in that charset; but unicode_to_cell * returns 1 for U+0000...U+00FF so it's not a problem. */ if (unicode_to_cell(data) == 2 && x + 1 > term->width) INTERNAL("Attempt to draw double-width glyph on last column!"); #endif /* CONFIG_DEBUG */ if (data == UCS_NO_CHAR) screen_char->attr = 0; #endif /* CONFIG_UTF8 */ set_screen_dirty(term->screen, y, y); }
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 cells = 0; while(cells < max_cells) { unicode_val_T data = utf8_to_unicode(&text, end); if (data == UCS_NO_CHAR) break; cells += unicode_to_cell(data); } fs->state = (int)(text - fs->value); }
/*! Used by viewer to copy over a document. * When doing frame drawing @a x can be different than 0. */ void draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line) { struct screen_char *screen_char = get_char(term, x, y); int size; assert(line); if_assert_failed return; if (!screen_char) return; size = int_min(l, term->width - x); if (size == 0) return; #ifdef CONFIG_UTF8 if (term->utf8_cp) { struct screen_char *sc; if (line[0].data == UCS_NO_CHAR && x == 0) { unicode_val_T data_save; sc = line; data_save = sc->data; sc->data = UCS_ORPHAN_CELL; copy_screen_chars(screen_char, line, 1); sc->data = data_save; size--; line++; screen_char++; } /* Instead of displaying double-width character at last column * display only UCS_ORPHAN_CELL. */ 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 = UCS_ORPHAN_CELL; 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); }
static void draw_text_utf8(struct terminal *term, int x, int y, const unsigned char *text, int length, int 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 = utf8_to_unicode(&text, end); if (data == UCS_NO_CHAR) return; start = get_char(term, x, y); if (color) { start->attr = attr; set_term_color(start, color, 0, get_opt_int_tree(term->spec, (const unsigned char *)"colors", NULL)); } if (start->data == UCS_NO_CHAR && x - 1 > 0) draw_char_data(term, x - 1, y, UCS_ORPHAN_CELL); 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++; pos->data = UCS_NO_CHAR; pos->attr = 0; } else { pos->data = UCS_ORPHAN_CELL; } } else { pos->data = data; } pos++; x++; for (; x < term->width; x++, pos++) { data = utf8_to_unicode(&text, end); if (data == UCS_NO_CHAR) break; if (color) copy_screen_chars(pos, start, 1); 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 = UCS_ORPHAN_CELL; } } else { pos->data = data; } } set_screen_dirty(term->screen, y, y); }
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; struct form_control *fc; struct box *box; int vx, vy; int sl, ye; int x, xbase, y; assert(term && doc_view && doc_view->document && doc_view->vs && link); if_assert_failed return; fc = get_link_form_control(link); assertm(fc != NULL, "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, 1); linex = format_textutf8(fs->value, fc->cols, fc->wrap, 0); if (!linex) return; line = linex; sl = fs->vypos; while (line->start != -1 && sl) sl--, line++; xbase = 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; text += utf8_cells2bytes(text, fs->vpos, end); if (!row_is_in_box(box, y)) continue; for (i = 0, x = xbase; i < fc->cols; i++, x++) { unicode_val_T data; if (i >= -fs->vpos && text < end) { /* utf8_to_unicode will increment text. */ data = utf8_to_unicode(&text, end); } else data = '_'; if (col_is_in_box(box, x)) { int cell = unicode_to_cell(data); if (cell == 2) { draw_char_data(term, x++, y, data); i++; data = UCS_NO_CHAR; } draw_char_data(term, x, y, data); } } } for (; y < ye; y++) { int i; if (!row_is_in_box(box, y)) continue; for (i = 0, x = xbase; i < fc->cols; i++, x++) { if (col_is_in_box(box, x)) draw_char_data(term, x, y, '_'); } } mem_free(linex); }