pidgin/gtkdebug.c

changeset 33923
0fcc5635daba
parent 33922
61f997b47954
child 33924
788678d2e035
equal deleted inserted replaced
33922:61f997b47954 33923:0fcc5635daba
164 164
165 gtk_widget_modify_base(w, GTK_STATE_NORMAL, &color); 165 gtk_widget_modify_base(w, GTK_STATE_NORMAL, &color);
166 } 166 }
167 167
168 static void 168 static void
169 regex_toggle_div(WebKitDOMNode *div)
170 {
171 WebKitDOMDOMTokenList *classes;
172
173 if (!WEBKIT_DOM_IS_HTML_ELEMENT(div))
174 return;
175
176 #if (WEBKIT_MAJOR_VERSION == 1 && \
177 WEBKIT_MINOR_VERSION == 9 && \
178 WEBKIT_MICRO_VERSION == 90)
179 /* Workaround WebKit API bug. */
180 classes = webkit_dom_element_get_class_list(WEBKIT_DOM_ELEMENT(div));
181 #else
182 classes = webkit_dom_html_element_get_class_list(WEBKIT_DOM_HTML_ELEMENT(div));
183 #endif
184 webkit_dom_dom_token_list_toggle(classes, "hide", NULL);
185 g_object_unref(classes);
186 }
187
188 static void
189 regex_highlight_clear(WebKitDOMDocument *dom)
190 {
191 WebKitDOMNodeList *nodes;
192 gulong i;
193
194 /* Remove highlighting SPANs */
195 nodes = webkit_dom_document_get_elements_by_class_name(dom, "regex");
196 i = webkit_dom_node_list_get_length(nodes);
197 while (i--) {
198 WebKitDOMNode *span, *parent;
199 char *content;
200 WebKitDOMText *text;
201 GError *err = NULL;
202
203 span = webkit_dom_node_list_item(nodes, i);
204 parent = webkit_dom_node_get_parent_node(span);
205
206 content = webkit_dom_node_get_text_content(span);
207 text = webkit_dom_document_create_text_node(dom, content);
208 g_free(content);
209
210 webkit_dom_node_replace_child(parent, WEBKIT_DOM_NODE(text), span, &err);
211 }
212
213 g_object_unref(nodes);
214 }
215
216 static void
217 regex_highlight_text_nodes(WebKitDOMDocument *dom, WebKitDOMNode *div,
218 gint start_pos, gint end_pos)
219 {
220 GSList *data = NULL;
221 WebKitDOMNode *node;
222 WebKitDOMRange *range;
223 WebKitDOMElement *span;
224 gint ind, end_ind;
225 gint this_start, this_end;
226
227 ind = 0;
228 webkit_dom_node_normalize(div);
229 node = div;
230
231 /* First, find the container nodes and offsets to apply highlighting. */
232 do {
233 if (webkit_dom_node_get_node_type(node) == 3/*TEXT_NODE*/) {
234 /* The GObject model does not correctly reflect the type, hence the
235 regular cast. */
236 end_ind = ind + webkit_dom_character_data_get_length((WebKitDOMCharacterData*)node);
237
238 if (start_pos <= ind)
239 this_start = 0;
240 else if (start_pos < end_ind)
241 this_start = start_pos - ind;
242 else
243 this_start = -1;
244
245 if (end_pos < end_ind)
246 this_end = end_pos - ind;
247 else
248 this_end = end_ind - ind;
249
250 if (this_start != -1 && this_start < this_end) {
251 data = g_slist_prepend(data, GINT_TO_POINTER(this_end));
252 data = g_slist_prepend(data, GINT_TO_POINTER(this_start));
253 data = g_slist_prepend(data, node);
254 }
255
256 ind = end_ind;
257 }
258
259 if (webkit_dom_node_has_child_nodes(node)) {
260 node = webkit_dom_node_get_first_child(node);
261 } else {
262 while (node != div) {
263 WebKitDOMNode *next;
264
265 next = webkit_dom_node_get_next_sibling(node);
266 if (next) {
267 node = next;
268 break;
269 } else {
270 node = webkit_dom_node_get_parent_node(node);
271 }
272 }
273 }
274 } while (node != div);
275
276 /* Second, apply highlighting to saved sections. Changing the DOM is
277 automatically reflected in all WebKit API, so we have to do this after
278 finding the offsets, or things could get complicated. */
279 while (data) {
280 node = WEBKIT_DOM_NODE(data->data);
281 data = g_slist_delete_link(data, data);
282 this_start = GPOINTER_TO_INT(data->data);
283 data = g_slist_delete_link(data, data);
284 this_end = GPOINTER_TO_INT(data->data);
285 data = g_slist_delete_link(data, data);
286
287 range = webkit_dom_document_create_range(dom);
288 webkit_dom_range_set_start(range, node, this_start, NULL);
289 webkit_dom_range_set_end(range, node, this_end, NULL);
290 span = webkit_dom_document_create_element(dom, "span", NULL);
291 webkit_dom_html_element_set_class_name(WEBKIT_DOM_HTML_ELEMENT(span),
292 "regex");
293 webkit_dom_range_surround_contents(range, WEBKIT_DOM_NODE(span), NULL);
294 }
295 }
296
297 static void
298 regex_match(DebugWindow *win, WebKitDOMDocument *dom, WebKitDOMNode *div)
299 {
300 GMatchInfo *match_info;
301 gchar *text;
302 gchar *plaintext;
303
304 text = webkit_dom_node_get_text_content(div);
305 if (!text)
306 return;
307
308 /* I don't like having to do this, but we need it for highlighting. Plus
309 * it makes the ^ and $ operators work :)
310 */
311 plaintext = purple_markup_strip_html(text);
312
313 /* We do a first pass to see if it matches at all. If it does we work out
314 * the offsets to highlight.
315 */
316 if (g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) {
317 /* If we're not highlighting or the expression is inverted, we're
318 * done and move on.
319 */
320 if (!win->highlight || win->invert) {
321 g_free(plaintext);
322 g_match_info_free(match_info);
323 return;
324 }
325
326 do {
327 gint m, count;
328 gint start_pos, end_pos;
329
330 if (!g_match_info_matches(match_info))
331 break;
332
333 count = g_match_info_get_match_count(match_info);
334 if (count == 1)
335 m = 0;
336 else
337 m = 1;
338
339 for (; m < count; m++)
340 {
341 g_match_info_fetch_pos(match_info, m, &start_pos, &end_pos);
342
343 if (end_pos == -1)
344 break;
345
346 regex_highlight_text_nodes(dom, div, start_pos, end_pos);
347 }
348 } while (g_match_info_next(match_info, NULL));
349
350 g_match_info_free(match_info);
351 } else {
352 regex_toggle_div(div);
353 }
354
355 g_free(plaintext);
356 g_free(text);
357 }
358
359 static void
360 regex_toggle_filter(DebugWindow *win, gboolean filter) 169 regex_toggle_filter(DebugWindow *win, gboolean filter)
361 { 170 {
362 WebKitDOMDocument *dom; 171 gtk_webview_safe_execute_script(GTK_WEBVIEW(win->text), "regex.clear();");
363 WebKitDOMNodeList *list;
364 gulong i;
365
366 dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text));
367
368 if (win->highlight)
369 regex_highlight_clear(dom);
370
371 /* Re-show debug lines that didn't match regex */
372 list = webkit_dom_document_get_elements_by_class_name(dom, "hide");
373 i = webkit_dom_node_list_get_length(list);
374
375 while (i--) {
376 WebKitDOMNode *div = webkit_dom_node_list_item(list, i);
377 regex_toggle_div(div);
378 }
379
380 g_object_unref(list);
381 172
382 if (filter) { 173 if (filter) {
383 list = webkit_dom_document_get_elements_by_tag_name(dom, "div"); 174 const char *text;
384 175 char *regex;
385 for (i = 0; i < webkit_dom_node_list_get_length(list); i++) { 176 char *script;
386 WebKitDOMNode *div = webkit_dom_node_list_item(list, i); 177
387 regex_match(win, dom, div); 178 text = gtk_entry_get_text(GTK_ENTRY(win->expression));
388 } 179 regex = gtk_webview_quote_js_string(text);
389 180 script = g_strdup_printf("regex.filterAll(%s, %s, %s);",
390 g_object_unref(list); 181 regex,
182 win->invert ? "true" : "false",
183 win->highlight ? "true" : "false");
184 gtk_webview_safe_execute_script(GTK_WEBVIEW(win->text), script);
185 g_free(script);
186 g_free(regex);
391 } 187 }
392 } 188 }
393 189
394 static void 190 static void
395 regex_pref_filter_cb(const gchar *name, PurplePrefType type, 191 regex_pref_filter_cb(const gchar *name, PurplePrefType type,
474 return; 270 return;
475 } 271 }
476 272
477 if (win->regex) 273 if (win->regex)
478 g_regex_unref(win->regex); 274 g_regex_unref(win->regex);
275 #if GLIB_CHECK_VERSION(2,34,0)
276 win->regex = g_regex_new(text, G_REGEX_CASELESS|G_REGEX_JAVASCRIPT_COMPAT, 0, NULL);
277 #else
479 win->regex = g_regex_new(text, G_REGEX_CASELESS, 0, NULL); 278 win->regex = g_regex_new(text, G_REGEX_CASELESS, 0, NULL);
279 #endif
480 if (win->regex == NULL) { 280 if (win->regex == NULL) {
481 /* failed to compile */ 281 /* failed to compile */
482 regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF); 282 regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF);
483 gtk_widget_set_sensitive(win->filter, FALSE); 283 gtk_widget_set_sensitive(win->filter, FALSE);
484 } else { 284 } else {
595 } 395 }
596 396
597 gtk_widget_show_all(menu); 397 gtk_widget_show_all(menu);
598 398
599 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); 399 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time);
600 return FALSE;
601 }
602
603 static void
604 debug_window_appended(DebugWindow *win)
605 {
606 WebKitDOMDocument *dom;
607 WebKitDOMHTMLElement *body;
608 WebKitDOMNode *div;
609
610 if (!gtk_toggle_tool_button_get_active(
611 GTK_TOGGLE_TOOL_BUTTON(win->filter)))
612 return;
613
614 dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text));
615 body = webkit_dom_document_get_body(dom);
616 div = webkit_dom_node_get_last_child(WEBKIT_DOM_NODE(body));
617
618 if (webkit_dom_element_webkit_matches_selector(
619 WEBKIT_DOM_ELEMENT(div), "body>div:not(#pause)", NULL))
620 regex_match(win, dom, div);
621 }
622
623 static gboolean debug_window_alert_cb(WebKitWebView *webview,
624 WebKitWebFrame *frame, gchar *message, gpointer _win)
625 {
626 DebugWindow *win = _win;
627
628 if (!win || !win->window)
629 return FALSE;
630
631 if (g_strcmp0(message, "appended") == 0) {
632 debug_window_appended(win);
633 return TRUE;
634 }
635
636 return FALSE; 400 return FALSE;
637 } 401 }
638 402
639 static DebugWindow * 403 static DebugWindow *
640 debug_window_new(void) 404 debug_window_new(void)
796 GTK_WEBVIEW_ALL ^ GTK_WEBVIEW_SMILEY ^ GTK_WEBVIEW_IMAGE); 560 GTK_WEBVIEW_ALL ^ GTK_WEBVIEW_SMILEY ^ GTK_WEBVIEW_IMAGE);
797 gtk_webview_set_autoscroll(GTK_WEBVIEW(win->text), TRUE); 561 gtk_webview_set_autoscroll(GTK_WEBVIEW(win->text), TRUE);
798 gtk_webview_load_html_string(GTK_WEBVIEW(win->text), gtkdebug_html); 562 gtk_webview_load_html_string(GTK_WEBVIEW(win->text), gtkdebug_html);
799 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 563 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
800 gtk_widget_show(frame); 564 gtk_widget_show(frame);
801
802 g_signal_connect(G_OBJECT(win->text), "script-alert",
803 G_CALLBACK(debug_window_alert_cb), win);
804 565
805 clear_cb(NULL, win); 566 clear_cb(NULL, win);
806 567
807 gtk_widget_show_all(win->window); 568 gtk_widget_show_all(win->window);
808 569

mercurial