Mercurial > pidgin
comparison src/gtkimhtml.c @ 4032:2b3a9d8f168e
[gaim-migrate @ 4238]
Smileys. These are just the default smileys--I'm adding the prpl-specific smileys right now.
If you want to help by creating some png's, IM me.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Tue, 03 Dec 2002 02:02:16 +0000 |
parents | 23c430e780eb |
children | 3a36ec242415 |
comparison
equal
deleted
inserted
replaced
4031:ec7e8c93c2ee | 4032:2b3a9d8f168e |
---|---|
45 struct _FontDetail { | 45 struct _FontDetail { |
46 gushort size; | 46 gushort size; |
47 gchar *face; | 47 gchar *face; |
48 gchar *fore; | 48 gchar *fore; |
49 gchar *back; | 49 gchar *back; |
50 gchar *sml; | |
50 }; | 51 }; |
52 | |
53 struct _GtkSmileyTree { | |
54 GString *values; | |
55 GtkSmileyTree **children; | |
56 gchar *image; | |
57 }; | |
58 | |
59 static GtkSmileyTree* | |
60 gtk_smiley_tree_new () | |
61 { | |
62 return g_new0 (GtkSmileyTree, 1); | |
63 } | |
64 | |
65 static void | |
66 gtk_smiley_tree_insert (GtkSmileyTree *tree, | |
67 const gchar *text, | |
68 const gchar *path) | |
69 { | |
70 GtkSmileyTree *t = tree; | |
71 const gchar *x = text; | |
72 | |
73 if (!strlen (x)) | |
74 return; | |
75 | |
76 while (*x) { | |
77 gchar *pos; | |
78 gint index; | |
79 | |
80 if (!t->values) | |
81 t->values = g_string_new (""); | |
82 | |
83 pos = strchr (t->values->str, *x); | |
84 if (!pos) { | |
85 t->values = g_string_append_c (t->values, *x); | |
86 index = t->values->len - 1; | |
87 t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); | |
88 t->children [index] = g_new0 (GtkSmileyTree, 1); | |
89 } else | |
90 index = (int) pos - (int) t->values->str; | |
91 | |
92 t = t->children [index]; | |
93 | |
94 x++; | |
95 } | |
96 | |
97 t->image = path; | |
98 } | |
99 gtk_smiley_tree_destroy (GtkSmileyTree *tree) | |
100 { | |
101 GSList *list = g_slist_append (NULL, tree); | |
102 | |
103 while (list) { | |
104 GtkSmileyTree *t = list->data; | |
105 gint i; | |
106 list = g_slist_remove(list, t); | |
107 if (t->values) { | |
108 for (i = 0; i < t->values->len; i++) | |
109 list = g_slist_append (list, t->children [i]); | |
110 g_string_free (t->values, TRUE); | |
111 g_free (t->children); | |
112 } | |
113 g_free (t); | |
114 } | |
115 } | |
116 | |
117 static GtkTextViewClass *parent_class = NULL; | |
118 | |
51 | 119 |
52 /* GtkIMHtml has one signal--URL_CLICKED */ | 120 /* GtkIMHtml has one signal--URL_CLICKED */ |
53 enum { | 121 enum { |
54 URL_CLICKED, | 122 URL_CLICKED, |
55 LAST_SIGNAL | 123 LAST_SIGNAL |
56 }; | 124 }; |
57 static guint signals [LAST_SIGNAL] = { 0 }; | 125 static guint signals [LAST_SIGNAL] = { 0 }; |
58 | 126 |
127 static void | |
128 gtk_imhtml_finalize (GObject *object) | |
129 { | |
130 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
131 | |
132 g_hash_table_foreach_remove(imhtml->smiley_data, gtk_smiley_tree_destroy, NULL); | |
133 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
134 G_OBJECT_CLASS(parent_class)->finalize (object); | |
135 } | |
59 | 136 |
60 /* Boring GTK stuff */ | 137 /* Boring GTK stuff */ |
61 static void gtk_imhtml_class_init (GtkIMHtmlClass *class) | 138 static void gtk_imhtml_class_init (GtkIMHtmlClass *class) |
62 { | 139 { |
63 GtkObjectClass *object_class; | 140 GtkObjectClass *object_class; |
141 GObjectClass *gobject_class; | |
64 object_class = (GtkObjectClass*) class; | 142 object_class = (GtkObjectClass*) class; |
143 gobject_class = (GObjectClass*) class; | |
144 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); | |
65 signals[URL_CLICKED] = gtk_signal_new("url_clicked", | 145 signals[URL_CLICKED] = gtk_signal_new("url_clicked", |
66 GTK_RUN_FIRST, | 146 GTK_RUN_FIRST, |
67 GTK_CLASS_TYPE(object_class), | 147 GTK_CLASS_TYPE(object_class), |
68 GTK_SIGNAL_OFFSET(GtkIMHtmlClass, url_clicked), | 148 GTK_SIGNAL_OFFSET(GtkIMHtmlClass, url_clicked), |
69 gtk_marshal_NONE__POINTER, | 149 gtk_marshal_NONE__POINTER, |
70 GTK_TYPE_NONE, 1, | 150 GTK_TYPE_NONE, 1, |
71 GTK_TYPE_POINTER); | 151 GTK_TYPE_POINTER); |
152 gobject_class->finalize = gtk_imhtml_finalize; | |
72 } | 153 } |
73 | 154 |
74 static void gtk_imhtml_init (GtkIMHtml *imhtml) | 155 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
75 { | 156 { |
76 GtkTextIter iter; | 157 GtkTextIter iter; |
96 | 177 |
97 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ | 178 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
98 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | 179 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); |
99 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | 180 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); |
100 | 181 |
182 imhtml->smiley_data = g_hash_table_new (g_str_hash, g_str_equal); | |
183 imhtml->default_smilies = gtk_smiley_tree_new(); | |
101 } | 184 } |
102 | 185 |
103 GtkWidget *gtk_imhtml_new(void *a, void *b) | 186 GtkWidget *gtk_imhtml_new(void *a, void *b) |
104 { | 187 { |
105 return GTK_WIDGET(gtk_type_new(gtk_imhtml_get_type())); | 188 return GTK_WIDGET(gtk_type_new(gtk_imhtml_get_type())); |
137 } else if (event->type == GDK_LEAVE_NOTIFY) { | 220 } else if (event->type == GDK_LEAVE_NOTIFY) { |
138 /* clear timeout and make an arrow cursor again --if GTK worked as it should */ | 221 /* clear timeout and make an arrow cursor again --if GTK worked as it should */ |
139 } | 222 } |
140 } | 223 } |
141 | 224 |
225 static void | |
226 gtk_smiley_tree_remove (GtkSmileyTree *tree, | |
227 const gchar *text) | |
228 { | |
229 GtkSmileyTree *t = tree; | |
230 const gchar *x = text; | |
231 gint len = 0; | |
232 | |
233 while (*x) { | |
234 gchar *pos; | |
235 | |
236 if (!t->values) | |
237 return; | |
238 | |
239 pos = strchr (t->values->str, *x); | |
240 if (pos) | |
241 t = t->children [(int) pos - (int) t->values->str]; | |
242 else | |
243 return; | |
244 | |
245 x++; len++; | |
246 } | |
247 | |
248 if (t->image) | |
249 t->image = NULL; | |
250 } | |
251 | |
252 static gint | |
253 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
254 const gchar *text) | |
255 { | |
256 GtkSmileyTree *t = tree; | |
257 const gchar *x = text; | |
258 gint len = 0; | |
259 | |
260 while (*x) { | |
261 gchar *pos; | |
262 | |
263 if (!t->values) | |
264 break; | |
265 | |
266 pos = strchr (t->values->str, *x); | |
267 if (pos) | |
268 t = t->children [(int) pos - (int) t->values->str]; | |
269 else | |
270 break; | |
271 | |
272 x++; len++; | |
273 } | |
274 | |
275 if (t->image) | |
276 return len; | |
277 | |
278 return 0; | |
279 } | |
280 | |
281 void | |
282 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, | |
283 gchar *text, | |
284 gchar *sml, | |
285 gchar *path) | |
286 { | |
287 GtkSmileyTree *tree; | |
288 g_return_if_fail (imhtml != NULL); | |
289 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
290 g_return_if_fail (text != NULL); | |
291 | |
292 if (sml == NULL) | |
293 tree = imhtml->default_smilies; | |
294 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
295 } else { | |
296 tree = gtk_smiley_tree_new(); | |
297 g_hash_table_insert(imhtml->smiley_data, sml, tree); | |
298 } | |
299 | |
300 if (path == NULL) | |
301 gtk_smiley_tree_remove (tree, text); | |
302 else | |
303 gtk_smiley_tree_insert (tree, text, path); | |
304 } | |
305 | |
306 static gboolean | |
307 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
308 GSList *fonts, | |
309 const gchar *text, | |
310 gint *len) | |
311 { | |
312 GtkSmileyTree *tree; | |
313 FontDetail *font; | |
314 char *sml = NULL; | |
315 | |
316 if (fonts) { | |
317 font = fonts->data; | |
318 sml = font->sml; | |
319 } | |
320 | |
321 if (sml == NULL) | |
322 tree = imhtml->default_smilies; | |
323 else { | |
324 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
325 } | |
326 if (tree == NULL) | |
327 return FALSE; | |
328 | |
329 *len = gtk_smiley_tree_lookup (tree, text); | |
330 return (*len > 0); | |
331 } | |
332 | |
333 static gchar* | |
334 gtk_smiley_tree_image (GtkIMHtml *imhtml, | |
335 const gchar *sml, | |
336 const gchar *text) | |
337 { | |
338 GtkSmileyTree *t; | |
339 const gchar *x = text; | |
340 | |
341 if (sml == NULL) | |
342 t = imhtml->default_smilies; | |
343 else | |
344 t = g_hash_table_lookup(imhtml->smiley_data, sml); | |
345 | |
346 | |
347 if (t == NULL) | |
348 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
349 | |
350 while (*x) { | |
351 gchar *pos; | |
352 | |
353 if (!t->values) { | |
354 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
355 } | |
356 | |
357 pos = strchr (t->values->str, *x); | |
358 if (pos) { | |
359 t = t->children [(int) pos - (int) t->values->str]; | |
360 } else { | |
361 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
362 } | |
363 x++; | |
364 } | |
365 | |
366 return t->image; | |
367 } | |
142 #define VALID_TAG(x) if (!g_strncasecmp (string, x ">", strlen (x ">"))) { \ | 368 #define VALID_TAG(x) if (!g_strncasecmp (string, x ">", strlen (x ">"))) { \ |
143 *tag = g_strndup (string, strlen (x)); \ | 369 *tag = g_strndup (string, strlen (x)); \ |
144 *len = strlen (x) + 1; \ | 370 *len = strlen (x) + 1; \ |
145 return TRUE; \ | 371 return TRUE; \ |
146 } \ | 372 } \ |
412 GtkRequisition req; | 638 GtkRequisition req; |
413 gchar *ws; | 639 gchar *ws; |
414 gchar *tag; | 640 gchar *tag; |
415 gchar *url = NULL; | 641 gchar *url = NULL; |
416 gchar *bg = NULL; | 642 gchar *bg = NULL; |
417 gint tlen, wpos=0; | 643 gint tlen, smilelen, wpos=0; |
418 gint type; | 644 gint type; |
419 const gchar *c; | 645 const gchar *c; |
420 gchar amp; | 646 gchar amp; |
421 | 647 |
422 guint bold = 0, | 648 guint bold = 0, |
555 g_free (font->face); | 781 g_free (font->face); |
556 if (font->fore) | 782 if (font->fore) |
557 g_free (font->fore); | 783 g_free (font->fore); |
558 if (font->back) | 784 if (font->back) |
559 g_free (font->back); | 785 g_free (font->back); |
786 if (font->sml) | |
787 g_free (font->sml); | |
560 g_free (font); | 788 g_free (font); |
561 } | 789 } |
562 break; | 790 break; |
563 case 28: /* /A */ | 791 case 28: /* /A */ |
564 if (url) { | 792 if (url) { |
582 case 40: /* BINARY */ | 810 case 40: /* BINARY */ |
583 case 41: /* /BINARY */ | 811 case 41: /* /BINARY */ |
584 break; | 812 break; |
585 case 43: /* FONT (opt) */ | 813 case 43: /* FONT (opt) */ |
586 { | 814 { |
587 gchar *color, *back, *face, *size; | 815 gchar *color, *back, *face, *size, *sml; |
588 FontDetail *font, *oldfont = NULL; | 816 FontDetail *font, *oldfont = NULL; |
589 color = gtk_imhtml_get_html_opt (tag, "COLOR="); | 817 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
590 back = gtk_imhtml_get_html_opt (tag, "BACK="); | 818 back = gtk_imhtml_get_html_opt (tag, "BACK="); |
591 face = gtk_imhtml_get_html_opt (tag, "FACE="); | 819 face = gtk_imhtml_get_html_opt (tag, "FACE="); |
592 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | 820 size = gtk_imhtml_get_html_opt (tag, "SIZE="); |
593 | 821 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
594 if (!(color || back || face || size)) | 822 if (!(color || back || face || size || sml)) |
595 break; | 823 break; |
596 | 824 |
597 NEW_BIT (NEW_TEXT_BIT); | 825 NEW_BIT (NEW_TEXT_BIT); |
598 | 826 |
599 font = g_new0 (FontDetail, 1); | 827 font = g_new0 (FontDetail, 1); |
612 | 840 |
613 if (face && !(options & GTK_IMHTML_NO_FONTS)) | 841 if (face && !(options & GTK_IMHTML_NO_FONTS)) |
614 font->face = face; | 842 font->face = face; |
615 else if (oldfont && oldfont->face) | 843 else if (oldfont && oldfont->face) |
616 font->face = g_strdup(oldfont->face); | 844 font->face = g_strdup(oldfont->face); |
617 | 845 |
846 if (sml) | |
847 font->sml = sml; | |
848 else if (oldfont && oldfont->sml) | |
849 font->sml = g_strdup(oldfont->sml); | |
850 | |
618 if (size && !(options & GTK_IMHTML_NO_SIZES)) { | 851 if (size && !(options & GTK_IMHTML_NO_SIZES)) { |
619 if (*size == '+') { | 852 if (*size == '+') { |
620 sscanf (size + 1, "%hd", &font->size); | 853 sscanf (size + 1, "%hd", &font->size); |
621 font->size += 3; | 854 font->size += 3; |
622 } else if (*size == '-') { | 855 } else if (*size == '-') { |
676 wpos++; | 909 wpos++; |
677 NEW_BIT (NEW_TEXT_BIT); | 910 NEW_BIT (NEW_TEXT_BIT); |
678 } | 911 } |
679 c++; | 912 c++; |
680 pos++; | 913 pos++; |
681 } else if (*c) { | 914 } else if (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen)) { |
915 FontDetail *fd; | |
916 gchar *sml = NULL; | |
917 if (fonts) { | |
918 fd = fonts->data; | |
919 sml = fd->sml; | |
920 } | |
921 NEW_BIT (NEW_TEXT_BIT); | |
922 wpos = g_snprintf (ws, smilelen + 1, "%s", c); | |
923 gtk_text_buffer_insert_pixbuf(imhtml->text_buffer, &iter, gdk_pixbuf_new_from_file(gtk_smiley_tree_image (imhtml, sml, ws), NULL)); | |
924 c += smilelen; | |
925 pos += smilelen; | |
926 wpos = 0; | |
927 ws[0] = 0; | |
928 } else if (*c) { | |
682 ws [wpos++] = *c++; | 929 ws [wpos++] = *c++; |
683 pos++; | 930 pos++; |
684 } else { | 931 } else { |
685 break; | 932 break; |
686 } | 933 } |
691 g_free (url); | 938 g_free (url); |
692 if (str) | 939 if (str) |
693 str = g_string_append (str, "</A>"); | 940 str = g_string_append (str, "</A>"); |
694 } | 941 } |
695 | 942 |
943 while (fonts) { | |
944 FontDetail *font = fonts->data; | |
945 fonts = g_slist_remove (fonts, font); | |
946 if (font->face) | |
947 g_free (font->face); | |
948 if (font->fore) | |
949 g_free (font->fore); | |
950 if (font->back) | |
951 g_free (font->back); | |
952 if (font->sml) | |
953 g_free (font->sml); | |
954 g_free (font); | |
955 if (str) | |
956 str = g_string_append (str, "</FONT>"); | |
957 } | |
958 | |
696 if (str) { | 959 if (str) { |
697 while (bold) { | 960 while (bold) { |
698 str = g_string_append (str, "</B>"); | 961 str = g_string_append (str, "</B>"); |
699 bold--; | 962 bold--; |
700 } | 963 } |
725 while (pre) { | 988 while (pre) { |
726 str = g_string_append (str, "</PRE>"); | 989 str = g_string_append (str, "</PRE>"); |
727 pre--; | 990 pre--; |
728 } | 991 } |
729 } | 992 } |
730 g_free(ws); | 993 g_free (ws); |
731 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | 994 if (!(options & GTK_IMHTML_NO_SCROLL)) |
732 0, TRUE, 0.0, 1.0); | 995 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, |
996 0, TRUE, 0.0, 1.0); | |
733 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); | 997 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); |
734 return str; | 998 return str; |
735 } | 999 } |
736 | 1000 |
737 void gtk_imhtml_set_adjustments (GtkIMHtml *imhtml, | 1001 void gtk_imhtml_set_adjustments (GtkIMHtml *imhtml, |
744 GdkColor *bg_color){} | 1008 GdkColor *bg_color){} |
745 | 1009 |
746 void gtk_imhtml_set_img_handler (GtkIMHtml *imhtml, | 1010 void gtk_imhtml_set_img_handler (GtkIMHtml *imhtml, |
747 GtkIMHtmlImage handler){} | 1011 GtkIMHtmlImage handler){} |
748 | 1012 |
749 void gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, | |
750 gchar *text, | |
751 gchar **xpm){} | |
752 void gtk_imhtml_init_smileys (GtkIMHtml *imhtml){} | 1013 void gtk_imhtml_init_smileys (GtkIMHtml *imhtml){} |
753 void gtk_imhtml_remove_smileys (GtkIMHtml *imhtml){} | 1014 void gtk_imhtml_remove_smileys (GtkIMHtml *imhtml){} |
754 void gtk_imhtml_reset_smileys (GtkIMHtml *imhtml){} | 1015 void gtk_imhtml_reset_smileys (GtkIMHtml *imhtml){} |
755 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, | 1016 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
756 gboolean show){} | 1017 gboolean show){} |