int strlen_big5(const unsigned char *str) { int len=0; while (*str != '\0') { if (is_big5(str[0], str[1])) str++; len++; str++; } return len; }
void big5_to_unichars(const char *str, unichar *out) { const unsigned char *p = (const unsigned char *) str; while (*p != '\0') { if (is_big5(p[0], p[1])) { *out++ = p[0] << 8 | p[1]; p += 2; } else { *out++ = *p++; } } *out = '\0'; }
static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, int subline, int ypos, int max) { INDENT_FUNC indent_func; LINE_CACHE_REC *cache; const unsigned char *text, *end, *text_newline; unsigned char *tmp; int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width; if (view->dirty) /* don't bother drawing anything - redraw is coming */ return 0; cache = textbuffer_view_get_line_cache(view, line); if (subline >= cache->count) return 0; color = ATTR_RESET; need_move = TRUE; need_clrtoeol = FALSE; xpos = drawcount = 0; first = TRUE; text_newline = text = subline == 0 ? line->text : cache->lines[subline-1].start; for (;;) { if (text == text_newline) { if (need_clrtoeol && xpos < term_width) { term_set_color(view->window, ATTR_RESET); term_clrtoeol(view->window); } if (first) first = FALSE; else { ypos++; if (--max == 0) break; } if (subline > 0) { /* continuing previous line - indent it */ indent_func = cache->lines[subline-1].indent_func; if (indent_func == NULL) xpos = cache->lines[subline-1].indent; color = cache->lines[subline-1].color; } else { indent_func = NULL; } if (xpos == 0 && indent_func == NULL) need_clrtoeol = TRUE; else { /* line was indented - need to clear the indented area first */ term_set_color(view->window, ATTR_RESET); term_move(view->window, 0, ypos); term_clrtoeol(view->window); if (indent_func != NULL) xpos = indent_func(view, line, ypos); } if (need_move || xpos > 0) term_move(view->window, xpos, ypos); term_set_color(view->window, color); if (subline == cache->count-1) { text_newline = NULL; need_move = FALSE; } else { /* get the beginning of the next subline */ text_newline = cache->lines[subline].start; need_move = !cache->lines[subline].continues; } drawcount++; subline++; } if (*text == '\0') { /* command */ text++; if (*text == LINE_CMD_EOL || *text == LINE_CMD_FORMAT) break; if (*text == LINE_CMD_CONTINUE) { /* jump to next block */ memcpy(&tmp, text+1, sizeof(unsigned char *)); text = tmp; continue; } else if (*text == LINE_CMD_INDENT_FUNC) { text += sizeof(INDENT_FUNC); } else { update_cmd_color(*text, &color); term_set_color(view->window, color); } text++; continue; } end = text; if (view->utf8) { unichar chr; if (get_utf8_char(&end, 6, &chr)<0) char_width = 1; else char_width = utf8_width(chr); } else { if (term_type == TERM_TYPE_BIG5 && is_big5(end[0], end[1])) char_width = 2; else char_width = 1; end += char_width-1; } xpos += char_width; if (xpos <= term_width) { if (*text >= 32 && (end != text || (*text & 127) >= 32)) { for (; text < end; text++) term_addch(view->window, *text); term_addch(view->window, *text); } else { /* low-ascii */ term_set_color(view->window, ATTR_RESET|ATTR_REVERSE); term_addch(view->window, (*text & 127)+'A'-1); term_set_color(view->window, color); } } text++; } if (need_clrtoeol && xpos < term_width) { term_set_color(view->window, ATTR_RESET); term_clrtoeol(view->window); } return drawcount; }
static LINE_CACHE_REC * view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) { INDENT_FUNC indent_func; LINE_CACHE_REC *rec; LINE_CACHE_SUB_REC *sub; GSList *lines; unsigned char cmd; const unsigned char *ptr, *next_ptr, *last_space_ptr; int xpos, pos, indent_pos, last_space, last_color, color, linecount; int char_len; unichar chr; g_return_val_if_fail(line->text != NULL, NULL); color = ATTR_RESETFG | ATTR_RESETBG; xpos = 0; indent_pos = view->default_indent; last_space = last_color = 0; last_space_ptr = NULL; sub = NULL; indent_func = view->default_indent_func; linecount = 1; lines = NULL; for (ptr = line->text;;) { if (*ptr == '\0') { /* command */ ptr++; cmd = *ptr; ptr++; if (cmd == LINE_CMD_EOL || cmd == LINE_CMD_FORMAT) break; if (cmd == LINE_CMD_CONTINUE) { unsigned char *tmp; memcpy(&tmp, ptr, sizeof(char *)); ptr = tmp; continue; } if (cmd == LINE_CMD_INDENT) { /* set indentation position here - don't do it if we're too close to right border */ if (xpos < view->width-5) indent_pos = xpos; } else if (cmd == LINE_CMD_INDENT_FUNC) { memcpy(&indent_func, ptr, sizeof(INDENT_FUNC)); ptr += sizeof(INDENT_FUNC); if (indent_func == NULL) indent_func = view->default_indent_func; } else update_cmd_color(cmd, &color); continue; } if (!view->utf8) { /* MH */ if (term_type != TERM_TYPE_BIG5 || ptr[1] == '\0' || !is_big5(ptr[0], ptr[1])) char_len = 1; else char_len = 2; next_ptr = ptr+char_len; } else { char_len = 1; while (ptr[char_len] != '\0' && char_len < 6) char_len++; next_ptr = ptr; if (get_utf8_char(&next_ptr, char_len, &chr) < 0) char_len = 1; else char_len = utf8_width(chr); next_ptr++; } if (xpos + char_len > view->width && sub != NULL && (last_space <= indent_pos || last_space <= 10) && view->longword_noindent) { /* long word, remove the indentation from this line */ xpos -= sub->indent; sub->indent = 0; } if (xpos + char_len > view->width) { xpos = indent_func == NULL ? indent_pos : indent_func(view, line, -1); sub = g_new0(LINE_CACHE_SUB_REC, 1); if (last_space > indent_pos && last_space > 10) { /* go back to last space */ color = last_color; ptr = last_space_ptr; while (*ptr == ' ') ptr++; } else if (view->longword_noindent) { /* long word, no indentation in next line */ xpos = 0; sub->continues = TRUE; } sub->start = ptr; sub->indent = xpos; sub->indent_func = indent_func; sub->color = color; lines = g_slist_append(lines, sub); linecount++; last_space = 0; continue; } if (!view->utf8 && char_len > 1) { last_space = xpos; last_space_ptr = next_ptr; last_color = color; } else if (*ptr == ' ') { last_space = xpos; last_space_ptr = ptr; last_color = color; } xpos += char_len; ptr = next_ptr; } rec = g_malloc(sizeof(LINE_CACHE_REC)-sizeof(LINE_CACHE_SUB_REC) + sizeof(LINE_CACHE_SUB_REC) * (linecount-1)); rec->last_access = time(NULL); rec->count = linecount; if (rec->count > 1) { for (pos = 0; lines != NULL; pos++) { void *data = lines->data; memcpy(&rec->lines[pos], data, sizeof(LINE_CACHE_SUB_REC)); lines = g_slist_remove(lines, data); g_free(data); } } g_hash_table_insert(view->cache->line_cache, line, rec); return rec; }
static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, int subline, int ypos, int max) { INDENT_FUNC indent_func; LINE_CACHE_REC *cache; const unsigned char *text, *end, *text_newline; unsigned char *tmp; unichar chr; int xpos, color, fg24, bg24, drawcount, first, need_move, need_clrtoeol, char_width; if (view->dirty) /* don't bother drawing anything - redraw is coming */ return 0; cache = textbuffer_view_get_line_cache(view, line); if (subline >= cache->count) return 0; color = ATTR_RESET; need_move = TRUE; need_clrtoeol = FALSE; xpos = drawcount = 0; first = TRUE; text_newline = text = subline == 0 ? line->text : cache->lines[subline-1].start; for (;;) { if (text == text_newline) { if (need_clrtoeol && xpos < term_width) { term_set_color(view->window, ATTR_RESET); term_clrtoeol(view->window); } if (first) first = FALSE; else { ypos++; if (--max == 0) break; } if (subline > 0) { /* continuing previous line - indent it */ indent_func = cache->lines[subline-1].indent_func; if (indent_func == NULL) xpos = cache->lines[subline-1].indent; color = cache->lines[subline-1].color; #ifdef TERM_TRUECOLOR fg24 = cache->lines[subline-1].fg24; bg24 = cache->lines[subline-1].bg24; #endif } else { indent_func = NULL; } if (xpos == 0 && indent_func == NULL) need_clrtoeol = TRUE; else { /* line was indented - need to clear the indented area first */ term_set_color(view->window, ATTR_RESET); term_move(view->window, 0, ypos); term_clrtoeol(view->window); if (indent_func != NULL) xpos = indent_func(view, line, ypos); } if (need_move || xpos > 0) term_move(view->window, xpos, ypos); term_set_color2(view->window, color, fg24, bg24); if (subline == cache->count-1) { text_newline = NULL; need_move = FALSE; } else { /* get the beginning of the next subline */ text_newline = cache->lines[subline].start; need_move = !cache->lines[subline].continues; } drawcount++; subline++; } if (*text == '\0') { /* command */ text++; if (*text == LINE_CMD_EOL) break; if (*text == LINE_CMD_CONTINUE) { /* jump to next block */ memcpy(&tmp, text+1, sizeof(unsigned char *)); text = tmp; continue; } else { if (*text == LINE_COLOR_EXT) color = (color & BGATTR & ~ATTR_FGCOLOR24) | *++text; else if (*text == LINE_COLOR_EXT_BG) color = (color & FGATTR & ~ATTR_BGCOLOR24) | (*++text << BG_SHIFT); #ifdef TERM_TRUECOLOR else if (*text == LINE_COLOR_24) unformat_24bit_line_color(&text, 1, &color, &fg24, &bg24); #endif else update_cmd_color(*text, &color); term_set_color2(view->window, color, fg24, bg24); } text++; continue; } if (view->utf8) { chr = read_unichar(text, &end, &char_width); } else { chr = *text; end = text; if (term_type == TERM_TYPE_BIG5 && is_big5(end[0], end[1])) char_width = 2; else char_width = 1; end += char_width; } xpos += char_width; if (xpos <= term_width) { if (unichar_isprint(chr)) { if (view->utf8) term_add_unichar(view->window, chr); else for (; text < end; text++) term_addch(view->window, *text); } else { /* low-ascii */ term_set_color(view->window, ATTR_RESET|ATTR_REVERSE); term_addch(view->window, (chr & 127)+'A'-1); term_set_color2(view->window, color, fg24, bg24); } } text = end; } if (need_clrtoeol && xpos < term_width) { term_set_color(view->window, ATTR_RESET); term_clrtoeol(view->window); } return drawcount; }
static LINE_CACHE_REC * view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) { INDENT_FUNC indent_func; LINE_CACHE_REC *rec; LINE_CACHE_SUB_REC *sub; GSList *lines; unsigned char cmd; const unsigned char *ptr, *next_ptr, *last_space_ptr; int xpos, pos, indent_pos, last_space, last_color, color, linecount; int last_bg24, last_fg24, bg24, fg24; int char_width; g_return_val_if_fail(line->text != NULL, NULL); color = ATTR_RESETFG | ATTR_RESETBG; xpos = 0; indent_pos = view->default_indent; last_space = last_color = 0; last_space_ptr = NULL; sub = NULL; indent_func = view->default_indent_func; linecount = 1; lines = NULL; for (ptr = line->text;;) { if (*ptr == '\0') { /* command */ ptr++; cmd = *ptr; ptr++; if (cmd == LINE_CMD_EOL) break; if (cmd == LINE_CMD_CONTINUE) { unsigned char *tmp; memcpy(&tmp, ptr, sizeof(char *)); ptr = tmp; continue; } if (cmd == LINE_CMD_INDENT) { /* set indentation position here - don't do it if we're too close to right border */ if (xpos < view->width-5) indent_pos = xpos; } else if (cmd == LINE_COLOR_EXT) { color &= ~ATTR_FGCOLOR24; color = (color & BGATTR) | *ptr++; } else if (cmd == LINE_COLOR_EXT_BG) { color &= ~ATTR_BGCOLOR24; color = (color & FGATTR) | (*ptr++ << BG_SHIFT); } #ifdef TERM_TRUECOLOR else if (cmd == LINE_COLOR_24) unformat_24bit_line_color(&ptr, 0, &color, &fg24, &bg24); #endif else update_cmd_color(cmd, &color); continue; } if (!view->utf8) { /* MH */ if (term_type != TERM_TYPE_BIG5 || ptr[1] == '\0' || !is_big5(ptr[0], ptr[1])) char_width = 1; else char_width = 2; next_ptr = ptr+char_width; } else { read_unichar(ptr, &next_ptr, &char_width); } if (xpos + char_width > view->width && sub != NULL && (last_space <= indent_pos || last_space <= 10) && view->longword_noindent) { /* long word, remove the indentation from this line */ xpos -= sub->indent; sub->indent = 0; } if (xpos + char_width > view->width) { xpos = indent_func == NULL ? indent_pos : indent_func(view, line, -1); sub = g_new0(LINE_CACHE_SUB_REC, 1); if (last_space > indent_pos && last_space > 10) { /* go back to last space */ color = last_color; fg24 = last_fg24; bg24 = last_bg24; ptr = last_space_ptr; while (*ptr == ' ') ptr++; } else if (view->longword_noindent) { /* long word, no indentation in next line */ xpos = 0; sub->continues = TRUE; } sub->start = ptr; sub->indent = xpos; sub->indent_func = indent_func; sub->color = color; #ifdef TERM_TRUECOLOR sub->fg24 = fg24; sub->bg24 = bg24; #endif lines = g_slist_append(lines, sub); linecount++; last_space = 0; continue; } if (!view->utf8 && char_width > 1) { last_space = xpos; last_space_ptr = next_ptr; last_color = color; last_fg24 = fg24; last_bg24 = bg24; } else if (*ptr == ' ') { last_space = xpos; last_space_ptr = ptr; last_color = color; last_fg24 = fg24; last_bg24 = bg24; } xpos += char_width; ptr = next_ptr; } rec = g_malloc(sizeof(LINE_CACHE_REC)-sizeof(LINE_CACHE_SUB_REC) + sizeof(LINE_CACHE_SUB_REC) * (linecount-1)); rec->last_access = time(NULL); rec->count = linecount; if (rec->count > 1) { for (pos = 0; lines != NULL; pos++) { void *data = lines->data; memcpy(&rec->lines[pos], data, sizeof(LINE_CACHE_SUB_REC)); lines = g_slist_remove(lines, data); g_free(data); } } g_hash_table_insert(view->cache->line_cache, line, rec); return rec; }