Пример #1
0
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;
}
Пример #2
0
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';
}
Пример #3
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;
}
Пример #4
0
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;
}
Пример #5
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;
	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;
}
Пример #6
0
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;
}