Mercurial > pidgin.yaz
comparison gtk/gtkdebug.c @ 20389:e354528c4163
propagate from branch 'im.pidgin.gaim' (head 70ac931e4936c7916eec18a07fe46a0af0fd7403)
to branch 'im.pidgin.rlaager.merging.soc-msnp13-to-svn18164' (head 5b5cde92182d2a922a8e7e6c2308342a5490a8c9)
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 15 Apr 2007 02:10:37 +0000 |
parents | aca9a7b62a23 |
children |
comparison
equal
deleted
inserted
replaced
19796:21cb7a79ac7f | 20389:e354528c4163 |
---|---|
1 /** | |
2 * @file gtkdebug.c GTK+ Debug API | |
3 * @ingroup gtkui | |
4 * | |
5 * gaim | |
6 * | |
7 * Gaim is the legal property of its developers, whose names are too numerous | |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 #include "internal.h" | |
26 #include "gtkgaim.h" | |
27 | |
28 #include "notify.h" | |
29 #include "prefs.h" | |
30 #include "request.h" | |
31 #include "util.h" | |
32 | |
33 #include "gtkdebug.h" | |
34 #include "gtkdialogs.h" | |
35 #include "gtkimhtml.h" | |
36 #include "gtkutils.h" | |
37 #include "gaimstock.h" | |
38 | |
39 #ifdef HAVE_REGEX_H | |
40 # include <regex.h> | |
41 #endif /* HAVE_REGEX_H */ | |
42 | |
43 #include <gdk/gdkkeysyms.h> | |
44 | |
45 typedef struct | |
46 { | |
47 GtkWidget *window; | |
48 GtkWidget *text; | |
49 | |
50 GtkListStore *store; | |
51 | |
52 gboolean timestamps; | |
53 gboolean paused; | |
54 | |
55 #ifdef HAVE_REGEX_H | |
56 GtkWidget *filter; | |
57 GtkWidget *expression; | |
58 | |
59 gboolean invert; | |
60 gboolean highlight; | |
61 | |
62 guint timer; | |
63 | |
64 regex_t regex; | |
65 #else | |
66 GtkWidget *find; | |
67 #endif /* HAVE_REGEX_H */ | |
68 GtkWidget *filterlevel; | |
69 } DebugWindow; | |
70 | |
71 static char debug_fg_colors[][8] = { | |
72 "#000000", /**< All debug levels. */ | |
73 "#666666", /**< Misc. */ | |
74 "#000000", /**< Information. */ | |
75 "#660000", /**< Warnings. */ | |
76 "#FF0000", /**< Errors. */ | |
77 "#FF0000", /**< Fatal errors. */ | |
78 }; | |
79 | |
80 static DebugWindow *debug_win = NULL; | |
81 | |
82 #ifdef HAVE_REGEX_H | |
83 static void regex_filter_all(DebugWindow *win); | |
84 static void regex_show_all(DebugWindow *win); | |
85 #endif /* HAVE_REGEX_H */ | |
86 | |
87 static gint | |
88 debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused) | |
89 { | |
90 gaim_prefs_disconnect_by_handle(gaim_gtk_debug_get_handle()); | |
91 | |
92 #ifdef HAVE_REGEX_H | |
93 if(debug_win->timer != 0) { | |
94 const gchar *text; | |
95 | |
96 g_source_remove(debug_win->timer); | |
97 | |
98 text = gtk_entry_get_text(GTK_ENTRY(debug_win->expression)); | |
99 gaim_prefs_set_string("/gaim/gtk/debug/regex", text); | |
100 } | |
101 | |
102 regfree(&debug_win->regex); | |
103 #endif | |
104 | |
105 /* If the "Save Log" dialog is open then close it */ | |
106 gaim_request_close_with_handle(debug_win); | |
107 | |
108 g_free(debug_win); | |
109 debug_win = NULL; | |
110 | |
111 gaim_prefs_set_bool("/gaim/gtk/debug/enabled", FALSE); | |
112 | |
113 return FALSE; | |
114 } | |
115 | |
116 static gboolean | |
117 configure_cb(GtkWidget *w, GdkEventConfigure *event, DebugWindow *win) | |
118 { | |
119 if (GTK_WIDGET_VISIBLE(w)) { | |
120 gaim_prefs_set_int("/gaim/gtk/debug/width", event->width); | |
121 gaim_prefs_set_int("/gaim/gtk/debug/height", event->height); | |
122 } | |
123 | |
124 return FALSE; | |
125 } | |
126 | |
127 #ifndef HAVE_REGEX_H | |
128 struct _find { | |
129 DebugWindow *window; | |
130 GtkWidget *entry; | |
131 }; | |
132 | |
133 static void | |
134 do_find_cb(GtkWidget *widget, gint response, struct _find *f) | |
135 { | |
136 switch (response) { | |
137 case GTK_RESPONSE_OK: | |
138 gtk_imhtml_search_find(GTK_IMHTML(f->window->text), | |
139 gtk_entry_get_text(GTK_ENTRY(f->entry))); | |
140 break; | |
141 | |
142 case GTK_RESPONSE_DELETE_EVENT: | |
143 case GTK_RESPONSE_CLOSE: | |
144 gtk_imhtml_search_clear(GTK_IMHTML(f->window->text)); | |
145 gtk_widget_destroy(f->window->find); | |
146 f->window->find = NULL; | |
147 g_free(f); | |
148 break; | |
149 } | |
150 } | |
151 | |
152 static void | |
153 find_cb(GtkWidget *w, DebugWindow *win) | |
154 { | |
155 GtkWidget *hbox, *img, *label; | |
156 struct _find *f; | |
157 | |
158 if(win->find) | |
159 { | |
160 gtk_window_present(GTK_WINDOW(win->find)); | |
161 return; | |
162 } | |
163 | |
164 f = g_malloc(sizeof(struct _find)); | |
165 f->window = win; | |
166 win->find = gtk_dialog_new_with_buttons(_("Find"), | |
167 GTK_WINDOW(win->window), GTK_DIALOG_DESTROY_WITH_PARENT, | |
168 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, | |
169 GTK_STOCK_FIND, GTK_RESPONSE_OK, NULL); | |
170 gtk_dialog_set_default_response(GTK_DIALOG(win->find), | |
171 GTK_RESPONSE_OK); | |
172 g_signal_connect(G_OBJECT(win->find), "response", | |
173 G_CALLBACK(do_find_cb), f); | |
174 | |
175 gtk_container_set_border_width(GTK_CONTAINER(win->find), GAIM_HIG_BOX_SPACE); | |
176 gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE); | |
177 gtk_dialog_set_has_separator(GTK_DIALOG(win->find), FALSE); | |
178 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), GAIM_HIG_BORDER); | |
179 gtk_container_set_border_width( | |
180 GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), GAIM_HIG_BOX_SPACE); | |
181 | |
182 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); | |
183 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), | |
184 hbox); | |
185 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
186 GTK_ICON_SIZE_DIALOG); | |
187 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
188 | |
189 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
190 gtk_dialog_set_response_sensitive(GTK_DIALOG(win->find), | |
191 GTK_RESPONSE_OK, FALSE); | |
192 | |
193 label = gtk_label_new(NULL); | |
194 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Search for:")); | |
195 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
196 | |
197 f->entry = gtk_entry_new(); | |
198 gtk_entry_set_activates_default(GTK_ENTRY(f->entry), TRUE); | |
199 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(f->entry)); | |
200 g_signal_connect(G_OBJECT(f->entry), "changed", | |
201 G_CALLBACK(gaim_gtk_set_sensitive_if_input), | |
202 win->find); | |
203 gtk_box_pack_start(GTK_BOX(hbox), f->entry, FALSE, FALSE, 0); | |
204 | |
205 gtk_widget_show_all(win->find); | |
206 gtk_widget_grab_focus(f->entry); | |
207 } | |
208 #endif /* HAVE_REGEX_H */ | |
209 | |
210 static void | |
211 save_writefile_cb(void *user_data, const char *filename) | |
212 { | |
213 DebugWindow *win = (DebugWindow *)user_data; | |
214 FILE *fp; | |
215 char *tmp; | |
216 | |
217 if ((fp = g_fopen(filename, "w+")) == NULL) { | |
218 gaim_notify_error(win, NULL, _("Unable to open file."), NULL); | |
219 return; | |
220 } | |
221 | |
222 tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL); | |
223 fprintf(fp, "Gaim Debug Log : %s\n", gaim_date_format_full(NULL)); | |
224 fprintf(fp, "%s", tmp); | |
225 g_free(tmp); | |
226 | |
227 fclose(fp); | |
228 } | |
229 | |
230 static void | |
231 save_cb(GtkWidget *w, DebugWindow *win) | |
232 { | |
233 gaim_request_file(win, _("Save Debug Log"), "gaim-debug.log", TRUE, | |
234 G_CALLBACK(save_writefile_cb), NULL, win); | |
235 } | |
236 | |
237 static void | |
238 clear_cb(GtkWidget *w, DebugWindow *win) | |
239 { | |
240 gtk_imhtml_clear(GTK_IMHTML(win->text)); | |
241 | |
242 #ifdef HAVE_REGEX_H | |
243 gtk_list_store_clear(win->store); | |
244 #endif /* HAVE_REGEX_H */ | |
245 } | |
246 | |
247 static void | |
248 pause_cb(GtkWidget *w, DebugWindow *win) | |
249 { | |
250 win->paused = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); | |
251 | |
252 #ifdef HAVE_REGEX_H | |
253 if(!win->paused) { | |
254 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) | |
255 regex_filter_all(win); | |
256 else | |
257 regex_show_all(win); | |
258 } | |
259 #endif /* HAVE_REGEX_H */ | |
260 } | |
261 | |
262 static void | |
263 timestamps_cb(GtkWidget *w, DebugWindow *win) | |
264 { | |
265 win->timestamps = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); | |
266 | |
267 gaim_prefs_set_bool("/core/debug/timestamps", win->timestamps); | |
268 } | |
269 | |
270 static void | |
271 timestamps_pref_cb(const char *name, GaimPrefType type, | |
272 gconstpointer value, gpointer data) | |
273 { | |
274 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), GPOINTER_TO_INT(value)); | |
275 } | |
276 | |
277 /****************************************************************************** | |
278 * regex stuff | |
279 *****************************************************************************/ | |
280 #ifdef HAVE_REGEX_H | |
281 static void | |
282 regex_clear_color(GtkWidget *w) { | |
283 gtk_widget_modify_base(w, GTK_STATE_NORMAL, NULL); | |
284 } | |
285 | |
286 static void | |
287 regex_change_color(GtkWidget *w, guint16 r, guint16 g, guint16 b) { | |
288 GdkColor color; | |
289 | |
290 color.red = r; | |
291 color.green = g; | |
292 color.blue = b; | |
293 | |
294 gtk_widget_modify_base(w, GTK_STATE_NORMAL, &color); | |
295 } | |
296 | |
297 static void | |
298 regex_highlight_clear(DebugWindow *win) { | |
299 GtkIMHtml *imhtml = GTK_IMHTML(win->text); | |
300 GtkTextIter s, e; | |
301 | |
302 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &s); | |
303 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &e); | |
304 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "regex", &s, &e); | |
305 } | |
306 | |
307 static void | |
308 regex_match(DebugWindow *win, const gchar *text) { | |
309 GtkIMHtml *imhtml = GTK_IMHTML(win->text); | |
310 regmatch_t matches[4]; /* adjust if necessary */ | |
311 size_t n_matches = sizeof(matches) / sizeof(matches[0]); | |
312 gchar *plaintext; | |
313 gint inverted; | |
314 | |
315 if(!text) | |
316 return; | |
317 | |
318 inverted = (win->invert) ? REG_NOMATCH : 0; | |
319 | |
320 /* I don't like having to do this, but we need it for highlighting. Plus | |
321 * it makes the ^ and $ operators work :) | |
322 */ | |
323 plaintext = gaim_markup_strip_html(text); | |
324 | |
325 /* we do a first pass to see if it matches at all. If it does we append | |
326 * it, and work out the offsets to highlight. | |
327 */ | |
328 if(regexec(&win->regex, plaintext, n_matches, matches, 0) == inverted) { | |
329 GtkTextIter ins; | |
330 gchar *p = plaintext; | |
331 gint i, offset = 0; | |
332 | |
333 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, | |
334 gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
335 i = gtk_text_iter_get_offset(&ins); | |
336 | |
337 gtk_imhtml_append_text(imhtml, text, 0); | |
338 | |
339 /* If we're not highlighting or the expression is inverted, we're | |
340 * done and move on. | |
341 */ | |
342 if(!win->highlight || inverted == REG_NOMATCH) { | |
343 g_free(plaintext); | |
344 return; | |
345 } | |
346 | |
347 /* we use a do-while to highlight the first match, and then continue | |
348 * if necessary... | |
349 */ | |
350 do { | |
351 size_t m; | |
352 | |
353 for(m = 0; m < n_matches; m++) { | |
354 GtkTextIter ms, me; | |
355 | |
356 if(matches[m].rm_eo == -1) | |
357 break; | |
358 | |
359 i += offset; | |
360 | |
361 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms, | |
362 i + matches[m].rm_so); | |
363 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &me, | |
364 i + matches[m].rm_eo); | |
365 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "regex", | |
366 &ms, &me); | |
367 offset = matches[m].rm_eo; | |
368 } | |
369 | |
370 p += offset; | |
371 } while(regexec(&win->regex, p, n_matches, matches, REG_NOTBOL) == inverted); | |
372 } | |
373 | |
374 g_free(plaintext); | |
375 } | |
376 | |
377 static gboolean | |
378 regex_filter_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, | |
379 gpointer data) | |
380 { | |
381 DebugWindow *win = (DebugWindow *)data; | |
382 gchar *text; | |
383 GaimDebugLevel level; | |
384 | |
385 gtk_tree_model_get(m, iter, 0, &text, 1, &level, -1); | |
386 | |
387 if (level >= gaim_prefs_get_int("/gaim/gtk/debug/filterlevel")) | |
388 regex_match(win, text); | |
389 | |
390 g_free(text); | |
391 | |
392 return FALSE; | |
393 } | |
394 | |
395 static void | |
396 regex_filter_all(DebugWindow *win) { | |
397 gtk_imhtml_clear(GTK_IMHTML(win->text)); | |
398 | |
399 if(win->highlight) | |
400 regex_highlight_clear(win); | |
401 | |
402 gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_filter_all_cb, | |
403 win); | |
404 } | |
405 | |
406 static gboolean | |
407 regex_show_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, | |
408 gpointer data) | |
409 { | |
410 DebugWindow *win = (DebugWindow *)data; | |
411 gchar *text; | |
412 GaimDebugLevel level; | |
413 | |
414 gtk_tree_model_get(m, iter, 0, &text, 1, &level, -1); | |
415 if (level >= gaim_prefs_get_int("/gaim/gtk/debug/filterlevel")) | |
416 gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0); | |
417 g_free(text); | |
418 | |
419 return FALSE; | |
420 } | |
421 | |
422 static void | |
423 regex_show_all(DebugWindow *win) { | |
424 gtk_imhtml_clear(GTK_IMHTML(win->text)); | |
425 | |
426 if(win->highlight) | |
427 regex_highlight_clear(win); | |
428 | |
429 gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_show_all_cb, | |
430 win); | |
431 } | |
432 | |
433 static void | |
434 regex_compile(DebugWindow *win) { | |
435 const gchar *text; | |
436 | |
437 text = gtk_entry_get_text(GTK_ENTRY(win->expression)); | |
438 | |
439 if(text == NULL || *text == '\0') { | |
440 regex_clear_color(win->expression); | |
441 gtk_widget_set_sensitive(win->filter, FALSE); | |
442 return; | |
443 } | |
444 | |
445 regfree(&win->regex); | |
446 | |
447 if(regcomp(&win->regex, text, REG_EXTENDED | REG_ICASE) != 0) { | |
448 /* failed to compile */ | |
449 regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF); | |
450 gtk_widget_set_sensitive(win->filter, FALSE); | |
451 } else { | |
452 /* compiled successfully */ | |
453 regex_change_color(win->expression, 0xAFFF, 0xFFFF, 0xAFFF); | |
454 gtk_widget_set_sensitive(win->filter, TRUE); | |
455 } | |
456 | |
457 /* we check if the filter is on in case it was only of the options that | |
458 * got changed, and not the expression. | |
459 */ | |
460 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) | |
461 regex_filter_all(win); | |
462 } | |
463 | |
464 static void | |
465 regex_pref_filter_cb(const gchar *name, GaimPrefType type, | |
466 gconstpointer val, gpointer data) | |
467 { | |
468 DebugWindow *win = (DebugWindow *)data; | |
469 gboolean active = GPOINTER_TO_INT(val), current; | |
470 | |
471 if(!win || !win->window) | |
472 return; | |
473 | |
474 current = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)); | |
475 if(active != current) | |
476 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), active); | |
477 } | |
478 | |
479 static void | |
480 regex_pref_expression_cb(const gchar *name, GaimPrefType type, | |
481 gconstpointer val, gpointer data) | |
482 { | |
483 DebugWindow *win = (DebugWindow *)data; | |
484 const gchar *exp = (const gchar *)val; | |
485 | |
486 gtk_entry_set_text(GTK_ENTRY(win->expression), exp); | |
487 } | |
488 | |
489 static void | |
490 regex_pref_invert_cb(const gchar *name, GaimPrefType type, | |
491 gconstpointer val, gpointer data) | |
492 { | |
493 DebugWindow *win = (DebugWindow *)data; | |
494 gboolean active = GPOINTER_TO_INT(val); | |
495 | |
496 win->invert = active; | |
497 | |
498 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) | |
499 regex_filter_all(win); | |
500 } | |
501 | |
502 static void | |
503 regex_pref_highlight_cb(const gchar *name, GaimPrefType type, | |
504 gconstpointer val, gpointer data) | |
505 { | |
506 DebugWindow *win = (DebugWindow *)data; | |
507 gboolean active = GPOINTER_TO_INT(val); | |
508 | |
509 win->highlight = active; | |
510 | |
511 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) | |
512 regex_filter_all(win); | |
513 } | |
514 | |
515 static void | |
516 regex_row_changed_cb(GtkTreeModel *model, GtkTreePath *path, | |
517 GtkTreeIter *iter, DebugWindow *win) | |
518 { | |
519 gchar *text; | |
520 GaimDebugLevel level; | |
521 | |
522 if(!win || !win->window) | |
523 return; | |
524 | |
525 /* If the debug window is paused, we just return since it's in the store. | |
526 * We don't call regex_match because it doesn't make sense to check the | |
527 * string if it's paused. When we unpause we clear the imhtml and | |
528 * reiterate over the store to handle matches that were outputted when | |
529 * we were paused. | |
530 */ | |
531 if(win->paused) | |
532 return; | |
533 | |
534 gtk_tree_model_get(model, iter, 0, &text, 1, &level, -1); | |
535 | |
536 if (level >= gaim_prefs_get_int("/gaim/gtk/debug/filterlevel")) { | |
537 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) { | |
538 regex_match(win, text); | |
539 } else { | |
540 gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0); | |
541 } | |
542 } | |
543 | |
544 g_free(text); | |
545 } | |
546 | |
547 static gboolean | |
548 regex_timer_cb(DebugWindow *win) { | |
549 const gchar *text; | |
550 | |
551 text = gtk_entry_get_text(GTK_ENTRY(win->expression)); | |
552 gaim_prefs_set_string("/gaim/gtk/debug/regex", text); | |
553 | |
554 win->timer = 0; | |
555 | |
556 return FALSE; | |
557 } | |
558 | |
559 static void | |
560 regex_changed_cb(GtkWidget *w, DebugWindow *win) { | |
561 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) { | |
562 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), | |
563 FALSE); | |
564 } | |
565 | |
566 if(win->timer == 0) | |
567 win->timer = gaim_timeout_add(5000, (GSourceFunc)regex_timer_cb, win); | |
568 | |
569 regex_compile(win); | |
570 } | |
571 | |
572 static void | |
573 regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) { | |
574 if(e->keyval == GDK_Return && | |
575 GTK_WIDGET_IS_SENSITIVE(win->filter) && | |
576 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) | |
577 { | |
578 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), TRUE); | |
579 } | |
580 } | |
581 | |
582 static void | |
583 regex_menu_cb(GtkWidget *item, const gchar *pref) { | |
584 gboolean active; | |
585 | |
586 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)); | |
587 | |
588 gaim_prefs_set_bool(pref, active); | |
589 } | |
590 | |
591 static void | |
592 regex_popup_cb(GtkEntry *entry, GtkWidget *menu, DebugWindow *win) { | |
593 gaim_separator(menu); | |
594 gaim_new_check_item(menu, _("Invert"), | |
595 G_CALLBACK(regex_menu_cb), | |
596 "/gaim/gtk/debug/invert", win->invert); | |
597 gaim_new_check_item(menu, _("Highlight matches"), | |
598 G_CALLBACK(regex_menu_cb), | |
599 "/gaim/gtk/debug/highlight", win->highlight); | |
600 } | |
601 | |
602 static void | |
603 regex_filter_toggled_cb(GtkToggleButton *button, DebugWindow *win) { | |
604 gboolean active; | |
605 | |
606 active = gtk_toggle_button_get_active(button); | |
607 | |
608 gaim_prefs_set_bool("/gaim/gtk/debug/filter", active); | |
609 | |
610 if(!GTK_IS_IMHTML(win->text)) | |
611 return; | |
612 | |
613 if(active) | |
614 regex_filter_all(win); | |
615 else | |
616 regex_show_all(win); | |
617 } | |
618 | |
619 static void | |
620 filter_level_pref_changed(const char *name, GaimPrefType type, gconstpointer value, gpointer data) | |
621 { | |
622 DebugWindow *win = data; | |
623 | |
624 if (GPOINTER_TO_INT(value) != gtk_combo_box_get_active(GTK_COMBO_BOX(win->filterlevel))) | |
625 gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), GPOINTER_TO_INT(value)); | |
626 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) | |
627 regex_filter_all(win); | |
628 else | |
629 regex_show_all(win); | |
630 } | |
631 #endif /* HAVE_REGEX_H */ | |
632 | |
633 static void | |
634 filter_level_changed_cb(GtkWidget *combo, gpointer null) | |
635 { | |
636 gaim_prefs_set_int("/gaim/gtk/debug/filterlevel", | |
637 gtk_combo_box_get_active(GTK_COMBO_BOX(combo))); | |
638 } | |
639 | |
640 static void | |
641 toolbar_style_pref_changed_cb(const char *name, GaimPrefType type, gconstpointer value, gpointer data) | |
642 { | |
643 gtk_toolbar_set_style(GTK_TOOLBAR(data), GPOINTER_TO_INT(value)); | |
644 } | |
645 | |
646 static void | |
647 toolbar_icon_pref_changed(GtkWidget *item, GtkWidget *toolbar) | |
648 { | |
649 int style = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "user_data")); | |
650 gaim_prefs_set_int("/gaim/gtk/debug/style", style); | |
651 } | |
652 | |
653 static gboolean | |
654 toolbar_context(GtkWidget *toolbar, GdkEventButton *event, gpointer null) | |
655 { | |
656 GtkWidget *menu, *item; | |
657 const char *text[3]; | |
658 GtkToolbarStyle value[3]; | |
659 int i; | |
660 | |
661 if (!(event->button == 3 && event->type == GDK_BUTTON_PRESS)) | |
662 return FALSE; | |
663 | |
664 text[0] = _("_Icon Only"); value[0] = GTK_TOOLBAR_ICONS; | |
665 text[1] = _("_Text Only"); value[1] = GTK_TOOLBAR_TEXT; | |
666 text[2] = _("_Both Icon & Text"); value[2] = GTK_TOOLBAR_BOTH_HORIZ; | |
667 | |
668 menu = gtk_menu_new(); | |
669 | |
670 for (i = 0; i < 3; i++) { | |
671 item = gtk_check_menu_item_new_with_mnemonic(text[i]); | |
672 g_object_set_data(G_OBJECT(item), "user_data", GINT_TO_POINTER(value[i])); | |
673 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(toolbar_icon_pref_changed), toolbar); | |
674 if (value[i] == gaim_prefs_get_int("/gaim/gtk/debug/style")) | |
675 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); | |
676 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
677 } | |
678 | |
679 gtk_widget_show_all(menu); | |
680 | |
681 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); | |
682 return FALSE; | |
683 } | |
684 | |
685 static DebugWindow * | |
686 debug_window_new(void) | |
687 { | |
688 DebugWindow *win; | |
689 GtkWidget *vbox; | |
690 GtkWidget *toolbar; | |
691 GtkWidget *frame; | |
692 GtkWidget *button; | |
693 GtkWidget *image; | |
694 gint width, height; | |
695 void *handle; | |
696 | |
697 win = g_new0(DebugWindow, 1); | |
698 | |
699 width = gaim_prefs_get_int("/gaim/gtk/debug/width"); | |
700 height = gaim_prefs_get_int("/gaim/gtk/debug/height"); | |
701 | |
702 GAIM_DIALOG(win->window); | |
703 gaim_debug_info("gtkdebug", "Setting dimensions to %d, %d\n", | |
704 width, height); | |
705 | |
706 gtk_window_set_default_size(GTK_WINDOW(win->window), width, height); | |
707 gtk_window_set_role(GTK_WINDOW(win->window), "debug"); | |
708 gtk_window_set_title(GTK_WINDOW(win->window), _("Debug Window")); | |
709 | |
710 g_signal_connect(G_OBJECT(win->window), "delete_event", | |
711 G_CALLBACK(debug_window_destroy), NULL); | |
712 g_signal_connect(G_OBJECT(win->window), "configure_event", | |
713 G_CALLBACK(configure_cb), win); | |
714 | |
715 handle = gaim_gtk_debug_get_handle(); | |
716 | |
717 #ifdef HAVE_REGEX_H | |
718 /* the list store for all the messages */ | |
719 win->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); | |
720 | |
721 /* row-changed gets called when we do gtk_list_store_set, and row-inserted | |
722 * gets called with gtk_list_store_append, which is a | |
723 * completely empty row. So we just ignore row-inserted, and deal with row | |
724 * changed. -Gary | |
725 */ | |
726 g_signal_connect(G_OBJECT(win->store), "row-changed", | |
727 G_CALLBACK(regex_row_changed_cb), win); | |
728 | |
729 #endif /* HAVE_REGEX_H */ | |
730 | |
731 /* Setup the vbox */ | |
732 vbox = gtk_vbox_new(FALSE, 0); | |
733 gtk_container_add(GTK_CONTAINER(win->window), vbox); | |
734 | |
735 if (gaim_prefs_get_bool("/gaim/gtk/debug/toolbar")) { | |
736 /* Setup our top button bar thingie. */ | |
737 toolbar = gtk_toolbar_new(); | |
738 gtk_toolbar_set_tooltips(GTK_TOOLBAR(toolbar), TRUE); | |
739 #if GTK_CHECK_VERSION(2,4,0) | |
740 gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), TRUE); | |
741 #endif | |
742 g_signal_connect(G_OBJECT(toolbar), "button-press-event", G_CALLBACK(toolbar_context), win); | |
743 | |
744 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), | |
745 gaim_prefs_get_int("/gaim/gtk/debug/style")); | |
746 gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/style", | |
747 toolbar_style_pref_changed_cb, toolbar); | |
748 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), | |
749 GTK_ICON_SIZE_SMALL_TOOLBAR); | |
750 | |
751 gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); | |
752 | |
753 #ifndef HAVE_REGEX_H | |
754 /* Find button */ | |
755 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND, | |
756 _("Find"), NULL, G_CALLBACK(find_cb), | |
757 win, -1); | |
758 #endif /* HAVE_REGEX_H */ | |
759 | |
760 /* Save */ | |
761 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE, | |
762 _("Save"), NULL, G_CALLBACK(save_cb), | |
763 win, -1); | |
764 | |
765 /* Clear button */ | |
766 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR, | |
767 _("Clear"), NULL, G_CALLBACK(clear_cb), | |
768 win, -1); | |
769 | |
770 gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); | |
771 | |
772 /* Pause */ | |
773 image = gtk_image_new_from_stock(GAIM_STOCK_PAUSE, GTK_ICON_SIZE_MENU); | |
774 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
775 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, | |
776 NULL, _("Pause"), _("Pause"), | |
777 NULL, image, | |
778 G_CALLBACK(pause_cb), win); | |
779 | |
780 /* Timestamps */ | |
781 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
782 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, | |
783 NULL, _("Timestamps"), | |
784 _("Timestamps"), NULL, NULL, | |
785 G_CALLBACK(timestamps_cb), | |
786 win); | |
787 | |
788 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), | |
789 gaim_prefs_get_bool("/core/debug/timestamps")); | |
790 | |
791 gaim_prefs_connect_callback(handle, "/core/debug/timestamps", | |
792 timestamps_pref_cb, button); | |
793 | |
794 #ifdef HAVE_REGEX_H | |
795 /* regex stuff */ | |
796 gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); | |
797 | |
798 /* regex toggle button */ | |
799 win->filter = | |
800 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
801 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, | |
802 NULL, _("Filter"), _("Filter"), | |
803 NULL, NULL, | |
804 G_CALLBACK(regex_filter_toggled_cb), | |
805 win); | |
806 /* we purposely disable the toggle button here in case | |
807 * /gaim/gtk/debug/expression has an empty string. If it does not have | |
808 * an empty string, the change signal will get called and make the | |
809 * toggle button sensitive. | |
810 */ | |
811 gtk_widget_set_sensitive(win->filter, FALSE); | |
812 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), | |
813 gaim_prefs_get_bool("/gaim/gtk/debug/filter")); | |
814 gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/filter", | |
815 regex_pref_filter_cb, win); | |
816 | |
817 /* regex entry */ | |
818 win->expression = gtk_entry_new(); | |
819 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
820 GTK_TOOLBAR_CHILD_WIDGET, win->expression, | |
821 NULL, _("Right click for more options."), | |
822 NULL, NULL, NULL, NULL); | |
823 /* this needs to be before the text is set from the pref if we want it | |
824 * to colorize a stored expression. | |
825 */ | |
826 g_signal_connect(G_OBJECT(win->expression), "changed", | |
827 G_CALLBACK(regex_changed_cb), win); | |
828 gtk_entry_set_text(GTK_ENTRY(win->expression), | |
829 gaim_prefs_get_string("/gaim/gtk/debug/regex")); | |
830 g_signal_connect(G_OBJECT(win->expression), "populate-popup", | |
831 G_CALLBACK(regex_popup_cb), win); | |
832 g_signal_connect(G_OBJECT(win->expression), "key-release-event", | |
833 G_CALLBACK(regex_key_release_cb), win); | |
834 gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/regex", | |
835 regex_pref_expression_cb, win); | |
836 | |
837 /* connect the rest of our pref callbacks */ | |
838 win->invert = gaim_prefs_get_bool("/gaim/gtk/debug/invert"); | |
839 gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/invert", | |
840 regex_pref_invert_cb, win); | |
841 | |
842 win->highlight = gaim_prefs_get_bool("/gaim/gtk/debug/highlight"); | |
843 gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/highlight", | |
844 regex_pref_highlight_cb, win); | |
845 | |
846 #endif /* HAVE_REGEX_H */ | |
847 | |
848 gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); | |
849 | |
850 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
851 GTK_TOOLBAR_CHILD_WIDGET, gtk_label_new(_("Level ")), | |
852 NULL, _("Select the debug filter level."), | |
853 NULL, NULL, NULL, NULL); | |
854 | |
855 win->filterlevel = gtk_combo_box_new_text(); | |
856 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
857 GTK_TOOLBAR_CHILD_WIDGET, win->filterlevel, | |
858 NULL, _("Select the debug filter level."), | |
859 NULL, NULL, NULL, NULL); | |
860 gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("All")); | |
861 gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Misc")); | |
862 gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Info")); | |
863 gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Warning")); | |
864 gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Error ")); | |
865 gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Fatal Error")); | |
866 gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), | |
867 gaim_prefs_get_int("/gaim/gtk/debug/filterlevel")); | |
868 #ifdef HAVE_REGEX_H | |
869 gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/filterlevel", | |
870 filter_level_pref_changed, win); | |
871 #endif | |
872 g_signal_connect(G_OBJECT(win->filterlevel), "changed", | |
873 G_CALLBACK(filter_level_changed_cb), NULL); | |
874 } | |
875 | |
876 /* Add the gtkimhtml */ | |
877 frame = gaim_gtk_create_imhtml(FALSE, &win->text, NULL, NULL); | |
878 gtk_imhtml_set_format_functions(GTK_IMHTML(win->text), | |
879 GTK_IMHTML_ALL ^ GTK_IMHTML_SMILEY ^ GTK_IMHTML_IMAGE); | |
880 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); | |
881 gtk_widget_show(frame); | |
882 | |
883 #ifdef HAVE_REGEX_H | |
884 /* add the tag for regex highlighting */ | |
885 gtk_text_buffer_create_tag(GTK_IMHTML(win->text)->text_buffer, "regex", | |
886 "background", "#FFAFAF", | |
887 "weight", "bold", | |
888 NULL); | |
889 #endif /* HAVE_REGEX_H */ | |
890 | |
891 gtk_widget_show_all(win->window); | |
892 | |
893 return win; | |
894 } | |
895 | |
896 static void | |
897 debug_enabled_cb(const char *name, GaimPrefType type, | |
898 gconstpointer value, gpointer data) | |
899 { | |
900 if (value) | |
901 gaim_gtk_debug_window_show(); | |
902 else | |
903 gaim_gtk_debug_window_hide(); | |
904 } | |
905 | |
906 static void | |
907 gaim_glib_log_handler(const gchar *domain, GLogLevelFlags flags, | |
908 const gchar *msg, gpointer user_data) | |
909 { | |
910 GaimDebugLevel level; | |
911 char *new_msg = NULL; | |
912 char *new_domain = NULL; | |
913 | |
914 if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR) | |
915 level = GAIM_DEBUG_ERROR; | |
916 else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL) | |
917 level = GAIM_DEBUG_FATAL; | |
918 else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING) | |
919 level = GAIM_DEBUG_WARNING; | |
920 else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE) | |
921 level = GAIM_DEBUG_INFO; | |
922 else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO) | |
923 level = GAIM_DEBUG_INFO; | |
924 else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG) | |
925 level = GAIM_DEBUG_MISC; | |
926 else | |
927 { | |
928 gaim_debug_warning("gtkdebug", | |
929 "Unknown glib logging level in %d\n", flags); | |
930 | |
931 level = GAIM_DEBUG_MISC; /* This will never happen. */ | |
932 } | |
933 | |
934 if (msg != NULL) | |
935 new_msg = gaim_utf8_try_convert(msg); | |
936 | |
937 if (domain != NULL) | |
938 new_domain = gaim_utf8_try_convert(domain); | |
939 | |
940 if (new_msg != NULL) | |
941 { | |
942 gaim_debug(level, (new_domain != NULL ? new_domain : "g_log"), | |
943 "%s\n", new_msg); | |
944 | |
945 g_free(new_msg); | |
946 } | |
947 | |
948 g_free(new_domain); | |
949 } | |
950 | |
951 #ifdef _WIN32 | |
952 static void | |
953 gaim_glib_dummy_print_handler(const gchar *string) | |
954 { | |
955 } | |
956 #endif | |
957 | |
958 void | |
959 gaim_gtk_debug_init(void) | |
960 { | |
961 /* Debug window preferences. */ | |
962 /* | |
963 * NOTE: This must be set before prefs are loaded, and the callbacks | |
964 * set after they are loaded, since prefs sets the enabled | |
965 * preference here and that loads the window, which calls the | |
966 * configure event, which overrides the width and height! :P | |
967 */ | |
968 | |
969 gaim_prefs_add_none("/gaim/gtk/debug"); | |
970 | |
971 /* Controls printing to the debug window */ | |
972 gaim_prefs_add_bool("/gaim/gtk/debug/enabled", FALSE); | |
973 gaim_prefs_add_int("/gaim/gtk/debug/filterlevel", GAIM_DEBUG_ALL); | |
974 gaim_prefs_add_int("/gaim/gtk/debug/style", GTK_TOOLBAR_BOTH_HORIZ); | |
975 | |
976 gaim_prefs_add_bool("/gaim/gtk/debug/toolbar", TRUE); | |
977 gaim_prefs_add_int("/gaim/gtk/debug/width", 450); | |
978 gaim_prefs_add_int("/gaim/gtk/debug/height", 250); | |
979 | |
980 #ifdef HAVE_REGEX_H | |
981 gaim_prefs_add_string("/gaim/gtk/debug/regex", ""); | |
982 gaim_prefs_add_bool("/gaim/gtk/debug/filter", FALSE); | |
983 gaim_prefs_add_bool("/gaim/gtk/debug/invert", FALSE); | |
984 gaim_prefs_add_bool("/gaim/gtk/debug/case_insensitive", FALSE); | |
985 gaim_prefs_add_bool("/gaim/gtk/debug/highlight", FALSE); | |
986 #endif /* HAVE_REGEX_H */ | |
987 | |
988 gaim_prefs_connect_callback(NULL, "/gaim/gtk/debug/enabled", | |
989 debug_enabled_cb, NULL); | |
990 | |
991 #define REGISTER_G_LOG_HANDLER(name) \ | |
992 g_log_set_handler((name), G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \ | |
993 | G_LOG_FLAG_RECURSION, \ | |
994 gaim_glib_log_handler, NULL) | |
995 | |
996 /* Register the glib/gtk log handlers. */ | |
997 REGISTER_G_LOG_HANDLER(NULL); | |
998 REGISTER_G_LOG_HANDLER("Gdk"); | |
999 REGISTER_G_LOG_HANDLER("Gtk"); | |
1000 REGISTER_G_LOG_HANDLER("GdkPixbuf"); | |
1001 REGISTER_G_LOG_HANDLER("GLib"); | |
1002 REGISTER_G_LOG_HANDLER("GModule"); | |
1003 REGISTER_G_LOG_HANDLER("GLib-GObject"); | |
1004 REGISTER_G_LOG_HANDLER("GThread"); | |
1005 | |
1006 #ifdef _WIN32 | |
1007 if (!gaim_debug_is_enabled()) | |
1008 g_set_print_handler(gaim_glib_dummy_print_handler); | |
1009 #endif | |
1010 } | |
1011 | |
1012 void | |
1013 gaim_gtk_debug_uninit(void) | |
1014 { | |
1015 gaim_debug_set_ui_ops(NULL); | |
1016 } | |
1017 | |
1018 void | |
1019 gaim_gtk_debug_window_show(void) | |
1020 { | |
1021 if (debug_win == NULL) | |
1022 debug_win = debug_window_new(); | |
1023 | |
1024 gtk_widget_show(debug_win->window); | |
1025 | |
1026 gaim_prefs_set_bool("/gaim/gtk/debug/enabled", TRUE); | |
1027 } | |
1028 | |
1029 void | |
1030 gaim_gtk_debug_window_hide(void) | |
1031 { | |
1032 if (debug_win != NULL) { | |
1033 gtk_widget_destroy(debug_win->window); | |
1034 debug_window_destroy(NULL, NULL, NULL); | |
1035 } | |
1036 } | |
1037 | |
1038 static void | |
1039 gaim_gtk_debug_print(GaimDebugLevel level, const char *category, | |
1040 const char *arg_s) | |
1041 { | |
1042 #ifdef HAVE_REGEX_H | |
1043 GtkTreeIter iter; | |
1044 #endif /* HAVE_REGEX_H */ | |
1045 gboolean timestamps; | |
1046 gchar *ts_s; | |
1047 gchar *esc_s, *cat_s, *tmp, *s; | |
1048 | |
1049 if (!gaim_prefs_get_bool("/gaim/gtk/debug/enabled") || | |
1050 (debug_win == NULL)) | |
1051 { | |
1052 return; | |
1053 } | |
1054 | |
1055 timestamps = gaim_prefs_get_bool("/core/debug/timestamps"); | |
1056 | |
1057 /* | |
1058 * For some reason we only print the timestamp if category is | |
1059 * not NULL. Why the hell do we do that? --Mark | |
1060 */ | |
1061 if ((category != NULL) && (timestamps)) { | |
1062 const char *mdate; | |
1063 | |
1064 time_t mtime = time(NULL); | |
1065 mdate = gaim_utf8_strftime("%H:%M:%S", localtime(&mtime)); | |
1066 ts_s = g_strdup_printf("(%s) ", mdate); | |
1067 } else { | |
1068 ts_s = g_strdup(""); | |
1069 } | |
1070 | |
1071 if (category == NULL) | |
1072 cat_s = g_strdup(""); | |
1073 else | |
1074 cat_s = g_strdup_printf("<b>%s:</b> ", category); | |
1075 | |
1076 esc_s = g_markup_escape_text(arg_s, -1); | |
1077 | |
1078 s = g_strdup_printf("<font color=\"%s\">%s%s%s</font>", | |
1079 debug_fg_colors[level], ts_s, cat_s, esc_s); | |
1080 | |
1081 g_free(ts_s); | |
1082 g_free(cat_s); | |
1083 g_free(esc_s); | |
1084 | |
1085 tmp = gaim_utf8_try_convert(s); | |
1086 g_free(s); | |
1087 s = tmp; | |
1088 | |
1089 if (level == GAIM_DEBUG_FATAL) { | |
1090 tmp = g_strdup_printf("<b>%s</b>", s); | |
1091 g_free(s); | |
1092 s = tmp; | |
1093 } | |
1094 | |
1095 #ifdef HAVE_REGEX_H | |
1096 /* add the text to the list store */ | |
1097 gtk_list_store_append(debug_win->store, &iter); | |
1098 gtk_list_store_set(debug_win->store, &iter, 0, s, 1, level, -1); | |
1099 #else /* HAVE_REGEX_H */ | |
1100 if(!debug_win->paused && level >= gaim_prefs_get_int("/gaim/gtk/debug/filterlevel")) | |
1101 gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0); | |
1102 #endif /* !HAVE_REGEX_H */ | |
1103 | |
1104 g_free(s); | |
1105 } | |
1106 | |
1107 static GaimDebugUiOps ops = | |
1108 { | |
1109 gaim_gtk_debug_print, | |
1110 }; | |
1111 | |
1112 GaimDebugUiOps * | |
1113 gaim_gtk_debug_get_ui_ops(void) | |
1114 { | |
1115 return &ops; | |
1116 } | |
1117 | |
1118 void * | |
1119 gaim_gtk_debug_get_handle() { | |
1120 static int handle; | |
1121 | |
1122 return &handle; | |
1123 } |