aboutsummaryrefslogblamecommitdiffstats
path: root/mail/mail-signature-editor.c
blob: 48e11041c0180b86fe258ad215e5a234d2212880 (plain) (tree)
1
2
3
4


                                                                           
                                               














                                                                        
                                                                                  


   
                   
 
                   


                      
                  
 


                        

                    


                                        
                           

                                    


                                  
                        
 
            
 
                                                                                          
 
                                  

                           
                              
                              
 
                        
                        
                      
 
                                           
                   



                                                      
                          






                                               



                        

                                                                    
                  
 
                                                                     
 
                                                                                                                
 
                                                               
                                                                
 
                     

 





                                                                                  
 


                                                                                                               
 

                                             
 
                                                
 
                                   
                                                                                         
                                                     
 






                                             
 



                                                                         
 


                                          
 

                          
 


                        
           
                                                                             
 
                                             
                              
                                           
                                               
                             

                         
 
                                                                          
                                                             
                                              
                                                           
                                            
                                                              
                                                
                         
                      
 
                                   
                                                     


                                                                            

                                            
 
                                                                               
                               
 




                                                                                        
 
                                                                  



                                               
 

                                       
 
                                                             
                               
 
                          
 
                                         

                                                                                           
 

                                                                                     
                       
         
 

                                                                                                                                                                                 
                       
         
 

                                           
 

                                 

                                                                                      
                                                        
                                       


                                                                                     


                                
               

          

                                        
                            
                          





                                                    
                              
                                                       
                      
                             

                                        





                                  
                             
 
                                   

                                                                                                                                                       
                           

                                                                                                   
                                                
              
                                        
 
                                   

 
          


                                                                         
 
                    


           
                                                                            

                                 
 




                                           
                                                                                 

                                 
 
                                           
 
                                              






                                                                   
 






                                         
 
                           
                                               
 
                                           
                                                                                                                                                           
                                                                                  



                                                   
                                  
 
                                                                                          

                                                           
 
                                           

                                                                                    
                                                             
                                                                                     
 




                                                                      
 




                                                                                  
 



                                                             
 



                              


                                                         
                                                                                       

 








                                                             
 

                                                     
 
                                    
                                                                                                                         

 
    
                                                                           
 
                             


                                     
                                                       
                      
 
                                              
                       
 
                                              
 
                          
                                 
                                
 
                                                                              
                                                                                         
                                                                                              


                                                                                    

                                                                                      
 
                                                                                
 
                                                       
                                                                                                                    
                                                                               



                                                                     
                                                 
                                       
                                                                   
                         

                                                                                     
                                                                                                    
 
                                      
                                                                                
 


                                        
 
                                                                                    

                                                                                                                         
                                
 

                                                                                                                  
 
                                                                                             
 
                                       


                                                                  
                                                                      



                                                                    
                                              

                                                                                                
                                                                         




                                                                      

                                                                      
 
                                                                       
                                                                                                                         

                                                       
 






                                                                                           
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 *  Authors: Radek Doulik <rodo@ximian.com>
 *           Jeffrey Stedfast <fejj@ximian.com>
 *
 *  Copyright 2002 Ximian, Inc. (www.ximian.com)
 *
 *  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
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include <config.h>

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <glib.h>
#include <glib/gstdio.h>

#include <gtk/gtk.h>

#include <bonobo.h>
#include <bonobo/bonobo-stream-memory.h>

#include "e-util/e-error.h"
#include "e-util/e-signature-list.h"
#include "e-util/e-util-private.h"

#include "e-msg-composer.h"
#include "mail-signature-editor.h"
#include "mail-config.h"

#define d(x)

#define GNOME_GTKHTML_EDITOR_CONTROL_ID "OAFIID:GNOME_GtkHTML_Editor:" GTKHTML_API_VERSION

typedef struct _ESignatureEditor {
    GtkWidget *win;
    GtkWidget *control;
    GtkWidget *name_entry;
    GtkWidget *info_frame;

    ESignature *sig;
    gboolean is_new;
    gboolean html;

    GNOME_GtkHTML_Editor_Engine engine;
} ESignatureEditor;

#define E_SIGNATURE_EDITOR(o) ((ESignatureEditor *) o)

#define DEFAULT_WIDTH 600
#define DEFAULT_HEIGHT 350

enum { REPLY_YES = 0, REPLY_NO, REPLY_CANCEL };

static void
destroy_editor (ESignatureEditor *editor)
{
    gtk_widget_destroy (editor->win);
    g_free (editor);
}

