Added SILC Thread Queue API
[crypto.git] / apps / irssi / src / fe-text / textbuffer-view.c
index a5d7f2ed1d6b556d2a3351cfb71268d995275f6c..175bd4f6dc1f366f06ce96df6c0c4d0ea2f0675a 100644 (file)
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define        G_LOG_DOMAIN "TextBufferView"
+
 #include "module.h"
 #include "textbuffer-view.h"
 #include "utf8.h"
+#ifdef HAVE_CUIX
+#include "cuix.h"
+#endif
 
 typedef struct {
        char *name;
@@ -114,7 +119,7 @@ static void update_cmd_color(unsigned char cmd, int *color)
                        if ((cmd & LINE_COLOR_DEFAULT) == 0)
                                *color |= (cmd & 0x0f) << 4;
                        else {
-                               *color |= ATTR_RESETBG;
+                               *color = (*color & FGATTR) | ATTR_RESETBG;
                                 if (cmd & LINE_COLOR_BLINK)
                                        *color |= ATTR_BLINK;
                        }
@@ -124,7 +129,7 @@ static void update_cmd_color(unsigned char cmd, int *color)
                        if ((cmd & LINE_COLOR_DEFAULT) == 0)
                                *color |= cmd & 0x0f;
                        else {
-                               *color |= ATTR_RESETFG;
+                               *color = (*color & BGATTR) | ATTR_RESETFG;
                                 if (cmd & LINE_COLOR_BOLD)
                                        *color |= ATTR_BOLD;
                        }
@@ -150,8 +155,10 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
        LINE_CACHE_SUB_REC *sub;
        GSList *lines;
         unsigned char cmd;
-       const unsigned char *ptr, *last_space_ptr;
+       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);
 
@@ -194,7 +201,28 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
                        continue;
                }
 
-               if (xpos == view->width && sub != NULL &&
+               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 */
@@ -202,7 +230,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
                         sub->indent = 0;
                }
 
-               if (xpos == view->width) {
+               if (xpos + char_len > view->width) {
                        xpos = indent_func == NULL ? indent_pos :
                                indent_func(view, line, -1);
 
@@ -230,15 +258,18 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
                        continue;
                }
 
-               if (view->utf8)
-                       get_utf8_char(&ptr);
-
-               xpos++;
-               if (*ptr++ == ' ') {
-                       last_space = xpos-1;
+               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) +
@@ -248,11 +279,13 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
 
        if (rec->count > 1) {
                for (pos = 0; lines != NULL; pos++) {
-                       memcpy(&rec->lines[pos], lines->data,
+                       void *data = lines->data;
+
+                       memcpy(&rec->lines[pos], data,
                               sizeof(LINE_CACHE_SUB_REC));
 
-                       g_free(lines->data);
-                       lines = g_slist_remove(lines, lines->data);
+                       lines = g_slist_remove(lines, data);
+                       g_free(data);
                }
        }
 
@@ -307,9 +340,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
 {
         INDENT_FUNC indent_func;
        LINE_CACHE_REC *cache;
-        const unsigned char *text, *text_newline;
+        const unsigned char *text, *end, *text_newline;
        unsigned char *tmp;
-       int xpos, color, drawcount, first, need_move, need_clrtoeol;
+       int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width;
 
        if (view->dirty) /* don't bother drawing anything - redraw is coming */
                 return 0;
@@ -341,13 +374,14 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
                        if (subline > 0) {
                                 /* continuing previous line - indent it */
                                indent_func = cache->lines[subline-1].indent_func;
-                               xpos = indent_func != NULL ?
-                                       indent_func(view, line, ypos) :
-                                       cache->lines[subline-1].indent;
+                               if (indent_func == NULL)
+                                       xpos = cache->lines[subline-1].indent;
                                 color = cache->lines[subline-1].color;
+                       } else {
+                               indent_func = NULL;
                        }
 
-                       if (xpos == 0)
+                       if (xpos == 0 && indent_func == NULL)
                                 need_clrtoeol = TRUE;
                        else {
                                /* line was indented - need to clear the
@@ -355,6 +389,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
                                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)
@@ -395,11 +432,24 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
                        continue;
                }
 
-               if (xpos < term_width) {
-                       const unsigned char *end = text;
-                       if (view->utf8)
-                               get_utf8_char(&end);
+               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++)
@@ -413,7 +463,6 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
                        }
                }
                text++;
-               xpos++;
        }
 
        if (need_clrtoeol && xpos < term_width) {
@@ -713,6 +762,9 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
                         break;
                }
 
+               if ((*lines)->next == NULL)
+                       break;
+
                 *lines = (*lines)->next;
        }
 
@@ -879,8 +931,8 @@ LINE_CACHE_REC *textbuffer_view_get_line_cache(TEXT_BUFFER_VIEW_REC *view,
 {
        LINE_CACHE_REC *cache;
 
-        g_return_val_if_fail(view != NULL, NULL);
-        g_return_val_if_fail(line != NULL, NULL);
+        g_assert(view != NULL);
+        g_assert(line != NULL);
 
        cache = g_hash_table_lookup(view->cache->line_cache, line);
        if (cache == NULL)
@@ -1009,6 +1061,8 @@ static void view_bookmarks_check(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
                        if (new_line != NULL) {
                                g_hash_table_insert(view->bookmarks,
                                                    tmp->data, new_line);
+                       } else {
+                               g_free(tmp->data);
                        }
                }
                g_slist_free(rec.remove_list);
@@ -1089,11 +1143,15 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
 
                if (view->startline == line) {
                         /* removing the first line in screen */
+                       int is_last = view->startline->next == NULL;
+
                        realcount = view_scroll(view, &view->startline,
                                                &view->subline,
                                                linecount, FALSE);
                        view->ypos -= realcount;
                        view->empty_linecount += linecount-realcount;
+                       if (is_last == 1)
+                               view->startline = NULL;
                }
        } else {
                if (textbuffer_line_exists_after(view->bottom_startline,
@@ -1268,6 +1326,9 @@ static int sig_check_linecache(void)
 void textbuffer_view_init(void)
 {
        linecache_tag = g_timeout_add(LINE_CACHE_CHECK_TIME, (GSourceFunc) sig_check_linecache, NULL);
+#ifdef HAVE_CUIX
+        cuix_active = 0;
+#endif
 }
 
 void textbuffer_view_deinit(void)