Updated Traditional Chinese translation.
[evolution.git] / mail / mail-signature-editor.c
blobb34644676e16c0a4d986b89e65c7fd2a3efaebab
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Authors: Radek Doulik <rodo@ximian.com>
4 * Jeffrey Stedfast <fejj@ximian.com>
6 * Copyright 2002 Ximian, Inc. (www.ximian.com)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <errno.h>
34 #include <gtk/gtk.h>
36 #include <bonobo.h>
37 #include <bonobo/bonobo-stream-memory.h>
39 #include <e-util/e-signature-list.h>
40 #include "e-util/e-error.h"
42 #include "e-msg-composer.h"
43 #include "mail-signature-editor.h"
44 #include "mail-config.h"
46 #define d(x)
48 #define GNOME_GTKHTML_EDITOR_CONTROL_ID "OAFIID:GNOME_GtkHTML_Editor:" GTKHTML_API_VERSION
50 typedef struct _ESignatureEditor {
51 GtkWidget *win;
52 GtkWidget *control;
53 GtkWidget *name_entry;
54 GtkWidget *info_frame;
56 ESignature *sig;
57 gboolean is_new;
58 gboolean html;
60 GNOME_GtkHTML_Editor_Engine engine;
61 } ESignatureEditor;
63 #define E_SIGNATURE_EDITOR(o) ((ESignatureEditor *) o)
65 #define DEFAULT_WIDTH 600
66 #define DEFAULT_HEIGHT 350
68 enum { REPLY_YES = 0, REPLY_NO, REPLY_CANCEL };
70 static void
71 destroy_editor (ESignatureEditor *editor)
73 gtk_widget_destroy (editor->win);
74 g_free (editor);
77 static void
78 menu_file_save_error (BonoboUIComponent *uic, CORBA_Environment *ev)
80 char *err;
82 /* errno is set if the rename() fails in menu_file_save_cb */
84 err = ev->_major != CORBA_NO_EXCEPTION ? bonobo_exception_get_text (ev) : g_strdup (g_strerror (errno));
86 e_error_run(NULL, "mail:no-save-signature", err, NULL);
87 g_warning ("Exception while saving signature: %s", err);
89 g_free (err);
92 static GByteArray *
93 get_text (Bonobo_PersistStream persist, const char *format, CORBA_Environment *ev)
95 BonoboStream *stream;
96 BonoboStreamMem *stream_mem;
97 GByteArray *text;
99 stream = bonobo_stream_mem_create (NULL, 0, FALSE, TRUE);
100 Bonobo_PersistStream_save (persist, (Bonobo_Stream)bonobo_object_corba_objref (BONOBO_OBJECT (stream)),
101 format, ev);
103 if (ev->_major != CORBA_NO_EXCEPTION)
104 return NULL;
106 stream_mem = BONOBO_STREAM_MEM (stream);
108 text = g_byte_array_new ();
109 g_byte_array_append (text, stream_mem->buffer, stream_mem->pos);
110 bonobo_object_unref (BONOBO_OBJECT (stream));
112 return text;
115 static ssize_t
116 write_all (int fd, const char *buf, size_t n)
118 ssize_t w, nwritten = 0;
120 do {
121 do {
122 w = write (fd, buf + nwritten, n - nwritten);
123 } while (w == -1 && (errno == EINTR || errno == EAGAIN));
125 if (w > 0)
126 nwritten += w;
127 } while (nwritten < n && w != -1);
129 if (w == -1)
130 return -1;
132 return nwritten;
135 static void
136 menu_file_save_cb (BonoboUIComponent *uic, void *user_data, const char *path)
138 ESignatureEditor *editor = user_data;
139 Bonobo_PersistStream pstream_iface;
140 char *dirname, *base, *filename;
141 CORBA_Environment ev;
142 GByteArray *text;
143 int fd;
145 d(printf ("editor->sig->filename = %s\n", editor->sig->filename));
146 dirname = g_path_get_dirname (editor->sig->filename);
147 d(printf ("dirname = %s\n", dirname));
148 base = g_path_get_basename (editor->sig->filename);
149 d(printf ("basename = %s\n", base));
150 filename = g_strdup_printf ("%s/.#%s", dirname, base);
151 d(printf ("filename = %s\n", filename));
152 g_free (dirname);
153 g_free (base);
155 CORBA_exception_init (&ev);
156 pstream_iface = Bonobo_Unknown_queryInterface
157 (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
158 "IDL:Bonobo/PersistStream:1.0", &ev);
160 if (ev._major != CORBA_NO_EXCEPTION)
161 goto exception;
163 if ((fd = open (filename, O_WRONLY | O_TRUNC | O_CREAT, 0666)) == -1)
164 goto exception;
166 text = get_text (pstream_iface, editor->html ? "text/html" : "text/plain", &ev);
167 if (ev._major != CORBA_NO_EXCEPTION) {
168 close (fd);
169 goto exception;
172 if (write_all (fd, text->data, text->len) == -1) {
173 g_byte_array_free (text, TRUE);
174 close (fd);
175 goto exception;
178 g_byte_array_free (text, TRUE);
179 close (fd);
181 if (rename (filename, editor->sig->filename) == -1)
182 goto exception;
184 g_free (filename);
186 editor->sig->html = editor->html;
188 /* if the signature isn't already saved in the config, save it there now... */
189 if (editor->is_new) {
190 mail_config_add_signature (editor->sig);
191 editor->is_new = FALSE;
192 } else {
193 e_signature_list_change (mail_config_get_signatures (), editor->sig);
196 return;
198 exception:
200 menu_file_save_error (uic, &ev);
201 CORBA_exception_free (&ev);
202 unlink (filename);
203 g_free (filename);
206 static void
207 exit_dialog_cb (int reply, ESignatureEditor *editor)
209 switch (reply) {
210 case GTK_RESPONSE_YES:
211 menu_file_save_cb (NULL, editor, NULL);
212 break;
213 case GTK_RESPONSE_NO:
214 destroy_editor (editor);
215 break;
219 static void
220 do_exit (ESignatureEditor *editor)
222 CORBA_Environment ev;
224 CORBA_exception_init (&ev);
226 if (GNOME_GtkHTML_Editor_Engine_hasUndo (editor->engine, &ev)) {
227 int button;
229 button = e_error_run((GtkWindow *)editor->win, "mail:ask-signature-changed", NULL);
230 exit_dialog_cb (button, editor);
231 } else
232 destroy_editor (editor);
234 CORBA_exception_free (&ev);
237 static int
238 delete_event_cb (GtkWidget *w, GdkEvent *event, ESignatureEditor *editor)
240 do_exit (editor);
242 return FALSE;
245 static void
246 menu_file_close_cb (BonoboUIComponent *uic, gpointer data, const char *path)
248 ESignatureEditor *editor;
250 editor = E_SIGNATURE_EDITOR (data);
251 do_exit (editor);
254 static void
255 menu_file_save_close_cb (BonoboUIComponent *uic, gpointer data, const char *path)
257 ESignatureEditor *editor;
259 editor = E_SIGNATURE_EDITOR (data);
261 menu_file_save_cb (uic, editor, path);
262 destroy_editor (editor);
265 static BonoboUIVerb verbs [] = {
267 BONOBO_UI_VERB ("FileSave", menu_file_save_cb),
268 BONOBO_UI_VERB ("FileClose", menu_file_close_cb),
269 BONOBO_UI_VERB ("FileSaveClose", menu_file_save_close_cb),
271 BONOBO_UI_VERB_END
274 static void
275 load_signature (ESignatureEditor *editor)
277 CORBA_Environment ev;
279 if (editor->html) {
280 Bonobo_PersistFile pfile_iface;
282 CORBA_exception_init (&ev);
283 pfile_iface = Bonobo_Unknown_queryInterface (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
284 "IDL:Bonobo/PersistFile:1.0", &ev);
285 Bonobo_PersistFile_load (pfile_iface, editor->sig->filename, &ev);
286 CORBA_exception_free (&ev);
287 } else {
288 Bonobo_PersistStream pstream_iface;
289 BonoboStream *stream;
290 char *data, *html;
292 data = e_msg_composer_get_sig_file_content (editor->sig->filename, FALSE);
293 html = g_strdup_printf ("<PRE>\n%s", data);
294 g_free (data);
296 CORBA_exception_init (&ev);
297 pstream_iface = Bonobo_Unknown_queryInterface
298 (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
299 "IDL:Bonobo/PersistStream:1.0",&ev);
300 stream = bonobo_stream_mem_create (html, strlen (html), TRUE, FALSE);
302 if (stream == NULL) {
303 g_warning ("Couldn't create memory stream\n");
304 } else {
305 BonoboObject *stream_object;
306 Bonobo_Stream corba_stream;
308 stream_object = BONOBO_OBJECT (stream);
309 corba_stream = bonobo_object_corba_objref (stream_object);
310 Bonobo_PersistStream_load (pstream_iface, corba_stream,
311 "text/html", &ev);
314 Bonobo_Unknown_unref (pstream_iface, &ev);
315 CORBA_Object_release (pstream_iface, &ev);
316 CORBA_exception_free (&ev);
317 bonobo_object_unref (BONOBO_OBJECT (stream));
319 g_free (html);
323 static void
324 sig_name_changed (GtkWidget *w, ESignatureEditor *editor)
326 const char *name;
328 name = gtk_entry_get_text (GTK_ENTRY (editor->name_entry));
330 g_free (editor->sig->name);
331 editor->sig->name = g_strdup (name);
333 if (!editor->is_new)
334 e_signature_list_change (mail_config_get_signatures (), editor->sig);
337 static void
338 format_html_cb (BonoboUIComponent *component,
339 const char *path,
340 Bonobo_UIComponent_EventType type,
341 const char *state,
342 gpointer data)
345 ESignatureEditor *editor = (ESignatureEditor *) data;
347 if (type != Bonobo_UIComponent_STATE_CHANGED)
348 return;
350 editor->html = atoi (state);
351 bonobo_widget_set_property (BONOBO_WIDGET (editor->control), "FormatHTML", TC_CORBA_boolean, editor->html, NULL);
354 void
355 mail_signature_editor (ESignature *sig, GtkWindow *parent, gboolean is_new)
357 CORBA_Environment ev;
358 ESignatureEditor *editor;
359 BonoboUIComponent *component;
360 BonoboUIContainer *container;
361 GtkWidget *vbox, *hbox, *label, *frame, *vbox1;
363 if (!sig->filename || !*sig->filename)
364 return;
366 editor = g_new0 (ESignatureEditor, 1);
368 editor->sig = sig;
369 editor->html = sig->html;
370 editor->is_new = is_new;
372 editor->win = bonobo_window_new ("e-sig-editor", _("Edit signature"));
373 gtk_window_set_type_hint (GTK_WINDOW (editor->win), GDK_WINDOW_TYPE_HINT_DIALOG);
374 gtk_window_set_default_size (GTK_WINDOW (editor->win), DEFAULT_WIDTH, DEFAULT_HEIGHT);
375 if (parent != NULL)
376 gtk_window_set_transient_for (GTK_WINDOW (editor->win), parent);
377 g_object_set (editor->win, "allow_shrink", FALSE, "allow_grow", TRUE, NULL);
379 container = bonobo_window_get_ui_container (BONOBO_WINDOW(editor->win));
381 component = bonobo_ui_component_new_default ();
382 bonobo_ui_component_set_container (component, bonobo_object_corba_objref (BONOBO_OBJECT (container)), NULL);
383 bonobo_ui_component_add_verb_list_with_data (component, verbs, editor);
384 bonobo_ui_util_set_ui (component, PREFIX,
385 EVOLUTION_UIDIR "/evolution-signature-editor.xml",
386 "evolution-signature-editor", NULL);
388 editor->control = bonobo_widget_new_control (GNOME_GTKHTML_EDITOR_CONTROL_ID,
389 bonobo_ui_component_get_container (component));
391 if (editor->control == NULL) {
392 g_warning ("Cannot get '" GNOME_GTKHTML_EDITOR_CONTROL_ID "'.");
394 destroy_editor (editor);
395 return;
398 editor->engine = (GNOME_GtkHTML_Editor_Engine) Bonobo_Unknown_queryInterface
399 (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)), "IDL:GNOME/GtkHTML/Editor/Engine:1.0", &ev);
400 CORBA_exception_free(&ev);
401 load_signature (editor);
403 bonobo_ui_component_set_prop (component, "/commands/FormatHtml", "state", editor->html ? "1" : "0", NULL);
404 bonobo_ui_component_add_listener (component, "FormatHtml", format_html_cb, editor);
406 g_signal_connect (editor->win, "delete_event", G_CALLBACK (delete_event_cb), editor);
408 vbox = gtk_vbox_new (FALSE, 0);
409 hbox = gtk_hbox_new (FALSE, 4);
410 vbox1 = gtk_vbox_new (FALSE, 3);
411 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 3);
412 label = gtk_label_new (_("Enter a name for this signature."));
413 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
414 gtk_box_pack_start (GTK_BOX (vbox1), label, FALSE, TRUE, 0);
415 label = gtk_label_new (_("Name:"));
416 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
417 editor->name_entry = gtk_entry_new ();
418 gtk_entry_set_text (GTK_ENTRY (editor->name_entry), sig->name);
419 g_signal_connect (editor->name_entry, "changed", G_CALLBACK (sig_name_changed), editor);
420 gtk_box_pack_start_defaults (GTK_BOX (hbox), editor->name_entry);
421 frame = gtk_frame_new (NULL);
422 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
423 gtk_box_pack_start (GTK_BOX (vbox1), hbox, FALSE, TRUE, 0);
424 gtk_container_add (GTK_CONTAINER (frame), vbox1);
425 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
426 gtk_widget_show_all (vbox);
427 gtk_box_pack_start_defaults (GTK_BOX (vbox), editor->control);
429 bonobo_window_set_contents (BONOBO_WINDOW (editor->win), vbox);
430 bonobo_widget_set_property (BONOBO_WIDGET (editor->control), "FormatHTML", TC_CORBA_boolean, editor->html, NULL);
431 gtk_widget_show (GTK_WIDGET (editor->win));
432 gtk_widget_show (GTK_WIDGET (editor->control));
434 if (is_new)
435 gtk_widget_grab_focus (editor->name_entry);
436 else {
437 CORBA_exception_init (&ev);
438 GNOME_GtkHTML_Editor_Engine_runCommand (editor->engine, "grab-focus", &ev);
439 CORBA_exception_free (&ev);