static void
menu_file_save_error (BonoboUIComponent *uic, CORBA_Environment *ev)
{
    char *err;

    /* errno is set if the rename() fails in menu_file_save_cb */

    err = ev->_major != CORBA_NO_EXCEPTION ? bonobo_exception_get_text (ev) : g_strdup (g_strerror (errno));

    e_error_run(NULL, "mail:no-save-signature", err, NULL);
    g_warning ("Exception while saving signature: %s", err);

    g_free (err);
}

static GByteArray *
get_text (Bonobo_PersistStream persist, const char *format, CORBA_Environment *ev)
{
    BonoboStream *stream;
    BonoboStreamMem *stream_mem;
    GByteArray *text;

    stream = bonobo_stream_mem_create (NULL, 0, FALSE, TRUE);
    Bonobo_PersistStream_save (persist, (Bonobo_Stream)bonobo_object_corba_objref (BONOBO_OBJECT (stream)),
                   format, ev);

    if (ev->_major != CORBA_NO_EXCEPTION)
        return NULL;

    stream_mem = BONOBO_STREAM_MEM (stream);

    text = g_byte_array_new ();
    g_byte_array_append (text, (unsigned char *)stream_mem->buffer, stream_mem->pos);
    bonobo_object_unref (BONOBO_OBJECT (stream));

    return text;
}

static ssize_t
write_all (int fd, const char *buf, size_t n)
{
    ssize_t w, nwritten = 0;

    do {
        do {
            w = write (fd, buf + nwritten, n - nwritten);
        } while (w == -1 && (errno == EINTR || errno == EAGAIN));

        if (w > 0)
            nwritten += w;
    } while (nwritten < n && w != -1);

    if (w == -1)
        return -1;

    return nwritten;
}

static void
menu_file_save_cb (BonoboUIComponent *uic, void *user_data, const char *path)
{
    ESignatureEditor *editor = user_data;
    ESignature *signature;
    Bonobo_PersistStream pstream_iface;
    char *dirname, *base, *filename, *name;
    CORBA_Environment ev;
    GByteArray *text;
    int fd;

    d(printf ("editor->sig->filename = %s\n", editor->sig->filename));
    dirname = g_path_get_dirname (editor->sig->filename);
    d(printf ("dirname = %s\n", dirname));
    base = g_path_get_basename (editor->sig->filename);
    d(printf ("basename = %s\n", base));
    filename = g_strdup_printf ("%s/.#%s", dirname, base);
    d(printf ("filename = %s\n", filename));
    g_free (dirname);
    g_free (base);

    CORBA_exception_init (&ev);
    pstream_iface = Bonobo_Unknown_queryInterface
        (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
         "IDL:Bonobo/PersistStream:1.0", &ev);

    if (ev._major != CORBA_NO_EXCEPTION)
        goto exception;

    if ((fd = g_open (filename, O_WRONLY | O_TRUNC | O_CREAT, 0666)) == -1)
        goto exception;

    text = get_text (pstream_iface, editor->html ? "text/html" : "text/plain", &ev);
    if (ev._major != CORBA_NO_EXCEPTION) {
        close (fd);
        goto exception;
    }

    if (write_all (fd, (char *)text->data, text->len) == -1) {
        g_byte_array_free (text, TRUE);
        close (fd);
        goto exception;
    }

    g_byte_array_free (text, TRUE);
    close (fd);

    if (g_rename (filename, editor->sig->filename) == -1)
        goto exception;

    g_free (filename);

    editor->sig->html = editor->html;

    name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (editor->name_entry))));

    if (g_str_equal(name, "") ) {
        e_error_run ((GtkWindow *)editor->win, "mail:blank-signature", NULL);
        return;
    }

    if ( (signature = (ESignature *)e_signature_list_find (mail_config_get_signatures (), E_SIGNATURE_FIND_NAME, name)) && !g_str_equal(signature->uid, editor->sig->uid) ) {
        e_error_run ((GtkWindow *)editor->win, "mail:signature-already-exists", name, NULL);
        return;
    }

    if (editor->sig->name)
        g_free (editor->sig->name);

    editor->sig->name = name;

    /* if the signature isn't already saved in the config, save it there now... */
    if (editor->is_new) {
        mail_config_add_signature (editor->sig);
        editor->is_new = FALSE;
    } else {
        e_signature_list_change (mail_config_get_signatures (), editor->sig);
    }

    destroy_editor (editor);

    return;

exception:
    menu_file_save_error (uic, &ev);
    CORBA_exception_free (&ev);
    g_unlink (filename);
    g_free (filename);
}

