1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
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.
29 #include <sys/types.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"
48 #define GNOME_GTKHTML_EDITOR_CONTROL_ID "OAFIID:GNOME_GtkHTML_Editor:" GTKHTML_API_VERSION
50 typedef struct _ESignatureEditor
{
53 GtkWidget
*name_entry
;
54 GtkWidget
*info_frame
;
60 GNOME_GtkHTML_Editor_Engine engine
;
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
};
71 destroy_editor (ESignatureEditor
*editor
)
73 gtk_widget_destroy (editor
->win
);
78 menu_file_save_error (BonoboUIComponent
*uic
, CORBA_Environment
*ev
)
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
);
93 get_text (Bonobo_PersistStream persist
, const char *format
, CORBA_Environment
*ev
)
96 BonoboStreamMem
*stream_mem
;
99 stream
= bonobo_stream_mem_create (NULL
, 0, FALSE
, TRUE
);
100 Bonobo_PersistStream_save (persist
, (Bonobo_Stream
)bonobo_object_corba_objref (BONOBO_OBJECT (stream
)),
103 if (ev
->_major
!= CORBA_NO_EXCEPTION
)
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
));
116 write_all (int fd
, const char *buf
, size_t n
)
118 ssize_t w
, nwritten
= 0;
122 w
= write (fd
, buf
+ nwritten
, n
- nwritten
);
123 } while (w
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
127 } while (nwritten
< n
&& w
!= -1);
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
;
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
));
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
)
163 if ((fd
= open (filename
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666)) == -1)
166 text
= get_text (pstream_iface
, editor
->html
? "text/html" : "text/plain", &ev
);
167 if (ev
._major
!= CORBA_NO_EXCEPTION
) {
172 if (write_all (fd
, text
->data
, text
->len
) == -1) {
173 g_byte_array_free (text
, TRUE
);
178 g_byte_array_free (text
, TRUE
);
181 if (rename (filename
, editor
->sig
->filename
) == -1)
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
;
193 e_signature_list_change (mail_config_get_signatures (), editor
->sig
);
200 menu_file_save_error (uic
, &ev
);
201 CORBA_exception_free (&ev
);
207 exit_dialog_cb (int reply
, ESignatureEditor
*editor
)
210 case GTK_RESPONSE_YES
:
211 menu_file_save_cb (NULL
, editor
, NULL
);
213 case GTK_RESPONSE_NO
:
214 destroy_editor (editor
);
220 do_exit (ESignatureEditor
*editor
)
222 CORBA_Environment ev
;
224 CORBA_exception_init (&ev
);
226 if (GNOME_GtkHTML_Editor_Engine_hasUndo (editor
->engine
, &ev
)) {
229 button
= e_error_run((GtkWindow
*)editor
->win
, "mail:ask-signature-changed", NULL
);
230 exit_dialog_cb (button
, editor
);
232 destroy_editor (editor
);
234 CORBA_exception_free (&ev
);
238 delete_event_cb (GtkWidget
*w
, GdkEvent
*event
, ESignatureEditor
*editor
)
246 menu_file_close_cb (BonoboUIComponent
*uic
, gpointer data
, const char *path
)
248 ESignatureEditor
*editor
;
250 editor
= E_SIGNATURE_EDITOR (data
);
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
),
275 load_signature (ESignatureEditor
*editor
)
277 CORBA_Environment ev
;
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
);
288 Bonobo_PersistStream pstream_iface
;
289 BonoboStream
*stream
;
292 data
= e_msg_composer_get_sig_file_content (editor
->sig
->filename
, FALSE
);
293 html
= g_strdup_printf ("<PRE>\n%s", 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");
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
,
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
));
324 sig_name_changed (GtkWidget
*w
, ESignatureEditor
*editor
)
328 name
= gtk_entry_get_text (GTK_ENTRY (editor
->name_entry
));
330 g_free (editor
->sig
->name
);
331 editor
->sig
->name
= g_strdup (name
);
334 e_signature_list_change (mail_config_get_signatures (), editor
->sig
);
338 format_html_cb (BonoboUIComponent
*component
,
340 Bonobo_UIComponent_EventType type
,
345 ESignatureEditor
*editor
= (ESignatureEditor
*) data
;
347 if (type
!= Bonobo_UIComponent_STATE_CHANGED
)
350 editor
->html
= atoi (state
);
351 bonobo_widget_set_property (BONOBO_WIDGET (editor
->control
), "FormatHTML", TC_CORBA_boolean
, editor
->html
, NULL
);
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
)
366 editor
= g_new0 (ESignatureEditor
, 1);
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
);
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
);
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
));
435 gtk_widget_grab_focus (editor
->name_entry
);
437 CORBA_exception_init (&ev
);
438 GNOME_GtkHTML_Editor_Engine_runCommand (editor
->engine
, "grab-focus", &ev
);
439 CORBA_exception_free (&ev
);