--- a/src/gtkdebug.c Wed Oct 18 16:28:51 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1021 +0,0 @@ -/** - * @file gtkdebug.c GTK+ Debug API - * @ingroup gtkui - * - * gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "internal.h" -#include "gtkgaim.h" - -#include "notify.h" -#include "prefs.h" -#include "request.h" -#include "util.h" - -#include "gtkdebug.h" -#include "gtkdialogs.h" -#include "gtkimhtml.h" -#include "gtkutils.h" -#include "gtkstock.h" - -#ifdef HAVE_REGEX_H -# include <regex.h> -#endif /* HAVE_REGEX_H */ - -#include <gdk/gdkkeysyms.h> - -typedef struct -{ - GtkWidget *window; - GtkWidget *text; - - GtkListStore *store; - - gboolean timestamps; - gboolean paused; - -#ifdef HAVE_REGEX_H - GtkWidget *filter; - GtkWidget *expression; - - gboolean invert; - gboolean highlight; - - guint timer; - - regex_t regex; -#else - GtkWidget *find; -#endif /* HAVE_REGEX_H */ -} DebugWindow; - -static char debug_fg_colors[][8] = { - "#000000", /**< All debug levels. */ - "#666666", /**< Misc. */ - "#000000", /**< Information. */ - "#660000", /**< Warnings. */ - "#FF0000", /**< Errors. */ - "#FF0000", /**< Fatal errors. */ -}; - -static DebugWindow *debug_win = NULL; - -#ifdef HAVE_REGEX_H -static void regex_filter_all(DebugWindow *win); -static void regex_show_all(DebugWindow *win); -#endif /* HAVE_REGEX_H */ - -static gint -debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused) -{ - gaim_prefs_disconnect_by_handle(gaim_gtk_debug_get_handle()); - -#ifdef HAVE_REGEX_H - if(debug_win->timer != 0) { - const gchar *text; - - g_source_remove(debug_win->timer); - - text = gtk_entry_get_text(GTK_ENTRY(debug_win->expression)); - gaim_prefs_set_string("/gaim/gtk/debug/regex", text); - } - - regfree(&debug_win->regex); -#endif - - /* If the "Save Log" dialog is open then close it */ - gaim_request_close_with_handle(debug_win); - - g_free(debug_win); - debug_win = NULL; - - gaim_prefs_set_bool("/gaim/gtk/debug/enabled", FALSE); - - return FALSE; -} - -static gboolean -configure_cb(GtkWidget *w, GdkEventConfigure *event, DebugWindow *win) -{ - if (GTK_WIDGET_VISIBLE(w)) { - gaim_prefs_set_int("/gaim/gtk/debug/width", event->width); - gaim_prefs_set_int("/gaim/gtk/debug/height", event->height); - } - - return FALSE; -} - -#ifndef HAVE_REGEX_H -struct _find { - DebugWindow *window; - GtkWidget *entry; -}; - -static void -do_find_cb(GtkWidget *widget, gint response, struct _find *f) -{ - switch (response) { - case GTK_RESPONSE_OK: - gtk_imhtml_search_find(GTK_IMHTML(f->window->text), - gtk_entry_get_text(GTK_ENTRY(f->entry))); - break; - - case GTK_RESPONSE_DELETE_EVENT: - case GTK_RESPONSE_CLOSE: - gtk_imhtml_search_clear(GTK_IMHTML(f->window->text)); - gtk_widget_destroy(f->window->find); - f->window->find = NULL; - g_free(f); - break; - } -} - -static void -find_cb(GtkWidget *w, DebugWindow *win) -{ - GtkWidget *hbox, *img, *label; - struct _find *f; - - if(win->find) - { - gtk_window_present(GTK_WINDOW(win->find)); - return; - } - - f = g_malloc(sizeof(struct _find)); - f->window = win; - win->find = gtk_dialog_new_with_buttons(_("Find"), - GTK_WINDOW(win->window), GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, - GTK_STOCK_FIND, GTK_RESPONSE_OK, NULL); - gtk_dialog_set_default_response(GTK_DIALOG(win->find), - GTK_RESPONSE_OK); - g_signal_connect(G_OBJECT(win->find), "response", - G_CALLBACK(do_find_cb), f); - - gtk_container_set_border_width(GTK_CONTAINER(win->find), GAIM_HIG_BOX_SPACE); - gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE); - gtk_dialog_set_has_separator(GTK_DIALOG(win->find), FALSE); - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), GAIM_HIG_BORDER); - gtk_container_set_border_width( - GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), GAIM_HIG_BOX_SPACE); - - hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), - hbox); - img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, - GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); - - gtk_misc_set_alignment(GTK_MISC(img), 0, 0); - gtk_dialog_set_response_sensitive(GTK_DIALOG(win->find), - GTK_RESPONSE_OK, FALSE); - - label = gtk_label_new(NULL); - gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Search for:")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - f->entry = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(f->entry), TRUE); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(f->entry)); - g_signal_connect(G_OBJECT(f->entry), "changed", - G_CALLBACK(gaim_gtk_set_sensitive_if_input), - win->find); - gtk_box_pack_start(GTK_BOX(hbox), f->entry, FALSE, FALSE, 0); - - gtk_widget_show_all(win->find); - gtk_widget_grab_focus(f->entry); -} -#endif /* HAVE_REGEX_H */ - -static void -save_writefile_cb(void *user_data, const char *filename) -{ - DebugWindow *win = (DebugWindow *)user_data; - FILE *fp; - char *tmp; - - if ((fp = g_fopen(filename, "w+")) == NULL) { - gaim_notify_error(win, NULL, _("Unable to open file."), NULL); - return; - } - - tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL); - fprintf(fp, "Gaim Debug Log : %s\n", gaim_date_format_full(NULL)); - fprintf(fp, "%s", tmp); - g_free(tmp); - - fclose(fp); -} - -static void -save_cb(GtkWidget *w, DebugWindow *win) -{ - gaim_request_file(win, _("Save Debug Log"), "gaim-debug.log", TRUE, - G_CALLBACK(save_writefile_cb), NULL, win); -} - -static void -clear_cb(GtkWidget *w, DebugWindow *win) -{ - gtk_imhtml_clear(GTK_IMHTML(win->text)); - -#ifdef HAVE_REGEX_H - gtk_list_store_clear(win->store); -#endif /* HAVE_REGEX_H */ -} - -static void -pause_cb(GtkWidget *w, DebugWindow *win) -{ - win->paused = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); - -#ifdef HAVE_REGEX_H - if(!win->paused) { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) - regex_filter_all(win); - else - regex_show_all(win); - } -#endif /* HAVE_REGEX_H */ -} - -static void -timestamps_cb(GtkWidget *w, DebugWindow *win) -{ - win->timestamps = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); - - gaim_prefs_set_bool("/core/debug/timestamps", win->timestamps); -} - -static void -timestamps_pref_cb(const char *name, GaimPrefType type, - gconstpointer value, gpointer data) -{ - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), GPOINTER_TO_INT(value)); -} - -/****************************************************************************** - * regex stuff - *****************************************************************************/ -#ifdef HAVE_REGEX_H -static void -regex_clear_color(GtkWidget *w) { - gtk_widget_modify_base(w, GTK_STATE_NORMAL, NULL); -} - -static void -regex_change_color(GtkWidget *w, guint16 r, guint16 g, guint16 b) { - GdkColor color; - - color.red = r; - color.green = g; - color.blue = b; - - gtk_widget_modify_base(w, GTK_STATE_NORMAL, &color); -} - -static void -regex_highlight_clear(DebugWindow *win) { - GtkIMHtml *imhtml = GTK_IMHTML(win->text); - GtkTextIter s, e; - - gtk_text_buffer_get_start_iter(imhtml->text_buffer, &s); - gtk_text_buffer_get_end_iter(imhtml->text_buffer, &e); - gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "regex", &s, &e); -} - -static void -regex_match(DebugWindow *win, const gchar *text) { - GtkIMHtml *imhtml = GTK_IMHTML(win->text); - regmatch_t matches[4]; /* adjust if necessary */ - size_t n_matches = sizeof(matches) / sizeof(matches[0]); - gchar *plaintext; - gint inverted; - - if(!text) - return; - - inverted = (win->invert) ? REG_NOMATCH : 0; - - /* I don't like having to do this, but we need it for highlighting. Plus - * it makes the ^ and $ operators work :) - */ - plaintext = gaim_markup_strip_html(text); - - /* we do a first pass to see if it matches at all. If it does we append - * it, and work out the offsets to highlight. - */ - if(regexec(&win->regex, plaintext, n_matches, matches, 0) == inverted) { - GtkTextIter ins; - gchar *p = plaintext; - gint i, offset = 0; - - gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, - gtk_text_buffer_get_insert(imhtml->text_buffer)); - i = gtk_text_iter_get_offset(&ins); - - gtk_imhtml_append_text(imhtml, text, 0); - - /* If we're not highlighting or the expression is inverted, we're - * done and move on. - */ - if(!win->highlight || inverted == REG_NOMATCH) { - g_free(plaintext); - return; - } - - /* we use a do-while to highlight the first match, and then continue - * if necessary... - */ - do { - size_t m; - - for(m = 0; m < n_matches; m++) { - GtkTextIter ms, me; - - if(matches[m].rm_eo == -1) - break; - - i += offset; - - gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms, - i + matches[m].rm_so); - gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &me, - i + matches[m].rm_eo); - gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "regex", - &ms, &me); - offset = matches[m].rm_eo; - } - - p += offset; - } while(regexec(&win->regex, p, n_matches, matches, REG_NOTBOL) == inverted); - } - - g_free(plaintext); -} - -static gboolean -regex_filter_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, - gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gchar *text; - - gtk_tree_model_get(m, iter, 0, &text, -1); - - regex_match(win, text); - - g_free(text); - - return FALSE; -} - -static void -regex_filter_all(DebugWindow *win) { - gtk_imhtml_clear(GTK_IMHTML(win->text)); - - if(win->highlight) - regex_highlight_clear(win); - - gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_filter_all_cb, - win); -} - -static gboolean -regex_show_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, - gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gchar *text; - - gtk_tree_model_get(m, iter, 0, &text, -1); - gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0); - g_free(text); - - return FALSE; -} - -static void -regex_show_all(DebugWindow *win) { - gtk_imhtml_clear(GTK_IMHTML(win->text)); - - if(win->highlight) - regex_highlight_clear(win); - - gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_show_all_cb, - win); -} - -static void -regex_compile(DebugWindow *win) { - const gchar *text; - - text = gtk_entry_get_text(GTK_ENTRY(win->expression)); - - if(text == NULL || *text == '\0') { - regex_clear_color(win->expression); - gtk_widget_set_sensitive(win->filter, FALSE); - return; - } - - regfree(&win->regex); - - if(regcomp(&win->regex, text, REG_EXTENDED | REG_ICASE) != 0) { - /* failed to compile */ - regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF); - gtk_widget_set_sensitive(win->filter, FALSE); - } else { - /* compiled successfully */ - regex_change_color(win->expression, 0xAFFF, 0xFFFF, 0xAFFF); - gtk_widget_set_sensitive(win->filter, TRUE); - } - - /* we check if the filter is on in case it was only of the options that - * got changed, and not the expression. - */ - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) - regex_filter_all(win); -} - -static void -regex_pref_filter_cb(const gchar *name, GaimPrefType type, - gconstpointer val, gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gboolean active = GPOINTER_TO_INT(val), current; - - if(!win || !win->window) - return; - - current = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)); - if(active != current) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), active); -} - -static void -regex_pref_expression_cb(const gchar *name, GaimPrefType type, - gconstpointer val, gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - const gchar *exp = (const gchar *)val; - - gtk_entry_set_text(GTK_ENTRY(win->expression), exp); -} - -static void -regex_pref_invert_cb(const gchar *name, GaimPrefType type, - gconstpointer val, gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gboolean active = GPOINTER_TO_INT(val); - - win->invert = active; - - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) - regex_filter_all(win); -} - -static void -regex_pref_highlight_cb(const gchar *name, GaimPrefType type, - gconstpointer val, gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gboolean active = GPOINTER_TO_INT(val); - - win->highlight = active; - - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) - regex_filter_all(win); -} - -static void -regex_row_changed_cb(GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, DebugWindow *win) -{ - gchar *text; - - if(!win || !win->window) - return; - - /* If the debug window is paused, we just return since it's in the store. - * We don't call regex_match because it doesn't make sense to check the - * string if it's paused. When we unpause we clear the imhtml and - * reiterate over the store to handle matches that were outputted when - * we were paused. - */ - if(win->paused) - return; - - gtk_tree_model_get(model, iter, 0, &text, -1); - - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) { - regex_match(win, text); - } else { - gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0); - } - - g_free(text); -} - -static gboolean -regex_timer_cb(DebugWindow *win) { - const gchar *text; - - text = gtk_entry_get_text(GTK_ENTRY(win->expression)); - gaim_prefs_set_string("/gaim/gtk/debug/regex", text); - - win->timer = 0; - - return FALSE; -} - -static void -regex_changed_cb(GtkWidget *w, DebugWindow *win) { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), - FALSE); - } - - if(win->timer == 0) - win->timer = gaim_timeout_add(5000, (GSourceFunc)regex_timer_cb, win); - - regex_compile(win); -} - -static void -regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) { - if(e->keyval == GDK_Return && - GTK_WIDGET_IS_SENSITIVE(win->filter) && - !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) - { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), TRUE); - } -} - -static void -regex_menu_cb(GtkWidget *item, const gchar *pref) { - gboolean active; - - active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)); - - gaim_prefs_set_bool(pref, active); -} - -static void -regex_popup_cb(GtkEntry *entry, GtkWidget *menu, DebugWindow *win) { - gaim_separator(menu); - gaim_new_check_item(menu, _("Invert"), - G_CALLBACK(regex_menu_cb), - "/gaim/gtk/debug/invert", win->invert); - gaim_new_check_item(menu, _("Highlight matches"), - G_CALLBACK(regex_menu_cb), - "/gaim/gtk/debug/highlight", win->highlight); -} - -static void -regex_filter_toggled_cb(GtkToggleButton *button, DebugWindow *win) { - gboolean active; - - active = gtk_toggle_button_get_active(button); - - gaim_prefs_set_bool("/gaim/gtk/debug/filter", active); - - if(!GTK_IS_IMHTML(win->text)) - return; - - if(active) - regex_filter_all(win); - else - regex_show_all(win); -} - -#endif /* HAVE_REGEX_H */ - -static DebugWindow * -debug_window_new(void) -{ - DebugWindow *win; - GtkWidget *vbox; - GtkWidget *toolbar; - GtkWidget *frame; - GtkWidget *button; - GtkWidget *image; - gint width, height; - void *handle; - - win = g_new0(DebugWindow, 1); - - width = gaim_prefs_get_int("/gaim/gtk/debug/width"); - height = gaim_prefs_get_int("/gaim/gtk/debug/height"); - - GAIM_DIALOG(win->window); - gaim_debug_info("gtkdebug", "Setting dimensions to %d, %d\n", - width, height); - - gtk_window_set_default_size(GTK_WINDOW(win->window), width, height); - gtk_window_set_role(GTK_WINDOW(win->window), "debug"); - gtk_window_set_title(GTK_WINDOW(win->window), _("Debug Window")); - - g_signal_connect(G_OBJECT(win->window), "delete_event", - G_CALLBACK(debug_window_destroy), NULL); - g_signal_connect(G_OBJECT(win->window), "configure_event", - G_CALLBACK(configure_cb), win); - - handle = gaim_gtk_debug_get_handle(); - -#ifdef HAVE_REGEX_H - /* the list store for all the messages */ - win->store = gtk_list_store_new(1, G_TYPE_STRING); - - /* row-changed gets called when we do gtk_list_store_set, and row-inserted - * gets called with gtk_list_store_append, which is a - * completely empty row. So we just ignore row-inserted, and deal with row - * changed. -Gary - */ - g_signal_connect(G_OBJECT(win->store), "row-changed", - G_CALLBACK(regex_row_changed_cb), win); - -#endif /* HAVE_REGEX_H */ - - /* Setup the vbox */ - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(win->window), vbox); - - if (gaim_prefs_get_bool("/gaim/gtk/debug/toolbar")) { - /* Setup our top button bar thingie. */ - toolbar = gtk_toolbar_new(); - gtk_toolbar_set_tooltips(GTK_TOOLBAR(toolbar), TRUE); - - gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_BOTH_HORIZ); - gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), - GTK_ICON_SIZE_SMALL_TOOLBAR); - - gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); - -#ifndef HAVE_REGEX_H - /* Find button */ - gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND, - _("Find"), NULL, G_CALLBACK(find_cb), - win, -1); -#endif /* HAVE_REGEX_H */ - - /* Save */ - gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE, - _("Save"), NULL, G_CALLBACK(save_cb), - win, -1); - - /* Clear button */ - gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR, - _("Clear"), NULL, G_CALLBACK(clear_cb), - win, -1); - - gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); - - /* Pause */ - image = gtk_image_new_from_stock(GAIM_STOCK_PAUSE, GTK_ICON_SIZE_MENU); - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_TOGGLEBUTTON, - NULL, _("Pause"), _("Pause"), - NULL, image, - G_CALLBACK(pause_cb), win); - - /* Timestamps */ - button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_TOGGLEBUTTON, - NULL, _("Timestamps"), - _("Timestamps"), NULL, NULL, - G_CALLBACK(timestamps_cb), - win); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), - gaim_prefs_get_bool("/core/debug/timestamps")); - - gaim_prefs_connect_callback(handle, "/core/debug/timestamps", - timestamps_pref_cb, button); - -#ifdef HAVE_REGEX_H - /* regex stuff */ - gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); - - /* regex toggle button */ - win->filter = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_TOGGLEBUTTON, - NULL, _("Filter"), _("Filter"), - NULL, NULL, - G_CALLBACK(regex_filter_toggled_cb), - win); - /* we purposely disable the toggle button here in case - * /gaim/gtk/debug/expression has an empty string. If it does not have - * an empty string, the change signal will get called and make the - * toggle button sensitive. - */ - gtk_widget_set_sensitive(win->filter, FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), - gaim_prefs_get_bool("/gaim/gtk/debug/filter")); - gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/filter", - regex_pref_filter_cb, win); - - /* regex entry */ - win->expression = gtk_entry_new(); - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_WIDGET, win->expression, - NULL, _("Right click for more options."), - NULL, NULL, NULL, NULL); - /* this needs to be before the text is set from the pref if we want it - * to colorize a stored expression. - */ - g_signal_connect(G_OBJECT(win->expression), "changed", - G_CALLBACK(regex_changed_cb), win); - gtk_entry_set_text(GTK_ENTRY(win->expression), - gaim_prefs_get_string("/gaim/gtk/debug/regex")); - g_signal_connect(G_OBJECT(win->expression), "populate-popup", - G_CALLBACK(regex_popup_cb), win); - g_signal_connect(G_OBJECT(win->expression), "key-release-event", - G_CALLBACK(regex_key_release_cb), win); - gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/regex", - regex_pref_expression_cb, win); - - /* connect the rest of our pref callbacks */ - win->invert = gaim_prefs_get_bool("/gaim/gtk/debug/invert"); - gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/invert", - regex_pref_invert_cb, win); - - win->highlight = gaim_prefs_get_bool("/gaim/gtk/debug/highlight"); - gaim_prefs_connect_callback(handle, "/gaim/gtk/debug/highlight", - regex_pref_highlight_cb, win); - -#endif /* HAVE_REGEX_H */ - } - - /* Add the gtkimhtml */ - frame = gaim_gtk_create_imhtml(FALSE, &win->text, NULL, NULL); - gtk_imhtml_set_format_functions(GTK_IMHTML(win->text), - GTK_IMHTML_ALL ^ GTK_IMHTML_SMILEY ^ GTK_IMHTML_IMAGE); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - gtk_widget_show(frame); - -#ifdef HAVE_REGEX_H - /* add the tag for regex highlighting */ - gtk_text_buffer_create_tag(GTK_IMHTML(win->text)->text_buffer, "regex", - "background", "#FFAFAF", - "weight", "bold", - NULL); -#endif /* HAVE_REGEX_H */ - - gtk_widget_show_all(win->window); - - return win; -} - -static void -debug_enabled_cb(const char *name, GaimPrefType type, - gconstpointer value, gpointer data) -{ - if (value) - gaim_gtk_debug_window_show(); - else - gaim_gtk_debug_window_hide(); -} - -static void -gaim_glib_log_handler(const gchar *domain, GLogLevelFlags flags, - const gchar *msg, gpointer user_data) -{ - GaimDebugLevel level; - char *new_msg = NULL; - char *new_domain = NULL; - - if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR) - level = GAIM_DEBUG_ERROR; - else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL) - level = GAIM_DEBUG_FATAL; - else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING) - level = GAIM_DEBUG_WARNING; - else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE) - level = GAIM_DEBUG_INFO; - else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO) - level = GAIM_DEBUG_INFO; - else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG) - level = GAIM_DEBUG_MISC; - else - { - gaim_debug_warning("gtkdebug", - "Unknown glib logging level in %d\n", flags); - - level = GAIM_DEBUG_MISC; /* This will never happen. */ - } - - if (msg != NULL) - new_msg = gaim_utf8_try_convert(msg); - - if (domain != NULL) - new_domain = gaim_utf8_try_convert(domain); - - if (new_msg != NULL) - { - gaim_debug(level, (new_domain != NULL ? new_domain : "g_log"), - "%s\n", new_msg); - - g_free(new_msg); - } - - if (new_domain != NULL) - g_free(new_domain); -} - -#ifdef _WIN32 -static void -gaim_glib_dummy_print_handler(const gchar *string) -{ -} -#endif - -void -gaim_gtk_debug_init(void) -{ - /* Debug window preferences. */ - /* - * NOTE: This must be set before prefs are loaded, and the callbacks - * set after they are loaded, since prefs sets the enabled - * preference here and that loads the window, which calls the - * configure event, which overrides the width and height! :P - */ - - gaim_prefs_add_none("/gaim/gtk/debug"); - - /* Controls printing to the debug window */ - gaim_prefs_add_bool("/gaim/gtk/debug/enabled", FALSE); - - gaim_prefs_add_bool("/gaim/gtk/debug/toolbar", TRUE); - gaim_prefs_add_int("/gaim/gtk/debug/width", 450); - gaim_prefs_add_int("/gaim/gtk/debug/height", 250); - -#ifdef HAVE_REGEX_H - gaim_prefs_add_string("/gaim/gtk/debug/regex", ""); - gaim_prefs_add_bool("/gaim/gtk/debug/filter", FALSE); - gaim_prefs_add_bool("/gaim/gtk/debug/invert", FALSE); - gaim_prefs_add_bool("/gaim/gtk/debug/case_insensitive", FALSE); - gaim_prefs_add_bool("/gaim/gtk/debug/highlight", FALSE); -#endif /* HAVE_REGEX_H */ - - gaim_prefs_connect_callback(NULL, "/gaim/gtk/debug/enabled", - debug_enabled_cb, NULL); - -#define REGISTER_G_LOG_HANDLER(name) \ - g_log_set_handler((name), G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \ - | G_LOG_FLAG_RECURSION, \ - gaim_glib_log_handler, NULL) - - /* Register the glib/gtk log handlers. */ - REGISTER_G_LOG_HANDLER(NULL); - REGISTER_G_LOG_HANDLER("Gdk"); - REGISTER_G_LOG_HANDLER("Gtk"); - REGISTER_G_LOG_HANDLER("GdkPixbuf"); - REGISTER_G_LOG_HANDLER("GLib"); - REGISTER_G_LOG_HANDLER("GModule"); - REGISTER_G_LOG_HANDLER("GLib-GObject"); - REGISTER_G_LOG_HANDLER("GThread"); - -#ifdef _WIN32 - if (!gaim_debug_is_enabled()) - g_set_print_handler(gaim_glib_dummy_print_handler); -#endif -} - -void -gaim_gtk_debug_uninit(void) -{ - gaim_debug_set_ui_ops(NULL); -} - -void -gaim_gtk_debug_window_show(void) -{ - if (debug_win == NULL) - debug_win = debug_window_new(); - - gtk_widget_show(debug_win->window); - - gaim_prefs_set_bool("/gaim/gtk/debug/enabled", TRUE); -} - -void -gaim_gtk_debug_window_hide(void) -{ - if (debug_win != NULL) { - gtk_widget_destroy(debug_win->window); - debug_window_destroy(NULL, NULL, NULL); - } -} - -static void -gaim_gtk_debug_print(GaimDebugLevel level, const char *category, - const char *format, va_list args) -{ -#ifdef HAVE_REGEX_H - GtkTreeIter iter; -#endif /* HAVE_REGEX_H */ - gboolean timestamps; - gchar *arg_s, *ts_s; - gchar *esc_s, *cat_s, *tmp, *s; - - if (!gaim_prefs_get_bool("/gaim/gtk/debug/enabled") || - (debug_win == NULL)) - { - return; - } - - timestamps = gaim_prefs_get_bool("/core/debug/timestamps"); - - arg_s = g_strdup_vprintf(format, args); - - /* - * For some reason we only print the timestamp if category is - * not NULL. Why the hell do we do that? --Mark - */ - if ((category != NULL) && (timestamps)) { - const char *mdate; - - time_t mtime = time(NULL); - mdate = gaim_utf8_strftime("%H:%M:%S", localtime(&mtime)); - ts_s = g_strdup_printf("(%s) ", mdate); - } else { - ts_s = g_strdup(""); - } - - if (category == NULL) - cat_s = g_strdup(""); - else - cat_s = g_strdup_printf("<b>%s:</b> ", category); - - esc_s = g_markup_escape_text(arg_s, -1); - - g_free(arg_s); - - s = g_strdup_printf("<font color=\"%s\">%s%s%s</font>", - debug_fg_colors[level], ts_s, cat_s, esc_s); - - g_free(ts_s); - g_free(cat_s); - g_free(esc_s); - - tmp = gaim_utf8_try_convert(s); - g_free(s); - s = tmp; - - if (level == GAIM_DEBUG_FATAL) { - tmp = g_strdup_printf("<b>%s</b>", s); - g_free(s); - s = tmp; - } - -#ifdef HAVE_REGEX_H - /* add the text to the list store */ - gtk_list_store_append(debug_win->store, &iter); - gtk_list_store_set(debug_win->store, &iter, 0, s, -1); -#else /* HAVE_REGEX_H */ - if(!debug_win->paused) - gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0); -#endif /* !HAVE_REGEX_H */ - - g_free(s); -} - -static GaimDebugUiOps ops = -{ - gaim_gtk_debug_print, -}; - -GaimDebugUiOps * -gaim_gtk_debug_get_ui_ops(void) -{ - return &ops; -} - -void * -gaim_gtk_debug_get_handle() { - static int handle; - - return &handle; -}