static void
exit_dialog_cb (int reply, ESignatureEditor *editor)
{
    switch (reply) {
    case GTK_RESPONSE_YES:
        menu_file_save_cb (NULL, editor, NULL);
        break;
    case GTK_RESPONSE_NO:
        destroy_editor (editor);
        break;
    }
}

static void
do_exit (ESignatureEditor *editor)
{
    CORBA_Environment ev;

    CORBA_exception_init (&ev);

    if (GNOME_GtkHTML_Editor_Engine_hasUndo (editor->engine, &ev) || GPOINTER_TO_INT( g_object_get_data( G_OBJECT(editor->win), "name-changed"))) {
        int button;

        button = e_error_run((GtkWindow *)editor->win, "mail:ask-signature-changed", NULL);
        exit_dialog_cb (button, editor);
    } else
        destroy_editor (editor);

    CORBA_exception_free (&ev);
}

static int
delete_event_cb (GtkWidget *w, GdkEvent *event, ESignatureEditor *editor)
{
    do_exit (editor);

    return TRUE;
}

static void
menu_file_close_cb (BonoboUIComponent *uic, gpointer data, const char *path)
{
    ESignatureEditor *editor;

    editor = E_SIGNATURE_EDITOR (data);
    do_exit (editor);
}

static void
menu_file_save_close_cb (BonoboUIComponent *uic, gpointer data, const char *path)
{
    ESignatureEditor *editor;

    editor = E_SIGNATURE_EDITOR (data);

    menu_file_save_cb (uic, editor, path);
}

static BonoboUIVerb verbs [] = {

    BONOBO_UI_VERB ("FileSave",       menu_file_save_cb),
    BONOBO_UI_VERB ("FileClose",      menu_file_close_cb),
    BONOBO_UI_VERB ("FileSaveClose",  menu_file_save_close_cb),

    BONOBO_UI_VERB_END
};

static void
load_signature (ESignatureEditor *editor)
{
    CORBA_Environment ev;

    if (editor->html) {
        Bonobo_PersistFile pfile_iface;

        CORBA_exception_init (&ev);
        pfile_iface = Bonobo_Unknown_queryInterface (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),"IDL:Bonobo/PersistFile:1.0", &ev);
        Bonobo_PersistFile_load (pfile_iface, editor->sig->filename, &ev);
        CORBA_exception_free (&ev);
    } else {
        Bonobo_PersistStream pstream_iface;
        BonoboStream *stream;
        char *data, *html;

        data = e_msg_composer_get_sig_file_content (editor->sig->filename, FALSE);
        html = g_strdup_printf ("<PRE>\n%s", data);
        g_free (data);

        CORBA_exception_init (&ev);
        pstream_iface = Bonobo_Unknown_queryInterface
            (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
             "IDL:Bonobo/PersistStream:1.0",&ev);
        stream = bonobo_stream_mem_create (html, strlen (html), TRUE, FALSE);

        if (stream == NULL) {
            g_warning ("Couldn't create memory stream\n");
        } else {
            BonoboObject *stream_object;
            Bonobo_Stream corba_stream;

            stream_object = BONOBO_OBJECT (stream);
            corba_stream = bonobo_object_corba_objref (stream_object);
            Bonobo_PersistStream_load (pstream_iface, corba_stream,
                           "text/html", &ev);
        }

        Bonobo_Unknown_unref (pstream_iface, &ev);
        CORBA_Object_release (pstream_iface, &ev);
        CORBA_exception_free (&ev);
        bonobo_object_unref (BONOBO_OBJECT (stream));

        g_free (html);
    }
}

static void
sig_name_changed (GtkWidget *w, ESignatureEditor *editor)
{
    g_object_set_data ( G_OBJECT(editor->win), "name-changed", GINT_TO_POINTER(1));
}

static void
format_html_cb (BonoboUIComponent           *component,
        const char                  *path,
        Bonobo_UIComponent_EventType type,
        const char                  *state,
        gpointer                     data)

{
    ESignatureEditor *editor = (ESignatureEditor *) data;

    if (type != Bonobo_UIComponent_STATE_CHANGED)
        return;

    editor->html = atoi (state);
    bonobo_widget_set_property (BONOBO_WIDGET (editor->control), "FormatHTML", TC_CORBA_boolean, editor->html, NULL);
}

