fix bug 4239, 'Preferences: Text Options Header Display modal is not modal' (sic)
[claws.git] / src / gtk / logwindow.c
index fb0becb001092acad4367bcf5ca5051880eef95c..c88dfd98cf2716ed9167c0170fe709a05467cc41 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2018 Hiroyuki Yamamoto and the Claws Mail team
  *
  * 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
  *
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * 
  */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
 #include <glib.h>
@@ -62,11 +62,11 @@ static void size_allocate_cb(GtkWidget *widget,
        gint *prefs_logwin_height = NULL;
        LogInstance instance = GPOINTER_TO_INT(data);
 
-       g_return_if_fail(allocation != NULL);
+       cm_return_if_fail(allocation != NULL);
 
        get_log_prefs(instance, &prefs_logwin_width, &prefs_logwin_height);
-       g_return_if_fail(prefs_logwin_width != NULL);
-       g_return_if_fail(prefs_logwin_height != NULL);
+       cm_return_if_fail(prefs_logwin_width != NULL);
+       cm_return_if_fail(prefs_logwin_height != NULL);
 
        *prefs_logwin_width = allocation->width;
        *prefs_logwin_height = allocation->height;
@@ -87,14 +87,15 @@ LogWindow *log_window_create(LogInstance instance)
        debug_print("Creating log window...\n");
 
        get_log_prefs(instance, &prefs_logwin_width, &prefs_logwin_height);
-       g_return_val_if_fail(prefs_logwin_width != NULL, NULL);
-       g_return_val_if_fail(prefs_logwin_height != NULL, NULL);
+       cm_return_val_if_fail(prefs_logwin_width != NULL, NULL);
+       cm_return_val_if_fail(prefs_logwin_height != NULL, NULL);
 
        logwin = g_new0(LogWindow, 1);
 
        window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "logwindow");
        gtk_window_set_title(GTK_WINDOW(window), get_log_title(instance));
        gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
+       gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
        g_signal_connect(G_OBJECT(window), "delete_event",
                         G_CALLBACK(gtk_widget_hide_on_delete), NULL);
        g_signal_connect(G_OBJECT(window), "key_press_event",
@@ -146,8 +147,7 @@ LogWindow *log_window_create(LogInstance instance)
        logwin->scrolledwin = scrolledwin;
        logwin->text = text;
        logwin->hook_id = hooks_register_hook(get_log_hook(instance), log_window_append, logwin);
-
-       gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(text), logwin->end_mark);
+       logwin->has_error_capability = get_log_error_capability(instance);
 
        return logwin;
 }
@@ -158,18 +158,18 @@ void log_window_init(LogWindow *logwin)
 {
        GtkTextBuffer *buffer;
        GdkColormap *colormap;
-       GdkColor color[LOG_COLORS];
        gboolean success[LOG_COLORS];
+       GdkColor color[LOG_COLORS];
        gint i;
 
-       gtkut_convert_int_to_gdk_color(prefs_common.log_msg_color, &color[0]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_warn_color, &color[1]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_error_color, &color[2]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_in_color, &color[3]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_out_color, &color[4]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_status_ok_color, &color[5]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_status_nok_color, &color[6]);
-       gtkut_convert_int_to_gdk_color(prefs_common.log_status_skip_color, &color[7]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_MSG], &color[0]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_WARN], &color[1]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_ERROR], &color[2]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_IN], &color[3]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_OUT], &color[4]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_STATUS_OK], &color[5]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_STATUS_NOK], &color[6]);
+       gtkut_convert_int_to_gdk_color(prefs_common.color[COL_LOG_STATUS_SKIP], &color[7]);
 
        logwin->msg_color = color[0];
        logwin->warn_color = color[1];
@@ -180,14 +180,14 @@ void log_window_init(LogWindow *logwin)
        logwin->status_nok_color = color[6];
        logwin->status_skip_color = color[7];
 
