talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

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 }