void
mail_signature_editor (ESignature *sig, GtkWindow *parent, gboolean is_new)
{
    CORBA_Environment ev;
    ESignatureEditor *editor;
    BonoboUIComponent *component;
    BonoboUIContainer *container;
    GtkWidget *vbox, *hbox, *label, *frame, *vbox1;
    char *xmlfile;

    if (!sig->filename || !*sig->filename)
        return;

    editor = g_new0 (ESignatureEditor, 1);

    editor->sig = sig;
    editor->html = sig->html;
    editor->is_new = is_new;

    editor->win = bonobo_window_new ("e-sig-editor", _("Edit signature"));
    gtk_window_set_type_hint (GTK_WINDOW (editor->win), GDK_WINDOW_TYPE_HINT_DIALOG);
    gtk_window_set_default_size (GTK_WINDOW (editor->win), DEFAULT_WIDTH, DEFAULT_HEIGHT);
    if (parent != NULL)
        gtk_window_set_transient_for (GTK_WINDOW (editor->win), parent);
    g_object_set (editor->win, "allow_shrink", FALSE, "allow_grow", TRUE, NULL);

    g_object_set_data (G_OBJECT(editor->win), "name-changed", GINT_TO_POINTER(0));

    container = bonobo_window_get_ui_container (BONOBO_WINDOW(editor->win));

    component = bonobo_ui_component_new_default ();
    bonobo_ui_component_set_container (component, bonobo_object_corba_objref (BONOBO_OBJECT (container)), NULL);
    bonobo_ui_component_add_verb_list_with_data (component, verbs, editor);

    xmlfile = g_build_filename (EVOLUTION_UIDIR,
                    "evolution-signature-editor.xml",
                    NULL);
    bonobo_ui_util_set_ui (component, PREFIX,
                   xmlfile,
                   "evolution-signature-editor", NULL);
    g_free (xmlfile);

    editor->control = bonobo_widget_new_control (GNOME_GTKHTML_EDITOR_CONTROL_ID,
                             bonobo_ui_component_get_container (component));

    if (editor->control == NULL) {
        g_warning ("Cannot get '" GNOME_GTKHTML_EDITOR_CONTROL_ID "'.");

        destroy_editor (editor);
        return;
    }

    editor->engine = (GNOME_GtkHTML_Editor_Engine) Bonobo_Unknown_queryInterface
        (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)), "IDL:GNOME/GtkHTML/Editor/Engine:1.0", &ev);
    CORBA_exception_free(&ev);
    load_signature (editor);

    bonobo_ui_component_set_prop (component, "/commands/FormatHtml", "state", editor->html ? "1" : "0", NULL);
    bonobo_ui_component_add_listener (component, "FormatHtml", format_html_cb, editor);

    g_signal_connect (editor->win, "delete_event", G_CALLBACK (delete_event_cb), editor);

    vbox = gtk_vbox_new (FALSE, 0);
    hbox = gtk_hbox_new (FALSE, 4);
    vbox1 = gtk_vbox_new (FALSE, 3);
    gtk_container_set_border_width (GTK_CONTAINER (vbox1), 3);
    label = gtk_label_new (_("Enter a name for this signature."));
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
    gtk_box_pack_start (GTK_BOX (vbox1), label, FALSE, TRUE, 0);
    label = gtk_label_new (_("Name:"));
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
    editor->name_entry = gtk_entry_new ();
    gtk_entry_set_text (GTK_ENTRY (editor->name_entry), sig->name);
    g_signal_connect (editor->name_entry, "changed", G_CALLBACK (sig_name_changed), editor);
    gtk_box_pack_start_defaults (GTK_BOX (hbox), editor->name_entry);
    frame = gtk_frame_new (NULL);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
    gtk_box_pack_start (GTK_BOX (vbox1), hbox, FALSE, TRUE, 0);
    gtk_container_add (GTK_CONTAINER (frame), vbox1);
    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
    gtk_widget_show_all (vbox);
    gtk_box_pack_start_defaults (GTK_BOX (vbox), editor->control);

    bonobo_window_set_contents (BONOBO_WINDOW (editor->win), vbox);
    bonobo_widget_set_property (BONOBO_WIDGET (editor->control), "FormatHTML", TC_CORBA_boolean, editor->html, NULL);
    gtk_widget_show (GTK_WIDGET (editor->win));
    gtk_widget_show (GTK_WIDGET (editor->control));

    if (is_new)
        gtk_widget_grab_focus (editor->name_entry);
    else {
        CORBA_exception_init (&ev);
        GNOME_GtkHTML_Editor_Engine_runCommand (editor->engine, "grab-focus", &ev);
        CORBA_exception_free (&ev);
    }
}