-       colormap = gdk_drawable_get_colormap(logwin->window->window);
+       colormap = gdk_drawable_get_colormap(gtk_widget_get_window(logwin->window));
        gdk_colormap_alloc_colors(colormap, color, LOG_COLORS, FALSE, TRUE, success);
 
        for (i = 0; i < LOG_COLORS; i++) {
                if (success[i] == FALSE) {
                        GtkStyle *style;
 
-                       g_warning("LogWindow: color allocation failed\n");
+                       g_warning("LogWindow: color allocation failed");
                        style = gtk_widget_get_style(logwin->window);
                        logwin->msg_color = logwin->warn_color =
                                        logwin->error_color = logwin->in_color =
@@ -246,10 +246,6 @@ void log_window_show(LogWindow *logwin)
        gtk_window_deiconify(GTK_WINDOW(logwin->window));
        gtk_widget_show(logwin->window);
        gtk_window_present(GTK_WINDOW(logwin->window));
-#ifdef MAEMO
-       maemo_window_full_screen_if_needed(GTK_WINDOW(logwin->window));
-       maemo_connect_key_press_to_mainwindow(GTK_WINDOW(logwin->window));
-#endif
 }
 
 static void log_window_jump_to_error(LogWindow *logwin)
@@ -271,7 +267,7 @@ void log_window_show_error(LogWindow *logwin)
 
 void log_window_set_clipping(LogWindow *logwin, gboolean clip, guint clip_length)
 {
-       g_return_if_fail(logwin != NULL);
+       cm_return_if_fail(logwin != NULL);
 
        logwin->clip = clip;
        logwin->clip_length = clip_length;
@@ -287,9 +283,9 @@ static gboolean log_window_append(gpointer source, gpointer data)
        gchar *head = NULL;
        const gchar *tag;
 
-       g_return_val_if_fail(logtext != NULL, TRUE);
-       g_return_val_if_fail(logtext->text != NULL, TRUE);
-       g_return_val_if_fail(logwindow != NULL, FALSE);
+       cm_return_val_if_fail(logtext != NULL, TRUE);
+       cm_return_val_if_fail(logtext->text != NULL, TRUE);
+       cm_return_val_if_fail(logwindow != NULL, FALSE);
 
        if (logwindow->clip && !logwindow->clip_length)
                return FALSE;
@@ -310,6 +306,7 @@ static gboolean log_window_append(gpointer source, gpointer data)
        case LOG_ERROR:
                tag = "error";
                head = "*** ";
+               logwindow->has_error = TRUE;
                break;
        case LOG_STATUS_OK:
                tag = "status_ok";
@@ -330,14 +327,14 @@ static gboolean log_window_append(gpointer source, gpointer data)
 
        if (logtext->instance == LOG_PROTOCOL) {
                if (tag == NULL) {
-                       if (strstr(logtext->text, "] POP3>")
-                       ||  strstr(logtext->text, "] IMAP4>")
+                       if (strstr(logtext->text, "] POP>")
+                       ||  strstr(logtext->text, "] IMAP>")
                        ||  strstr(logtext->text, "] SMTP>")
                        ||  strstr(logtext->text, "] ESMTP>")
                        ||  strstr(logtext->text, "] NNTP>"))
                                tag = "output";
-                       if (strstr(logtext->text, "] POP3<")
-                       ||  strstr(logtext->text, "] IMAP4<")
+                       if (strstr(logtext->text, "] POP<")
+                       ||  strstr(logtext->text, "] IMAP<")
                        ||  strstr(logtext->text, "] SMTP<")
                        ||  strstr(logtext->text, "] ESMTP<")
                        ||  strstr(logtext->text, "] NNTP<"))
@@ -365,10 +362,12 @@ static gboolean log_window_append(gpointer source, gpointer data)
               log_window_clip (logwindow, logwindow->clip_length);
 
        if (!logwindow->hidden) {
-               GtkAdjustment *vadj = text->vadjustment;
-               gfloat upper = vadj->upper - vadj->page_size;
-               if (vadj->value == upper || 
-                   (upper - vadj->value < 16 && vadj->value < 8))
+               GtkAdjustment *vadj = gtk_text_view_get_vadjustment(text);
+               gfloat upper = gtk_adjustment_get_upper(vadj) -
+                   gtk_adjustment_get_page_size(vadj);
+               gfloat value = gtk_adjustment_get_value(vadj);
+               if (value == upper || 
+                   (upper - value < 16 && value < 8))
                        gtk_text_view_scroll_mark_onscreen(text, logwindow->end_mark);
        }
 
@@ -383,9 +382,9 @@ static void hide_cb(GtkWidget *widget, LogWindow *logwin)
 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
                        LogWindow *logwin)
 {
-       if (event && event->keyval == GDK_Escape)
+       if (event && event->keyval == GDK_KEY_Escape)
                gtk_widget_hide(logwin->window);
-       else if (event && event->keyval == GDK_Delete) 
+       else if (event && event->keyval == GDK_KEY_Delete) 
                log_window_clear(NULL, logwin);
 
        return FALSE;
@@ -410,6 +409,13 @@ static void log_window_clip(LogWindow *logwin, guint clip_length)
                        return;
                gtk_text_buffer_get_start_iter(textbuf, &start_iter);
                gtk_text_buffer_delete(textbuf, &start_iter, &end_iter);
+               if (logwin->has_error) {
+                       gtk_text_buffer_get_start_iter(textbuf, &start_iter);
+                       if (mainwindow_get_mainwindow() && !gtk_text_iter_forward_to_tag_toggle(&start_iter, logwin->error_tag)) {
+                               mainwindow_clear_error(mainwindow_get_mainwindow());
+                               logwin->has_error = FALSE;
+                       }
+               }
        }
 }
 
@@ -423,18 +429,31 @@ static void log_window_clear(GtkWidget *widget, LogWindow *logwin)
        gtk_text_buffer_delete(textbuf, &start_iter, &end_iter);
 }
 
+static void log_window_go_to_last_error(GtkWidget *widget, LogWindow *logwin)
+{
+       log_window_jump_to_error(logwin);
+}
+
 static void log_window_popup_menu_extend(GtkTextView *textview,
                        GtkMenu *menu, LogWindow *logwin)
 {
        GtkWidget *menuitem;
        
-       g_return_if_fail(menu != NULL);
-       g_return_if_fail(GTK_IS_MENU_SHELL(menu));
+       cm_return_if_fail(menu != NULL);
+       cm_return_if_fail(GTK_IS_MENU_SHELL(menu));
 
        menuitem = gtk_separator_menu_item_new();
        gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
        gtk_widget_show(menuitem);
-       
+
+       if (logwin->has_error_capability) {
+               menuitem = gtk_menu_item_new_with_mnemonic(_("_Go to last error"));
+               g_signal_connect(G_OBJECT(menuitem), "activate",
+                                G_CALLBACK(log_window_go_to_last_error), logwin);
+               gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
+               gtk_widget_show(menuitem);
+       }
+
        menuitem = gtk_menu_item_new_with_mnemonic(_("Clear _Log"));
        g_signal_connect(G_OBJECT(menuitem), "activate",
                         G_CALLBACK(log_window_clear), logwin);