From 02da1bb7a1b16fee9e0e5c4a42c8aff7928db6cc Mon Sep 17 00:00:00 2001 From: Charlie Gordon Date: Wed, 15 Jan 2014 19:44:24 +0000 Subject: [PATCH] add generic styles buffer from shell color mode * styles_buffer hold static style info for each character in the buffer * new buffer flags to create styles buffers with 1, 2 or 4 bytes per char * copy static styles to the kill_ring and pasted them style enabled buffers * preserve static styles in convert-buffer-file-coding-system * display style bytes in bufed list * add commands set-region-color, set-region-style, drop-styles --- bufed.c | 5 ++- buffer.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++--- display.h | 6 --- extras.c | 69 ++++++++++++++++++++++++++++- orgmode.c | 6 +-- qe.c | 62 +++++++++++++++++++++----- qe.h | 26 ++++++++++- qeconfig.h | 4 +- shell.c | 120 ++++++++------------------------------------------ tty.c | 73 +++++++++++++++++++++++++++++++ 10 files changed, 361 insertions(+), 136 deletions(-) diff --git a/bufed.c b/bufed.c index 329b8d5..a2c9573 100644 --- a/bufed.c +++ b/bufed.c @@ -86,8 +86,9 @@ static void build_bufed_list(EditState *s) } } - eb_printf(b, " %10d %-8s %-8s %s", - b1->total_size, b1->charset->name, mode_name, + eb_printf(b, " %10d %c %-8s %-8s %s", + b1->total_size, " 1234567"[b1->style_bytes & 7], + b1->charset->name, mode_name, make_user_path(path, sizeof(path), b1->filename)); } eb_printf(b, "\n"); diff --git a/buffer.c b/buffer.c index 5f19e72..517db53 100644 --- a/buffer.c +++ b/buffer.c @@ -475,7 +475,7 @@ EditBuffer *eb_new(const char *name, int flags) // should ensure name uniqueness ? pstrcpy(b->name, sizeof(b->name), name); - b->flags = flags; + b->flags = flags & ~BF_STYLES; /* set default data type */ b->data_type = &raw_data_type; @@ -509,6 +509,9 @@ EditBuffer *eb_new(const char *name, int flags) if (strequal(name, "*trace*")) qs->trace_buffer = b; + if (flags & BF_STYLES) + eb_create_style_buffer(b, flags); + return b; } @@ -581,6 +584,8 @@ void eb_free(EditBuffer *b) if (b == qs->trace_buffer) qs->trace_buffer = NULL; + eb_free_style_buffer(b); + qe_free(&b); } @@ -754,6 +759,82 @@ void eb_offset_callback(__unused__ EditBuffer *b, void *opaque, int edge, } } +int eb_create_style_buffer(EditBuffer *b, int flags) +{ + if (b->b_styles) { + return 0; + } else { + b->b_styles = eb_new("*", BF_SYSTEM); + b->flags |= flags & BF_STYLES; + b->style_shift = ((flags & BF_STYLES) / BF_STYLE1) - 1; + b->style_bytes = 1 << b->style_shift; + eb_set_style(b, 0, LOGOP_INSERT, 0, b->total_size); + eb_add_callback(b, eb_style_callback, NULL, 0); + return 1; + } +} + +void eb_free_style_buffer(EditBuffer *b) +{ + if (b->b_styles) { + eb_free(b->b_styles); + b->b_styles = NULL; + } + b->style_shift = b->style_bytes = 0; + eb_free_callback(b, eb_style_callback, NULL); +} + +/* XXX: should compress styles buffer with run length encoding */ +void eb_set_style(EditBuffer *b, int style, enum LogOperation op, + int offset, int size) +{ + unsigned char buf[256]; + int i, len; + + if (!b->b_styles || !size) + return; + + offset = (offset >> b->char_shift) << b->style_shift; + size = (size >> b->char_shift) << b->style_shift; + + switch (op) { + case LOGOP_WRITE: + case LOGOP_INSERT: + while (size > 0) { + len = min(size, ssizeof(buf)); + if (b->style_shift == 2) { + for (i = 0; i < len; i += 4) { + *(uint32_t*)(buf + i) = style; + } + } else + if (b->style_shift == 1) { + for (i = 0; i < len; i += 2) { + *(uint16_t*)(buf + i) = style; + } + } else { + memset(buf, style, len); + } + if (op == LOGOP_WRITE) + eb_write(b->b_styles, offset, buf, len); + else + eb_insert(b->b_styles, offset, buf, len); + size -= len; + offset += len; + } + break; + case LOGOP_DELETE: + eb_delete(b->b_styles, offset, size); + break; + default: + break; + } +} + +void eb_style_callback(EditBuffer *b, void *opaque, int arg, + enum LogOperation op, int offset, int size) +{ + eb_set_style(b, b->cur_style, op, offset, size); +} /************************************************************/ @@ -1031,6 +1112,16 @@ void eb_set_charset(EditBuffer *b, QECharset *charset) b->flags |= BF_UTF8; charset_decode_init(&b->charset_state, charset); + b->char_bytes = 1; + b->char_shift = 0; + if (charset) { + b->char_bytes = charset->char_size; + if (charset->char_size == 4) + b->char_shift = 2; + else + b->char_shift = charset->char_size - 1; + } + /* Reset page cache flags */ for (n = 0; n < b->nb_pages; n++) { Page *p = &b->page_table[n]; @@ -1044,6 +1135,22 @@ int eb_nextc(EditBuffer *b, int offset, int *next_ptr) u8 buf[MAX_CHAR_BYTES]; int ch; + if (b->b_styles) { + if (b->style_shift == 2) { + *(uint32_t*)buf = 0; + eb_read(b->b_styles, (offset >> b->char_shift) << 2, buf, 4); + b->cur_style = *(uint32_t*)buf; + } else + if (b->style_shift == 1) { + *(uint16_t*)buf = 0; + eb_read(b->b_styles, (offset >> b->char_shift) << 1, buf, 2); + b->cur_style = *(uint16_t*)buf; + } else { + *(uint8_t*)buf = 0; + eb_read(b->b_styles, (offset >> b->char_shift), buf, 1); + b->cur_style = *(uint8_t*)buf; + } + } if (eb_read(b, offset, buf, 1) <= 0) { ch = '\n'; if (offset < 0) @@ -1758,16 +1865,20 @@ int eb_insert_buffer_convert(EditBuffer *dest, int dest_offset, EditBuffer *src, int src_offset, int size) { - if (dest->charset == src->charset) { + int styles_flags = min((dest->flags & BF_STYLES), (src->flags & BF_STYLES)); + + if (dest->charset == src->charset && !styles_flags) { return eb_insert_buffer(dest, dest_offset, src, src_offset, size); } else { EditBuffer *b; - int offset, offset_max; + int offset, offset_max, offset1 = dest_offset; b = dest; - if ((b->flags & BF_SAVELOG) || dest_offset != b->total_size) { - b = eb_new("*tmp*", 0); + if (!styles_flags + && ((b->flags & BF_SAVELOG) || dest_offset != b->total_size)) { + b = eb_new("*tmp*", BF_SYSTEM); eb_set_charset(b, dest->charset); + offset1 = 0; } /* well, not very fast, but simple */ @@ -1778,7 +1889,8 @@ int eb_insert_buffer_convert(EditBuffer *dest, int dest_offset, char buf[MAX_CHAR_BYTES]; int c = eb_nextc(src, offset, &offset); int len = unicode_to_charset(buf, c, b->charset); - eb_write(b, b->total_size, buf, len); + b->cur_style = src->cur_style; + eb_insert(b, offset1 + size, buf, len); size += len; } @@ -1810,7 +1922,7 @@ int eb_get_line(EditBuffer *b, unsigned int *buf, int buf_size, if (c == '\n') break; if (buf_ptr < buf_end) - *buf_ptr++ = c; + *buf_ptr++ = c & CHAR_MASK; } *buf_ptr = '\0'; *offset_ptr = offset; diff --git a/display.h b/display.h index d295f3f..524a478 100644 --- a/display.h +++ b/display.h @@ -24,12 +24,6 @@ #define MAX_SCREEN_WIDTH 1024 /* in chars */ #define MAX_SCREEN_LINES 256 /* in text lines */ -typedef unsigned int QEColor; -#define QEARGB(a,r,g,b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -#define QERGB(r,g,b) QEARGB(0xff, r, g, b) -#define COLOR_TRANSPARENT 0 -#define QECOLOR_XOR 1 - /* XXX: use different name prefix to avoid conflict */ #define QE_STYLE_NORM 0x0001 #define QE_STYLE_BOLD 0x0002 diff --git a/extras.c b/extras.c index bf3e6af..c23af17 100644 --- a/extras.c +++ b/extras.c @@ -1,7 +1,7 @@ /* * QEmacs, extra commands non full version * - * Copyright (c) 2000-2008 Charlie Gordon. + * Copyright (c) 2000-2014 Charlie Gordon. * * 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 @@ -575,6 +575,64 @@ static void do_about_qemacs(EditState *s) show_popup(b); } +static void do_set_region_color(EditState *s, const char *str) +{ + int offset, size, style; + + /* deactivate region hilite */ + s->region_style = 0; + + style = get_tty_style(str); + if (style < 0) { + put_status(s, "Invalid color '%s'", str); + return; + } + + offset = s->b->mark; + size = s->offset - offset; + if (size < 0) { + offset += size; + size = -size; + } + if (size > 0) { + eb_create_style_buffer(s->b, BF_STYLE2); + eb_set_style(s->b, style, LOGOP_WRITE, offset, size); + } +} + +static void do_set_region_style(EditState *s, const char *str) +{ + int offset, size, style; + QEStyleDef *st; + + /* deactivate region hilite */ + s->region_style = 0; + + st = find_style(str); + if (!st) { + put_status(s, "Invalid style '%s'", str); + return; + } + style = st - qe_styles; + + offset = s->b->mark; + size = s->offset - offset; + if (size < 0) { + offset += size; + size = -size; + } + if (size > 0) { + eb_create_style_buffer(s->b, BF_STYLE2); + eb_set_style(s->b, style, LOGOP_WRITE, offset, size); + } +} + +static void do_drop_styles(EditState *s) +{ + eb_free_style_buffer(s->b); + s->b->flags &= ~BF_STYLES; +} + static CmdDef extra_commands[] = { CMD2( KEY_META('='), KEY_NONE, "compare-windows", do_compare_windows, ESi, "ui" ) @@ -622,6 +680,15 @@ static CmdDef extra_commands[] = { "show-bindings", do_show_bindings, ESs, "s{Show bindings of command: }[command]|command|") + CMD2( KEY_CTRLC('c'), KEY_NONE, + "set-region-color", do_set_region_color, ESs, + "s{Select color: }[color]|color|") + CMD2( KEY_CTRLC('s'), KEY_NONE, + "set-region-style", do_set_region_style, ESs, + "s{Select style: }[style]|style|") + CMD0( KEY_NONE, KEY_NONE, + "drop-styles", do_drop_styles) + CMD_DEF_END, }; diff --git a/orgmode.c b/orgmode.c index 5c6d241..428ebf3 100644 --- a/orgmode.c +++ b/orgmode.c @@ -672,13 +672,13 @@ static void do_org_move_subtree(EditState *s, int dir) } offset2 = org_next_heading(s, offset1, level, &level2); } - b1 = eb_new("*tmp*", 0); + b1 = eb_new("*tmp*", BF_SYSTEM | (s->b->flags & BF_STYLES)); eb_set_charset(b1, s->b->charset); - eb_insert_buffer(b1, 0, s->b, offset, size); + eb_insert_buffer_convert(b1, 0, s->b, offset, size); eb_delete(s->b, offset, size); if (offset2 > offset) offset2 -= size; - eb_insert_buffer(s->b, offset2, b1, 0, size); + eb_insert_buffer_convert(s->b, offset2, b1, 0, b1->total_size); eb_free(b1); s->offset = offset2; } diff --git a/qe.c b/qe.c index ade03cd..a15d0d7 100644 --- a/qe.c +++ b/qe.c @@ -1445,7 +1445,7 @@ EditBuffer *new_yank_buffer(QEmacsState *qs, EditBuffer *base) } } snprintf(bufname, sizeof(bufname), "*kill-%d*", qs->yank_current + 1); - b = eb_new(bufname, base->flags & BF_UTF8); + b = eb_new(bufname, base->flags & (BF_STYLES | BF_UTF8)); eb_set_charset(b, base->charset); qs->yank_buffers[qs->yank_current] = b; return b; @@ -1824,7 +1824,7 @@ void do_convert_buffer_file_coding_system(EditState *s, b = s->b; - b1 = eb_new("*tmp*", 0); + b1 = eb_new("*tmp*", b->flags & BF_STYLES); eb_set_charset(b1, charset); /* preserve positions */ @@ -1840,13 +1840,19 @@ void do_convert_buffer_file_coding_system(EditState *s, for (offset = 0; offset < b->total_size;) { c = eb_nextc(b, offset, &offset); len = unicode_to_charset(buf, c, charset); + b1->cur_style = b->cur_style; eb_write(b1, b1->total_size, buf, len); } /* replace current buffer with conversion */ + /* quick hack to transfer styles from tmp buffer to b */ + eb_free(b->b_styles); + b->b_styles = NULL; eb_delete(b, 0, b->total_size); eb_set_charset(b, charset); eb_insert_buffer(b, 0, b1, 0, b1->total_size); + b->b_styles = b1->b_styles; + b1->b_styles = NULL; /* restore positions */ cb = b->first_callback; @@ -3232,14 +3238,42 @@ void set_colorize_func(EditState *s, ColorizeFunc colorize_func) #endif /* CONFIG_TINY */ +int get_staticly_colorized_line(EditState *s, unsigned int *buf, int buf_size, + int *offset_ptr, int line_num) +{ + EditBuffer *b = s->b; + unsigned int *buf_ptr, *buf_end; + int c, offset; + + offset = *offset_ptr; + + buf_ptr = buf; + buf_end = buf + buf_size - 1; + b->cur_style = 0; + for (;;) { + c = eb_nextc(b, offset, &offset); + if (c == '\n') + break; + if (buf_ptr < buf_end) { + c |= b->cur_style << STYLE_SHIFT; + *buf_ptr++ = c; + } + } + *buf_ptr = '\0'; + *offset_ptr = offset; + return buf_ptr - buf; +} + int get_non_colorized_line(EditState *s, unsigned int *buf, int buf_size, int *offsetp, int line_num) { - /* compute line color */ + if (s->b->b_styles) { + return get_staticly_colorized_line(s, buf, buf_size, offsetp, line_num); + } + int len = eb_get_line(s->b, buf, buf_size, offsetp); // XXX: should force \0 instead of \n buf[len] = '\n'; - return len; } @@ -3256,7 +3290,8 @@ int text_display(EditState *s, DisplayState *ds, int offset) unsigned int colored_chars[COLORED_MAX_LINE_SIZE]; int char_index, colored_nb_chars; - line_num = 0; /* avoid warning */ + line_num = 0; + /* XXX: should test a flag, to avoid this call in hex/binary */ if (s->line_numbers || s->get_colorized_line != get_non_colorized_line) { eb_get_pos(s->b, &line_num, &col_num, offset); } @@ -3305,7 +3340,9 @@ int text_display(EditState *s, DisplayState *ds, int offset) /* colorize */ colored_nb_chars = 0; offset0 = offset; - if (s->get_colorized_line != get_non_colorized_line) { + if (s->get_colorized_line != get_non_colorized_line + || s->curline_style || s->region_style + || s->b->b_styles) { colored_nb_chars = s->get_colorized_line(s, colored_chars, countof(colored_chars), &offset0, line_num); @@ -3314,11 +3351,6 @@ int text_display(EditState *s, DisplayState *ds, int offset) #if 1 /* colorize regions */ if (s->curline_style || s->region_style) { - if (s->get_colorized_line == get_non_colorized_line) { - offset0 = offset; - colored_nb_chars = eb_get_line(s->b, colored_chars, - countof(colored_chars), &offset0); - } /* CG: Should combine styles instead of replacing */ if (s->region_style) { int line, start, stop; @@ -4533,6 +4565,9 @@ void switch_to_buffer(EditState *s, EditBuffer *b) ModeSavedData *saved_data, **psaved_data; ModeDef *mode; + /* remove region hilite */ + s->region_style = 0; + b1 = s->b; if (b1) { /* save mode data if no other window uses the buffer */ @@ -4870,6 +4905,8 @@ void do_completion(EditState *s) * through the window, if at end, should remove focus from * completion_popup_window or close it. */ + /* check completion window */ + completion_popup_window = check_window(completion_popup_window); if (completion_popup_window && qs->last_cmd_func == qs->this_cmd_func) { edit_close(completion_popup_window); completion_popup_window = NULL; @@ -4952,7 +4989,7 @@ void do_completion(EditState *s) e->offset = 0; } } - complete_end(&cs); + complete_end(&cs); } void do_electric_filename(EditState *s, int key) @@ -5107,6 +5144,7 @@ void do_minibuffer_exit(EditState *s, int do_abort) /* restore active window */ qs->active_window = check_window(minibuffer_saved_active); + minibuffer_saved_active = NULL; /* force status update */ //pstrcpy(qs->status_shadow, sizeof(qs->status_shadow), " "); diff --git a/qe.h b/qe.h index 62b3fce..6d1b28f 100644 --- a/qe.h +++ b/qe.h @@ -193,6 +193,12 @@ typedef struct CSSRect { int x1, y1, x2, y2; } CSSRect; +typedef unsigned int QEColor; +#define QEARGB(a,r,g,b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define QERGB(r,g,b) QEARGB(0xff, r, g, b) +#define COLOR_TRANSPARENT 0 +#define QECOLOR_XOR 1 + typedef struct FindFileState FindFileState; FindFileState *find_file_open(const char *path, const char *pattern); @@ -302,7 +308,7 @@ const char *keys_to_str(char *buf, int buf_size, int to_hex(int key); void color_completion(CompleteState *cp); int css_define_color(const char *name, const char *value); -int css_get_color(unsigned int *color_ptr, const char *p); +int css_get_color(QEColor *color_ptr, const char *p); int css_get_font_family(const char *str); void css_union_rect(CSSRect *a, const CSSRect *b); static inline int css_is_null_rect(const CSSRect *a) { @@ -712,6 +718,10 @@ typedef struct EditBufferCallbackList { #define BF_UTF8 0x0200 /* buffer charset is utf-8 */ #define BF_RAW 0x0400 /* buffer charset is raw (same as latin1) */ #define BF_TRANSIENT 0x0800 /* buffer is deleted upon window close */ +#define BF_STYLES 0x3000 /* buffer has styles */ +#define BF_STYLE1 0x1000 /* buffer has 1 byte styles */ +#define BF_STYLE2 0x2000 /* buffer has 2 byte styles */ +#define BF_STYLE4 0x3000 /* buffer has 4 byte styles */ struct EditBuffer { Page *page_table; @@ -734,6 +744,7 @@ struct EditBuffer { /* charset handling */ CharsetDecodeState charset_state; QECharset *charset; + int char_bytes, char_shift; /* undo system */ int save_log; /* if true, each buffer operation is logged */ @@ -743,6 +754,12 @@ struct EditBuffer { EditBuffer *log_buffer; int nb_logs; + /* style system */ + EditBuffer *b_styles; + int cur_style; + int style_bytes; + int style_shift; + /* modification callbacks */ EditBufferCallbackList *first_callback; @@ -846,6 +863,12 @@ int eb_add_callback(EditBuffer *b, EditBufferCallback cb, void *opaque, int arg) void eb_free_callback(EditBuffer *b, EditBufferCallback cb, void *opaque); void eb_offset_callback(EditBuffer *b, void *opaque, int edge, enum LogOperation op, int offset, int size); +int eb_create_style_buffer(EditBuffer *b, int flags); +void eb_free_style_buffer(EditBuffer *b); +void eb_set_style(EditBuffer *b, int style, enum LogOperation op, + int offset, int size); +void eb_style_callback(EditBuffer *b, void *opaque, int arg, + enum LogOperation op, int offset, int size); int eb_delete_uchar(EditBuffer *b, int offset); int eb_insert_uchar(EditBuffer *b, int offset, int c); int eb_insert_utf8_buf(EditBuffer *b, int offset, const char *buf, int len); @@ -1141,6 +1164,7 @@ extern int tty_bg_colors_count; extern unsigned int const *tty_fg_colors; extern int tty_fg_colors_count; int get_tty_color(QEColor color, unsigned int const *colors, int count); +int get_tty_style(const char *style); /* special selection style (cumulative with another style) */ #define QE_STYLE_SEL 0x400 diff --git a/qeconfig.h b/qeconfig.h index 76bedf3..7d611fc 100644 --- a/qeconfig.h +++ b/qeconfig.h @@ -291,10 +291,10 @@ static CmdDef basic_commands[] = { CMD2( KEY_CTRLXRET('f'), KEY_NONE, "set-buffer-file-coding-system", do_set_buffer_file_coding_system, ESs, - "s{Charset: }[charset]") + "s{Charset: }[charset]|charset|") CMD2( KEY_NONE, KEY_NONE, "convert-buffer-file-coding-system", do_convert_buffer_file_coding_system, ESs, - "*" "s{Charset: }[charset]") + "*" "s{Charset: }[charset]|charset|") CMD0( KEY_CTRLXRET('b'), KEY_NONE, "toggle-bidir", do_toggle_bidir) CMD2( KEY_CTRLXRET(KEY_CTRL('\\')), KEY_NONE, diff --git a/shell.c b/shell.c index 36927ff..e341041 100644 --- a/shell.c +++ b/shell.c @@ -465,6 +465,8 @@ static void tty_goto_xy(ShellState *s, int x, int y, int relative) line_num += y; /* add lines if necessary */ while (line_num >= total_lines) { + /* XXX: color may be wrong */ + s->b->cur_style = QE_STYLE_TTY | s->color | s->attr; eb_insert_uchar(s->b, s->b->total_size, '\n'); total_lines++; } @@ -473,6 +475,7 @@ static void tty_goto_xy(ShellState *s, int x, int y, int relative) c = eb_nextc(s->b, offset, &offset1); if (c == '\n') { for (; x > 0; x--) { + /* duplicate style of last char */ offset += eb_insert_uchar(s->b, offset, ' '); } break; @@ -492,6 +495,7 @@ static int tty_put_char(ShellState *s, int c) offset = s->cur_offset; buf[0] = c; c1 = eb_nextc(s->b, offset, &offset1); + s->b->cur_style = QE_STYLE_TTY | s->color | s->attr; if (c1 == '\n') { /* insert */ eb_insert(s->b, offset, buf, 1); @@ -793,6 +797,7 @@ static void tty_emulate(ShellState *s, int c) if (offset == s->b->total_size) { /* add a new line */ /* CG: XXX: ignoring charset */ + s->b->cur_style = QE_STYLE_TTY | s->color | s->attr; buf1[0] = '\n'; eb_insert(s->b, offset, buf1, 1); offset = s->b->total_size; @@ -874,6 +879,7 @@ static void tty_emulate(ShellState *s, int c) len = 1; } c1 = eb_nextc(s->b, offset, &offset1); + s->b->cur_style = QE_STYLE_TTY | s->color | s->attr; /* Should simplify with tty_put_char */ if (c1 == '\n') { /* insert */ @@ -899,6 +905,7 @@ static void tty_emulate(ShellState *s, int c) len = s->utf8_len; c1 = eb_nextc(s->b, offset, &offset1); + s->b->cur_style = QE_STYLE_TTY | s->color | s->attr; if (c1 == '\n') { /* insert */ eb_insert(s->b, offset, s->utf8_buf, len); @@ -1123,6 +1130,7 @@ static void tty_emulate(ShellState *s, int c) case '@': /* ICH: insert chars (no cursor update) */ buf1[0] = ' '; offset1 = offset; + s->b->cur_style = QE_STYLE_TTY | s->color | s->attr; for (n = s->esc_params[0]; n > 0; n--) { /* XXX: incorrect for non 8 bit charsets */ eb_insert(s->b, offset1, buf1, 1); @@ -1208,86 +1216,6 @@ static void tty_emulate(ShellState *s, int c) tty_update_cursor(s); } -/* modify the color according to the current one (may be incorrect if - we are editing because we should write default color) */ -static void shell_color_callback(__unused__ EditBuffer *b, - void *opaque, int arg, - enum LogOperation op, int offset, int size) -{ - ShellState *s = opaque; - unsigned char buf[256]; - int len; - - switch (op) { - case LOGOP_WRITE: - while (size > 0) { - len = size; - if (len > ssizeof(buf)) - len = ssizeof(buf); - memset(buf, s->color | s->attr, len); - eb_write(s->b_color, offset, buf, len); - size -= len; - offset += len; - } - break; - case LOGOP_INSERT: - while (size > 0) { - len = size; - if (len > ssizeof(buf)) - len = ssizeof(buf); - memset(buf, s->color | s->attr, len); - eb_insert(s->b_color, offset, buf, len); - size -= len; - offset += len; - } - break; - case LOGOP_DELETE: - eb_delete(s->b_color, offset, size); - break; - default: - break; - } -} - -static int shell_get_colorized_line(EditState *e, - unsigned int *buf, int buf_size, - int *offsetp, __unused__ int line_num) -{ - EditBuffer *b = e->b; - ShellState *s = b->priv_data; - EditBuffer *b_color = s->b_color; - int color, offset, offset1, c; - unsigned int *buf_ptr, *buf_end; - unsigned char buf1[1]; - - /* record line */ - offset = *offsetp; - buf_ptr = buf; - buf_end = buf + buf_size - 1; - for (;;) { - c = eb_nextc(b, offset, &offset1); - if (c == '\n') - break; - if (buf_ptr < buf_end) { - if (b_color) { - eb_read(b_color, offset, buf1, 1); - color = buf1[0]; - /* XXX: test */ - //if (color != s->def_color) - { - c |= (QE_STYLE_TTY | color) << STYLE_SHIFT; - } - } - *buf_ptr++ = c; - } - offset = offset1; - } - *buf_ptr = '\0'; - *offsetp = offset1; - - return buf_ptr - buf; -} - /* buffer related functions */ /* called when characters are available on the tty */ @@ -1414,15 +1342,20 @@ EditBuffer *new_shell_buffer(EditBuffer *b0, const char *bufname, { QEmacsState *qs = &qe_state; ShellState *s; - EditBuffer *b, *b_color; + EditBuffer *b; const char *lang; int rows, cols; b = b0; - if (!b) - b = eb_new("", BF_SAVELOG); - if (!b) - return NULL; + if (!b) { + int bf_flags = BF_SAVELOG; + if (shell_flags & SF_COLOR) + bf_flags |= BF_STYLE2; + b = eb_new("", bf_flags); + if (!b) + return NULL; + } + eb_set_buffer_name(b, bufname); /* ensure that the name is unique */ /* Select shell output buffer encoding from LANG setting */ @@ -1451,21 +1384,6 @@ EditBuffer *new_shell_buffer(EditBuffer *b0, const char *bufname, s->shell_flags = shell_flags; tty_init(s); - /* add color buffer */ - if (shell_flags & SF_COLOR) { - b_color = eb_new("*color*", BF_SYSTEM); - if (!b_color) { - if (!b0) - eb_free(b); - qe_free(&s); - return NULL; - } - /* no undo info in this color buffer */ - b_color->save_log = 0; - eb_add_callback(b, shell_color_callback, s, 0); - s->b_color = b_color; - } - /* launch shell */ cols = TTY_XSIZE; rows = TTY_YSIZE; @@ -1901,7 +1819,6 @@ static int shell_mode_init(EditState *s, __unused__ ModeSavedData *saved_data) text_mode_init(s, saved_data); s->tab_size = 8; s->wrap = WRAP_TRUNCATE; - s->get_colorized_line = shell_get_colorized_line; s->interactive = 1; return 0; } @@ -1911,7 +1828,6 @@ static int pager_mode_init(EditState *s, __unused__ ModeSavedData *saved_data) text_mode_init(s, saved_data); s->tab_size = 8; s->wrap = WRAP_TRUNCATE; - s->get_colorized_line = shell_get_colorized_line; return 0; } diff --git a/tty.c b/tty.c index 3fd207b..3162a80 100644 --- a/tty.c +++ b/tty.c @@ -857,6 +857,79 @@ static void tty_term_fill_rectangle(QEditScreen *s, } } +int str_get_word(char *buf, int size, const char *p, const char **pp) +{ + int len; + + while (*p == ' ') + p++; + + for (len = 0; *p != '\0' && *p != ' ' && *p != '/'; p++, len++) { + if (len < size - 1) + buf[len] = *p; + } + if (len < size - 1) + buf[len] = '\0'; + + while (*p == ' ') + p++; + + if (pp) + *pp = p; + + return len; +} + +/* match a keyword, ignore case, check word boundary */ +int str_match_word(const char *str, const char *val, const char **pp) +{ + if (stristart(str, val, &str) && (*str == '\0' || *str == ' ')) { + while (*str == ' ') + str++; + if (pp) + *pp = str; + return 1; + } + return 0; +} + +int get_tty_style(const char *str) +{ + char buf[128]; + QEColor fg_color, bg_color; + int fg, bg, style; + const char *p = str; + + style = 0; + for (;;) { + if (str_match_word(p, "bold", &p)) { + style |= TTY_BOLD; + continue; + } + if (str_match_word(p, "blinking", &p) + || str_match_word(p, "blink", &p)) { + style |= TTY_BLINK; + continue; + } + break; + } + fg_color = QERGB(0xbb, 0xbb, 0xbb); + bg_color = QERGB(0x00, 0x00, 0x00); + if (str_get_word(buf, sizeof(buf), p, &p)) { + if (css_get_color(&fg_color, buf)) + return -1; + if (str_match_word(p, "on", &p) || (*p == '/' && p++)) { + str_get_word(buf, sizeof(buf), p, &p); + if (css_get_color(&bg_color, buf)) + return -1; + } + } + fg = get_tty_color(fg_color, tty_fg_colors, tty_fg_colors_count); + bg = get_tty_color(bg_color, tty_fg_colors, tty_fg_colors_count); + + return QE_STYLE_TTY | style | TTY_MAKE_COLOR(fg, bg); +} + /* XXX: could alloc font in wrapper */ static QEFont *tty_term_open_font(__unused__ QEditScreen *s, __unused__ int style, __unused__ int size)