Mercurial > pidgin
diff console/libgnt/gnttextview.c @ 13896:a621329e8c85
[gaim-migrate @ 16381]
Changes in GntTextView. Things go somewhat 'smooth' when run inside
valgrind. Otherwise, it's kind of flaky. I don't mind a single bit
if someone gave me a hint :)
committer: Tailor Script <tailor@pidgin.im>
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 01 Jul 2006 00:56:05 +0000 |
parents | 9d66969a2e32 |
children | 9309d27d780c |
line wrap: on
line diff
--- a/console/libgnt/gnttextview.c Fri Jun 30 16:23:56 2006 +0000 +++ b/console/libgnt/gnttextview.c Sat Jul 01 00:56:05 2006 +0000 @@ -5,6 +5,18 @@ SIGS = 1, }; +typedef struct +{ + GntTextViewFlags flags; + char *text; +} GntTextSegment; + +typedef struct +{ + GList *segments; /* A list of GntTextSegments */ + int length; /* The current length of the line so far */ +} GntTextLine; + static GntWidgetClass *parent_class = NULL; static guint signals[SIGS] = { 0 }; @@ -12,9 +24,27 @@ gnt_text_view_draw(GntWidget *widget) { GntTextView *view = GNT_TEXT_VIEW(widget); + int i = 0; + GList *lines; - copywin(view->scroll, widget->window, view->pos, 0, 0, 0, - widget->priv.height - 1, widget->priv.width - 1, FALSE); + werase(widget->window); + + for (i = 0, lines = view->list; i < widget->priv.height && lines; i++, lines = lines->next) + { + GList *iter; + GntTextLine *line = lines->data; + + wmove(widget->window, widget->priv.height - 1 - i, 0); + + for (iter = line->segments; iter; iter = iter->next) + { + GntTextSegment *seg = iter->data; + wattrset(widget->window, seg->flags); + wprintw(widget->window, "%s", seg->text); + if (!iter->next) + whline(widget->window, ' ' | seg->flags, widget->priv.width - line->length - 1); + } + } DEBUG; } @@ -43,8 +73,28 @@ } static void +free_text_segment(gpointer data, gpointer null) +{ + GntTextSegment *seg = data; + g_free(seg->text); + g_free(seg); +} + +static void +free_text_line(gpointer data, gpointer null) +{ + GntTextLine *line = data; + g_list_foreach(line->segments, free_text_segment, NULL); + g_list_free(line->segments); + g_free(line); +} + +static void gnt_text_view_destroy(GntWidget *widget) { + GntTextView *view = GNT_TEXT_VIEW(widget); + g_list_foreach(view->list, free_text_line, NULL); + g_list_free(view->list); } static void @@ -100,14 +150,12 @@ { GntWidget *widget = g_object_new(GNT_TYPE_TEXTVIEW, NULL); GntTextView *view = GNT_TEXT_VIEW(widget); + GntTextLine *line = g_new0(GntTextLine, 1); - view->scroll = newwin(255, widget->priv.width, widget->priv.y, widget->priv.x); - scrollok(view->scroll, TRUE); - wsetscrreg(view->scroll, 0, 254); - wbkgd(view->scroll, COLOR_PAIR(GNT_COLOR_NORMAL)); - werase(view->scroll); GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER); + view->list = g_list_append(view->list, line); + return widget; } @@ -117,6 +165,7 @@ int fl = 0; char **split; int i; + GList *list = view->list; if (text == NULL || *text == '\0') return; @@ -128,48 +177,80 @@ if (flags & GNT_TEXT_FLAG_BLINK) fl |= A_BLINK; - wattrset(view->scroll, fl | COLOR_PAIR(GNT_COLOR_NORMAL)); + if (flags & GNT_TEXT_FLAG_DIM) + fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED)); + else if (flags & GNT_TEXT_FLAG_HIGHLIGHT) + fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + else + fl |= COLOR_PAIR(GNT_COLOR_NORMAL); + + view->list = g_list_first(view->list); split = g_strsplit(text, "\n", 0); - for (i = 0; split[i + 1]; i++) + for (i = 0; split[i]; i++) { - /* XXX: Do something if the strlen of split[i] is big - * enough to cause the text to wrap. */ - wprintw(view->scroll, "%s\n", split[i]); - view->lines++; + GntTextLine *line = view->list->data; + int len = g_utf8_strlen(split[i], -1); + char *iter = split[i]; + int prev = 0; + + while (iter && *iter) + { + GntTextSegment *seg = g_new0(GntTextSegment, 1); + seg->flags = fl; + seg->text = g_new0(char, len); /* XXX: MUST be improved */ + g_utf8_strncpy(seg->text, iter, widget->priv.width - line->length - 1); + line->segments = g_list_append(line->segments, seg); + + prev = g_utf8_strlen(seg->text, -1); + line->length += prev; + iter = g_utf8_offset_to_pointer(iter, prev); + if (line->length >= widget->priv.width - 1 && *iter) + { + line = g_new0(GntTextLine, 1); + view->list = g_list_prepend(g_list_first(view->list), line); + } + /*len -= prev;*/ + } } - wprintw(view->scroll, "%s", split[i]); + g_strfreev(split); + view->list = list; gnt_widget_draw(widget); } void gnt_text_view_scroll(GntTextView *view, int scroll) { - GntWidget *widget = GNT_WIDGET(view); - int height; - if (scroll == 0) { - view->pos = view->lines - widget->priv.height + 1; + view->list = g_list_first(view->list); } - else + else if (scroll > 0) { - view->pos += scroll; + GList *list = g_list_nth_prev(view->list, scroll); + if (list == NULL) + list = g_list_first(view->list); + view->list = list; } - - if (view->pos + (height = widget->priv.height) > view->lines) - view->pos = view->lines - height + 1; - - if (view->pos < 0) - view->pos = 0; - + else if (scroll < 0) + { + GList *list = g_list_nth(view->list, -scroll); + if (list == NULL) + list = g_list_last(view->list); + view->list = list; + } + gnt_widget_draw(GNT_WIDGET(view)); } void gnt_text_view_next_line(GntTextView *view) { - wclrtoeol(view->scroll); - gnt_text_view_append_text_with_flags(view, "\n", 0); + GntTextLine *line = g_new0(GntTextLine, 1); + GList *list = view->list; + + view->list = g_list_prepend(g_list_first(view->list), line); + view->list = list; + gnt_widget_draw(GNT_WIDGET(view)); }