pidgin/gtkdebug.c

branch
cpw.qulogic.gtk3-required
changeset 33163
e15b0467ef3b
parent 33142
6ebeb0beef64
parent 33095
1e0b4fac0fed
child 33167
fce72d79861f
equal deleted inserted replaced
33162:fff0550b435b 33163:e15b0467ef3b
31 #include "request.h" 31 #include "request.h"
32 #include "util.h" 32 #include "util.h"
33 33
34 #include "gtkdebug.h" 34 #include "gtkdebug.h"
35 #include "gtkdialogs.h" 35 #include "gtkdialogs.h"
36 #include "gtkimhtml.h"
37 #include "gtkutils.h" 36 #include "gtkutils.h"
37 #include "gtkwebview.h"
38 #include "pidginstock.h" 38 #include "pidginstock.h"
39
40 #ifdef HAVE_REGEX_H
41 # include <regex.h>
42 # define USE_REGEX 1
43 #else
44 #if GLIB_CHECK_VERSION(2,14,0)
45 # define USE_REGEX 1
46 #endif
47 #endif /* HAVE_REGEX_H */
48 39
49 #include <gdk/gdkkeysyms.h> 40 #include <gdk/gdkkeysyms.h>
50 41
51 typedef struct 42 typedef struct
52 { 43 {
53 GtkWidget *window; 44 GtkWidget *window;
54 GtkWidget *text; 45 GtkWidget *text;
55
56 GtkListStore *store;
57
58 gboolean paused;
59
60 #ifdef USE_REGEX
61 GtkWidget *filter; 46 GtkWidget *filter;
62 GtkWidget *expression; 47 GtkWidget *expression;
48 GtkWidget *filterlevel;
49
50 gboolean paused;
63 51
64 gboolean invert; 52 gboolean invert;
65 gboolean highlight; 53 gboolean highlight;
66
67 guint timer; 54 guint timer;
68 # ifdef HAVE_REGEX_H
69 regex_t regex;
70 # else
71 GRegex *regex; 55 GRegex *regex;
72 # endif /* HAVE_REGEX_H */
73 #else
74 GtkWidget *find;
75 #endif /* USE_REGEX */
76 GtkWidget *filterlevel;
77 } DebugWindow; 56 } DebugWindow;
78 57
79 static const char debug_fg_colors[][8] = { 58 #define EMPTY_HTML \
80 "#000000", /**< All debug levels. */ 59 "<html><head><style>" \
81 "#666666", /**< Misc. */ 60 "body{white-space:pre-wrap;}" \
82 "#000000", /**< Information. */ 61 "div.l0{color:#000000;}" /* All debug levels. */ \
83 "#660000", /**< Warnings. */ 62 "div.l1{color:#666666;}" /* Misc. */ \
84 "#FF0000", /**< Errors. */ 63 "div.l2{color:#000000;}" /* Information. */ \
85 "#FF0000", /**< Fatal errors. */ 64 "div.l3{color:#660000;}" /* Warnings. */ \
86 }; 65 "div.l4{color:#FF0000;}" /* Errors. */ \
66 "div.l5{color:#FF0000;font-weight:bold;}" /* Fatal errors. */ \
67 /* Filter levels */ \
68 "div#pause~div{display:none;}" \
69 "body.l1 div.l0{display:none;}" \
70 "body.l2 div.l0,body.l2 div.l1{display:none;}" \
71 "body.l3 div.l0,body.l3 div.l1,body.l3 div.l2{display:none;}" \
72 "body.l4 div.l0,body.l4 div.l1,body.l4 div.l2,body.l4 div.l3{display:none;}" \
73 "body.l5 div.l0,body.l5 div.l1,body.l5 div.l2,body.l5 div.l3,body.l5 div.l4{display:none;}" \
74 /* Regex */ \
75 "div.hide{display:none;}" \
76 "span.regex{background-color:#ffafaf;font-weight:bold;}" \
77 "</style></head></html>"
87 78
88 static DebugWindow *debug_win = NULL; 79 static DebugWindow *debug_win = NULL;
89 static guint debug_enabled_timer = 0; 80 static guint debug_enabled_timer = 0;
90 81
91 #ifdef USE_REGEX
92 static void regex_filter_all(DebugWindow *win);
93 static void regex_show_all(DebugWindow *win);
94 #endif /* USE_REGEX */
95
96 static gint 82 static gint
97 debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused) 83 debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused)
98 { 84 {
99 purple_prefs_disconnect_by_handle(pidgin_debug_get_handle()); 85 purple_prefs_disconnect_by_handle(pidgin_debug_get_handle());
100 86
101 #ifdef USE_REGEX
102 if(debug_win->timer != 0) { 87 if(debug_win->timer != 0) {
103 const gchar *text; 88 const gchar *text;
104 89
105 purple_timeout_remove(debug_win->timer); 90 purple_timeout_remove(debug_win->timer);
106 91
107 text = gtk_entry_get_text(GTK_ENTRY(debug_win->expression)); 92 text = gtk_entry_get_text(GTK_ENTRY(debug_win->expression));
108 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/debug/regex", text); 93 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/debug/regex", text);
109 } 94 }
110 #ifdef HAVE_REGEX_H
111 regfree(&debug_win->regex);
112 #else
113 g_regex_unref(debug_win->regex); 95 g_regex_unref(debug_win->regex);
114 #endif /* HAVE_REGEX_H */
115 #endif /* USE_REGEX */
116 96
117 /* If the "Save Log" dialog is open then close it */ 97 /* If the "Save Log" dialog is open then close it */
118 purple_request_close_with_handle(debug_win); 98 purple_request_close_with_handle(debug_win);
119 99
120 g_free(debug_win); 100 g_free(debug_win);
134 } 114 }
135 115
136 return FALSE; 116 return FALSE;
137 } 117 }
138 118
139 #ifndef USE_REGEX
140 struct _find {
141 DebugWindow *window;
142 GtkWidget *entry;
143 };
144
145 static void
146 do_find_cb(GtkWidget *widget, gint response, struct _find *f)
147 {
148 switch (response) {
149 case GTK_RESPONSE_OK:
150 gtk_imhtml_search_find(GTK_IMHTML(f->window->text),
151 gtk_entry_get_text(GTK_ENTRY(f->entry)));
152 break;
153
154 case GTK_RESPONSE_DELETE_EVENT:
155 case GTK_RESPONSE_CLOSE:
156 gtk_imhtml_search_clear(GTK_IMHTML(f->window->text));
157 gtk_widget_destroy(f->window->find);
158 f->window->find = NULL;
159 g_free(f);
160 break;
161 }
162 }
163
164 static void
165 find_cb(GtkWidget *w, DebugWindow *win)
166 {
167 GtkWidget *hbox, *img, *label;
168 struct _find *f;
169
170 if(win->find)
171 {
172 gtk_window_present(GTK_WINDOW(win->find));
173 return;
174 }
175
176 f = g_malloc(sizeof(struct _find));
177 f->window = win;
178 win->find = gtk_dialog_new_with_buttons(_("Find"),
179 GTK_WINDOW(win->window), GTK_DIALOG_DESTROY_WITH_PARENT,
180 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
181 GTK_STOCK_FIND, GTK_RESPONSE_OK, NULL);
182 gtk_dialog_set_default_response(GTK_DIALOG(win->find),
183 GTK_RESPONSE_OK);
184 g_signal_connect(G_OBJECT(win->find), "response",
185 G_CALLBACK(do_find_cb), f);
186
187 gtk_container_set_border_width(GTK_CONTAINER(win->find), PIDGIN_HIG_BOX_SPACE);
188 gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE);
189 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BORDER);
190 gtk_container_set_border_width(
191 GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BOX_SPACE);
192
193 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
194 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win->find)->vbox),
195 hbox);
196 img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION,
197 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
198 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
199
200 gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
201 gtk_dialog_set_response_sensitive(GTK_DIALOG(win->find),
202 GTK_RESPONSE_OK, FALSE);
203
204 label = gtk_label_new(NULL);
205 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Search for:"));
206 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
207
208 f->entry = gtk_entry_new();
209 gtk_entry_set_activates_default(GTK_ENTRY(f->entry), TRUE);
210 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(f->entry));
211 g_signal_connect(G_OBJECT(f->entry), "changed",
212 G_CALLBACK(pidgin_set_sensitive_if_input),
213 win->find);
214 gtk_box_pack_start(GTK_BOX(hbox), f->entry, FALSE, FALSE, 0);
215
216 gtk_widget_show_all(win->find);
217 gtk_widget_grab_focus(f->entry);
218 }
219 #endif /* USE_REGEX */
220
221 static void 119 static void
222 save_writefile_cb(void *user_data, const char *filename) 120 save_writefile_cb(void *user_data, const char *filename)
223 { 121 {
224 DebugWindow *win = (DebugWindow *)user_data; 122 DebugWindow *win = (DebugWindow *)user_data;
225 FILE *fp; 123 FILE *fp;
228 if ((fp = g_fopen(filename, "w+")) == NULL) { 126 if ((fp = g_fopen(filename, "w+")) == NULL) {
229 purple_notify_error(win, NULL, _("Unable to open file."), NULL); 127 purple_notify_error(win, NULL, _("Unable to open file."), NULL);
230 return; 128 return;
231 } 129 }
232 130
233 tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL); 131 tmp = gtk_webview_get_body_text(GTK_WEBVIEW(win->text));
234 fprintf(fp, "Pidgin Debug Log : %s\n", purple_date_format_full(NULL)); 132 fprintf(fp, "Pidgin Debug Log : %s\n", purple_date_format_full(NULL));
235 fprintf(fp, "%s", tmp); 133 fprintf(fp, "%s", tmp);
236 g_free(tmp); 134 g_free(tmp);
237 135
238 fclose(fp); 136 fclose(fp);
248 } 146 }
249 147
250 static void 148 static void
251 clear_cb(GtkWidget *w, DebugWindow *win) 149 clear_cb(GtkWidget *w, DebugWindow *win)
252 { 150 {
253 gtk_imhtml_clear(GTK_IMHTML(win->text)); 151 gtk_webview_load_html_string(GTK_WEBVIEW(win->text), EMPTY_HTML);
254
255 #ifdef USE_REGEX
256 gtk_list_store_clear(win->store);
257 #endif /* USE_REGEX */
258 } 152 }
259 153
260 static void 154 static void
261 pause_cb(GtkWidget *w, DebugWindow *win) 155 pause_cb(GtkWidget *w, DebugWindow *win)
262 { 156 {
263 win->paused = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w)); 157 win->paused = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w));
264 158
265 #ifdef USE_REGEX 159 if (win->paused) {
266 if(!win->paused) { 160 gtk_webview_append_html(GTK_WEBVIEW(win->text), "<div id=pause></div>");
267 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) 161 } else {
268 regex_filter_all(win); 162 WebKitDOMDocument *dom;
269 else 163 WebKitDOMElement *pause;
270 regex_show_all(win); 164
271 } 165 dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text));
272 #endif /* USE_REGEX */ 166 pause = webkit_dom_document_get_element_by_id(dom, "pause");
167 if (pause) {
168 WebKitDOMNode *parent;
169 parent = webkit_dom_node_get_parent_node(WEBKIT_DOM_NODE(pause));
170 webkit_dom_node_remove_child(parent, WEBKIT_DOM_NODE(pause), NULL);
171 }
172 }
273 } 173 }
274 174
275 /****************************************************************************** 175 /******************************************************************************
276 * regex stuff 176 * regex stuff
277 *****************************************************************************/ 177 *****************************************************************************/
278 #ifdef USE_REGEX
279 static void 178 static void
280 regex_clear_color(GtkWidget *w) { 179 regex_clear_color(GtkWidget *w) {
281 gtk_widget_modify_base(w, GTK_STATE_NORMAL, NULL); 180 gtk_widget_modify_base(w, GTK_STATE_NORMAL, NULL);
282 } 181 }
283 182
291 190
292 gtk_widget_modify_base(w, GTK_STATE_NORMAL, &color); 191 gtk_widget_modify_base(w, GTK_STATE_NORMAL, &color);
293 } 192 }
294 193
295 static void 194 static void
296 regex_highlight_clear(DebugWindow *win) { 195 regex_toggle_div(WebKitDOMNode *div)
297 GtkIMHtml *imhtml = GTK_IMHTML(win->text); 196 {
298 GtkTextIter s, e; 197 WebKitDOMDOMTokenList *classes;
299 198
300 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &s); 199 if (!WEBKIT_DOM_IS_HTML_ELEMENT(div))
301 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &e); 200 return;
302 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "regex", &s, &e); 201
303 } 202 classes = webkit_dom_html_element_get_class_list(WEBKIT_DOM_HTML_ELEMENT(div));
304 203 webkit_dom_dom_token_list_toggle(classes, "hide", NULL);
305 static void 204 }
306 regex_match(DebugWindow *win, const gchar *text) { 205
307 GtkIMHtml *imhtml = GTK_IMHTML(win->text); 206 static void
308 #ifdef HAVE_REGEX_H 207 regex_highlight_clear(WebKitDOMDocument *dom)
309 regmatch_t matches[4]; /* adjust if necessary */ 208 {
310 size_t n_matches = sizeof(matches) / sizeof(matches[0]); 209 WebKitDOMNodeList *nodes;
311 gint inverted; 210 gulong i;
312 #else 211
212 /* Remove highlighting SPANs */
213 nodes = webkit_dom_document_get_elements_by_class_name(dom, "regex");
214 i = webkit_dom_node_list_get_length(nodes);
215 while (i--) {
216 WebKitDOMNode *span, *parent;
217 char *content;
218 WebKitDOMText *text;
219 GError *err = NULL;
220
221 span = webkit_dom_node_list_item(nodes, i);
222 parent = webkit_dom_node_get_parent_node(span);
223
224 content = webkit_dom_node_get_text_content(span);
225 text = webkit_dom_document_create_text_node(dom, content);
226 g_free(content);
227
228 webkit_dom_node_replace_child(parent, WEBKIT_DOM_NODE(text), span, &err);
229 }
230 }
231
232 static void
233 regex_highlight_text_nodes(WebKitDOMDocument *dom, WebKitDOMNode *div,
234 gint start_pos, gint end_pos)
235 {
236 GSList *data = NULL;
237 WebKitDOMNode *node;
238 WebKitDOMRange *range;
239 WebKitDOMElement *span;
240 gint ind, end_ind;
241 gint this_start, this_end;
242
243 ind = 0;
244 webkit_dom_node_normalize(div);
245 node = div;
246
247 /* First, find the container nodes and offsets to apply highlighting. */
248 do {
249 if (webkit_dom_node_get_node_type(node) == 3/*TEXT_NODE*/) {
250 /* The GObject model does not correctly reflect the type, hence the
251 regular cast. */
252 end_ind = ind + webkit_dom_character_data_get_length((WebKitDOMCharacterData*)node);
253
254 if (start_pos <= ind)
255 this_start = 0;
256 else if (start_pos < end_ind)
257 this_start = start_pos - ind;
258 else
259 this_start = -1;
260
261 if (end_pos < end_ind)
262 this_end = end_pos - ind;
263 else
264 this_end = end_ind - ind;
265
266 if (this_start != -1 && this_start < this_end) {
267 data = g_slist_prepend(data, GINT_TO_POINTER(this_end));
268 data = g_slist_prepend(data, GINT_TO_POINTER(this_start));
269 data = g_slist_prepend(data, node);
270 }
271
272 ind = end_ind;
273 }
274
275 if (webkit_dom_node_has_child_nodes(node)) {
276 node = webkit_dom_node_get_first_child(node);
277 } else {
278 while (node != div) {
279 WebKitDOMNode *next;
280
281 next = webkit_dom_node_get_next_sibling(node);
282 if (next) {
283 node = next;
284 break;
285 } else {
286 node = webkit_dom_node_get_parent_node(node);
287 }
288 }
289 }
290 } while (node != div);
291
292 /* Second, apply highlighting to saved sections. Changing the DOM is
293 automatically reflected in all WebKit API, so we have to do this after
294 finding the offsets, or things could get complicated. */
295 while (data) {
296 node = WEBKIT_DOM_NODE(data->data);
297 data = g_slist_delete_link(data, data);
298 this_start = GPOINTER_TO_INT(data->data);
299 data = g_slist_delete_link(data, data);
300 this_end = GPOINTER_TO_INT(data->data);
301 data = g_slist_delete_link(data, data);
302
303 range = webkit_dom_document_create_range(dom);
304 webkit_dom_range_set_start(range, node, this_start, NULL);
305 webkit_dom_range_set_end(range, node, this_end, NULL);
306 span = webkit_dom_document_create_element(dom, "span", NULL);
307 webkit_dom_html_element_set_class_name(WEBKIT_DOM_HTML_ELEMENT(span),
308 "regex");
309 webkit_dom_range_surround_contents(range, WEBKIT_DOM_NODE(span), NULL);
310 }
311 }
312
313 static void
314 regex_match(DebugWindow *win, WebKitDOMDocument *dom, WebKitDOMNode *div)
315 {
313 GMatchInfo *match_info; 316 GMatchInfo *match_info;
314 #endif /* HAVE_REGEX_H */ 317 gchar *text;
315 gchar *plaintext; 318 gchar *plaintext;
316 319
317 if(!text) 320 text = webkit_dom_node_get_text_content(div);
321 if (!text)
318 return; 322 return;
319 323
320 /* I don't like having to do this, but we need it for highlighting. Plus 324 /* I don't like having to do this, but we need it for highlighting. Plus
321 * it makes the ^ and $ operators work :) 325 * it makes the ^ and $ operators work :)
322 */ 326 */
323 plaintext = purple_markup_strip_html(text); 327 plaintext = purple_markup_strip_html(text);
324 328
325 /* we do a first pass to see if it matches at all. If it does we append 329 /* We do a first pass to see if it matches at all. If it does we work out
326 * it, and work out the offsets to highlight. 330 * the offsets to highlight.
327 */ 331 */
328 #ifdef HAVE_REGEX_H 332 if (g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) {
329 inverted = (win->invert) ? REG_NOMATCH : 0;
330 if(regexec(&win->regex, plaintext, n_matches, matches, 0) == inverted) {
331 #else
332 if(g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) {
333 #endif /* HAVE_REGEX_H */
334 gchar *p = plaintext;
335 GtkTextIter ins;
336 gint i, offset = 0;
337
338 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins,
339 gtk_text_buffer_get_insert(imhtml->text_buffer));
340 i = gtk_text_iter_get_offset(&ins);
341
342 gtk_imhtml_append_text(imhtml, text, 0);
343
344 /* If we're not highlighting or the expression is inverted, we're 333 /* If we're not highlighting or the expression is inverted, we're
345 * done and move on. 334 * done and move on.
346 */ 335 */
347 if(!win->highlight || win->invert) { 336 if (!win->highlight || win->invert) {
348 g_free(plaintext); 337 g_free(plaintext);
349 #ifndef HAVE_REGEX_H
350 g_match_info_free(match_info); 338 g_match_info_free(match_info);
351 #endif
352 return; 339 return;
353 } 340 }
354 341
355 /* we use a do-while to highlight the first match, and then continue
356 * if necessary...
357 */
358 #ifdef HAVE_REGEX_H
359 do { 342 do {
360 size_t m; 343 gint m, count;
361
362 for(m = 0; m < n_matches; m++) {
363 GtkTextIter ms, me;
364
365 if(matches[m].rm_eo == -1)
366 break;
367
368 i += offset;
369
370 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms,
371 i + matches[m].rm_so);
372 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &me,
373 i + matches[m].rm_eo);
374 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "regex",
375 &ms, &me);
376 offset = matches[m].rm_eo;
377 }
378
379 p += offset;
380 } while(regexec(&win->regex, p, n_matches, matches, REG_NOTBOL) == inverted);
381 #else
382 do
383 {
384 gint m;
385 gint start_pos, end_pos; 344 gint start_pos, end_pos;
386 GtkTextIter ms, me;
387 345
388 if (!g_match_info_matches(match_info)) 346 if (!g_match_info_matches(match_info))
389 break; 347 break;
390 348
391 for (m = 0; m < g_match_info_get_match_count(match_info); m++) 349 count = g_match_info_get_match_count(match_info);
350 if (count == 1)
351 m = 0;
352 else
353 m = 1;
354
355 for (; m < count; m++)
392 { 356 {
393 if (m == 1)
394 continue;
395
396 g_match_info_fetch_pos(match_info, m, &start_pos, &end_pos); 357 g_match_info_fetch_pos(match_info, m, &start_pos, &end_pos);
397 358
398 if (end_pos == -1) 359 if (end_pos == -1)
399 break; 360 break;
400 361
401 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms, 362 regex_highlight_text_nodes(dom, div, start_pos, end_pos);
402 i + start_pos);
403 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &me,
404 i + end_pos);
405 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "regex",
406 &ms, &me);
407 offset = end_pos;
408 } 363 }
409 364 } while (g_match_info_next(match_info, NULL));
410 g_match_info_free(match_info); 365
411 p += offset;
412 i += offset;
413 } while (g_regex_match(win->regex, p, G_REGEX_MATCH_NOTBOL, &match_info) != win->invert);
414 g_match_info_free(match_info); 366 g_match_info_free(match_info);
415 #endif /* HAVE_REGEX_H */ 367 } else {
368 regex_toggle_div(div);
416 } 369 }
417 370
418 g_free(plaintext); 371 g_free(plaintext);
372 g_free(text);
373 }
374
375 static void
376 regex_toggle_filter(DebugWindow *win, gboolean filter)
377 {
378 WebKitDOMDocument *dom;
379 WebKitDOMNodeList *list;
380 gulong i;
381
382 dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text));
383
384 if (win->highlight)
385 regex_highlight_clear(dom);
386
387 /* Re-show debug lines that didn't match regex */
388 list = webkit_dom_document_get_elements_by_class_name(dom, "hide");
389 i = webkit_dom_node_list_get_length(list);
390 while (i--) {
391 WebKitDOMNode *div = webkit_dom_node_list_item(list, i);
392 regex_toggle_div(div);
393 }
394
395 if (filter) {
396 list = webkit_dom_document_get_elements_by_tag_name(dom, "div");
397
398 for (i = 0; i < webkit_dom_node_list_get_length(list); i++) {
399 WebKitDOMNode *div = webkit_dom_node_list_item(list, i);
400 regex_match(win, dom, div);
401 }
402 }
403 }
404
405 static void
406 regex_pref_filter_cb(const gchar *name, PurplePrefType type,
407 gconstpointer val, gpointer data)
408 {
409 DebugWindow *win = (DebugWindow *)data;
410 gboolean active = GPOINTER_TO_INT(val), current;
411
412 if (!win || !win->window)
413 return;
414
415 current = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter));
416 if (active != current)
417 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), active);
418 }
419
420 static void
421 regex_pref_expression_cb(const gchar *name, PurplePrefType type,
422 gconstpointer val, gpointer data)
423 {
424 DebugWindow *win = (DebugWindow *)data;
425 const gchar *exp = (const gchar *)val;
426
427 gtk_entry_set_text(GTK_ENTRY(win->expression), exp);
428 }
429
430 static void
431 regex_pref_invert_cb(const gchar *name, PurplePrefType type,
432 gconstpointer val, gpointer data)
433 {
434 DebugWindow *win = (DebugWindow *)data;
435 gboolean active = GPOINTER_TO_INT(val);
436
437 win->invert = active;
438
439 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
440 regex_toggle_filter(win, TRUE);
441 }
442
443 static void
444 regex_pref_highlight_cb(const gchar *name, PurplePrefType type,
445 gconstpointer val, gpointer data)
446 {
447 DebugWindow *win = (DebugWindow *)data;
448 gboolean active = GPOINTER_TO_INT(val);
449
450 win->highlight = active;
451
452 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
453 regex_toggle_filter(win, TRUE);
419 } 454 }
420 455
421 static gboolean 456 static gboolean
422 regex_filter_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, 457 regex_timer_cb(DebugWindow *win) {
423 gpointer data) 458 const gchar *text;
424 { 459
425 DebugWindow *win = (DebugWindow *)data; 460 text = gtk_entry_get_text(GTK_ENTRY(win->expression));
426 gchar *text; 461 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/debug/regex", text);
427 PurpleDebugLevel level; 462
428 463 win->timer = 0;
429 gtk_tree_model_get(m, iter, 0, &text, 1, &level, -1);
430
431 if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel"))
432 regex_match(win, text);
433
434 g_free(text);
435 464
436 return FALSE; 465 return FALSE;
437 } 466 }
438 467
439 static void 468 static void
440 regex_filter_all(DebugWindow *win) { 469 regex_changed_cb(GtkWidget *w, DebugWindow *win) {
441 gtk_imhtml_clear(GTK_IMHTML(win->text));
442
443 if(win->highlight)
444 regex_highlight_clear(win);
445
446 gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_filter_all_cb,
447 win);
448 }
449
450 static gboolean
451 regex_show_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter,
452 gpointer data)
453 {
454 DebugWindow *win = (DebugWindow *)data;
455 gchar *text;
456 PurpleDebugLevel level;
457
458 gtk_tree_model_get(m, iter, 0, &text, 1, &level, -1);
459 if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel"))
460 gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0);
461 g_free(text);
462
463 return FALSE;
464 }
465
466 static void
467 regex_show_all(DebugWindow *win) {
468 gtk_imhtml_clear(GTK_IMHTML(win->text));
469
470 if(win->highlight)
471 regex_highlight_clear(win);
472
473 gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_show_all_cb,
474 win);
475 }
476
477 static void
478 regex_compile(DebugWindow *win) {
479 const gchar *text; 470 const gchar *text;
480 471
472 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) {
473 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter),
474 FALSE);
475 }
476
477 if (win->timer == 0)
478 win->timer = purple_timeout_add_seconds(5, (GSourceFunc)regex_timer_cb, win);
479
481 text = gtk_entry_get_text(GTK_ENTRY(win->expression)); 480 text = gtk_entry_get_text(GTK_ENTRY(win->expression));
482 481
483 if(text == NULL || *text == '\0') { 482 if (text == NULL || *text == '\0') {
484 regex_clear_color(win->expression); 483 regex_clear_color(win->expression);
485 gtk_widget_set_sensitive(win->filter, FALSE); 484 gtk_widget_set_sensitive(win->filter, FALSE);
486 return; 485 return;
487 } 486 }
488 487
489 #ifdef HAVE_REGEX_H
490 regfree(&win->regex);
491 if(regcomp(&win->regex, text, REG_EXTENDED | REG_ICASE) != 0) {
492 #else
493 if (win->regex) 488 if (win->regex)
494 g_regex_unref(win->regex); 489 g_regex_unref(win->regex);
495 win->regex = g_regex_new(text, G_REGEX_EXTENDED | G_REGEX_CASELESS, 0, NULL); 490 win->regex = g_regex_new(text, G_REGEX_CASELESS, 0, NULL);
496 if(win->regex == NULL) { 491 if (win->regex == NULL) {
497 #endif
498 /* failed to compile */ 492 /* failed to compile */
499 regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF); 493 regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF);
500 gtk_widget_set_sensitive(win->filter, FALSE); 494 gtk_widget_set_sensitive(win->filter, FALSE);
501 } else { 495 } else {
502 /* compiled successfully */ 496 /* compiled successfully */
503 regex_change_color(win->expression, 0xAFFF, 0xFFFF, 0xAFFF); 497 regex_change_color(win->expression, 0xAFFF, 0xFFFF, 0xAFFF);
504 gtk_widget_set_sensitive(win->filter, TRUE); 498 gtk_widget_set_sensitive(win->filter, TRUE);
505 } 499 }
506
507 /* we check if the filter is on in case it was only of the options that
508 * got changed, and not the expression.
509 */
510 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
511 regex_filter_all(win);
512 }
513
514 static void
515 regex_pref_filter_cb(const gchar *name, PurplePrefType type,
516 gconstpointer val, gpointer data)
517 {
518 DebugWindow *win = (DebugWindow *)data;
519 gboolean active = GPOINTER_TO_INT(val), current;
520
521 if(!win || !win->window)
522 return;
523
524 current = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter));
525 if(active != current)
526 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), active);
527 }
528
529 static void
530 regex_pref_expression_cb(const gchar *name, PurplePrefType type,
531 gconstpointer val, gpointer data)
532 {
533 DebugWindow *win = (DebugWindow *)data;
534 const gchar *exp = (const gchar *)val;
535
536 gtk_entry_set_text(GTK_ENTRY(win->expression), exp);
537 }
538
539 static void
540 regex_pref_invert_cb(const gchar *name, PurplePrefType type,
541 gconstpointer val, gpointer data)
542 {
543 DebugWindow *win = (DebugWindow *)data;
544 gboolean active = GPOINTER_TO_INT(val);
545
546 win->invert = active;
547
548 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
549 regex_filter_all(win);
550 }
551
552 static void
553 regex_pref_highlight_cb(const gchar *name, PurplePrefType type,
554 gconstpointer val, gpointer data)
555 {
556 DebugWindow *win = (DebugWindow *)data;
557 gboolean active = GPOINTER_TO_INT(val);
558
559 win->highlight = active;
560
561 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
562 regex_filter_all(win);
563 }
564
565 static void
566 regex_row_changed_cb(GtkTreeModel *model, GtkTreePath *path,
567 GtkTreeIter *iter, DebugWindow *win)
568 {
569 gchar *text;
570 PurpleDebugLevel level;
571
572 if(!win || !win->window)
573 return;
574
575 /* If the debug window is paused, we just return since it's in the store.
576 * We don't call regex_match because it doesn't make sense to check the
577 * string if it's paused. When we unpause we clear the imhtml and
578 * reiterate over the store to handle matches that were outputted when
579 * we were paused.
580 */
581 if(win->paused)
582 return;
583
584 gtk_tree_model_get(model, iter, 0, &text, 1, &level, -1);
585
586 if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")) {
587 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) {
588 regex_match(win, text);
589 } else {
590 gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0);
591 }
592 }
593
594 g_free(text);
595 }
596
597 static gboolean
598 regex_timer_cb(DebugWindow *win) {
599 const gchar *text;
600
601 text = gtk_entry_get_text(GTK_ENTRY(win->expression));
602 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/debug/regex", text);
603
604 win->timer = 0;
605
606 return FALSE;
607 }
608
609 static void
610 regex_changed_cb(GtkWidget *w, DebugWindow *win) {
611 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) {
612 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter),
613 FALSE);
614 }
615
616 if(win->timer == 0)
617 win->timer = purple_timeout_add_seconds(5, (GSourceFunc)regex_timer_cb, win);
618
619 regex_compile(win);
620 } 500 }
621 501
622 static void 502 static void
623 regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) { 503 regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) {
624 if(e->keyval == GDK_KEY_Return && 504 if(e->keyval == GDK_KEY_Return &&
648 G_CALLBACK(regex_menu_cb), 528 G_CALLBACK(regex_menu_cb),
649 PIDGIN_PREFS_ROOT "/debug/highlight", win->highlight); 529 PIDGIN_PREFS_ROOT "/debug/highlight", win->highlight);
650 } 530 }
651 531
652 static void 532 static void
653 regex_filter_toggled_cb(GtkToggleToolButton *button, DebugWindow *win) { 533 regex_filter_toggled_cb(GtkToggleToolButton *button, DebugWindow *win)
534 {
654 gboolean active; 535 gboolean active;
655 536
656 active = gtk_toggle_tool_button_get_active(button); 537 active = gtk_toggle_tool_button_get_active(button);
657 538
658 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/filter", active); 539 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/filter", active);
659 540
660 if(!GTK_IS_IMHTML(win->text)) 541 if (!GTK_IS_WEBVIEW(win->text))
661 return; 542 return;
662 543
663 if(active) 544 regex_toggle_filter(win, active);
664 regex_filter_all(win);
665 else
666 regex_show_all(win);
667 } 545 }
668 546
669 static void 547 static void
670 filter_level_pref_changed(const char *name, PurplePrefType type, gconstpointer value, gpointer data) 548 filter_level_pref_changed(const char *name, PurplePrefType type, gconstpointer value, gpointer data)
671 { 549 {
672 DebugWindow *win = data; 550 DebugWindow *win = data;
673 551 WebKitDOMDocument *dom;
674 if (GPOINTER_TO_INT(value) != gtk_combo_box_get_active(GTK_COMBO_BOX(win->filterlevel))) 552 WebKitDOMHTMLElement *body;
675 gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), GPOINTER_TO_INT(value)); 553 int level = GPOINTER_TO_INT(value);
676 if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) 554 char *tmp;
677 regex_filter_all(win); 555
678 else 556 if (level != gtk_combo_box_get_active(GTK_COMBO_BOX(win->filterlevel)))
679 regex_show_all(win); 557 gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), level);
680 } 558
681 #endif /* USE_REGEX */ 559 dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text));
560 body = webkit_dom_document_get_body(dom);
561 tmp = g_strdup_printf("l%d", level);
562 webkit_dom_html_element_set_class_name(body, tmp);
563 g_free(tmp);
564 }
682 565
683 static void 566 static void
684 filter_level_changed_cb(GtkWidget *combo, gpointer null) 567 filter_level_changed_cb(GtkWidget *combo, gpointer null)
685 { 568 {
686 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/filterlevel", 569 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/filterlevel",
761 G_CALLBACK(debug_window_destroy), NULL); 644 G_CALLBACK(debug_window_destroy), NULL);
762 g_signal_connect(G_OBJECT(win->window), "configure_event", 645 g_signal_connect(G_OBJECT(win->window), "configure_event",
763 G_CALLBACK(configure_cb), win); 646 G_CALLBACK(configure_cb), win);
764 647
765 handle = pidgin_debug_get_handle(); 648 handle = pidgin_debug_get_handle();
766
767 #ifdef USE_REGEX
768 /* the list store for all the messages */
769 win->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
770
771 /* row-changed gets called when we do gtk_list_store_set, and row-inserted
772 * gets called with gtk_list_store_append, which is a
773 * completely empty row. So we just ignore row-inserted, and deal with row
774 * changed. -Gary
775 */
776 g_signal_connect(G_OBJECT(win->store), "row-changed",
777 G_CALLBACK(regex_row_changed_cb), win);
778
779 #endif /* USE_REGEX */
780 649
781 /* Setup the vbox */ 650 /* Setup the vbox */
782 vbox = gtk_vbox_new(FALSE, 0); 651 vbox = gtk_vbox_new(FALSE, 0);
783 gtk_container_add(GTK_CONTAINER(win->window), vbox); 652 gtk_container_add(GTK_CONTAINER(win->window), vbox);
784 653
801 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), 670 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar),
802 GTK_ICON_SIZE_SMALL_TOOLBAR); 671 GTK_ICON_SIZE_SMALL_TOOLBAR);
803 672
804 gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); 673 gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
805 674
806 #ifndef USE_REGEX
807 /* Find button */
808 item = gtk_tool_button_new_from_stock(GTK_STOCK_FIND);
809 gtk_tool_item_set_is_important(item, TRUE);
810 #if GTK_CHECK_VERSION(2,12,0)
811 gtk_tool_item_set_tooltip_text(item, _("Find"));
812 #else
813 gtk_tool_item_set_tooltip(item, tooltips, _("Find"), NULL);
814 #endif
815 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(find_cb), win);
816 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
817 #endif /* USE_REGEX */
818
819 /* Save */ 675 /* Save */
820 item = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE); 676 item = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
821 gtk_tool_item_set_is_important(item, TRUE); 677 gtk_tool_item_set_is_important(item, TRUE);
822 #if GTK_CHECK_VERSION(2,12,0) 678 #if GTK_CHECK_VERSION(2,12,0)
823 gtk_tool_item_set_tooltip_text(item, _("Save")); 679 gtk_tool_item_set_tooltip_text(item, _("Save"));
850 gtk_tool_item_set_tooltip(item, tooltips, _("Pause"), NULL); 706 gtk_tool_item_set_tooltip(item, tooltips, _("Pause"), NULL);
851 #endif 707 #endif
852 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(pause_cb), win); 708 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(pause_cb), win);
853 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); 709 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
854 710
855 #ifdef USE_REGEX
856 /* regex stuff */ 711 /* regex stuff */
857 item = gtk_separator_tool_item_new(); 712 item = gtk_separator_tool_item_new();
858 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); 713 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
859 714
860 /* regex toggle button */ 715 /* regex toggle button */
913 768
914 win->highlight = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/highlight"); 769 win->highlight = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/highlight");
915 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/highlight", 770 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/highlight",
916 regex_pref_highlight_cb, win); 771 regex_pref_highlight_cb, win);
917 772
918 #endif /* USE_REGEX */
919
920 item = gtk_separator_tool_item_new(); 773 item = gtk_separator_tool_item_new();
921 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); 774 gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
922 775
923 item = gtk_tool_item_new(); 776 item = gtk_tool_item_new();
924 gtk_container_add(GTK_CONTAINER(item), gtk_label_new(_("Level "))); 777 gtk_container_add(GTK_CONTAINER(item), gtk_label_new(_("Level ")));
936 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Warning")); 789 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Warning"));
937 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Error ")); 790 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Error "));
938 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Fatal Error")); 791 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Fatal Error"));
939 gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), 792 gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel),
940 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")); 793 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel"));
941 #ifdef USE_REGEX 794
942 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/filterlevel", 795 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/filterlevel",
943 filter_level_pref_changed, win); 796 filter_level_pref_changed, win);
944 #endif
945 g_signal_connect(G_OBJECT(win->filterlevel), "changed", 797 g_signal_connect(G_OBJECT(win->filterlevel), "changed",
946 G_CALLBACK(filter_level_changed_cb), NULL); 798 G_CALLBACK(filter_level_changed_cb), NULL);
947 } 799 }
948 800
949 /* Add the gtkimhtml */ 801 /* Add the gtkwebview */
950 frame = pidgin_create_imhtml(FALSE, &win->text, NULL, NULL); 802 frame = pidgin_create_webview(FALSE, &win->text, NULL, NULL);
951 gtk_imhtml_set_format_functions(GTK_IMHTML(win->text), 803 gtk_webview_set_format_functions(GTK_WEBVIEW(win->text),
952 GTK_IMHTML_ALL ^ GTK_IMHTML_SMILEY ^ GTK_IMHTML_IMAGE); 804 GTK_WEBVIEW_ALL ^ GTK_WEBVIEW_SMILEY ^ GTK_WEBVIEW_IMAGE);
953 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 805 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
954 gtk_widget_show(frame); 806 gtk_widget_show(frame);
955 807
956 #ifdef USE_REGEX 808 gtk_webview_load_html_string(GTK_WEBVIEW(win->text), EMPTY_HTML);
957 /* add the tag for regex highlighting */
958 gtk_text_buffer_create_tag(GTK_IMHTML(win->text)->text_buffer, "regex",
959 "background", "#FFAFAF",
960 "weight", "bold",
961 NULL);
962 #endif /* USE_REGEX */
963 809
964 gtk_widget_show_all(win->window); 810 gtk_widget_show_all(win->window);
965 811
966 return win; 812 return win;
967 } 813 }
1058 904
1059 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/toolbar", TRUE); 905 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/toolbar", TRUE);
1060 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/debug/width", 450); 906 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/debug/width", 450);
1061 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/debug/height", 250); 907 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/debug/height", 250);
1062 908
1063 #ifdef USE_REGEX
1064 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/debug/regex", ""); 909 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/debug/regex", "");
1065 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/filter", FALSE); 910 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/filter", FALSE);
1066 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/invert", FALSE); 911 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/invert", FALSE);
1067 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/case_insensitive", FALSE); 912 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/case_insensitive", FALSE);
1068 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/highlight", FALSE); 913 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/highlight", FALSE);
1069 #endif /* USE_REGEX */
1070 914
1071 purple_prefs_connect_callback(NULL, PIDGIN_PREFS_ROOT "/debug/enabled", 915 purple_prefs_connect_callback(NULL, PIDGIN_PREFS_ROOT "/debug/enabled",
1072 debug_enabled_cb, NULL); 916 debug_enabled_cb, NULL);
1073 917
1074 #define REGISTER_G_LOG_HANDLER(name) \ 918 #define REGISTER_G_LOG_HANDLER(name) \
1126 970
1127 static void 971 static void
1128 pidgin_debug_print(PurpleDebugLevel level, const char *category, 972 pidgin_debug_print(PurpleDebugLevel level, const char *category,
1129 const char *arg_s) 973 const char *arg_s)
1130 { 974 {
1131 #ifdef USE_REGEX
1132 GtkTreeIter iter;
1133 #endif /* USE_REGEX */
1134 gchar *ts_s; 975 gchar *ts_s;
1135 gchar *esc_s, *cat_s, *tmp, *s; 976 gchar *esc_s, *cat_s, *tmp, *s;
1136 const char *mdate; 977 const char *mdate;
1137 time_t mtime; 978 time_t mtime;
1138 979
1148 if (category == NULL) 989 if (category == NULL)
1149 cat_s = g_strdup(""); 990 cat_s = g_strdup("");
1150 else 991 else
1151 cat_s = g_strdup_printf("<b>%s:</b> ", category); 992 cat_s = g_strdup_printf("<b>%s:</b> ", category);
1152 993
1153 esc_s = g_markup_escape_text(arg_s, -1); 994 tmp = purple_utf8_try_convert(arg_s);
1154 995 esc_s = g_markup_escape_text(tmp, -1);
1155 s = g_strdup_printf("<font color=\"%s\">%s%s%s</font>", 996
1156 debug_fg_colors[level], ts_s, cat_s, esc_s); 997 s = g_strdup_printf("<div class=\"l%d\">%s%s%s</div>",
998 level, ts_s, cat_s, esc_s);
1157 999
1158 g_free(ts_s); 1000 g_free(ts_s);
1159 g_free(cat_s); 1001 g_free(cat_s);
1160 g_free(esc_s); 1002 g_free(esc_s);
1161 1003 g_free(tmp);
1162 tmp = purple_utf8_try_convert(s); 1004
1163 g_free(s); 1005 gtk_webview_append_html(GTK_WEBVIEW(debug_win->text), s);
1164 s = tmp; 1006
1165 1007 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(debug_win->filter))) {
1166 if (level == PURPLE_DEBUG_FATAL) { 1008 WebKitDOMDocument *dom = NULL;
1167 tmp = g_strdup_printf("<b>%s</b>", s); 1009 WebKitDOMHTMLElement *body = NULL;
1168 g_free(s); 1010 WebKitDOMNode *div = NULL;
1169 s = tmp; 1011 dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(debug_win->text));
1170 } 1012 if (dom)
1171 1013 body = webkit_dom_document_get_body(dom);
1172 #ifdef USE_REGEX 1014 if (body)
1173 /* add the text to the list store */ 1015 div = webkit_dom_node_get_last_child(WEBKIT_DOM_NODE(body));
1174 gtk_list_store_append(debug_win->store, &iter); 1016 if (div)
1175 gtk_list_store_set(debug_win->store, &iter, 0, s, 1, level, -1); 1017 regex_match(debug_win, dom, div);
1176 #else /* USE_REGEX */ 1018 }
1177 if(!debug_win->paused && level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel"))
1178 gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0);
1179 #endif /* !USE_REGEX */
1180 1019
1181 g_free(s); 1020 g_free(s);
1182 } 1021 }
1183 1022
1184 static gboolean 1023 static gboolean
1208 pidgin_debug_get_handle() { 1047 pidgin_debug_get_handle() {
1209 static int handle; 1048 static int handle;
1210 1049
1211 return &handle; 1050 return &handle;
1212 } 1051 }
1052

mercurial