Mercurial > pidgin.yaz
comparison console/libgnt/gnttextview.c @ 15172:a00712d0522e
[gaim-migrate @ 17957]
Show 'ABC is typing...' in the conversation window for typing notification.
seanegan suggested this, and it sounded like an interesting thing to do.
The change in gnttextview.c will need some more work if it is to be used for
some other task, but its current use should be OK.
committer: Tailor Script <tailor@pidgin.im>
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Mon, 11 Dec 2006 06:02:15 +0000 |
parents | 5228f8cf2a6a |
children | e9963b2cfcaf |
comparison
equal
deleted
inserted
replaced
15171:b7f83eba6029 | 15172:a00712d0522e |
---|---|
20 { | 20 { |
21 GList *segments; /* A list of GntTextSegments */ | 21 GList *segments; /* A list of GntTextSegments */ |
22 int length; /* The current length of the line so far (ie. onscreen width) */ | 22 int length; /* The current length of the line so far (ie. onscreen width) */ |
23 gboolean soft; /* TRUE if it's an overflow from prev. line */ | 23 gboolean soft; /* TRUE if it's an overflow from prev. line */ |
24 } GntTextLine; | 24 } GntTextLine; |
25 | |
26 typedef struct | |
27 { | |
28 char *name; | |
29 int start; | |
30 int end; | |
31 } GntTextTag; | |
25 | 32 |
26 static GntWidgetClass *parent_class = NULL; | 33 static GntWidgetClass *parent_class = NULL; |
27 | 34 |
28 static void | 35 static void |
29 gnt_text_view_draw(GntWidget *widget) | 36 gnt_text_view_draw(GntWidget *widget) |
132 g_list_free(line->segments); | 139 g_list_free(line->segments); |
133 g_free(line); | 140 g_free(line); |
134 } | 141 } |
135 | 142 |
136 static void | 143 static void |
144 free_tag(gpointer data, gpointer null) | |
145 { | |
146 GntTextTag *tag = data; | |
147 g_free(tag->name); | |
148 g_free(tag); | |
149 } | |
150 | |
151 static void | |
137 gnt_text_view_destroy(GntWidget *widget) | 152 gnt_text_view_destroy(GntWidget *widget) |
138 { | 153 { |
139 GntTextView *view = GNT_TEXT_VIEW(widget); | 154 GntTextView *view = GNT_TEXT_VIEW(widget); |
140 view->list = g_list_first(view->list); | 155 view->list = g_list_first(view->list); |
141 g_list_foreach(view->list, free_text_line, NULL); | 156 g_list_foreach(view->list, free_text_line, NULL); |
142 g_list_free(view->list); | 157 g_list_free(view->list); |
158 g_list_foreach(view->tags, free_tag, NULL); | |
159 g_list_free(view->tags); | |
143 g_string_free(view->string, TRUE); | 160 g_string_free(view->string, TRUE); |
144 } | 161 } |
145 | 162 |
146 static gboolean | 163 static gboolean |
147 gnt_text_view_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | 164 gnt_text_view_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) |
295 return widget; | 312 return widget; |
296 } | 313 } |
297 | 314 |
298 void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags) | 315 void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags) |
299 { | 316 { |
317 gnt_text_view_append_text_with_tag(view, text, flags, NULL); | |
318 } | |
319 | |
320 void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text, | |
321 GntTextFormatFlags flags, const char *tagname) | |
322 { | |
300 GntWidget *widget = GNT_WIDGET(view); | 323 GntWidget *widget = GNT_WIDGET(view); |
301 int fl = 0; | 324 int fl = 0; |
302 const char *start, *end; | 325 const char *start, *end; |
303 GList *list = view->list; | 326 GList *list = view->list; |
304 GntTextLine *line; | 327 GntTextLine *line; |
309 | 332 |
310 fl = gnt_text_format_flag_to_chtype(flags); | 333 fl = gnt_text_format_flag_to_chtype(flags); |
311 | 334 |
312 len = view->string->len; | 335 len = view->string->len; |
313 view->string = g_string_append(view->string, text); | 336 view->string = g_string_append(view->string, text); |
337 | |
338 if (tagname) { | |
339 GntTextTag *tag = g_new0(GntTextTag, 1); | |
340 tag->name = g_strdup(tagname); | |
341 tag->start = len; | |
342 tag->end = view->string->len; | |
343 view->tags = g_list_append(view->tags, tag); | |
344 } | |
314 | 345 |
315 view->list = g_list_first(view->list); | 346 view->list = g_list_first(view->list); |
316 | 347 |
317 start = end = view->string->str + len; | 348 start = end = view->string->str + len; |
318 | 349 |
469 while ((list = list->next)) | 500 while ((list = list->next)) |
470 ++above; | 501 ++above; |
471 return above; | 502 return above; |
472 } | 503 } |
473 | 504 |
505 /** | |
506 * XXX: There are quite possibly more than a few bugs here. | |
507 */ | |
508 int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all) | |
509 { | |
510 GList *list, *next, *iter, *inext; | |
511 int count = 0; | |
512 for (list = view->tags; list; list = next) { | |
513 GntTextTag *tag = list->data; | |
514 next = list->next; | |
515 if (strcmp(tag->name, name) == 0) { | |
516 int change; | |
517 char *before, *after; | |
518 | |
519 count++; | |
520 | |
521 before = g_strndup(view->string->str, tag->start); | |
522 after = g_strdup(view->string->str + tag->end); | |
523 change = (tag->end - tag->start) - (text ? strlen(text) : 0); | |
524 | |
525 g_string_printf(view->string, "%s%s%s", before, text ? text : "", after); | |
526 g_free(before); | |
527 g_free(after); | |
528 | |
529 /* Update the offsets of the next tags */ | |
530 for (iter = next; iter; iter = iter->next) { | |
531 GntTextTag *t = iter->data; | |
532 t->start -= change; | |
533 t->end -= change; | |
534 } | |
535 | |
536 /* Update the offsets of the segments */ | |
537 for (iter = view->list; iter; iter = inext) { | |
538 GList *segs, *snext; | |
539 GntTextLine *line = iter->data; | |
540 inext = iter->next; | |
541 for (segs = line->segments; segs; segs = snext) { | |
542 GntTextSegment *seg = segs->data; | |
543 snext = segs->next; | |
544 if (seg->start >= tag->end) { | |
545 seg->start -= change; | |
546 seg->end -= change; | |
547 continue; | |
548 } | |
549 if (seg->end < tag->start) | |
550 continue; | |
551 | |
552 if (seg->start >= tag->start && seg->end <= tag->end) { | |
553 free_text_segment(seg, NULL); | |
554 line->segments = g_list_delete_link(line->segments, segs); | |
555 if (line->segments == NULL) { | |
556 free_text_line(line, NULL); | |
557 view->list = g_list_delete_link(view->list, iter); | |
558 } | |
559 } | |
560 /* XXX: handle the rest of the conditions */ | |
561 } | |
562 } | |
563 if (text == NULL) { | |
564 /* Remove the tag */ | |
565 view->tags = g_list_delete_link(view->tags, list); | |
566 free_tag(tag, NULL); | |
567 } | |
568 if (!all) | |
569 break; | |
570 } | |
571 } | |
572 return count; | |
573 } | |
574 |