sourcewindow.c (5785B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2024 the Claws Mail team and Hiroyuki Yamamoto 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 #include "defs.h" 21 22 #include <glib.h> 23 #include <glib/gi18n.h> 24 #include <gdk/gdkkeysyms.h> 25 #include <gtk/gtk.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 29 #include "sourcewindow.h" 30 #include "utils.h" 31 #include "gtkutils.h" 32 #include "prefs_common.h" 33 #include "file-utils.h" 34 35 static void source_window_size_alloc_cb (GtkWidget *widget, 36 GtkAllocation *allocation); 37 static gint source_window_delete_cb (GtkWidget *widget, 38 GdkEventAny *event, 39 SourceWindow *sourcewin); 40 static gboolean key_pressed (GtkWidget *widget, 41 GdkEventKey *event, 42 SourceWindow *sourcewin); 43 static void source_window_append (SourceWindow *sourcewin, 44 const gchar *str); 45 static void source_window_destroy (SourceWindow *sourcewin); 46 47 static void source_window_init() 48 { 49 } 50 51 SourceWindow *source_window_create(void) 52 { 53 SourceWindow *sourcewin; 54 GtkWidget *window; 55 GtkWidget *scrolledwin; 56 GtkWidget *text; 57 58 static GdkGeometry geometry; 59 60 debug_print("Creating source window...\n"); 61 sourcewin = g_new0(SourceWindow, 1); 62 63 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "sourcewindow"); 64 gtk_window_set_title(GTK_WINDOW(window), _("Source of the message")); 65 gtk_window_set_resizable(GTK_WINDOW(window), TRUE); 66 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); 67 68 if (!geometry.min_height) { 69 geometry.min_width = 400; 70 geometry.min_height = 320; 71 } 72 gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry, 73 GDK_HINT_MIN_SIZE); 74 gtk_window_set_default_size(GTK_WINDOW(window), prefs_common.sourcewin_width, 75 prefs_common.sourcewin_height); 76 77 g_signal_connect(G_OBJECT(window), "size_allocate", 78 G_CALLBACK(source_window_size_alloc_cb), 79 sourcewin); 80 g_signal_connect(G_OBJECT(window), "delete_event", 81 G_CALLBACK(source_window_delete_cb), sourcewin); 82 g_signal_connect(G_OBJECT(window), "key_press_event", 83 G_CALLBACK(key_pressed), sourcewin); 84 gtk_widget_realize(window); 85 86 scrolledwin = gtk_scrolled_window_new(NULL, NULL); 87 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), 88 GTK_POLICY_AUTOMATIC, 89 GTK_POLICY_AUTOMATIC); 90 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin), 91 GTK_SHADOW_IN); 92 gtk_container_add(GTK_CONTAINER(window), scrolledwin); 93 gtk_widget_show(scrolledwin); 94 95 text = gtk_text_view_new(); 96 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD_CHAR); 97 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE); 98 gtk_container_add(GTK_CONTAINER(scrolledwin), text); 99 gtk_widget_show(text); 100 101 sourcewin->window = window; 102 sourcewin->scrolledwin = scrolledwin; 103 sourcewin->text = text; 104 105 source_window_init(); 106 107 return sourcewin; 108 } 109 110 void source_window_show(SourceWindow *sourcewin) 111 { 112 gtk_widget_show_all(sourcewin->window); 113 } 114 115 static void source_window_destroy(SourceWindow *sourcewin) 116 { 117 if (sourcewin->updating) { 118 debug_print("deferring destroy\n"); 119 sourcewin->deferred_destroy = TRUE; 120 return; 121 } 122 gtk_widget_destroy(sourcewin->window); 123 g_free(sourcewin); 124 } 125 126 void source_window_show_msg(SourceWindow *sourcewin, MsgInfo *msginfo) 127 { 128 gchar *file; 129 gchar *title; 130 FILE *fp; 131 gchar buf[BUFFSIZE]; 132 133 cm_return_if_fail(msginfo != NULL); 134 135 sourcewin->updating = TRUE; 136 file = procmsg_get_message_file(msginfo); 137 sourcewin->updating = FALSE; 138 139 if (sourcewin->deferred_destroy) { 140 g_free(file); 141 source_window_destroy(sourcewin); 142 return; 143 } 144 145 cm_return_if_fail(file != NULL); 146 147 if ((fp = g_fopen(file, "rb")) == NULL) { 148 FILE_OP_ERROR(file, "g_fopen"); 149 g_free(file); 150 return; 151 } 152 153 debug_print("Displaying the source of %s ...\n", file); 154 155 title = g_strdup_printf(_("%s - Source"), file); 156 gtk_window_set_title(GTK_WINDOW(sourcewin->window), title); 157 g_free(title); 158 g_free(file); 159 160 while (fgets(buf, sizeof(buf), fp) != NULL) 161 source_window_append(sourcewin, buf); 162 163 fclose(fp); 164 } 165 166 static void source_window_append(SourceWindow *sourcewin, const gchar *str) 167 { 168 GtkTextView *text = GTK_TEXT_VIEW(sourcewin->text); 169 GtkTextBuffer *buffer = gtk_text_view_get_buffer(text); 170 GtkTextIter iter; 171 gchar *out; 172 gint len; 173 174 len = strlen(str) + 1; 175 Xalloca(out, len, return); 176 conv_utf8todisp(out, len, str); 177 178 gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1); 179 gtk_text_buffer_insert(buffer, &iter, out, -1); 180 } 181 182 static void source_window_size_alloc_cb(GtkWidget *widget, 183 GtkAllocation *allocation) 184 { 185 cm_return_if_fail(allocation != NULL); 186 187 gtk_window_get_size(GTK_WINDOW(widget), 188 &prefs_common.sourcewin_width, &prefs_common.sourcewin_height); 189 } 190 191 static gint source_window_delete_cb(GtkWidget *widget, GdkEventAny *event, 192 SourceWindow *sourcewin) 193 { 194 source_window_destroy(sourcewin); 195 return TRUE; 196 } 197 198 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, 199 SourceWindow *sourcewin) 200 { 201 if (!event || !sourcewin) return FALSE; 202 203 switch (event->keyval) { 204 case GDK_KEY_W: 205 case GDK_KEY_w: 206 if ((event->state & GDK_CONTROL_MASK) != 0) 207 gtk_widget_destroy(sourcewin->window); 208 break; 209 } 210 211 return FALSE; 212 }