diff options
Diffstat (limited to 'composer')
-rw-r--r-- | composer/.cvsignore | 20 | ||||
-rw-r--r-- | composer/ChangeLog | 2034 | ||||
-rw-r--r-- | composer/Composer.idl | 4 | ||||
-rw-r--r-- | composer/Evolution-Composer.idl | 105 | ||||
-rw-r--r-- | composer/Makefile.am | 95 | ||||
-rw-r--r-- | composer/bad-icon.xpm | 53 | ||||
-rw-r--r-- | composer/e-icon-list.c | 2675 | ||||
-rw-r--r-- | composer/e-icon-list.h | 178 | ||||
-rw-r--r-- | composer/e-msg-composer-attachment-bar.c | 820 | ||||
-rw-r--r-- | composer/e-msg-composer-attachment-bar.h | 76 | ||||
-rw-r--r-- | composer/e-msg-composer-attachment.c | 444 | ||||
-rw-r--r-- | composer/e-msg-composer-attachment.glade | 280 | ||||
-rw-r--r-- | composer/e-msg-composer-attachment.h | 75 | ||||
-rw-r--r-- | composer/e-msg-composer-hdrs.c | 969 | ||||
-rw-r--r-- | composer/e-msg-composer-hdrs.h | 119 | ||||
-rw-r--r-- | composer/e-msg-composer-select-file.c | 229 | ||||
-rw-r--r-- | composer/e-msg-composer-select-file.h | 35 | ||||
-rw-r--r-- | composer/e-msg-composer.c | 3516 | ||||
-rw-r--r-- | composer/e-msg-composer.h | 178 | ||||
-rw-r--r-- | composer/evolution-composer.c | 380 | ||||
-rw-r--r-- | composer/evolution-composer.h | 70 | ||||
-rw-r--r-- | composer/listener.c | 253 | ||||
-rw-r--r-- | composer/listener.h | 56 |
23 files changed, 0 insertions, 12664 deletions
diff --git a/composer/.cvsignore b/composer/.cvsignore deleted file mode 100644 index ec7a9d7288..0000000000 --- a/composer/.cvsignore +++ /dev/null @@ -1,20 +0,0 @@ -.deps -.libs -evolution-msg-composer -Makefile -Makefile.in -*.lo -*.la -Composer-stubs.c -Composer-skels.c -Composer-common.c -Composer.h -Editor-stubs.c -Editor-skels.c -Editor.h -Editor-common.c -Evolution-Addressbook-SelectNames-common.c -Evolution-Addressbook-SelectNames-skels.c -Evolution-Addressbook-SelectNames-stubs.c -Evolution-Addressbook-SelectNames.h -HTMLEditor*.[ch] diff --git a/composer/ChangeLog b/composer/ChangeLog deleted file mode 100644 index 5ac58d046d..0000000000 --- a/composer/ChangeLog +++ /dev/null @@ -1,2034 +0,0 @@ -2001-07-18 Jason Leach <jleach@ximian.com> - - * e-msg-composer-hdrs.c (create_from_optionmenu): Update to the - new way of finding the default account. - -2001-07-18 Iain Holmes <iain@ximian.com> - - * e-msg-composer.c (do_exit): Use a messagebox. - -2001-07-17 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (drag_data_received): Correctly handle - text/uri-list's that contain more than a single file reference. - -2001-07-12 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (menu_changed_charset_cb): Removed a warning - that I don't need anymore. This code is working wonderfully ;-) - -2001-07-10 Kjartan Maraas <kmaraas@gnome.org> - - * e-msg-composer.c: Fix typo. s/sesiion/session/ - -2001-07-09 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (autosave_manager_query_load_orphans): Only ask - once about recovery, assume if they want to recover one file they - want to recover all of them. - -2001-07-09 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Use - camel_internet_address_format_address rather than - camel_address_encode since we want display-friendly addresses. - -2001-07-09 Iain Holmes <iain@ximian.com> - - * e-msg-composer-select-file.c (file_selection_info_destroy_notify): - Unref the file selection dialog when the data is destroyed. - -2001-07-09 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (composer_shutdown): Do the - autosave_manager_unregister at shutdown time instead of destroy - time (by which point the contents of the window, including the - remote editor control, will have already been destroyed). - -2001-07-09 Zbigniew Chyla <cyba@gnome.pl> - - * e-msg-composer-select-file.c: Added missing #include <config.h> to - make translations working. - -2001-07-07 Jon Trowbridge <trow@ximian.com> - - * e-msg-composer-hdrs.c (set_recipients): Make sure that our - destination string (dest_str) is not the empty string before we - try to use it. - -2001-07-06 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (autosave_manager_new): add missing static. - (best_encoding): make sure we don't try to call iconv_open with a - NULL tocode. - (autosave_manager_query_load_orphans): remove zero length orphans - so that they don't clutter things up. - -2001-07-06 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): - Convert the filename string to UTF8 before setting it on the - CamelMimePart because that code expects it to be in UTF8. - -2001-07-06 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (autosave_manager_query_load_orphans): only ask - if there are actually contents in the file. Asking about an - emptry fil is not very useful. - (autosave_load_draft): add some sanity chacks. - (autosave_run_foreach_cb): remove debugging warning. - (autosave_manager_new): add a missing static. - -2001-07-06 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (autosave_manager_unregister): make sure we - only remove the file if we think we saved it properly. - (autosave_manager_stop): make sure we set the timeout back to 0 so - that we will restart next time since we stop the timer when there - are no active composers. - (destroy): move this to the beginning of the destroy process. - (autosave_save_draft): add a return value indicating success. - (autosave_manager_register): go ahead and ask next time. - -2001-07-05 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c: add ask argment. - (autosave_manager_query_load_orphans): move the load loop out of - the dir reading loop. - (autosave_manager_new): move initialization out or register. - (autosave_manager_register): protect against recursion with ask. - (init): call new, this still needs to be moved. - -2001-07-05 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (save): Play the "File exists, overwrite?" - game. - (autosave_run_foreach_cb): Change the return val from a gboolean - to void. - -2001-07-04 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (autosave_load_draft): attach send and postpone - handlers. and be more tolerant of errors. - -2001-07-03 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (autosave_save_draft): make sure we seek to the - begining. - - * e-msg-composer.h: remove the timer id. - - * e-msg-composer.c: use autosave manager. - (autosave_save_draft): moved initialization to - autosave_init_file. Only save the buffer if we get a valid - message. - (autosave_load_draft): unlink the old file, we own it now. and - unref the stream when we are done with it. - (autosave_is_owned): check if we own the file, this needs to be - extended to check for other valid processes. - (autosave_query_load_orphans): make this search through the - managers list as it walks the dir. - (autosave_query_load_orphans): make sure we use the full path. - (autosave_run_foreach_cb): timeout foreach handler. - (autosave_run): the timeout function. - (autosave_start): start timer. - (autosave_stop): stop timer. - (autosave_register): register a composer with the autosave manager. - (autosave_unregister): unregister a composer. - (destroy): unregister the composer, everything is okay. - (init): register the composer. - -2001-07-02 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.h: add autosave members. - - * e-msg-composer.c (autosave_query_load_orphans): query the user to - check if they want to load any orphans we've found. - (autosave_query_cb): the dialog callback. - (autosave_is_orphan): test if if a particular file is orphaned. - (autosave_load_draft): load a message from an autosave file. - (autosave_save_draft): save the current buffer to the autosave file. - -2001-07-02 Christopher James Lahey <clahey@ximian.com> - - * Makefile.am (INCLUDES): Added $(BONOBO_CONF_CFLAGS). - -2001-07-02 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): Set the - user-chosen charset. - - * e-msg-composer.c (menu_change_charset_cb): New callback function - to get the user-set charset. - (init): Set the charset to NULL. - (best_charset): Take a default_charset param that holds the value - the user set for this particular message using the menu. - (destroy): Free the charset. - -2001-07-02 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (setup_ui): Construct an e-charset-picker - bonobo-ui menu. - (menu_change_charset_cb): - -2001-06-30 Jon Trowbridge <trow@ximian.com> - - * e-msg-composer-hdrs.c (set_recipients): Touch all of our - EDestinations before we unref them, updating the last-use records - in the addressbook. - -2001-06-29 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (e_msg_composer_show_sig_file): remove now - invalid argument in the documentation. - -2001-06-28 Radek Doulik <rodo@ximian.com> - - * e-msg-composer.c: removed obsolete e_msg_composer_get_sig_file - - * e-msg-composer.h: removed sig_file field from EMsgComposer - - * e-msg-composer.c (e_msg_composer_get_sig_file_content): exported - (get_file_content): make it const safe - (e_msg_composer_get_sig_file_content): refactored, don't try to be - clever about signature filename, as it's exact now - (get_signature_html): use has_html_signature flag - (e_msg_composer_show_sig_file): renamed from - e_msg_composer_set_sig_file, removed sig_file parameter as it's - obsolete now - (e_msg_composer_new_with_sig_file): removed obsolete parameters - -2001-06-27 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (menu_file_insert_file_cb): make hook this up. - (get_sig_file_content): use get_file_content. - (get_file_content): make this usable for both insertion and - signatures. - (read_file_content): added helper function to read file. - -2001-06-27 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c: Added a pixcache array for special pixmaps to - use in the composer. - (setup_ui): Set the pixcache. - -2001-06-21 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (menu_file_send_cb): Emit the POSTPONE signal - if we are offline. - (setup_ui): If we are offline, change the Control+Enter accel to - be on the SendLater menu item. - -2001-06-20 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (save_draft): Save the formatting preference - for this message draft using a X-Evolution-Format header. - (e_msg_composer_new_with_message): Restore the format editing - preference and also remove any other X-Evolution-* headers that we - may have set. - -2001-06-20 Dave Camp <dave@ximian.com> - - * Evolution-Composer.idl: Changed attachData to accept a sequence of - chars rather than a string. - - * evolution-composer.c (impl_Composer_attach_data): Changed the 'data' - argument to a GNOME_Evolution_Composer_AttachmentData, and pass - data->_buffer and data->_length to camel_mime_part_set_content(). - -2001-06-19 JP Rosevear <jpr@ximian.com> - - * evolution-composer.c (impl_Composer_send): send the message - - * Evolution-Composer.idl: add a "send" method to send a message - without showing the editor - -2001-06-19 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (e_msg_composer_construct): Don't define the - drop_types here. - (drag_data_received): Implement message/rfc822 dnd drop type - handling. - -2001-06-12 Dan Winship <danw@ximian.com> - - * e-msg-composer-attachment.glade: Replace the disposition option - menu with a checkbox. - - * e-msg-composer-select-file.c - (e_msg_composer_select_file_attachment): New function to select a - file to attach. Adds a "suggest inline disposition" checkbox. - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): Add - a disposition argument rather than always defaulting to - "attachment". - (struct _DialogData, ok_cb, e_msg_composer_attachment_edit): - Update for optionmenu->checkbox change for disposition. - - * e-msg-composer-attachment-bar.c (add_from_file): Add a - disposition argument. - (add_from_user): Use e_msg_composer_select_file_attachment, pass - chosen disposition to add_from_file. - (e_msg_composer_attachment_bar_attach): Pass "attachment" to - add_from_file for the disposition. - -2001-06-11 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (best_charset): Fix again... don't leave - *encoding uninitialized in the US-ASCII case. - -2001-06-11 Jon Trowbridge <trow@ximian.com> - - * e-msg-composer.c (e_msg_composer_construct): Rearranged - gtk_widget_show()s a bit to fix Bug#3204. The composer is now - (like the rest of Evo) properly network transparent. - -2001-06-08 Jon Trowbridge <trow@ximian.com> - - * e-msg-composer.c (save_draft): When saving a draft, attach - information about the From: identity via X-Evolution-Account. - This lets us select the correct identity when we edit it later. - (e_msg_composer_new_with_message): If the message we are editting - is tagged with an account (via X-Evolution-Account), make sure - that the composer chooses that account's identity by default. - -2001-06-08 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (best_charset): Don't use the default charset - if the message is US-ASCII. - -2001-06-07 Radek Doulik <rodo@ximian.com> - - * e-msg-composer.c (e_msg_composer_new_with_sig_file): just set - sig_file field, but don't actualy insert signature, it will be - done by format menu item callback - (e_msg_composer_set_body_text): don't set signature here - -2001-06-01 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): If user is trying to sign - his/her message, try first to use the key that they might have - provided in their account settings. If that was never set, default - to their email address. Also respect their config option to - encrypt-to-self. - -2001-05-31 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Oops. Fix a few compile problems. - -2001-05-31 Christopher James Lahey <clahey@ximian.com> - - * Makefile.am (HTML_EDITOR_GENERATED): Use GTKHTML_DATADIR here. - -2001-05-31 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Fixed up the S/MIME - signing/encrypting code to work with the new API. - -2001-05-31 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (best_encoding): Add a missing iconv_close - -2001-05-30 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (build_message): Use the config-specified - default character set (which in turn defaults to the locale - character set) as the default for encoding non-US-ASCII messages, - assuming it works. Fall back to camel_charset_best() if it fails. - Also, pick the Content-Transfer-Encoding based on how the data - looks in the destination charset, not in UTF8. - - While I was here, I also refactored a bunch and tried to reduce - redundant code. There are still too many places that set the - transfer-encoding on the plaintext part though... Also, I think - some more cleanliness could happen if the sign/encrypt interfaces - returned CamelMultiparts instead of CamelMimeParts. - -2001-05-28 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-attachment-bar.c (update): Use - e_utf8_to_gtk_string() on the description of the attachment since - camel stores these as utf-8 strings. - -2001-05-28 Jason Leach <jleach@ximian.com> - - * Makefile.am (INCLUDES): srcdir != builddir fix. - -2001-05-24 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Populate the - extra_hdr_* arrays with any non-special-case headers. - (is_special_header): New convenience function to determine if a - header is a "special" header or not. - -2001-05-24 Radek Doulik <rodo@ximian.com> - - * e-msg-composer.c (menu_edit_delete_all_cb): new callback - (menu_edit_delete_all_cb): set orig to 0 too - (menu_edit_delete_all_cb): be more careful about text color and - style - -2001-05-23 Radek Doulik <rodo@ximian.com> - - * e-msg-composer.c (e_msg_composer_set_sig_file): set orig to 0 - -2001-05-18 Jon Trowbridge <trow@ximian.com> - - * e-msg-composer-hdrs.c (set_recipients): Properly unserialize the - string returned by the "text" property of the bonobo control, - convert it into EDestinations, and use them to get the e-mail - addresses of our recipients. - -2001-05-17 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (save_draft): Draft messages should be marked - read. - -2001-05-16 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Added S/MIME sign/encrypt code. - (init): Initalize smime_sign/encrypt. - (e_msg_composer_get_smime_encrypt): new - (e_msg_composer_set_smime_encrypt): new - (e_msg_composer_get_smime_sign): new - (e_msg_composer_set_smime_sign): new - (menu_security_smime_sign_cb): new - (menu_security_smime_encrypt_cb): new - (setup_ui): Setup the UI for S/MIME stuff. - -2001-05-10 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): If we are creating a message - with only a single part (ie no attachments and we will not be - signing/encrypting the part) then `part = CAMEL_MIME_PART(message)` - otherwise create a new MIME part and set it's content-object as the - message's content-object at a later date. - -2001-05-09 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (add_inlined_image): Don't wrap content-id with - brackets here as it is now done internally in camel. - -2001-05-03 Radek Doulik <rodo@ximian.com> - - * e-msg-composer.c (get_signature_html): put signature in 100% - width table - (delete_old_signature): look only for first flow with signature == 1 - (e_msg_composer_new): don't insert <BR> - (e_msg_composer_new_with_sig_file): ditto - (delete_old_signature): don't delete whole signature paragraph, - but just it's content - (delete_old_signature): if signature isn't found, insert new empty - paragraph to end of document for new signature - (e_msg_composer_set_sig_file): delete signature always - (e_msg_composer_set_sig_file): don't place signature to the end of - document, but place it where previous one was (if there wasn't - then new one is appended to the document) - -2001-05-02 Radek Doulik <rodo@ximian.com> - - * listener.c (impl_event): do automagic indenting only when - in_signature_insert is FALSE - - * e-msg-composer.c (e_msg_composer_set_sig_file): do indent-zero - before signature inserting - (e_msg_composer_set_sig_file): use in_signature_insert flag - -2001-05-01 Radek Doulik <rodo@ximian.com> - - * listener.c (impl_event): set signature to 0 in newly created - empty paragraphs - (clear_signature): new helper function - -2001-04-26 Dan Winship <danw@ximian.com> - - * Makefile.am (INCLUDES): Remove UNICODE_CFLAGS - -2001-04-25 Radek Doulik <rodo@ximian.com> - - * e-msg-composer.c (e_msg_composer_set_send_html): block/unblock - redraw - - * listener.c (impl_event): reflect object data type change - - * e-msg-composer.c (get_sig_file_content): renamed from - get_signature - (get_signature_html): new helper function, uses - get_sig_file_content - (set_editor_text): removed signature parameters - (from_changed_cb): new signal handler, sets signature by identity - change - (delete_old_signature): new function, deletes old signature from - the document - (e_msg_composer_set_sig_file): new method, set's signature - filename - (e_msg_composer_mark_text_orig): removed (obsolete) - - * e-msg-composer-hdrs.c: added signal FROM_CHANGED - -2001-04-21 Duncan Mak <duncan@ximian.com> - - * e-msg-composer.c (e_msg_composer_construct): Set window_icon to - "compose-message.png" for the composer window. - - Did #include <libgnomeui/gnome-window-icon.h> so we could use - gnome_window_icon_set_from_file() here. - -2001-04-17 Radek Doulik <rodo@ximian.com> - - * listener.c (reply_indent): more auto-indentation magic - -2001-04-12 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Use the mail-crypto pgp-mime - wrappers. - (build_message): s/CAMEL_PGP_HASH_TYPE_SHA1/CAMEL_CIPHER_HASH_SHA1 - -2001-04-11 Dan Winship <danw@ximian.com> - - * e-msg-composer-select-file.c (create_file_selection): Fix - previous. - -2001-04-11 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-select-file.c (create_file_selection): Set the - default filename to the user's homedir. - -2001-04-04 Kjartan Maraas <kmaraas@gnome.org> - - * e-msg-composer-attachment.c: Fix headers. - * e-msg-composer-hdrs.c: Same here. - -2001-03-29 Kjartan Maraas <kmaraas@gnome.org> - - * e-icon-list.c: Replace #include <gtk/gtk.h> - * e-msg-composer-attachment-bar.c: Replace #include <gnome.h> - * e-msg-composer-attachment-bar.h: Remove #include <gnome.h> - * e-msg-composer-attachment.c: Remove #include <gnome.h> - * e-msg-composer-attachment.h: Same here. - * e-msg-composer-hdrs.c: Replace #include <gnome.h> and <bonobo.h> - * e-msg-composer-hdrs.h: Replace #include <gnome.h> - * e-msg-composer-file.c: #include <gtk/gtkmain.h>, <gtk/gtksignal.h> - * e-msg-composer.c: Replace #include <bonobo.h>, <gnome.h> - * e-msg-composer.h: Replace #include <gnome.h> and <bonobo.h> - * evolution-composer.c: Replace #include <bonobo.h> - * listener.c: Same here. - -2001-03-28 Dan Winship <danw@ximian.com> - - * e-msg-composer.c (save_draft): Use the drafts folder specified - by the account, if possible. Also, fix the setting of "send_html" - after saving the draft in case the user plans to keep editting... - -2001-03-27 Larry Ewing <lewing@ximian.com> - - * e-msg-composer.c (e_msg_composer_set_send_html): set the - FormatHTML property on the editor to let it know the mode. - (e_msg_composer_construct): set the property at construct time. - -2001-03-26 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): Set - the mime part content-id. - -2001-03-19 Radek Doulik <rodo@ximian.com> - - * listener.c (reply_indent): set default text color - -2001-03-17 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_get_reply_to): Make - sure the reply_to text is non-NULL before trying to pass it off to - the address parser. - -2001-03-13 Dan Winship <danw@ximian.com> - - * e-msg-composer-attachment.c (update_mime_type): Use - gnome_vfs_mime_type_from_name rather than gnome_vfs_mime_info, - since the entered filename doesn't have to be a real file on disk. - Deal with it returning NULL too. - (e_msg_composer_attachment_edit): Select the right item in the - inline/attachment menu. - - * e-msg-composer-hdrs.c: s/Pair/EMsgComposerHdrPair/. Namespace! - -2001-03-12 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.h: Added view_replyto member. - - * e-msg-composer.c (e_msg_composer_get_visible_flags): Find out if - we want to view the Reply-To header. - (e_msg_composer_set_view_replyto): A new function to set the state - of the replyto header. - (menu_view_replyto_cb): Callback for setting the ReplyTo state. - (set_config): Make static. - (setup_ui): Setup the ReplyTo bonobo stuff. - (load_from_property_bag): More defaults for the ReplyTo, yay. - (load_from_gnome_config): Again... - (e_msg_composer_get_view_bcc): Implemented. - (e_msg_composer_get_view_cc): Implemented. - (e_msg_composer_get_view_from): Implemented. - (e_msg_composer_get_view_replyto): Implemented. - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_get_reply_to_entry): - New function, yay. - (e_msg_composer_hdrs_get_reply_to): Another new function. - (e_msg_composer_hdrs_set_reply_to): Yet another new function... - (create_headers): Create the reply-to header. - (attach_headers): Attach the reply_to. - (headers_set_visibility): Set the reply_to visibility. - (e_msg_composer_hdrs_to_message): Set the message's reply-to here - based on the user-set reply-to header. - -2001-03-06 Miguel de Icaza <miguel@ximian.com> - - * e-msg-composer.c (set_config): New function. Used to store - integer values into the configuration engine. Handles the case of - Bonobo-conf being installed, or falls back to gnome_config. - - * e-msg-composer-hdrs.c (add_header): Renamed to be - header_new_recipient(). Now we take care of the other cases in - create_headers, which is a lot nicer now. - - (create_optionmenu): Removed extra "name" argument which was not - being used anyways (the only arg passed was From:). - (init): Removed all the redundant NULL initialization by using - nice g_new0 - - (create_headers): New function, much cleaner. - - Use of Pair structure everywhere instead of individual widgets to - keep track of which ones are visible and which ones are not. - - * e-msg-composer.c (setup_ui): Handle ViewFrom and ViewBCC - commands. - (menu_view_bcc_cb, menu_view_from_cb): New functions that - implement the features described. - - (menu_format_html_cb): Removed unrequired test, as - e_msg_composer_set_send_html already optimizes the case of the - state being the same. - (menu_security_pgp_encrypt_cb): Remove redundant code. - (menu_security_pgp_sign_cb): ditto. - -2001-03-02 Jeffrey Stedfast <fejj@ximian.com> - - * e-icon-list.c (icon_new_from_pixbuf): Added a comment reminding - us that we should probably not force a particular font in the icon - caption. - -2001-02-27 Dan Winship <danw@ximian.com> - - * evolution-composer.c (factory_fn): If - !mail_config_is_configured(), give an error and return NULL. - -2001-02-22 Ettore Perazzoli <ettore@ximian.com> - - * Makefile.am (INCLUDES): Add `-I$(top_srcdir)/shell'. - -2001-02-21 Not Zed <NotZed@Ximian.com> - - * e-msg-composer.c (menu_file_save_draft_cb): - (exit_dialog_cb): Use mail_append_mail to save to drafts instead - of custom thread handler. - -2001-02-19 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Handle exceptions a little - nicer and pop up a nice GnomeDialog with the error message - also, - don't return a CamelMimeMessage if it fails to sign/decrypt - because we want to let the user decide what to do based on the - error message he/she gets. - -2001-02-15 Dan Winship <danw@ximian.com> - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_set_from_account): If - @account_name is NULL, pick the default account rather than giving - a g_warning. - - * e-msg-composer.c (e_msg_composer_set_headers): Note in the - doc comment that @from can be NULL if you want the default account - (since there is code that expects this). - -2001-02-13 Jeffrey Stedfast <fejj@ximian.com> - - * evolution-composer.c (corba_recipientlist_to_glist): Use the - camel-internet-address code to format the address rather than - doing it the broken way. - -2001-02-10 Jeffrey Stedfast <fejj@ximian.com> - - * evolution-composer.c (impl_Composer_set_headers): Updated. We - might want to change the corba interface for this to allow setting - the from-address as well. - - * e-msg-composer.c (e_msg_composer_new_with_message): Updated. - (e_msg_composer_set_headers): Now takes a 'From' argument so that - we can try to pre-determine the account the user will want to send - from. - -2001-02-11 Gediminas Paulauskas <menesis@delfi.lt> - - * e-msg-composer-attachment.glade.h: removed. - * e-msg-composer-attachment.glade: do not write strings to above. - * Makefile.am: don't include glade.h in EXTRA_DIST. - -2001-02-10 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): - multipart/* is another mime type we DO NOT want to encode ;-) - -2001-02-06 Christopher James Lahey <clahey@ximian.com> - - * e-msg-composer-hdrs.c (address_button_clicked_cb, add_header): - Set the default argument to - GNOME_Evolution_Addressbook_SelectNames_activateDialog correctly. - -2001-01-30 Larry Ewing <lewing@ximian.com> - - * e-msg-composer-hdrs.c (create_optionmenu): make sure we convert - from utf-8 before creating the option menu items. - -2001-01-25 Jason Leach <jasonleach@usa.net> - - (Moving the flag for has_changed from the Hdrs to the Composer - itself. Providing public methods to set/unset a composer as - changed. Adding attachments now flags the composer as changed) - - * e-msg-composer.c (e_msg_composer_unset_changed): New function. - (e_msg_composer_set_changed): New function. - - * e-msg-composer.c (hdrs_changed_cb): Callback to the new signal, - uses the new composer_set_changed. - (attachment_bar_changed_cb): Add a call to the new - composer_set_changed. - - * e-msg-composer-hdrs.c (class_init): New signal "hdrs_changed" to - tell the parent composer that any of the headers have changed. - (addressbook_entry_changed): emit the new signal here. - (entry_changed): And here. - -2001-01-24 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (menu_security_pgp_encrypt_cb): New callback. - (menu_security_pgp_sign_cb): Another new callback. - (setup_ui): Added initialization for the PGP sign and encrypt - bonobo menu items. - (e_msg_composer_set_pgp_encrypt): Change the Bonobo UI name to - SecurityPGPEncrypt. - (e_msg_composer_set_pgp_sign): Change the Bonobo UI name to - SecurityPGPSign. - -2001-01-21 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Fixed some memory leaks - dealing with content-type temp strings. Also implemented code to - sign and/or encrypt the message if the user has specified that it - should. - -2001-01-20 Jason Leach <jasonleach@usa.net> - - (Fix #1222: doing File->New->Mail Message doesn't include .sig) - - * evolution-composer.c (init): Get the users account information, - see if they've specified a sig file, if they do, create a composer - with that sig. - -2001-01-19 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-hdrs.c (create_optionmenu): Use "Full Name - <address>" for the label in the menu rather than the account - name. Specify the account name only if it's not the same as the - address. - -2001-01-19 Jason Leach <jasonleach@usa.net> - - * e-msg-composer-hdrs.c (create_addressbook_entry): Listen for - property bag changes to "entry_changed" on here, which means on - the To, Cc, and Bcc entries. - (addressbook_entry_changed): New function that gets called when - "entry_changed" property is changed (to TRUE). - -2001-01-18 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer.c (build_message): Updated to reflect changes to - e_msg_composer_hdrs_get_from(). - - * e-msg-composer-hdrs.c (set_recipients): Don't do anymore utf8 - conversions, the widget already does this (or should unless there - is brokenness). - (e_msg_composer_hdrs_get_from): Return a CamelInternetAddress like - we should. - (e_msg_composer_hdrs_to_message): Update to reflect changes made - the the above function. - -2001-01-12 Miguel de Icaza <miguel@gnu.org> - - * Makefile.am: Make the composer a standard library, not a libtool - one. Nobody ever uses it as a shared library and it is not - installed. - -2001-01-17 Jason Leach <jasonleach@usa.net> - - (Bug #1192: Set the Composer window title to something useful) - - * e-msg-composer.c (e_msg_composer_construct): Connect up the new - signal here. - (subject_changed_cb): Set the composer window title to the subject - as it's changed, or if it goes blank make it the default "Compose - a message". - - * e-msg-composer-hdrs.c (class_init): Create a new signal - "subject_changed". - (entry_changed): Emit the signal here when the subject entry is - changed. - -2001-01-17 Iain Holmes <iain@ximian.com> - - * e-msg-composer-attachment.c (e_msg_composer_attachment_edit): - Get the option menu from the XML file. - (ok_cb): Set the attachment disposition depending on the option - menu results. - (option_menu_get_history): Really should have been in GTK at some - point. - - * e-msg-composer-attachment.glade: Add the option menu. - -2001-01-17 Michael Meeks <michael@helixcode.com> - - * evolution-composer.c (enum_objects): comment out for now - to ease compat issues. - (evolution_composer_construct): pass in NULL for the item - handler enum_objects fn + calm warning. - -2001-01-17 JP Rosevear <jpr@ximian.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Use the - to/cc/bcc addresses insted of just the to. - -2001-01-17 Federico Mena Quintero <federico@ximian.com> - - * e-icon-list.[ch]: Ximianified email addresses. - -2001-01-16 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer.c (e_msg_composer_mark_text_orig): publicate - mark_orig_text - (set_editor_text): don't call mark_orig_text, let it for reply - -2001-01-15 Jason Leach <jasonleach@usa.net> - - (Plug leaking the subject string on each message sent) - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_get_subject): Don't - strdup before returning the subject, it's already been strdup'd - from the gtk_object_get(). - -2001-01-13 Jason Leach <jasonleach@usa.net> - - (Fix Bug #1083: Composer IDLs not getting installed) - - * Makefile.am: add @idl and @idl_DATA vars. - -2001-01-12 Jeffrey Stedfast <fejj@ximian.com> - - * e-msg-composer-hdrs.c (create_optionmenu): Oops. Make sure to - attach the item to the menu ;-) - -2001-01-12 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (build_message): Call set_from_account which - means we no longer have to do all the crap involved in formatting - strings into an internet-address. - (e_msg_composer_get_preferred_account): New access function. - - * e-msg-composer-hdrs.c (add_header): case COMBOBOX has changed to - OPTIOMENU. - (create_optionmenu): Update to use an optionmenu of accounts. - (from_changed): New callback for the From optionmenu. - (setup_headers): s/COMBOBOX/OPTIONMENU - (init): Set the account and from_options to NULL. - (e_msg_composer_hdrs_get_from): Updated. - (destroy): free the from_options. - (e_msg_composer_hdrs_set_from_address): Renamed from set_from - because it no longer takes a string arg but rather an account arg. - -2001-01-12 Miguel de Icaza <miguel@ximian.com> - - * e-msg-composer-hdrs.c (add_header): Only attach to "changed" if - the widget is an EEntry. The HEADER_COMBOBOX and the - HEADER_ADDRBOOK are a ComboBox and a remote Bonobo control - respectively. - - * evolution-composer.c (get_object): Move getObject functionality - here from e-msg-composer.c - -2001-01-11 Miguel de Icaza <miguel@ximian.com> - - * e-msg-composer-hdrs.c (create_dropdown_entry): Only set the - popdown strings if we have anything to popdown. - -2001-01-10 Miguel de Icaza <miguel@helixcode.com> - - * evolution-composer.c (evolution_composer_construct): Add an - ItemContainer Bonobo interface to allow client applications to - locate the Message Composer component. - -2001-01-11 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (menu_file_save_draft_cb): New callback to save - draft. Fixes bug #1045. - -2001-01-10 Miguel de Icaza <miguel@helixcode.com> - - * e-msg-composer.c: Removed more UNSAFE stuff. Maybe we should - kill this macro, and have people that want these broken things - define their own macros. - (setup_item_container): Add an ItemContainer bonobo interface to - handle options to the window component. - -2001-01-08 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (create_dropdown_entry): Updated for new - config code - this time it works! - -2001-01-08 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (create_dropdown_entry): Reverted back to - old config code temporarily until I get the new config code - working 100%. - -2001-01-07 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (create_dropdown_entry): Updated to - reflect changes to the mail-config API. - -2001-01-05 Radek Doulik <rodo@helixcode.com> - - * listener.c (impl_event): disable indenting for now, it crashes - editor - -2001-01-03 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (do_exit): If the headers have changed, then - continue with the prompt else just destroy the window. - - * e-msg-composer-hdrs.c (init): Initialize has_changed to FALSE. - (entry_changed): New callback to set the value of has_changed. - (add_header): Attach the "changed" signal. - -2001-01-02 Dan Winship <danw@helixcode.com> - - * e-msg-composer-attachment.c (e_msg_composer_attachment_edit): - * e-msg-composer-attachment-bar.c (update): Use - header_content_type_simple, not header_content_type_format. - - * e-msg-composer-hdrs.c (create_dropdown_entry): Call - e_utf8_to_gtk_string on the combobox strings. - -2000-12-28 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (handle_multipart_alternative, - handle_multipart, e_msg_composer_new_with_message): Use - CamelContentType instead of GMimeContentField. - - * e-msg-composer-attachment.c (e_msg_composer_attachment_edit): - * e-msg-composer-attachment-bar.c (update, attach_to_multipart): - Use CamelContentType, and use the header_content_type_* functions - rather than operating on the structure by hand. - -2000-12-15 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_get_pgp_encrypt): New function - to get whether or not to encrypt the message. - (e_msg_composer_set_pgp_encrypt): New function to set encryption. - (e_msg_composer_get_pgp_sign): New function to get whether or not - to sign the message. - (e_msg_composer_set_pgp_sign): New function to set pgp_sign. - (init): Initialize pgp_sign and pgp_encrypt to FALSE. - -2000-12-14 Christopher James Lahey <clahey@helixcode.com> - - * e-msg-composer-hdrs.c (add_header): Made it so that carriage - return doesn't insert a newline in the subject entry. - -2000-12-12 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (set_entry): Don't convert the utf-8 - string to a gtkstring because the widget expects to get a utf-8 - string. - -2000-12-12 Dan Winship <danw@helixcode.com> - - * Makefile.am (EXTRA_DIST): Add $(IDLS). (From campd.) - -2000-12-07 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer.c (prepare_engine): added warnings - (prepare_engine): updated to IDL:GNOME/GtkHTML/Editor/Engine:1.0 - - * Makefile.am: renamed HTMLEditor* to Editor*, added Editor-common.c: - $(HTML_EDITOR_GENERATED) rule - -2000-12-05 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (add_recipients): Use camel to construct the - list of recipients rather than just strchr(recips, ',') which is - very prone to errors. - -2000-11-03 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-attachment-bar.c (update): Pass NULL - instead of icon_name to the e_icon_list_append_pixbuf - function. - (init) Take the font size into account when setting the - height of the bar. - -2000-11-02 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-attachment-bar.c (update): Use the - pixbuf_for_mime_type function to get the icon. - (pixbuf_for_mime_type): Functino that searches nautilus/ - and mc/ for icon files. - -2000-11-15 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer.c (prepare_engine): update namespace - - * updates for HTMLEditor API changes - - * e-msg-composer.c: added #include <libgnomevfs/gnome-vfs.h> - - * e-msg-composer.h: e_msg_composer_guess_mime_type renamed and - moved mime_guess_type_from_file_name from camel as it uses VFS - -2000-11-14 Radek Doulik <rodo@helixcode.com> - - * listener.c (reply_indent): rename command to runCommand - - * e-msg-composer.c: updated to HTMLEditor API changes - - * listener.c: updated to HTMLEditor API changes - -2000-11-13 Radek Doulik <rodo@helixcode.com> - - * listener.c (reply_indent): extracted function, does reply - indentation, use updated editor engine api - -2000-11-10 Michael Meeks <michael@helixcode.com> - - * Makefile.am ($(HTML_EDITOR_GENERATED)): rearrnace - includes. - -2000-11-10 Larry Ewing <lewing@helixcode.com> - - * e-msg-composer.c (build_message): set the HTML charset to utf-8 - for all the html message parts. - (build_message): make sure we set the proper encoding on the html - part now that it may contain utf-8 characters - -2000-11-08 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer.c (e_msg_composer_clear_inlined_table): new - function - (destroy): use e_msg_composer_clear_inlined_table, destroy - inlined_images hash table - (get_signature): added in_html arg, it tells if we should use HTML - signature - (set_editor_text): try to use HTML signature - (e_msg_composer_new_with_sig_file): added send_html arg to be able - to use HTML signature - - * listener.c (resolve_image_url): don't add inlined images to - attachement bar - - * e-msg-composer.c (add_inlined_images): new function, adds - inlined images to multipart - (add_inlined_image): helper function, adds one image to multipart - (build_message): store HTML messages with inlined images to - multipart/related - - * e-msg-composer-attachment-bar.c (add_from_file): removed - content_id arg - (e_msg_composer_attachment_bar_attach): likewise - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): - removed content_id arg - -2000-11-06 Not Zed <NotZed@HelixCode.com> - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_to_message): Changed - for message api changes. Use camel_address_unformat to convert - the editable->usable. - (set_recipients): Same. Now we set the recipients as - camel_internet_address's. Fixed a memleak indirectly. - (decode_addresses): Removed, no longer needed. - (create_dropdown_entry): We dont want to use _encode(), we want to - _format, as we are displaying the result. We can use the static - function too to avoid the object creation, and the memory leak! - (set_entry): Convert the args to gtk-safe characters, since the - entry doesn't understand utf8. - (set_recipients): And likewise do the reverse when retrieving the - contents of the widget. - -2000-11-06 Larry Ewing <lewing@helixcode.com> - - * e-msg-composer.c (build_message): set the content type on the - plain part of outgoing messages. - (best_content): a helper function to get the best content type for - the attachment. This should probably use the helper functions in - the future. - -2000-11-06 Kjartan Maraas <kmaraas@gnome.org> - - * e-msg-composer-attachment.c: Added #include <config.h> - * e-msg-composer-hdrs.c: s/_HAVE_CONFIG_H/HAVE_CONFIG_H for - working i18n. - -2000-11-04 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): fix - test for regular file to !S_ISREG (statbuf.st_mode) - - * listener.c (resolve_image_url): use inline images hash table - - * e-msg-composer.c (init): create inlined images hash table - (destroy): destroy it - (clear_inline_images): helper function, used from - g_hash_table_foreach_remove to destroy one inline image record - - * e-msg-composer.h: added hash table with inlined images url -> - cid info - -2000-11-03 Radek Doulik <rodo@helixcode.com> - - * listener.c (impl_event): updated for API changed - implemented image_url event - (resolve_image_url): new helper function, attaches image to mail - and returns new (resolved) url pointing to mime component - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): - added conponent_id parameter - - * e-msg-composer-attachment-bar.c - (e_msg_composer_attachment_bar_attach): added parameter content_id - (add_from_file): likewise - -2000-11-03 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-attachment.c (e_msg_composer_attachment_new): - Don't allow attaching anything but regular files. - -2000-11-03 Federico Mena Quintero <federico@helixcode.com> - - * Makefile.am: Clean the idl-generated files properly. - -2000-11-02 Peter Williams <peterw@helixcode.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): CamelStreamMem - steals our byte array; we can't destroy the byte array explicitly, and - we must unref the stream only when done using the array. - -2000-11-01 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Don't create - the To, Cc, and Bcc lists based only on the address, use both the - name and address and camel_address_encode() them. - -2000-11-01 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): Fix the - CTE kludge, calculate the best mime transfer encoding for the mime - part and use that. Include e-msg-composer-select-file.h - -2000-10-31 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer.c (prepare_engine): new function, tries prepare - editor engine - (mark_orig_text): marks original text in editor - (set_editor_text): call mark_orig_text - (create_composer): call prepare_engine - - * Makefile.am (IDL_GENERATED): added HTMLEditor generated files to - IDL_GENERATED - ($(IDL_GENERATED)): generate also files from HTMLEditor.idl - (libcomposer_la_SOURCES): added listener.[ch] - - * e-msg-composer.h: added editor_engine and editor_listener to - EMsgComposer - - * listener.[ch]: new files, implementation of HTMLEditor::Listener - -2000-10-27 Ettore Perazzoli <ettore@helixcode.com> - - * Makefile.am ($(IDL_GENERATED)): Get `Composer.idl' from - `$(srcdir)' so that it builds with builddir != srcdir. - -2000-10-27 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Fixed my - not-quite-right logic so that we don't accidently set the body - contents using a plain text attachment instead of the actual body - of the message :-) - -2000-10-25 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Populate the - composer with any attachments. - -2000-10-25 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-select-file.c (create_file_selection): Set the - wmclass and wmclass_name for the file selectors so that Sawfish - doesn't make the dialogs the same size as the parent. - -2000-10-25 Dan Winship <danw@helixcode.com> - - * evolution-composer.c (init): Attach send/postpone signal - handlers to the EMsgComposer. - (evolution_composer_factory_init): Take send/postpone signal - handlers as arguments. - -2000-10-23 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c, e-msg-composer-attachment-bar.c: add some - missing _()s. - - * e-msg-composer-address-dialog.*, e-msg-composer-address-entry.*: - Old cruft. Remove. - - * Makefile.am: Update for removed files. - - * e-msg-composer-hdrs.c: Remove e-msg-composer-address-entry.h - include. - - * e-msg-composer.c: Remove e-msg-composer-address-dialog.h include - -2000-10-23 Ariel Rios <ariel@arcavia.com> - - * e-msg-composer-hdrs.c: Include Composer.h - instead of volution-Addressbook-SelectNames.h - -2000-10-22 Dan Winship <danw@helixcode.com> - - * .cvsignore: No, don't ignore Evolution-Addressbook-SelectNames*. - They're not supposed to be there any more. - -2000-10-22 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer-attachment-bar.c (attach_cb): Removed. - (add_from_user): Use `e_msg_composer_select_file()' instead of - doing the file selector widget magic by yourself. - -2000-10-20 Jeffrey Stedfast <fejj@helixcode.com> - - * .cvsignore: Ignore Evolution-Addressbook-SelectNames* - -2000-10-20 Dan Winship <danw@helixcode.com> - - * Evolution-Composer.idl: Evolution::Composer interface - - * evolution-composer.[ch]: Implementation and factory. So - entirely not tested. - - * Makefile.am (libcomposer_la_SOURCES): Add - evolution-composer.[ch] - (IDLS): Update this for Evolution-Composer.idl / Composer.idl - - * main.c: Removed. (Old, dead code) - -2000-10-19 Ettore Perazzoli <ettore@helixcode.com> - - * Makefile.am (glade_data): Add `e-msg-composer-attachment.glade'. - (glade_messages): New. - (EXTRA_DIST): Add `$(glade_messages)'. - -2000-10-19 Michael Meeks <michael@helixcode.com> - - * e-msg-composer.c (create_menubar_file, create_menubar_edit), - (create_menubar_format, create_menubar_view, create_menubar): kill. - (create_toolbar): die. - (setup_ui): impl. - (e_msg_composer_construct): hook in. - (menu_format_html_cb): update. - (menu_view_attachments_activate_cb): ditto. - (destroy): upd. - (e_msg_composer_construct): upd. - (e_msg_composer_set_send_html): upd. - -2000-10-16 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-hdrs.c (init): Don't need the ID anymore. - -2000-10-17 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): If the body - text was NULL, then don't bother turning it into HTML (besides, it - causes a nasty segfault). - -2000-10-15 Dan Winship <danw@helixcode.com> - - * Makefile.am: Move CPPFLAGS flags to INCLUDES to avoid bashing - any CPPFLAGS set at configure time. - -2000-10-14 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-attachment.c (set_entry): If the entry widget is - NULL, obviously we can't set any text on it. - -2000-10-14 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-hdrs.c (init): Create a unique-ish id for this set - of headers, so that only one select-names dialog will be created for - a given set of headers. - (address_button_clicked_cb): Pass the unique-ish id to the activate - dialog command. - -2000-10-13 Larry Ewing <lewing@helixcode.com> - - * e-msg-composer.c (build_message): stop using format_text, - gtkhtml handles this now. - (format_text): function removed. - -2000-10-10 Iain Holmes <iain@helixcode.com> - - * e-icon-list.c: Allow NULL pixbufs, and load the "broken" image - - * e-msg-composer-attachment-bar.c (update): If the image isn't - found load the default text/plain icon. - -2000-10-02 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (build_message): If the body of the message has - 8-bit chars, set the Content-Transfer-Encoding type to the best - encoding. - -2000-10-02 Dan Winship <danw@helixcode.com> - - * e-icon-list.c: fix #include of gnome-canvas-pixbuf.h - -2000-10-02 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-attachment-bar.c: If the description of an attachment - is a blank string, revert to displaying the filename. - -2000-10-01 Iain Holmes <iain@helixcode.com> - - * e-icon-list.c: If you try to add an icon from a file that doesn't - exist put a "Broken icon" image. - - * bad-icon.xpm: Broken icon image. - -2000-10-01 Iain Holmes <iain@helixcode.com> - - * e-msg-composer-attachment-bar.[ch] (update): If the attachment is - an image, then make a thumbnail for it. - Base the attachment bar on e-icon-list instead of gnome-icon-list. - - * e-icon-list.[ch]: New files. These are modified versions of - gnome-icon-list from gnome-libs HEAD that uses gdk-pixbuf instead - of the evil Imlib. - - * e-msg-composer-attachment.[ch]: Add a pixbuf_cache member, to - save us having to generate a thumbnail for the attachment every - time the bar changes. - - * e-msg-composer.c (e_msg_composer_construct): Add dnd support for - files. Drag a file to the composer to add it as an attachment. - -2000-09-28 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (build_message): Check to see if the body has - 8bit chars, if so - set the Content-Transfer-Encoding to 8bit. - Addresses Bugzilla bug #652. - -2000-09-25 Dan Winship <danw@helixcode.com> - - * e-msg-composer-hdrs.c (setup_headers): fix typo in tooltip. - * e-msg-composer.c (create_menubar_file): fix accelerator for - "Save as" to be different from "Save". (Both problems pointed out - by menthos@menthos.com.) - -2000-09-24 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (get_signature): Updated to handle FIFO - streams. - -2000-09-19 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (e_msg_composer_construct): Don't g_error out - if the html-editor-control fails. - (create_composer): New internal function to create and construct a - msg_composer and pop up an error message if it fails. - (e_msg_composer_new, e_msg_composer_new_with_sig_file, - e_msg_composer_new_with_message, e_msg_composer_new_from_url): Use - create_composer, return if it fails, change return type to - EMsgComposer *. - -2000-09-18 Dan Winship <danw@helixcode.com> - - * e-msg-composer-attachment.c (get_mime_type): Use - gnome_vfs_get_file_info. - - * e-msg-composer-attachment-bar.c (update): Use gnome_vfs_mime - functions, not old gnome_mime. - -2000-09-18 Christopher James Lahey <clahey@helixcode.com> - - * Makefile.am: Added $(EXTRA_GNOME_CFLAGS) and - $(EXTRA_GNOME_LIBS). Removed unneeded libraries. - - * e-msg-composer-address-dialog.c, e-msg-composer-address-entry.c, - e-msg-composer-attachment.c, e-msg-composer-hdrs.c, - e-msg-composer.c: Fixed the #include lines to deal properly with - gal. - -2000-09-12 Michael Meeks <michael@helixcode.com> - - * e-msg-composer.c: Update for new UI handler. - -2000-09-12 Larry Ewing <lewing@helixcode.com> - - * e-msg-composer-attachment-bar.c (add_common): add a make sure - the attachment isn't NULL. A more complete fix coming soon. - -2000-09-12 Ettore Perazzoli <ettore@helixcode.com> - - * Makefile.am ($(IDL_GENERATED)): Add space after `-I'. - -2000-09-05 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c (create_menubar_format): Accelerate the - `Format' menu with an `o' instead of an `f' [the `f' is already - taken by the "File" menu]. - -2000-09-04 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_sig_file): Applied - Jesse's patch that sets the composer's sig_file - -2000-09-02 Lauris Kaplinski <lauris@helixcode.com> - - * e-msg-composer-address-dialog.c: Use e_utf8 wrappers - -2000-09-01 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_get_sig_file): This needs to - return a const char * and not a char *, because we're not actually - allocating memory here. - (create_menubar_file): Changed "Send" to "Send Now" and added - "Send Later" - (menu_file_send_later_cb): New callback that emits the POSTPONE - signal (equivalent to "Send Later" - -2000-08-28 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Always - request to import the HTML version if at all possible so that we - maintain formatting and other nifty stuff :-) - -2000-08-28 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_to_message): Set the - "From" address in the CamelMimeMessage. Also updated to use - get_subject to both make our lives easier and prepare for using UTF8 - (e_msg_composer_hdrs_get_subject): Updated to behave similarly to - get_from and return allocated memory (it will have to return - allocated memory once it's converted to use UTF8 anyways) - - * e-msg-composer.c (setup_save_draft): Always set - composer->send_html = TRUE so that formatting is preserved. - -2000-08-24 Lauris Kaplinski <lauris@helixcode.com> - - * e-msg-composer-address-entry.c: Use e_utf8 wrappers - - * e-msg-composer-attachment.c: Use e_utf8 wrappers - - * e-msg-composer-hdrs.c: Use e_utf8 wrappers - -2000-08-24 Peter Williams <peterw@helixcode.com> - - * Makefile.am (INCLUDES): Add builddir/shell so we can - get Evolution.h - -2000-08-12 Michael Meeks <michael@helixcode.com> - - * e-msg-composer.c (get_text): get_text not get_txt. - -2000-08-11 JP Rosevear <jpr@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Use - new config accessors - -2000-08-10 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c: Remove unneeded e-setup.h include - -2000-08-10 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (exit_dialog_cb): Made async - -2000-08-10 Peter Williams <peterw@helixcode.com> - - * e-msg-composer.c (do_exit): Temporarily disable draft saving - while we figure out how to work around Zucchi's new append_message. - -2000-08-10 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_get_from): Return the - text in GtkCombo->entry - -2000-08-09 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (create_dropdown_entry): Fixed the GList - identity stuff, should now display all configured identities. - -2000-08-09 Christopher James Lahey <clahey@helixcode.com> - - * e-msg-composer-address-dialog.c: Fixed some warnings. - - * e-msg-composer-hdrs.c: Switched the composer to use an EEntry - for the subject field. - - * e-msg-composer.c: Changed the non scaling objects in this vbox - to be FALSE, FALSE instead of FALSE, TRUE. - -2000-08-09 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-hdrs.c (add_header): Modified to allow dropdown - entry-boxes as well (for headers like From:) - (setup_headers): Modified to use the correct enum type. - (create_dropdown_entry): New convenience function to add a - drop-down combo box and fill it in with identities - (init): Set from_entry to NULL - (e_msg_composer_hdrs_get_from): New convenience function to get - the text in the From widget in the composer - (e_msg_composer_hdrs_set_from): New convenience function to set - the From header in the composer - -2000-08-08 JP Rosevear <jpr@helixcode.com> - - * Makefile.am: Fix build by allowing includes for e-table dir - -2000-08-07 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): - s/strcasecmp/g_strcasecmp - - * e-msg-composer.c: s/strncasecmp/g_strncasecmp - this will help - later with building on different platforms :-) - -2000-08-07 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_message): Added code - to set the body text based on the CamelMimeMessage. - (set_editor_text): Use lowercase html tags... - -2000-08-07 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c (do_exit): Prompt the user to save their - composition in Drafts. - (set_editor_text): Uhm, use "-- \n" not "--\n" because the space - is called for in the standard - (e_msg_composer_new_with_message): New convenience function that - takes a CamelMimeMessage as an argument. This will be useful when - we code the ability to resume the editing of a message draft (like - in the Drafts folder). - -2000-08-01 JP Rosevear <jpr@helixcode.com> - - * e-msg-composer.h: Constify param - - * e-msg-composer.c (get_signature): Constify param - (set_editor_text): ditto - (e_msg_composer_new_with_sig_file): ditto - -2000-08-01 Peter Williams <peterw@helixcode.com> - - * e-msg-composer.c (set_editor_text): sizeof("--\") != - strlen("--\n"), breaking the test for the signature prefix. - -2000-07-28 JP Rosevear <jpr@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_with_sig_file): New - function to create composer with sig file set. - (e_msg_composer_get_sig_file): New function to get sig file - (e_msg_composer_set_sig_file): New function to set sig file - -2000-07-25 Michael Meeks <michael@helixcode.com> - - * e-msg-composer.c (get_text): add textual exception printout. - (set_editor_text): close pre tags & check for pre-existing - sig separator. - -2000-07-25 Peter Williams <peterw@helixcode.com> - - * e-msg-composer.c (menu_file_insert_file_cb): Mark this function - as FIXME because we're waiting for the HTML Editor Control to - support paste commands. Also some updates for when that happens. - -2000-07-24 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c: Remove GOAD support. - (create_editor): Try to give a more helpful error message when - failing to load the editor control. - -2000-07-23 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c (menu_format_html_cb): New callback for the - "Send HTML" menu toggle item. - (create_menubar_format): New. - (create_menubar): Call it. - (create_menubar_options): Removed. - (init): Initialize `send_html' and `attachment_bar_visible' to - FALSE. - (get_signature): Add `void' to the declaration. This is C, not - C++. - (menu_file_close_cb): Renamed from `exit_cb'. - (menu_file_send_cb): Renamed from `send_cb'. - (menu_file_save_as_cb): Renamed from `save_as_cb'. - (menu_file_save_cb): Renamed from `save_cb'. - (menu_file_open_cb): Renamed from `open_cb'. - (menu_file_add_attachment_cb): Renamed from `add_attachment_cb'. - (menu_file_insert_file_cb): Renamed from `insert_file_cb'. - (e_msg_composer_set_send_html): New. - (build_message): Use the `send_html' flag instead of peeking the - `msg_format' gnome-config value directly. - - * e-msg-composer.h: New member `send_html' in `EMsgComposer'. - -2000-07-23 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c: Changed to use BonoboUIHandler stuff directly - instead of translating from GnomeUIInfo. - (create_menubar_file): New. - (create_menubar_edit): New. - (create_menubar_view): New. - (create_menubar_options): New. - (create_menubar): Use these functions to set up the menu bar. - (create_toolbar): Use BonoboUIHandler directly instead of - converting from GnomeUIInfo. - (toolbar_view_attachments_clicked_cb): Removed. - (address_dialog_cb): Removed. - (address_dialog_destroy_cb): Removed. - (address_dialog_apply_cb): Removed. - (setup_address_dialog): Removed. - -2000-07-12 Peter Williams <peterw@helixcode.com> - - * e-msg-composer.c: (view_tree) Make the "View Attachments" item - a toggleitem ... so that it can be toggled... - (menu_view_attachments_activate_cb): Treat the widget correctly - and toggle correctly. - -2000-07-10 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c (exit_cb): Use it. - (delete_event): New, handler for the "delete_event" signal. - -2000-07-09 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (set_editor_text): Don't load "" into the - editor, because it will cause the editor component to g_warning. - -2000-07-09 Christopher James Lahey <clahey@helixcode.com> - - * e-msg-composer-hdrs.c: Removed the extra frame here. - -2000-07-08 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (create_menubar): Create an empty "Edit" menu - for the editor control to insert itself into. - -2000-07-08 Jeffrey Stedfast <fejj@helixcode.com> - - * .cvsignore: Ignore dynamically created source files - -2000-07-08 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer-hdrs.c (set_entry): New. - (e_msg_composer_hdrs_set_to): Use it. - (e_msg_composer_hdrs_set_cc): Likewise - (e_msg_composer_hdrs_set_bcc): Likewise. - (e_msg_composer_hdrs_get_to): Replace implementation with a - `g_assert_not_reached()'. - (e_msg_composer_hdrs_get_cc): Likewise. - (e_msg_composer_hdrs_get_bcc): Likewise. - - * e-msg-composer.c: Get rid of cut/copy/paste/undo as they - duplicate the editor toolbar and cannot be made to work for all - the widgets anyway. - -2000-07-08 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer-hdrs.c: New member `corba_select_names' in - `EMsgComposerHdrsPrivate'. - (destroy): If not `CORBA_OBJECT_NIL', release. - (init): Init to `CORBA_OBJECT_NIL'. - (setup_corba): New. - (e_msg_composer_hdrs_new): Call it. - (add_entry): Create the entries by using the ::SelectNames - interface. - (address_button_clicked_cb): Activate the dialog through the - ::SelectNames interface. - -2000-06-29 Jeffrey Stedfast <fejj@helixcode.com> - - * e-msg-composer.c: Changed "Exit" to "Close" in the File menu. - This is a little more intuitive as it does not suggest exiting - the application, just says "close this window". - -2000-06-26 Christopher James Lahey <clahey@helixcode.com> - - * Makefile.am: Added e-msg-composer-select-file.h for make - distcheck. - -2000-06-26 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c - (load): New. - (open_cb): Use it. - (save): New function. - (save_cb): Implemented by using it. - (save_as_cb): Likewise. - -2000-06-17 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c (e_msg_composer_construct): I18N the title bar. - - * Makefile.am (libcomposerinclude_HEADERS): Removed. Move all the - `.h' files into `libcomposer_la_SOURCES' so that they get - distributed, but not installed. - - * e-msg-composer.c (open_cb): New; implement the `Open' command. - (save_as_cb): New; implement the `Save as' command. - (init): Initialize the `persist_file_interface' and - `persist_stream_interface' members to NULL. - (destroy): Release the PersistStream and PersistFile interfaces. - (e_msg_composer_construct): Query the PersistFile and - PersistStream interfaces on the control and save them in the - `persist_file_interface' and `persist_stream_interface' members. - (get_text): Renamed from `get_editor_text'. Get a - @persist_stream_interface instead of querying it a the control. - (build_message): Return NULL if `persist_stream_interface' is nil. - - * e-msg-composer.h: New member `persist_file_interface' in - `EMsgComposer'. - - * e-msg-composer-select-file.c: New. - * e-msg-composer-select-file.h: New. - - * e-msg-composer.c (e_msg_composer_construct): Make the `To:' - entry grab the keyboard focus. - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_get_to_entry): New. - (e_msg_composer_hdrs_get_cc_entry): New. - (e_msg_composer_hdrs_get_bcc_entry): New. - (e_msg_composer_hdrs_get_subject_entry): New. - - * e-msg-composer.c (e_msg_composer_construct): Set the scroll - frame's shadow type to `GTK_SHADOW_IN'. - (format_text): Initialize `tabbing' to zero to shut down the - compiler. - -2000-06-14 Dan Winship <danw@helixcode.com> - - * e-msg-composer-attachment-bar.c (add_from_user): keep the - GtkFileSelection around between calls so we start up in the same - directory we ended up in last time around. (Also fixes a big - memory leak in that the code was already keeping the - GtkFileSelection around, it just wasn't remembering to reuse it.) - - * e-msg-composer.c (format_text): Don't line-wrap lines that start - with ">". - -2000-06-12 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (format_text): If a paragraph starts with TABs, - indent the whole paragraph to that tab level. - -2000-06-12 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c: Make the `attachment_scroll_frame' an - `EScrollFrame'. - (exit_cb): I18N the quit message. - - * e-msg-composer.h: `attachment_scrolled_window' renamed to - `attachment_scroll_frame'. - -2000-06-12 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (format_text): Don't break on non-breaking - spaces, don't keep non-breaking spaces that fall after a line - wrap, and translate non-breaking spaces to regular ones after - wrapping. - -2000-06-05 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (e_msg_composer_attach): New convenience - function. - - * e-msg-composer-attachment.c: Store a CamelMimePart rather than - filename/description/mime_type info. Also record whether we were - told or guessed the MIME type. - (e_msg_composer_attachment_new_from_mime_part): New constructor. - (e_msg_composer_attachment_edit): Remove the "browse" button. (If - the user wants to change the actual file that the attachment is - based on, he should delete the attachment and create a new one...) - Remove the "Apply" button, because it's not all that useful. Make - the MIME type only track the filename if it was guessed rather - than being provided. - - * e-msg-composer-attachment.glade: Remove "browse" and "apply" - buttons. Make filename editable. - - * e-msg-composer-attachment-bar.c (sort): Removed. Send the - attachments in the order the user attached them in. - (text_changed): Removed, since we weren't enabling the relevant - GnomeIconList functionality that would have used this. - (update): Don't print the size if it's 0. - (attach_to_multipart, etc): adjust for EMsgComposerAttachment - changes. - (attach_to_multipart): Use 7bit encoding for message/ subparts. - (e_msg_composer_attachment_bar_attach_mime_part): New convenience - function. - - -2000-06-02 Christopher James Lahey <clahey@helixcode.com> - - * e-msg-composer.c: Added the ability to save plain text mail. - -2000-05-29 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (get_editor_text): add a "format" argument so - we can fetch different kinds of text. - (format_text): New function to do line wrapping on plain text. - (build_message): Build multipart/alternative messages rather than - HTML-only ones. Yay. We don't suck (as much) any more! - -2000-05-28 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c: #include <errno.h> - -2000-05-26 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (get_editor_text, set_editor_text): Update for - PersistStream changes - (build_message): Update for CamelMultipart changes. - - * e-msg-composer.c (get_signature): routine to read the user's - signature file. - (set_editor_text): If the user has configured a signature, append - it to the set text. - (e_msg_composer_new): Call set_editor_text with "" to load the - signature (if any). - -2000-05-25 Not Zed <NotZed@HelixCode.com> - - * e-msg-composer.c (build_message): Use camel_data_wrapper_new - instead of camel_simple_data_wrapper_new. - -2000-05-17 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (build_message): Use - camel_simple_data_wrapper_new rather than camel_data_wrapper_new. - -2000-05-13 Valek Filippov <frob@df.ru> - - * e-msg-composer-attachment.glade: save translatable strings - * e-msg-composer-attachment.glade.h: file with strings - * e-msg-composer-address-dialog.glade: save translatable strings - * e-msg-composer-address-dialog.glade.h: file with strings - -2000-05-12 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (get_editor_text): NUL-terminate the data - extracted from the BonoboStream. - -2000-05-10 Dan Winship <danw@helixcode.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): deal with - Content-Transfer-Encoding a little bit at least. - -2000-05-07 Mathieu Lacage <mathieu@gnu.org> - - * e-msg-composer.c (create_editor): remove FIXME and hardcoded - string. You can write mails with OAF now. - -2000-05-07 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (build_message): unref content, etc. after - attaching it to message. - - * e-msg-composer-attachment-bar.c (attach_to_multipart): unref - part after attaching it. - -2000-05-06 Christopher James Lahey <clahey@helixcode.com> - - * e-msg-composer-hdrs.c: Turned off focus in the To, Cc, and Bcc - buttons. - -2000-05-02 Matt Loper <matt@helixcode.com> - - * Makefile.am: set G_LOG_DOMAIN. - -2000-04-28 Dan Winship <danw@helixcode.com> - - * e-msg-composer-hdrs.c (set_recipients): Update (minimally) for - Camel recipient changes. - -2000-04-27 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new_from_url): New routine, to - process mailto URLs. - -2000-04-26 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (build_message): Only generate a multipart - message if there are attachments. Otherwise generate a single - part. - - * Update for CamelMimeBodyPart -> CamelMimePart - -2000-04-26 Dan Winship <danw@helixcode.com> - - * e-msg-composer-attachment-bar.c (attach_to_multipart): add a - s/SIMPLE_// that notzed missed. Update to use - camel_mime_part_set_content. - * e-msg-composer.c (build_message): remove a now-unused variable. - Update for camel_mime_part_set_content. - -2000-04-26 NotZed <NotZed@HelixCode.com> - - * e-msg-composer.c (build_message): Use camel_mime_part_set_text() - to set the text rather than messing with data wrappers. - - * e-msg-composer-attachment-bar.c (attach_to_multipart): Change - for new camel-stream interfaces. - (attach_to_multipart): Also set base64 encoding by default. - -2000-04-25 Radek Doulik <rodo@helixcode.com> - - * e-msg-composer.c (create_editor): use uih here - (e_msg_composer_construct): create menubar/toolbar before creating - editor control - -2000-04-23 Dan Winship <danw@helixcode.com> - - * Makefile.am: build libcomposer static and don't install it. - - * e-msg-composer-attachment-bar.c (attach_to_multipart): This was - only half-implemented. Finish it, mostly. - -2000-04-22 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (e_msg_composer_add_header): new function to - make the composer record additional headers it should output. - (In-Reply-To), etc. - (build_message): output them - -2000-04-21 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (e_msg_composer_set_headers): - (e_msg_composer_set_body_text): new functions - (exit_cb): Connect "Exit" menu item finally. - - * e-msg-composer-hdrs.c: const poisoning - (e_msg_composer_hdrs_set_subject): - (e_msg_composer_hdrs_get_subject): new functions - - * e-msg-composer-address-entry.c: const poisoning - -2000-04-20 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (get_editor_text, set_editor_text): new - functions to get and set the contents of the HTML editor via - Bonobo::PersistStream. - (build_message): use get_editor_text. This works again. - -2000-04-17 Dan Winship <danw@helixcode.com> - - * e-msg-composer.c (build_message): Change - camel_mime_message_new_with_session to camel_mime_message_new - -2000-03-17 bertrand <bertrand@helixcode.com> - - * e-msg-composer.c (create_menubar): Pass the composer as the data - for the menubar callbacks. - -2000-03-12 Matt Loper <matt@helixcode.com> - - * Makefile.am: Modified to make the composer into a library, to be - used by the mail component. - -2000-03-07 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c (create_toolbar): Pass the composer as the data - for the toolbar callbacks. - (e_msg_composer_construct): Connect the "changed" signal of the - attachment bar to `attachment_bar_changed()'. - (attachment_bar_changed): Renamed to `attachment_bar_changed_cb'. - -2000-03-02 Ettore Perazzoli <ettore@helixcode.com> - - * e-msg-composer.c (e_msg_composer_new): Precondition: - gtk_main_level() greater than zero. - (e_msg_composer_construct): Likewise. - (create_menus): New function. Set up menus through - BonoboUIHandler. - (e_msg_composer_construct): Use it. - - * main.c (main): Initialize Bonobo. - - * e-msg-composer.c (init): Initialize `uih' and `editor' to NULL. - Do not init `text' and `text_scrolled_window' anymore. - (destroy): Unref `uih'. - (e_msg_composer_construct): Create a new BonoboUIHandler and put - it into `uih'. - (create_editor): New helper function. - (e_msg_composer_construct): Use it to set up the editor. - - * e-msg-composer.h: New member `uih' in `EMsgComposer'. Removed - members `text', `text_scrolled_window'. New member `editor'. - - * Makefile.am (INCLUDES): Add `$(BONOBO_GNOME_CFLAGS)'. - (evolution_msg_composer_LDADD): Add `$(BONOBO_GNOME_LIBS)'. - - * e-msg-composer.c (glade_connect): Removed. - (setup_signals): Removed. - (e_msg_composer_construct): Do not use libglade to set the toolbar - and menubar up. - (destroy): Removed libglade stuff. - (init): Likewise. - - * e-msg-composer.h: Removed `menubar_gui', `toolbar_gui', - `appbar_gui'. - - * e-msg-composer.glade: Removed. - -2000-01-12 bertrand <bertrand@helixcode.com> - - * Makefile.am (evolution_msg_composer_LDADD): - use $(EXTRA_GNOME_LIBS_THREADS) to link with gthread - -1999-11-17 Ettore Perazzoli <ettore@gnu.org> - - * Makefile.am: New Makefile to compile the message composer - executable. - - * main.c: New file. - - * e-msg-composer-hdrs.c (e_msg_composer_hdrs_to_message): Use - `CAMEL_RECIPIENT*' macros instead of the old `RECIPIENT*' ones - that do not exist anymore. - - * e-msg-composer-address-dialog.c - (e_msg_composer_address_dialog_construct): Use `E_GLADEDIR' - instead of `E_GUIDIR'. - * e-msg-composer-attachment.c (e_msg_composer_attachment_edit): - Likewise. - * e-msg-composer.c (e_msg_composer_construct): Likewise. - -(See `$(top_srcdir)/widgets/ChangeLog' for previous changes to the -message composer.) diff --git a/composer/Composer.idl b/composer/Composer.idl deleted file mode 100644 index a6cb35c037..0000000000 --- a/composer/Composer.idl +++ /dev/null @@ -1,4 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -#include <Evolution-Addressbook-SelectNames.idl> -#include <Evolution-Composer.idl> diff --git a/composer/Evolution-Composer.idl b/composer/Evolution-Composer.idl deleted file mode 100644 index c15597068a..0000000000 --- a/composer/Evolution-Composer.idl +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Evolution-Composer.idl: Mail composer interfaces for Evolution - * - * Author: - * Dan Winship <danw@ximian.com> - * - * (C) 2000 Ximian, Inc. - */ - -#include <Bonobo.idl> - -module GNOME { -module Evolution { - - interface Composer : Bonobo::Unknown { - struct Recipient { - string name; /* UTF-8 */ - string address; - }; - typedef sequence<Recipient> RecipientList; - - typedef sequence<char> AttachmentData; - - /** - * setHeaders: - * @to: the "To" recipients - * @cc: the "CC" recipients - * @bcc: the "Bcc" recipients - * @subject: the subject of the message - * - * Sets the composer headers. Any of @to, @cc, and - * @bcc may be an empty list, and @subject may be an - * empty string. - **/ - void setHeaders (in RecipientList to, in RecipientList cc, - in RecipientList bcc, in string subject); - - /** - * setBodyText: - * @body: the body - * - * Sets the text in the body of the composer to - * the given UTF-8 plain text. - **/ - void setBodyText (in string body); - - /** - * attachMIME: - * @data: the attachment data - * - * This adds an attachment to the composer. @data - * should be a fully-formed MIME body part. - **/ - exception CouldNotParse {}; - void attachMIME (in string data) - raises (CouldNotParse); - - /** - * attachData: - * @content_type: the Content-Type header - * @filename: the suggested filename, or "" - * @description: a description of the data, or "" - * @show_inline: whether the attachment should be - * displayed inline or not. - * @data: the raw attachment data - * - * This adds @data as an attachment, using the provided - * information to generate MIME headers. @content_type - * may contain just a MIME content type, or it may - * contain a complete Content-Type header. @filename - * is a filename for the Content-Disposition header - * @description (if not "") provides the - * Content-Description, and @show_inline determines if the - * Content-Disposition is "inline" or "attachment". - * - * If you need to specify headers or values other than - * what this function can do, you will need to generate - * all of the MIME headers yourself and use - * add_attachment (). - **/ - void attachData (in string content_type, - in string filename, - in string description, - in boolean show_inline, - in AttachmentData data); - - /** - * show: - * - * Shows the composer and lets the user edit things - * and send the message. - **/ - void show (); - - - /** - * send: - * - * Send the message without showing the user the composer - **/ - void send (); - }; -}; -}; diff --git a/composer/Makefile.am b/composer/Makefile.am deleted file mode 100644 index 22b80e24e0..0000000000 --- a/composer/Makefile.am +++ /dev/null @@ -1,95 +0,0 @@ -## CORBA stuff - -IDLS = \ - Evolution-Composer.idl \ - Composer.idl - -IDL_GENERATED = \ - Composer.h \ - Composer-common.c \ - Composer-skels.c \ - Composer-stubs.c - -HTML_EDITOR_GENERATED = \ - Editor.h \ - Editor-common.c \ - Editor-skels.c \ - Editor-stubs.c - -selectnamesdir = $(top_srcdir)/addressbook/gui/component/select-names - -$(IDL_GENERATED): $(IDLS) $(selectnamesdir)/Evolution-Addressbook-SelectNames.idl - $(ORBIT_IDL) -I $(srcdir) -I $(datadir)/idl `$(GNOME_CONFIG) --cflags idl` \ - -I $(selectnamesdir) $(srcdir)/Composer.idl - -Editor-commmon.c: $(GTKHTML_DATADIR)/gtkhtml/Editor.idl - -$(HTML_EDITOR_GENERATED): $(GTKHTML_DATADIR)/gtkhtml/Editor.idl - $(ORBIT_IDL) -I $(srcdir) `$(GNOME_CONFIG) --cflags idl` -I $(GTKHTML_DATADIR)/gtkhtml $(GTKHTML_DATADIR)/gtkhtml/Editor.idl - -## - -idldir = $(datadir)/idl -idl_DATA = $(IDLS) - -gladedir = $(datadir)/evolution/glade - -glade_DATA = \ - e-msg-composer-attachment.glade - -libcomposerincludedir = $(includedir)/composer - -noinst_LIBRARIES = libcomposer.a - -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_builddir) \ - -I$(top_srcdir)/widgets \ - -I$(top_builddir)/widgets \ - -I$(top_srcdir)/camel \ - -I$(top_builddir)/camel \ - -I$(top_srcdir)/addressbook/backend/ebook \ - -I$(top_builddir)/addressbook/backend/ebook \ - -I$(top_builddir)/addressbook/gui/component/select-names \ - -I$(top_builddir)/shell \ - -I$(top_srcdir)/shell \ - $(EXTRA_GNOME_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(BONOBO_GNOME_CFLAGS) \ - $(BONOBO_CONF_CFLAGS) \ - $(GTKHTML_CFLAGS) \ - $(BONOBO_CONF_CFLAGS) \ - -DEVOLUTION_DATADIR=\"$(datadir)\" \ - -DE_GLADEDIR=\"$(gladedir)\" \ - -DG_LOG_DOMAIN=\"composer\" - -libcomposer_a_SOURCES = \ - $(IDL_GENERATED) \ - $(HTML_EDITOR_GENERATED) \ - e-msg-composer-attachment-bar.c \ - e-msg-composer-attachment-bar.h \ - e-msg-composer-attachment.c \ - e-msg-composer-attachment.h \ - e-msg-composer-hdrs.c \ - e-msg-composer-hdrs.h \ - e-msg-composer-select-file.c \ - e-msg-composer-select-file.h \ - e-msg-composer.c \ - e-msg-composer.h \ - e-icon-list.c \ - e-icon-list.h \ - evolution-composer.c \ - evolution-composer.h \ - listener.c \ - listener.h - -EXTRA_DIST = \ - $(glade_DATA) \ - $(IDLS) \ - bad-icon.xpm - -BUILT_SOURCES = $(IDL_GENERATED) $(HTML_EDITOR_GENERATED) -CLEANFILES += $(BUILT_SOURCES) - -dist-hook: - cd $(distdir); rm -f $(BUILT_SOURCES) diff --git a/composer/bad-icon.xpm b/composer/bad-icon.xpm deleted file mode 100644 index 0a9cac23cd..0000000000 --- a/composer/bad-icon.xpm +++ /dev/null @@ -1,53 +0,0 @@ -/* XPM */ -static char * bad_icon_xpm[] = { -"48 48 2 1", -" g None", -". g #000000", -"................................................", -". .", -". .", -". .", -". .", -". .", -". .", -". .", -". .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". .. .", -". .. .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". . . .", -". .", -". .", -". .", -". .", -". .", -". .", -"................................................"}; diff --git a/composer/e-icon-list.c b/composer/e-icon-list.c deleted file mode 100644 index a5e7ac45cd..0000000000 --- a/composer/e-icon-list.c +++ /dev/null @@ -1,2675 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 1998, 1999, 2000 Free Software Foundation - * All rights reserved. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ - */ - -/* - * GnomeIconList widget - scrollable icon list - * - * Authors: - * Federico Mena <federico@ximian.com> - * Miguel de Icaza <miguel@ximian.com> - * - * Rewrote from scratch from the code written by Federico Mena - * <federico@ximian.com> to be based on a GnomeCanvas, and - * to support banding selection and allow inline icon renaming. - * - * Redone somewhat by Elliot to support gdk-pixbuf, and to use GArray instead of - * GList for item storage. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdio.h> -#include <gtk/gtkmain.h> -#include <gtk/gtkobject.h> -#include <gtk/gtksignal.h> -#include <gtk/gtkwidget.h> -#include <libgnomeui/gnome-icon-item.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <gdk-pixbuf/gnome-canvas-pixbuf.h> -#include "e-icon-list.h" - -#include "bad-icon.xpm" - -/* Aliases to minimize screen use in my laptop */ -#define EIL(x) E_ICON_LIST(x) -#define EIL_CLASS(x) E_ICON_LIST_CLASS(x) -#define IS_EIL(x) E_IS_ICON_LIST(x) - -typedef EIconList Eil; -typedef EIconListClass EilClass; - - -/* default spacings */ -#define DEFAULT_ROW_SPACING 4 -#define DEFAULT_COL_SPACING 2 -#define DEFAULT_TEXT_SPACING 2 -#define DEFAULT_ICON_BORDER 2 - -/* Autoscroll timeout in milliseconds */ -#define SCROLL_TIMEOUT 30 - - -/* Signals */ -enum { - SELECT_ICON, - UNSELECT_ICON, - TEXT_CHANGED, - LAST_SIGNAL -}; - -typedef enum { - SYNC_INSERT, - SYNC_REMOVE -} SyncType; - -enum { - ARG_0, -}; - -static guint eil_signals[LAST_SIGNAL] = { 0 }; - - -static GnomeCanvasClass *parent_class; - - -/* Icon structure */ -typedef struct { - /* Icon image and text items */ - GnomeCanvasPixbuf *image; - GnomeIconTextItem *text; - - /* Filename of the icon file. */ - gchar *icon_filename; - - /* User data and destroy notify function */ - gpointer data; - GtkDestroyNotify destroy; - - /* ID for the text item's event signal handler */ - guint text_event_id; - - /* Whether the icon is selected, and temporary storage for rubberband - * selections. - */ - guint selected : 1; - guint tmp_selected : 1; -} Icon; - -/* A row of icons */ -typedef struct { - GList *line_icons; - gint16 y; - gint16 icon_height, text_height; -} IconLine; - -/* Private data of the EIconList structure */ -struct _EIconListPrivate { - /* List of icons */ - GArray *icon_list; - - /* List of rows of icons */ - GList *lines; - - /* Separators used to wrap the text below icons */ - char *separators; - - Icon *last_selected_icon; - - /* Rubberband rectangle */ - GnomeCanvasItem *sel_rect; - - /* Saved event for a pending selection */ - GdkEvent select_pending_event; - - /* Max of the height of all the icon rows and window height */ - int total_height; - - /* Selection mode */ - GtkSelectionMode selection_mode; - - /* A list of integers with the indices of the currently selected icons */ - GList *selection; - - /* Number of icons in the list */ - int icons; - - /* Freeze count */ - int frozen; - - /* Width allocated for icons */ - int icon_width; - - /* Spacing values */ - int row_spacing; - int col_spacing; - int text_spacing; - int icon_border; - - /* Index and pointer to last selected icon */ - int last_selected_idx; - - /* Timeout ID for autoscrolling */ - guint timer_tag; - - /* Change the adjustment value by this amount when autoscrolling */ - int value_diff; - - /* Mouse position for autoscrolling */ - int event_last_x; - int event_last_y; - - /* Selection start position */ - int sel_start_x; - int sel_start_y; - - /* Modifier state when the selection began */ - guint sel_state; - - /* Whether the icon texts are editable */ - guint is_editable : 1; - - /* Whether the icon texts need to be copied */ - guint static_text : 1; - - /* Whether the icons need to be laid out */ - guint dirty : 1; - - /* Whether the user is performing a rubberband selection */ - guint selecting : 1; - - /* Whether editing an icon is pending after a button press */ - guint edit_pending : 1; - - /* Whether selection is pending after a button press */ - guint select_pending : 1; - - /* Whether the icon that is pending selection was selected to begin with */ - guint select_pending_was_selected : 1; -}; - - -static inline int -icon_line_height (Eil *eil, IconLine *il) -{ - EIconListPrivate *priv; - - priv = eil->_priv; - - return il->icon_height + il->text_height + priv->row_spacing + priv->text_spacing; -} - -static void -icon_get_height (Icon *icon, int *icon_height, int *text_height) -{ - double d_icon_height; - gtk_object_get(GTK_OBJECT(icon->image), "height", &d_icon_height, NULL); - *icon_height = d_icon_height; - *text_height = icon->text->ti->height; -} - -static int -eil_get_items_per_line (Eil *eil) -{ - EIconListPrivate *priv; - int items_per_line; - - priv = eil->_priv; - - items_per_line = GTK_WIDGET (eil)->allocation.width / (priv->icon_width + priv->col_spacing); - if (items_per_line == 0) - items_per_line = 1; - - return items_per_line; -} - -/** - * e_icon_list_get_items_per_line: - * @eil: An icon list. - * - * Returns the number of icons that fit in a line or row. - */ -int -e_icon_list_get_items_per_line (EIconList *eil) -{ - g_return_val_if_fail (eil != NULL, 1); - g_return_val_if_fail (IS_EIL (eil), 1); - - return eil_get_items_per_line (eil); -} - -static void -eil_place_icon (Eil *eil, Icon *icon, int x, int y, int icon_height) -{ - EIconListPrivate *priv; - int x_offset, y_offset; - double d_icon_image_height; - double d_icon_image_width; - int icon_image_height; - int icon_image_width; - - priv = eil->_priv; - - gtk_object_get(GTK_OBJECT(icon->image), "height", &d_icon_image_height, NULL); - icon_image_height = d_icon_image_height; - g_assert(icon_image_height != 0); - if (icon_height > icon_image_height) - y_offset = (icon_height - icon_image_height) / 2; - else - y_offset = 0; - - gtk_object_get(GTK_OBJECT(icon->image), "width", &d_icon_image_width, NULL); - icon_image_width = d_icon_image_width; - g_assert(icon_image_width != 0); - if (priv->icon_width > icon_image_width) - x_offset = (priv->icon_width - icon_image_width) / 2; - else - x_offset = 0; - - gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->image), - "x", (double) (x + x_offset), - "y", (double) (y + y_offset), - NULL); - gnome_icon_text_item_setxy (icon->text, - x, - y + icon_height + priv->text_spacing); -} - -static void -eil_layout_line (Eil *eil, IconLine *il) -{ - EIconListPrivate *priv; - GList *l; - int x; - - priv = eil->_priv; - - x = 0; - for (l = il->line_icons; l; l = l->next) { - Icon *icon = l->data; - - eil_place_icon (eil, icon, x, il->y, il->icon_height); - x += priv->icon_width + priv->col_spacing; - } -} - -static void -eil_add_and_layout_line (Eil *eil, GList *line_icons, int y, - int icon_height, int text_height) -{ - EIconListPrivate *priv; - IconLine *il; - - priv = eil->_priv; - - il = g_new (IconLine, 1); - il->line_icons = line_icons; - il->y = y; - il->icon_height = icon_height; - il->text_height = text_height; - - eil_layout_line (eil, il); - priv->lines = g_list_append (priv->lines, il); -} - -static void -eil_relayout_icons_at (Eil *eil, int pos, int y) -{ - EIconListPrivate *priv; - int col, row, text_height, icon_height; - int items_per_line, n; - GList *line_icons; - - priv = eil->_priv; - items_per_line = eil_get_items_per_line (eil); - - col = row = text_height = icon_height = 0; - line_icons = NULL; - - for (n = pos; n < priv->icon_list->len; n++) { - Icon *icon = g_array_index(priv->icon_list, Icon*, n); - int ih, th; - - if (!(n % items_per_line)) { - if (line_icons) { - eil_add_and_layout_line (eil, line_icons, y, - icon_height, text_height); - line_icons = NULL; - - y += (icon_height + text_height - + priv->row_spacing + priv->text_spacing); - } - - icon_height = 0; - text_height = 0; - } - - icon_get_height (icon, &ih, &th); - - icon_height = MAX (ih, icon_height); - text_height = MAX (th, text_height); - - line_icons = g_list_append (line_icons, icon); - } - - if (line_icons) - eil_add_and_layout_line (eil, line_icons, y, icon_height, text_height); -} - -static void -eil_free_line_info (Eil *eil) -{ - EIconListPrivate *priv; - GList *l; - - priv = eil->_priv; - - for (l = priv->lines; l; l = l->next) { - IconLine *il = l->data; - - g_list_free (il->line_icons); - g_free (il); - } - - g_list_free (priv->lines); - priv->lines = NULL; - priv->total_height = 0; -} - -static void -eil_free_line_info_from (Eil *eil, int first_line) -{ - EIconListPrivate *priv; - GList *l, *ll; - - priv = eil->_priv; - ll = g_list_nth (priv->lines, first_line); - - for (l = ll; l; l = l->next) { - IconLine *il = l->data; - - g_list_free (il->line_icons); - g_free (il); - } - - if (priv->lines) { - if (ll->prev) - ll->prev->next = NULL; - else - priv->lines = NULL; - } - - g_list_free (ll); -} - -static void -eil_layout_from_line (Eil *eil, int line) -{ - EIconListPrivate *priv; - GList *l; - int height; - - priv = eil->_priv; - - eil_free_line_info_from (eil, line); - - height = 0; - for (l = priv->lines; l; l = l->next) { - IconLine *il = l->data; - - height += icon_line_height (eil, il); - } - - eil_relayout_icons_at (eil, line * eil_get_items_per_line (eil), height); -} - -static void -eil_layout_all_icons (Eil *eil) -{ - EIconListPrivate *priv; - - priv = eil->_priv; - - if (!GTK_WIDGET_REALIZED (eil)) - return; - - eil_free_line_info (eil); - eil_relayout_icons_at (eil, 0, 0); - priv->dirty = FALSE; -} - -static void -eil_scrollbar_adjust (Eil *eil) -{ - EIconListPrivate *priv; - GtkAdjustment *adj; - GList *l; - double wx, wy, wx1, wy1, wx2, wy2; - int height, step_increment; - - priv = eil->_priv; - - if (!GTK_WIDGET_REALIZED (eil)) - return; - - height = 0; - step_increment = 0; - for (l = priv->lines; l; l = l->next) { - IconLine *il = l->data; - - height += icon_line_height (eil, il); - - if (l == priv->lines) - step_increment = height; - } - - if (!step_increment) - step_increment = 10; - - priv->total_height = MAX (height, GTK_WIDGET (eil)->allocation.height); - - gnome_canvas_c2w (GNOME_CANVAS (eil), 0, 0, &wx1, &wy1); - gnome_canvas_c2w (GNOME_CANVAS (eil), - GTK_WIDGET (eil)->allocation.width, - priv->total_height, - &wx2, &wy2); - - gnome_canvas_set_scroll_region (GNOME_CANVAS (eil), - wx1, wy1, wx2, wy2); - - wx = wy = 0; - gnome_canvas_window_to_world (GNOME_CANVAS (eil), 0, 0, &wx, &wy); - - adj = gtk_layout_get_vadjustment (GTK_LAYOUT (eil)); - - adj->upper = priv->total_height; - adj->step_increment = step_increment; - adj->page_increment = GTK_WIDGET (eil)->allocation.height; - adj->page_size = GTK_WIDGET (eil)->allocation.height; - - if (wy > adj->upper - adj->page_size) - wy = adj->upper - adj->page_size; - - adj->value = wy; - - gtk_adjustment_changed (adj); -} - -/* Emits the select_icon or unselect_icon signals as appropriate */ -static void -emit_select (Eil *eil, int sel, int i, GdkEvent *event) -{ - gtk_signal_emit (GTK_OBJECT (eil), - eil_signals[sel ? SELECT_ICON : UNSELECT_ICON], - i, - event); -} - -static int -eil_unselect_all (EIconList *eil, GdkEvent *event, gpointer keep) -{ - EIconListPrivate *priv; - Icon *icon; - int i, idx = 0; - - g_return_val_if_fail (eil != NULL, 0); - g_return_val_if_fail (IS_EIL (eil), 0); - - priv = eil->_priv; - - for (i = 0; i < priv->icon_list->len; i++) { - icon = g_array_index(priv->icon_list, Icon*, i); - - if (icon == keep) - idx = i; - else if (icon->selected) - emit_select (eil, FALSE, i, event); - } - - return idx; -} - -/** - * e_icon_list_unselect_all: - * @eil: An icon list. - * - * Returns: the number of icons in the icon list - */ -int -e_icon_list_unselect_all (EIconList *eil) -{ - return eil_unselect_all (eil, NULL, NULL); -} - -static void -sync_selection (Eil *eil, int pos, SyncType type) -{ - GList *list; - - for (list = eil->_priv->selection; list; list = list->next) { - if (GPOINTER_TO_INT (list->data) >= pos) { - int i = GPOINTER_TO_INT (list->data); - - switch (type) { - case SYNC_INSERT: - list->data = GINT_TO_POINTER (i + 1); - break; - - case SYNC_REMOVE: - list->data = GINT_TO_POINTER (i - 1); - break; - - default: - g_assert_not_reached (); - } - } - } -} - -static int -eil_icon_to_index (Eil *eil, Icon *icon) -{ - EIconListPrivate *priv; - int n; - - priv = eil->_priv; - - for (n = 0; n < priv->icon_list->len; n++) - if (g_array_index(priv->icon_list, Icon*, n) == icon) - return n; - - g_assert_not_reached (); - return -1; /* Shut up the compiler */ -} - -/* Event handler for icons when we are in SINGLE or BROWSE mode */ -static gint -selection_one_icon_event (Eil *eil, Icon *icon, int idx, int on_text, GdkEvent *event) -{ - EIconListPrivate *priv; - GnomeIconTextItem *text; - int retval; - - priv = eil->_priv; - retval = FALSE; - - /* We use a separate variable and ref the object because it may be - * destroyed by one of the signal handlers. - */ - text = icon->text; - gtk_object_ref (GTK_OBJECT (text)); - - switch (event->type) { - case GDK_BUTTON_PRESS: - priv->edit_pending = FALSE; - priv->select_pending = FALSE; - - /* Ignore wheel mouse clicks for now */ - if (event->button.button > 3) - break; - - if (!icon->selected) { - eil_unselect_all (eil, NULL, NULL); - emit_select (eil, TRUE, idx, event); - } else { - if (priv->selection_mode == GTK_SELECTION_SINGLE - && (event->button.state & GDK_CONTROL_MASK)) - emit_select (eil, FALSE, idx, event); - else if (on_text && priv->is_editable && event->button.button == 1) - priv->edit_pending = TRUE; - else - emit_select (eil, TRUE, idx, event); - } - - retval = TRUE; - break; - - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - /* Ignore wheel mouse clicks for now */ - if (event->button.button > 3) - break; - - emit_select (eil, TRUE, idx, event); - retval = TRUE; - break; - - case GDK_BUTTON_RELEASE: - if (priv->edit_pending) { - gnome_icon_text_item_start_editing (text); - priv->edit_pending = FALSE; - } - - retval = TRUE; - break; - - default: - break; - } - - /* If the click was on the text and we actually did something, stop the - * icon text item's own handler from executing. - */ - if (on_text && retval) - gtk_signal_emit_stop_by_name (GTK_OBJECT (text), "event"); - - gtk_object_unref (GTK_OBJECT (text)); - - return retval; -} - -/* Handles range selections when clicking on an icon */ -static void -select_range (Eil *eil, Icon *icon, int idx, GdkEvent *event) -{ - EIconListPrivate *priv; - int a, b; - Icon *i; - - priv = eil->_priv; - - if (priv->last_selected_idx == -1) { - priv->last_selected_idx = idx; - priv->last_selected_icon = icon; - } - - if (idx < priv->last_selected_idx) { - a = idx; - b = priv->last_selected_idx; - } else { - a = priv->last_selected_idx; - b = idx; - } - - for (; a <= b; a++) { - i = g_array_index(priv->icon_list, Icon*, a); - - if (!i->selected) - emit_select (eil, TRUE, a, NULL); - } - - /* Actually notify the client of the event */ - emit_select (eil, TRUE, idx, event); -} - -/* Handles icon selection for MULTIPLE or EXTENDED selection modes */ -static void -do_select_many (Eil *eil, Icon *icon, int idx, GdkEvent *event, int use_event) -{ - EIconListPrivate *priv; - int range, additive; - - priv = eil->_priv; - - range = (event->button.state & GDK_SHIFT_MASK) != 0; - additive = (event->button.state & GDK_CONTROL_MASK) != 0; - - if (!additive) { - if (icon->selected) - eil_unselect_all (eil, NULL, icon); - else - eil_unselect_all (eil, NULL, NULL); - } - - if (!range) { - if (additive) - emit_select (eil, !icon->selected, idx, use_event ? event : NULL); - else - emit_select (eil, TRUE, idx, use_event ? event : NULL); - - priv->last_selected_idx = idx; - priv->last_selected_icon = icon; - } else - select_range (eil, icon, idx, use_event ? event : NULL); -} - -/* Event handler for icons when we are in MULTIPLE or EXTENDED mode */ -static gint -selection_many_icon_event (Eil *eil, Icon *icon, int idx, int on_text, GdkEvent *event) -{ - EIconListPrivate *priv; - GnomeIconTextItem *text; - int retval; - int additive, range; - int do_select; - - priv = eil->_priv; - retval = FALSE; - - /* We use a separate variable and ref the object because it may be - * destroyed by one of the signal handlers. - */ - text = icon->text; - gtk_object_ref (GTK_OBJECT (text)); - - range = (event->button.state & GDK_SHIFT_MASK) != 0; - additive = (event->button.state & GDK_CONTROL_MASK) != 0; - - switch (event->type) { - case GDK_BUTTON_PRESS: - priv->edit_pending = FALSE; - priv->select_pending = FALSE; - - /* Ignore wheel mouse clicks for now */ - if (event->button.button > 3) - break; - - do_select = TRUE; - - if (additive || range) { - if (additive && !range) { - priv->select_pending = TRUE; - priv->select_pending_event = *event; - priv->select_pending_was_selected = icon->selected; - - /* We have to emit this so that the client will - * know about the click. - */ - emit_select (eil, TRUE, idx, event); - do_select = FALSE; - } - } else if (icon->selected) { - priv->select_pending = TRUE; - priv->select_pending_event = *event; - priv->select_pending_was_selected = icon->selected; - - if (on_text && priv->is_editable && event->button.button == 1) - priv->edit_pending = TRUE; - - emit_select (eil, TRUE, idx, event); - do_select = FALSE; - } -#if 0 - } else if (icon->selected && on_text && priv->is_editable - && event->button.button == 1) { - priv->edit_pending = TRUE; - do_select = FALSE; - } -#endif - - if (do_select) - do_select_many (eil, icon, idx, event, TRUE); - - retval = TRUE; - break; - - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - /* Ignore wheel mouse clicks for now */ - if (event->button.button > 3) - break; - - emit_select (eil, TRUE, idx, event); - retval = TRUE; - break; - - case GDK_BUTTON_RELEASE: - if (priv->select_pending) { - icon->selected = priv->select_pending_was_selected; - do_select_many (eil, icon, idx, &priv->select_pending_event, FALSE); - priv->select_pending = FALSE; - retval = TRUE; - } - - if (priv->edit_pending) { - gnome_icon_text_item_start_editing (text); - priv->edit_pending = FALSE; - retval = TRUE; - } -#if 0 - if (priv->select_pending) { - icon->selected = priv->select_pending_was_selected; - do_select_many (eil, icon, idx, &priv->select_pending_event); - priv->select_pending = FALSE; - retval = TRUE; - } else if (priv->edit_pending) { - gnome_icon_text_item_start_editing (text); - priv->edit_pending = FALSE; - retval = TRUE; - } -#endif - - break; - - default: - break; - } - - /* If the click was on the text and we actually did something, stop the - * icon text item's own handler from executing. - */ - if (on_text && retval) - gtk_signal_emit_stop_by_name (GTK_OBJECT (text), "event"); - - gtk_object_unref (GTK_OBJECT (text)); - - return retval; -} - -/* Event handler for icons in the icon list */ -static gint -icon_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data) -{ - Icon *icon; - Eil *eil; - EIconListPrivate *priv; - int idx; - int on_text; - - icon = data; - eil = EIL (item->canvas); - priv = eil->_priv; - idx = eil_icon_to_index (eil, icon); - on_text = item == GNOME_CANVAS_ITEM (icon->text); - - switch (priv->selection_mode) { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_BROWSE: - return selection_one_icon_event (eil, icon, idx, on_text, event); - - case GTK_SELECTION_MULTIPLE: - case GTK_SELECTION_EXTENDED: - return selection_many_icon_event (eil, icon, idx, on_text, event); - - default: - g_assert_not_reached (); - return FALSE; /* Shut up the compiler */ - } -} - -/* Handler for the editing_started signal of an icon text item. We block the - * event handler so that it will not be called while the text is being edited. - */ -static void -editing_started (GnomeIconTextItem *iti, gpointer data) -{ - Icon *icon; - - icon = data; - gtk_signal_handler_block (GTK_OBJECT (iti), icon->text_event_id); - eil_unselect_all (EIL (GNOME_CANVAS_ITEM (iti)->canvas), NULL, icon); -} - -/* Handler for the editing_stopped signal of an icon text item. We unblock the - * event handler so that we can get events from it again. - */ -static void -editing_stopped (GnomeIconTextItem *iti, gpointer data) -{ - Icon *icon; - - icon = data; - gtk_signal_handler_unblock (GTK_OBJECT (iti), icon->text_event_id); -} - -static gboolean -text_changed (GnomeCanvasItem *item, Icon *icon) -{ - Eil *eil; - gboolean accept; - int idx; - - eil = EIL (item->canvas); - accept = TRUE; - - idx = eil_icon_to_index (eil, icon); - gtk_signal_emit (GTK_OBJECT (eil), - eil_signals[TEXT_CHANGED], - idx, gnome_icon_text_item_get_text (icon->text), - &accept); - - return accept; -} - -static void -height_changed (GnomeCanvasItem *item, Icon *icon) -{ - Eil *eil; - EIconListPrivate *priv; - int n; - - eil = EIL (item->canvas); - priv = eil->_priv; - - if (!GTK_WIDGET_REALIZED (eil)) - return; - - if (priv->frozen) { - priv->dirty = TRUE; - return; - } - - n = eil_icon_to_index (eil, icon); - eil_layout_from_line (eil, n / eil_get_items_per_line (eil)); - eil_scrollbar_adjust (eil); -} - -static Icon * -icon_new_from_pixbuf (EIconList *eil, GdkPixbuf *im, - const char *icon_filename, const char *text) -{ - EIconListPrivate *priv; - GnomeCanvas *canvas; - GnomeCanvasGroup *group; - Icon *icon; - - priv = eil->_priv; - canvas = GNOME_CANVAS (eil); - group = GNOME_CANVAS_GROUP (canvas->root); - - icon = g_new0 (Icon, 1); - - if (icon_filename) - icon->icon_filename = g_strdup (icon_filename); - else - icon->icon_filename = NULL; - - if (im == NULL) - im = gdk_pixbuf_new_from_xpm_data ((const char**) bad_icon_xpm); - else - gdk_pixbuf_ref (im); - - icon->image = GNOME_CANVAS_PIXBUF (gnome_canvas_item_new ( - group, - gnome_canvas_pixbuf_get_type (), - "x", 0.0, - "y", 0.0, - "width", (double) gdk_pixbuf_get_width (im), - "height", (double) gdk_pixbuf_get_height (im), - "pixbuf", im, - NULL)); - gdk_pixbuf_unref (im); - - icon->text = GNOME_ICON_TEXT_ITEM (gnome_canvas_item_new ( - group, - gnome_icon_text_item_get_type (), - NULL)); - - gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->text), - "use_broken_event_handling", FALSE, - NULL); - - /* FIXME: should this use a selectable font?? */ -#warning "Ettore: should we allow this font to be selectable??" - gnome_icon_text_item_configure (icon->text, - 0, 0, priv->icon_width, - "-adobe-helvetica-medium-r-normal-*-*-120-*-*-p-*-iso8859-1", - text, priv->is_editable, priv->static_text); - - gtk_signal_connect (GTK_OBJECT (icon->image), "event", - GTK_SIGNAL_FUNC (icon_event), - icon); - icon->text_event_id = gtk_signal_connect (GTK_OBJECT (icon->text), "event", - GTK_SIGNAL_FUNC (icon_event), - icon); - - gtk_signal_connect (GTK_OBJECT (icon->text), "editing_started", - GTK_SIGNAL_FUNC (editing_started), - icon); - gtk_signal_connect (GTK_OBJECT (icon->text), "editing_stopped", - GTK_SIGNAL_FUNC (editing_stopped), - icon); - - gtk_signal_connect (GTK_OBJECT (icon->text), "text_changed", - GTK_SIGNAL_FUNC (text_changed), - icon); - gtk_signal_connect (GTK_OBJECT (icon->text), "height_changed", - GTK_SIGNAL_FUNC (height_changed), - icon); - - return icon; -} - -static Icon * -icon_new (Eil *eil, const char *icon_filename, const char *text) -{ - GdkPixbuf *im; - Icon *retval; - - if (icon_filename) { - im = gdk_pixbuf_new_from_file (icon_filename); - - /* Bad icon image - Fixme. Need a better graphic. */ - if (im == NULL) - im = gdk_pixbuf_new_from_xpm_data ((const char**) bad_icon_xpm); - } else - im = NULL; - - retval = icon_new_from_pixbuf (eil, im, icon_filename, text); - - if(im) - gdk_pixbuf_unref(im); - - return retval; -} - -static int -icon_list_append (Eil *eil, Icon *icon) -{ - EIconListPrivate *priv; - int pos; - - priv = eil->_priv; - - pos = priv->icons++; - g_array_append_val(priv->icon_list, icon); - - switch (priv->selection_mode) { - case GTK_SELECTION_BROWSE: - e_icon_list_select_icon (eil, 0); - break; - - default: - break; - } - - if (!priv->frozen) { - /* FIXME: this should only layout the last line */ - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } else - priv->dirty = TRUE; - - return priv->icons - 1; -} - -static void -icon_list_insert (Eil *eil, int pos, Icon *icon) -{ - EIconListPrivate *priv; - - priv = eil->_priv; - - if (pos == priv->icons) { - icon_list_append (eil, icon); - return; - } - - g_array_insert_val(priv->icon_list, pos, icon); - priv->icons++; - - switch (priv->selection_mode) { - case GTK_SELECTION_BROWSE: - e_icon_list_select_icon (eil, 0); - break; - - default: - break; - } - - if (!priv->frozen) { - /* FIXME: this should only layout the lines from then one - * containing the Icon to the end. - */ - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } else - priv->dirty = TRUE; - - sync_selection (eil, pos, SYNC_INSERT); -} - -/** - * e_icon_list_insert_pixbuf: - * @eil: An icon list. - * @pos: Position at which the new icon should be inserted. - * @im: Pixbuf image with the icon image. - * @filename: Filename of the image file. - * @text: Text to be used for the icon's caption. - * - * Inserts an icon in the specified icon list. The icon is created from the - * specified Imlib image, and it is inserted at the @pos index. - */ -void -e_icon_list_insert_pixbuf (EIconList *eil, int pos, GdkPixbuf *im, - const char *icon_filename, const char *text) -{ - Icon *icon; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - icon = icon_new_from_pixbuf (eil, im, icon_filename, text); - icon_list_insert (eil, pos, icon); - return; -} - -/** - * e_icon_list_insert: - * @eil: An icon list. - * @pos: Position at which the new icon should be inserted. - * @icon_filename: Name of the file that holds the icon's image. - * @text: Text to be used for the icon's caption. - * - * Inserts an icon in the specified icon list. The icon's image is loaded - * from the specified file, and it is inserted at the @pos index. - */ -void -e_icon_list_insert (EIconList *eil, int pos, const char *icon_filename, const char *text) -{ - Icon *icon; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - icon = icon_new (eil, icon_filename, text); - icon_list_insert (eil, pos, icon); - return; -} - -/** - * e_icon_list_append_pixbuf: - * @eil: An icon list. - * @im: Pixbuf image with the icon image. - * @filename: Filename of the image file. - * @text: Text to be used for the icon's caption. - * - * Appends an icon to the specified icon list. The icon is created from - * the specified Imlib image. - */ -int -e_icon_list_append_pixbuf (EIconList *eil, GdkPixbuf *im, - const char *icon_filename, const char *text) -{ - Icon *icon; - - g_return_val_if_fail (eil != NULL, -1); - g_return_val_if_fail (IS_EIL (eil), -1); - - icon = icon_new_from_pixbuf (eil, im, icon_filename, text); - return icon_list_append (eil, icon); -} - -/** - * e_icon_list_append: - * @eil: An icon list. - * @icon_filename: Name of the file that holds the icon's image. - * @text: Text to be used for the icon's caption. - * - * Appends an icon to the specified icon list. The icon's image is loaded from - * the specified file, and it is inserted at the @pos index. - */ -int -e_icon_list_append (EIconList *eil, const char *icon_filename, - const char *text) -{ - Icon *icon; - - g_return_val_if_fail (eil != NULL, -1); - g_return_val_if_fail (IS_EIL (eil), -1); - - icon = icon_new (eil, icon_filename, text); - return icon_list_append (eil, icon); -} - -static void -icon_destroy (Icon *icon) -{ - if (icon->destroy) - (* icon->destroy) (icon->data); - - g_free (icon->icon_filename); - - gtk_object_destroy (GTK_OBJECT (icon->image)); - gtk_object_destroy (GTK_OBJECT (icon->text)); - g_free (icon); -} - -/** - * e_icon_list_remove: - * @eil: An icon list. - * @pos: Index of the icon that should be removed. - * - * Removes the icon at index position @pos. If a destroy handler was specified - * for that icon, it will be called with the appropriate data. - */ -void -e_icon_list_remove (EIconList *eil, int pos) -{ - EIconListPrivate *priv; - int was_selected; - Icon *icon; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (pos >= 0 && pos < eil->_priv->icons); - - priv = eil->_priv; - - was_selected = FALSE; - - icon = g_array_index(priv->icon_list, Icon*, pos); - - if (icon->selected) { - was_selected = TRUE; - - switch (priv->selection_mode) { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_BROWSE: - case GTK_SELECTION_MULTIPLE: - case GTK_SELECTION_EXTENDED: - e_icon_list_unselect_icon (eil, pos); - break; - - default: - break; - } - } - - g_array_remove_index(priv->icon_list, pos); - priv->icons--; - - sync_selection (eil, pos, SYNC_REMOVE); - - if (was_selected) { - switch (priv->selection_mode) { - case GTK_SELECTION_BROWSE: - if (pos == priv->icons) - e_icon_list_select_icon (eil, pos - 1); - else - e_icon_list_select_icon (eil, pos); - - break; - - default: - break; - } - } - - if (priv->icons >= priv->last_selected_idx) - priv->last_selected_idx = -1; - - if (priv->last_selected_icon == icon) - priv->last_selected_icon = NULL; - - icon_destroy (icon); - - if (!priv->frozen) { - /* FIXME: Optimize, only re-layout from pos to end */ - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } else - priv->dirty = TRUE; -} - -/** - * e_icon_list_clear: - * @eil: An icon list. - * - * Clears the contents for the icon list by removing all the icons. If destroy - * handlers were specified for any of the icons, they will be called with the - * appropriate data. - */ -void -e_icon_list_clear (EIconList *eil) -{ - EIconListPrivate *priv; - int i; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - - for (i = 0; i < priv->icon_list->len; i++) - icon_destroy (g_array_index (priv->icon_list, Icon*, i)); - - eil_free_line_info (eil); - - g_list_free (priv->selection); - priv->selection = NULL; - g_array_set_size(priv->icon_list, 0); - priv->icons = 0; - priv->last_selected_idx = -1; - priv->last_selected_icon = NULL; - - if (!priv->frozen) { - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } else - priv->dirty = TRUE; -} - -static void -eil_destroy (GtkObject *object) -{ - Eil *eil; - - /* remember, destroy can be run multiple times! */ - - eil = EIL (object); - - g_free (eil->_priv->separators); - eil->_priv->separators = NULL; - - eil->_priv->frozen = 1; - eil->_priv->dirty = TRUE; - if(eil->_priv->icon_list) { - e_icon_list_clear (eil); - g_array_free(eil->_priv->icon_list, TRUE); - } - eil->_priv->icon_list = NULL; - - if (eil->_priv->timer_tag != 0) { - gtk_timeout_remove (eil->_priv->timer_tag); - eil->_priv->timer_tag = 0; - } - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (*GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - -static void -eil_finalize (GtkObject *object) -{ - Eil *eil; - - eil = EIL (object); - - g_free (eil->_priv); - eil->_priv = NULL; - - if (GTK_OBJECT_CLASS (parent_class)->finalize) - (*GTK_OBJECT_CLASS (parent_class)->finalize) (object); -} - - -static void -select_icon (Eil *eil, int pos, GdkEvent *event) -{ - EIconListPrivate *priv; - gint i; - Icon *icon; - - priv = eil->_priv; - - switch (priv->selection_mode) { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_BROWSE: - i = 0; - - for (i = 0; i < priv->icon_list->len; i++) { - icon = g_array_index (priv->icon_list, Icon*, i); - - if (i != pos && icon->selected) - emit_select (eil, FALSE, i, event); - } - - emit_select (eil, TRUE, pos, event); - break; - - case GTK_SELECTION_MULTIPLE: - case GTK_SELECTION_EXTENDED: - emit_select (eil, TRUE, pos, event); - break; - - default: - break; - } -} - -/** - * e_icon_list_select_icon: - * @eil: An icon list. - * @pos: Index of the icon to be selected. - * - * Selects the icon at the index specified by @pos. - */ -void -e_icon_list_select_icon (EIconList *eil, int pos) -{ - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (pos >= 0 && pos < eil->_priv->icons); - - select_icon (eil, pos, NULL); -} - -static void -unselect_icon (Eil *eil, int pos, GdkEvent *event) -{ - EIconListPrivate *priv; - - priv = eil->_priv; - - switch (priv->selection_mode) { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_BROWSE: - case GTK_SELECTION_MULTIPLE: - case GTK_SELECTION_EXTENDED: - emit_select (eil, FALSE, pos, event); - break; - - default: - break; - } -} - -/** - * e_icon_list_unselect_icon: - * @eil: An icon list. - * @pos: Index of the icon to be unselected. - * - * Unselects the icon at the index specified by @pos. - */ -void -e_icon_list_unselect_icon (EIconList *eil, int pos) -{ - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (pos >= 0 && pos < eil->_priv->icons); - - unselect_icon (eil, pos, NULL); -} - -static void -eil_size_request (GtkWidget *widget, GtkRequisition *requisition) -{ - requisition->width = 1; - requisition->height = 1; -} - -static void -eil_size_allocate (GtkWidget *widget, GtkAllocation *allocation) -{ - Eil *eil; - EIconListPrivate *priv; - - eil = EIL (widget); - priv = eil->_priv; - - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - (* GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation); - - if (priv->frozen) - return; - - eil_layout_all_icons (eil); -} - -static void -eil_realize (GtkWidget *widget) -{ - Eil *eil; - EIconListPrivate *priv; - GtkStyle *style; - - eil = EIL (widget); - priv = eil->_priv; - - priv->frozen++; - - if (GTK_WIDGET_CLASS (parent_class)->realize) - (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); - - priv->frozen--; - - /* Change the style to use the base color as the background */ - - style = gtk_style_copy (gtk_widget_get_style (widget)); - style->bg[GTK_STATE_NORMAL] = style->base[GTK_STATE_NORMAL]; - gtk_widget_set_style (widget, style); - - gdk_window_set_background (GTK_LAYOUT (eil)->bin_window, - &widget->style->bg[GTK_STATE_NORMAL]); - - if (priv->frozen) - return; - - if (priv->dirty) { - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } -} - -static void -real_select_icon (Eil *eil, gint num, GdkEvent *event) -{ - EIconListPrivate *priv; - Icon *icon; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (num >= 0 && num < eil->_priv->icons); - - priv = eil->_priv; - - icon = g_array_index (priv->icon_list, Icon*, num); - - if (icon->selected) - return; - - icon->selected = TRUE; - gnome_icon_text_item_select (icon->text, TRUE); - priv->selection = g_list_append (priv->selection, GINT_TO_POINTER (num)); -} - -static void -real_unselect_icon (Eil *eil, gint num, GdkEvent *event) -{ - EIconListPrivate *priv; - Icon *icon; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (num >= 0 && num < eil->_priv->icons); - - priv = eil->_priv; - - icon = g_array_index (priv->icon_list, Icon*, num); - - if (!icon->selected) - return; - - icon->selected = FALSE; - gnome_icon_text_item_select (icon->text, FALSE); - priv->selection = g_list_remove (priv->selection, GINT_TO_POINTER (num)); -} - -/* Saves the selection of the icon list to temporary storage */ -static void -store_temp_selection (Eil *eil) -{ - EIconListPrivate *priv; - int i; - Icon *icon; - - priv = eil->_priv; - - for (i = 0; i < priv->icon_list->len; i++) { - icon = g_array_index(priv->icon_list, Icon*, i); - - icon->tmp_selected = icon->selected; - } -} - -#define gray50_width 2 -#define gray50_height 2 -static const char gray50_bits[] = { - 0x02, 0x01, }; - -/* Button press handler for the icon list */ -static gint -eil_button_press (GtkWidget *widget, GdkEventButton *event) -{ - Eil *eil; - EIconListPrivate *priv; - int only_one; - GdkBitmap *stipple; - double tx, ty; - - eil = EIL (widget); - priv = eil->_priv; - - /* Invoke the canvas event handler and see if an item picks up the event */ - - if ((* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event)) - return TRUE; - - if (!(event->type == GDK_BUTTON_PRESS - && event->button == 1 - && priv->selection_mode != GTK_SELECTION_BROWSE)) - return FALSE; - - only_one = priv->selection_mode == GTK_SELECTION_SINGLE; - - if (only_one || (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) == 0) - eil_unselect_all (eil, NULL, NULL); - - if (only_one) - return TRUE; - - if (priv->selecting) - return FALSE; - - gnome_canvas_window_to_world (GNOME_CANVAS (eil), event->x, event->y, &tx, &ty); - priv->sel_start_x = tx; - priv->sel_start_y = ty; - priv->sel_state = event->state; - priv->selecting = TRUE; - - store_temp_selection (eil); - - stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height); - priv->sel_rect = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (eil)), - gnome_canvas_rect_get_type (), - "x1", tx, - "y1", ty, - "x2", tx, - "y2", ty, - "outline_color", "black", - "width_pixels", 1, - "outline_stipple", stipple, - NULL); - gdk_bitmap_unref (stipple); - - gnome_canvas_item_grab (priv->sel_rect, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - NULL, event->time); - - return TRUE; -} - -/* Returns whether the specified icon is at least partially inside the specified - * rectangle. - */ -static int -icon_is_in_area (Icon *icon, int x1, int y1, int x2, int y2) -{ - double ix1, iy1, ix2, iy2; - - if (x1 == x2 && y1 == y2) - return FALSE; - - gnome_canvas_item_get_bounds (GNOME_CANVAS_ITEM (icon->image), &ix1, &iy1, &ix2, &iy2); - - if (ix1 <= x2 && iy1 <= y2 && ix2 >= x1 && iy2 >= y1) - return TRUE; - - gnome_canvas_item_get_bounds (GNOME_CANVAS_ITEM (icon->text), &ix1, &iy1, &ix2, &iy2); - - if (ix1 <= x2 && iy1 <= y2 && ix2 >= x1 && iy2 >= y1) - return TRUE; - - return FALSE; -} - -/* Updates the rubberband selection to the specified point */ -static void -update_drag_selection (Eil *eil, int x, int y) -{ - EIconListPrivate *priv; - int x1, x2, y1, y2; - int i; - Icon *icon; - int additive, invert; - - priv = eil->_priv; - - /* Update rubberband */ - - if (priv->sel_start_x < x) { - x1 = priv->sel_start_x; - x2 = x; - } else { - x1 = x; - x2 = priv->sel_start_x; - } - - if (priv->sel_start_y < y) { - y1 = priv->sel_start_y; - y2 = y; - } else { - y1 = y; - y2 = priv->sel_start_y; - } - - if (x1 < 0) - x1 = 0; - - if (y1 < 0) - y1 = 0; - - if (x2 >= GTK_WIDGET (eil)->allocation.width) - x2 = GTK_WIDGET (eil)->allocation.width - 1; - - if (y2 >= priv->total_height) - y2 = priv->total_height - 1; - - gnome_canvas_item_set (priv->sel_rect, - "x1", (double) x1, - "y1", (double) y1, - "x2", (double) x2, - "y2", (double) y2, - NULL); - - /* Select or unselect icons as appropriate */ - - additive = priv->sel_state & GDK_SHIFT_MASK; - invert = priv->sel_state & GDK_CONTROL_MASK; - - for (i = 0; i < priv->icon_list->len; i++) { - icon = g_array_index(priv->icon_list, Icon*, i); - - if (icon_is_in_area (icon, x1, y1, x2, y2)) { - if (invert) { - if (icon->selected == icon->tmp_selected) - emit_select (eil, !icon->selected, i, NULL); - } else if (additive) { - if (!icon->selected) - emit_select (eil, TRUE, i, NULL); - } else { - if (!icon->selected) - emit_select (eil, TRUE, i, NULL); - } - } else if (icon->selected != icon->tmp_selected) - emit_select (eil, icon->tmp_selected, i, NULL); - } -} - -/* Button release handler for the icon list */ -static gint -eil_button_release (GtkWidget *widget, GdkEventButton *event) -{ - Eil *eil; - EIconListPrivate *priv; - double x, y; - - eil = EIL (widget); - priv = eil->_priv; - - if (!priv->selecting) - return (* GTK_WIDGET_CLASS (parent_class)->button_release_event) (widget, event); - - if (event->button != 1) - return FALSE; - - gnome_canvas_window_to_world (GNOME_CANVAS (eil), event->x, event->y, &x, &y); - update_drag_selection (eil, x, y); - gnome_canvas_item_ungrab (priv->sel_rect, event->time); - - gtk_object_destroy (GTK_OBJECT (priv->sel_rect)); - priv->sel_rect = NULL; - priv->selecting = FALSE; - - if (priv->timer_tag != 0) { - gtk_timeout_remove (priv->timer_tag); - priv->timer_tag = 0; - } - - return TRUE; -} - -/* Autoscroll timeout handler for the icon list */ -static gint -scroll_timeout (gpointer data) -{ - Eil *eil; - EIconListPrivate *priv; - GtkAdjustment *adj; - double x, y; - int value; - - eil = data; - priv = eil->_priv; - - GDK_THREADS_ENTER (); - - adj = gtk_layout_get_vadjustment (GTK_LAYOUT (eil)); - - value = adj->value + priv->value_diff; - if (value > adj->upper - adj->page_size) - value = adj->upper - adj->page_size; - - gtk_adjustment_set_value (adj, value); - - gnome_canvas_window_to_world (GNOME_CANVAS (eil), - priv->event_last_x, priv->event_last_y, - &x, &y); - update_drag_selection (eil, x, y); - - GDK_THREADS_LEAVE(); - - return TRUE; -} - -/* Motion event handler for the icon list */ -static gint -eil_motion_notify (GtkWidget *widget, GdkEventMotion *event) -{ - Eil *eil; - EIconListPrivate *priv; - double x, y; - - eil = EIL (widget); - priv = eil->_priv; - - if (!priv->selecting) - return (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event); - - gnome_canvas_window_to_world (GNOME_CANVAS (eil), event->x, event->y, &x, &y); - update_drag_selection (eil, x, y); - - /* If we are out of bounds, schedule a timeout that will do the scrolling */ - - if (event->y < 0 || event->y > widget->allocation.height) { - if (priv->timer_tag == 0) - priv->timer_tag = gtk_timeout_add (SCROLL_TIMEOUT, scroll_timeout, eil); - - if (event->y < 0) - priv->value_diff = event->y; - else - priv->value_diff = event->y - widget->allocation.height; - - priv->event_last_x = event->x; - priv->event_last_y = event->y; - - /* Make the steppings be relative to the mouse distance from the - * canvas. Also notice the timeout above is small to give a - * more smooth movement. - */ - priv->value_diff /= 5; - } else if (priv->timer_tag != 0) { - gtk_timeout_remove (priv->timer_tag); - priv->timer_tag = 0; - } - - return TRUE; -} - -typedef gboolean (*xGtkSignal_BOOL__INT_POINTER) (GtkObject * object, - gint arg1, - gpointer arg2, - gpointer user_data); -static void -xgtk_marshal_BOOL__INT_POINTER (GtkObject *object, GtkSignalFunc func, gpointer func_data, - GtkArg *args) -{ - xGtkSignal_BOOL__INT_POINTER rfunc; - gboolean *return_val; - - return_val = GTK_RETLOC_BOOL (args[2]); - rfunc = (xGtkSignal_BOOL__INT_POINTER) func; - *return_val = (*rfunc) (object, - GTK_VALUE_INT (args[0]), - GTK_VALUE_POINTER (args[1]), - func_data); -} - -static void -eil_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - EIconList *eil; - - eil = E_ICON_LIST (object); - - switch (arg_id) { - default: - break; - } -} - -static void -eil_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - EIconList *eil; - EIconListPrivate *priv; - - eil = E_ICON_LIST (object); - priv = eil->_priv; - - switch (arg_id) { - default: - arg->type = GTK_TYPE_INVALID; - break; - } -} - -static void -eil_class_init (EilClass *eil_class) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkLayoutClass *layout_class; - GnomeCanvasClass *canvas_class; - - object_class = (GtkObjectClass *) eil_class; - widget_class = (GtkWidgetClass *) eil_class; - layout_class = (GtkLayoutClass *) eil_class; - canvas_class = (GnomeCanvasClass *) eil_class; - - parent_class = gtk_type_class (gnome_canvas_get_type ()); - - eil_signals[SELECT_ICON] = - gtk_signal_new ( - "select_icon", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (EIconListClass, select_icon), - gtk_marshal_NONE__INT_POINTER, - GTK_TYPE_NONE, 2, - GTK_TYPE_INT, - GTK_TYPE_GDK_EVENT); - - eil_signals[UNSELECT_ICON] = - gtk_signal_new ( - "unselect_icon", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (EIconListClass, unselect_icon), - gtk_marshal_NONE__INT_POINTER, - GTK_TYPE_NONE, 2, - GTK_TYPE_INT, - GTK_TYPE_GDK_EVENT); - - eil_signals[TEXT_CHANGED] = - gtk_signal_new ( - "text_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EIconListClass, text_changed), - xgtk_marshal_BOOL__INT_POINTER, - GTK_TYPE_BOOL, 2, - GTK_TYPE_INT, - GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, eil_signals, LAST_SIGNAL); - - object_class->destroy = eil_destroy; - object_class->finalize = eil_finalize; - object_class->set_arg = eil_set_arg; - object_class->get_arg = eil_get_arg; - - widget_class->size_request = eil_size_request; - widget_class->size_allocate = eil_size_allocate; - widget_class->realize = eil_realize; - widget_class->button_press_event = eil_button_press; - widget_class->button_release_event = eil_button_release; - widget_class->motion_notify_event = eil_motion_notify; - - eil_class->select_icon = real_select_icon; - eil_class->unselect_icon = real_unselect_icon; -} - -static void -eil_init (Eil *eil) -{ - eil->_priv = g_new0 (EIconListPrivate, 1); - - eil->_priv->icon_list = g_array_new(FALSE, FALSE, sizeof(gpointer)); - eil->_priv->row_spacing = DEFAULT_ROW_SPACING; - eil->_priv->col_spacing = DEFAULT_COL_SPACING; - eil->_priv->text_spacing = DEFAULT_TEXT_SPACING; - eil->_priv->icon_border = DEFAULT_ICON_BORDER; - eil->_priv->separators = g_strdup (" "); - - eil->_priv->selection_mode = GTK_SELECTION_SINGLE; - eil->_priv->dirty = TRUE; - - gnome_canvas_set_scroll_region (GNOME_CANVAS (eil), 0.0, 0.0, 1000000.0, 1000000.0); - gnome_canvas_scroll_to (GNOME_CANVAS (eil), 0, 0); -} - -/** - * e_icon_list_get_type: - * - * Registers the &EIconList class if necessary, and returns the type ID - * associated to it. - * - * Returns: The type ID of the &EIconList class. - */ -guint -e_icon_list_get_type (void) -{ - static guint eil_type = 0; - - if (!eil_type) { - GtkTypeInfo eil_info = { - "EIconList", - sizeof (EIconList), - sizeof (EIconListClass), - (GtkClassInitFunc) eil_class_init, - (GtkObjectInitFunc) eil_init, - NULL, - NULL, - NULL - }; - - eil_type = gtk_type_unique (gnome_canvas_get_type (), - &eil_info); - } - - return eil_type; -} - -/** - * e_icon_list_set_icon_width: - * @eil: An icon list. - * @w: New width for the icon columns. - * - * Sets the amount of horizontal space allocated to the icons, i.e. the column - * width of the icon list. - */ -void -e_icon_list_set_icon_width (EIconList *eil, int w) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - - priv->icon_width = w; - - if (priv->frozen) { - priv->dirty = TRUE; - return; - } - - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); -} - - -/** - * e_icon_list_construct: - * @eil: An icon list. - * @icon_width: Width for the icon columns. - * @flags: A combination of %E_ICON_LIST_IS_EDITABLE and %E_ICON_LIST_STATIC_TEXT. - * - * Constructor for the icon list, to be used by derived classes. - **/ -void -e_icon_list_construct (EIconList *eil, guint icon_width, int flags) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - - e_icon_list_set_icon_width (eil, icon_width); - priv->is_editable = (flags & E_ICON_LIST_IS_EDITABLE) != 0; - priv->static_text = (flags & E_ICON_LIST_STATIC_TEXT) != 0; -} - - -/** - * e_icon_list_new: [constructor] - * @icon_width: Width for the icon columns. - * @flags: A combination of %E_ICON_LIST_IS_EDITABLE and %E_ICON_LIST_STATIC_TEXT. - * - * Creates a new icon list widget. The icon columns are allocated a width of - * @icon_width pixels. Icon captions will be word-wrapped to this width as - * well. - * - * If @flags has the %E_ICON_LIST_IS_EDITABLE flag set, then the user will be - * able to edit the text in the icon captions, and the "text_changed" signal - * will be emitted when an icon's text is changed. - * - * If @flags has the %E_ICON_LIST_STATIC_TEXT flags set, then the text - * for the icon captions will not be copied inside the icon list; it will only - * store the pointers to the original text strings specified by the application. - * This is intended to save memory. If this flag is not set, then the text - * strings will be copied and managed internally. - * - * Returns: a newly-created icon list widget - */ -GtkWidget * -e_icon_list_new (guint icon_width, int flags) -{ - Eil *eil; - - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); - eil = EIL (gtk_type_new (e_icon_list_get_type ())); - gtk_widget_pop_colormap (); - - e_icon_list_construct (eil, icon_width, flags); - - return GTK_WIDGET (eil); -} - - -/** - * e_icon_list_freeze: - * @eil: An icon list. - * - * Freezes an icon list so that any changes made to it will not be - * reflected on the screen until it is thawed with e_icon_list_thaw(). - * It is recommended to freeze the icon list before inserting or deleting - * many icons, for example, so that the layout process will only be executed - * once, when the icon list is finally thawed. - * - * You can call this function multiple times, but it must be balanced with the - * same number of calls to e_icon_list_thaw() before the changes will take - * effect. - */ -void -e_icon_list_freeze (EIconList *eil) -{ - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - eil->_priv->frozen++; - - /* We hide the root so that the user will not see any changes while the - * icon list is doing stuff. - */ - - if (eil->_priv->frozen == 1) - gnome_canvas_item_hide (GNOME_CANVAS (eil)->root); -} - -/** - * e_icon_list_thaw: - * @eil: An icon list. - * - * Thaws the icon list and performs any pending layout operations. This - * is to be used in conjunction with e_icon_list_freeze(). - */ -void -e_icon_list_thaw (EIconList *eil) -{ - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (eil->_priv->frozen > 0); - - eil->_priv->frozen--; - - if (eil->_priv->dirty) { - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } - - if (eil->_priv->frozen == 0) - gnome_canvas_item_show (GNOME_CANVAS (eil)->root); -} - -/** - * e_icon_list_set_selection_mode - * @eil: An icon list. - * @mode: New selection mode. - * - * Sets the selection mode for an icon list. The %GTK_SELECTION_MULTIPLE and - * %GTK_SELECTION_EXTENDED modes are considered equivalent. - */ -void -e_icon_list_set_selection_mode (EIconList *eil, GtkSelectionMode mode) -{ - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - eil->_priv->selection_mode = mode; - eil->_priv->last_selected_idx = -1; - eil->_priv->last_selected_icon = NULL; -} - -/** - * e_icon_list_set_icon_data_full: - * @eil: An icon list. - * @pos: Index of an icon. - * @data: User data to set on the icon. - * @destroy: Destroy notification handler for the icon. - * - * Associates the @data pointer to the icon at the index specified by @pos. The - * @destroy argument points to a function that will be called when the icon is - * destroyed, or NULL if no function is to be called when this happens. - */ -void -e_icon_list_set_icon_data_full (EIconList *eil, - int pos, gpointer data, - GtkDestroyNotify destroy) -{ - Icon *icon; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (pos >= 0 && pos < eil->_priv->icons); - - icon = g_array_index (eil->_priv->icon_list, Icon*, pos); - icon->data = data; - icon->destroy = destroy; -} - -/** - * e_icon_list_get_icon_data: - * @eil: An icon list. - * @pos: Index of an icon. - * @data: User data to set on the icon. - * - * Associates the @data pointer to the icon at the index specified by @pos. - */ -void -e_icon_list_set_icon_data (EIconList *eil, int pos, gpointer data) -{ - e_icon_list_set_icon_data_full (eil, pos, data, NULL); -} - -/** - * e_icon_list_get_icon_data: - * @eil: An icon list. - * @pos: Index of an icon. - * - * Returns the user data pointer associated to the icon at the index specified - * by @pos. - */ -gpointer -e_icon_list_get_icon_data (EIconList *eil, int pos) -{ - Icon *icon; - - g_return_val_if_fail (eil != NULL, NULL); - g_return_val_if_fail (IS_EIL (eil), NULL); - g_return_val_if_fail (pos >= 0 && pos < eil->_priv->icons, NULL); - - icon = g_array_index (eil->_priv->icon_list, Icon*, pos); - return icon->data; -} - -/** - * e_icon_list_find_icon_from_data: - * @eil: An icon list. - * @data: Data pointer associated to an icon. - * - * Returns the index of the icon whose user data has been set to @data, - * or -1 if no icon has this data associated to it. - */ -int -e_icon_list_find_icon_from_data (EIconList *eil, gpointer data) -{ - EIconListPrivate *priv; - int n; - Icon *icon; - - g_return_val_if_fail (eil != NULL, -1); - g_return_val_if_fail (IS_EIL (eil), -1); - - priv = eil->_priv; - - for (n = 0; n < priv->icon_list->len; n++) { - icon = g_array_index(priv->icon_list, Icon*, n); - if (icon->data == data) - return n; - } - - return -1; -} - -/* Sets an integer value in the private structure of the icon list, and updates it */ -static void -set_value (EIconList *eil, EIconListPrivate *priv, int *dest, int val) -{ - if (val == *dest) - return; - - *dest = val; - - if (!priv->frozen) { - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); - } else - priv->dirty = TRUE; -} - -/** - * e_icon_list_set_row_spacing: - * @eil: An icon list. - * @pixels: Number of pixels for inter-row spacing. - * - * Sets the spacing to be used between rows of icons. - */ -void -e_icon_list_set_row_spacing (EIconList *eil, int pixels) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - set_value (eil, priv, &priv->row_spacing, pixels); -} - -/** - * e_icon_list_set_col_spacing: - * @eil: An icon list. - * @pixels: Number of pixels for inter-column spacing. - * - * Sets the spacing to be used between columns of icons. - */ -void -e_icon_list_set_col_spacing (EIconList *eil, int pixels) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - set_value (eil, priv, &priv->col_spacing, pixels); -} - -/** - * e_icon_list_set_text_spacing: - * @eil: An icon list. - * @pixels: Number of pixels between an icon's image and its caption. - * - * Sets the spacing to be used between an icon's image and its text caption. - */ -void -e_icon_list_set_text_spacing (EIconList *eil, int pixels) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - set_value (eil, priv, &priv->text_spacing, pixels); -} - -/** - * e_icon_list_set_icon_border: - * @eil: An icon list. - * @pixels: Number of border pixels to be used around an icon's image. - * - * Sets the width of the border to be displayed around an icon's image. This is - * currently not implemented. - */ -void -e_icon_list_set_icon_border (EIconList *eil, int pixels) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - - priv = eil->_priv; - set_value (eil, priv, &priv->icon_border, pixels); -} - -/** - * e_icon_list_set_separators: - * @eil: An icon list. - * @sep: String with characters to be used as word separators. - * - * Sets the characters that can be used as word separators when doing - * word-wrapping in the icon text captions. - */ -void -e_icon_list_set_separators (EIconList *eil, const char *sep) -{ - EIconListPrivate *priv; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (sep != NULL); - - priv = eil->_priv; - - if (priv->separators) - g_free (priv->separators); - - priv->separators = g_strdup (sep); - - if (priv->frozen) { - priv->dirty = TRUE; - return; - } - - eil_layout_all_icons (eil); - eil_scrollbar_adjust (eil); -} - -/** - * e_icon_list_moveto: - * @eil: An icon list. - * @pos: Index of an icon. - * @yalign: Vertical alignment of the icon. - * - * Makes the icon whose index is @pos be visible on the screen. The icon list - * gets scrolled so that the icon is visible. An alignment of 0.0 represents - * the top of the visible part of the icon list, and 1.0 represents the bottom. - * An icon can be centered on the icon list. - */ -void -e_icon_list_moveto (EIconList *eil, int pos, double yalign) -{ - EIconListPrivate *priv; - GtkAdjustment *adj; - IconLine *il; - GList *l; - int i, y, uh, line; - - g_return_if_fail (eil != NULL); - g_return_if_fail (IS_EIL (eil)); - g_return_if_fail (pos >= 0 && pos < eil->_priv->icons); - g_return_if_fail (yalign >= 0.0 && yalign <= 1.0); - - priv = eil->_priv; - - g_return_if_fail (priv->lines != NULL); - - line = pos / eil_get_items_per_line (eil); - - y = 0; - for (i = 0, l = priv->lines; l && i < line; l = l->next, i++) { - il = l->data; - y += icon_line_height (eil, il); - } - - il = l->data; - - uh = GTK_WIDGET (eil)->allocation.height - icon_line_height (eil,il); - adj = gtk_layout_get_vadjustment (GTK_LAYOUT (eil)); - gtk_adjustment_set_value (adj, y - uh * yalign); -} - -/** - * e_icon_list_is_visible: - * @eil: An icon list. - * @pos: Index of an icon. - * - * Returns whether the icon at the index specified by @pos is visible. This - * will be %GTK_VISIBILITY_NONE if the icon is not visible at all, - * %GTK_VISIBILITY_PARTIAL if the icon is at least partially shown, and - * %GTK_VISIBILITY_FULL if the icon is fully visible. - */ -GtkVisibility -e_icon_list_icon_is_visible (EIconList *eil, int pos) -{ - EIconListPrivate *priv; - GtkAdjustment *adj; - IconLine *il; - GList *l; - int line, y1, y2, i; - - g_return_val_if_fail (eil != NULL, GTK_VISIBILITY_NONE); - g_return_val_if_fail (IS_EIL (eil), GTK_VISIBILITY_NONE); - g_return_val_if_fail (pos >= 0 && pos < eil->_priv->icons, - GTK_VISIBILITY_NONE); - - priv = eil->_priv; - - if (priv->lines == NULL) - return GTK_VISIBILITY_NONE; - - line = pos / eil_get_items_per_line (eil); - y1 = 0; - for (i = 0, l = priv->lines; l && i < line; l = l->next, i++) { - il = l->data; - y1 += icon_line_height (eil, il); - } - - y2 = y1 + icon_line_height (eil, (IconLine *) l->data); - - adj = gtk_layout_get_vadjustment (GTK_LAYOUT (eil)); - - if (y2 < adj->value) - return GTK_VISIBILITY_NONE; - - if (y1 > adj->value + GTK_WIDGET (eil)->allocation.height) - return GTK_VISIBILITY_NONE; - - if (y2 <= adj->value + GTK_WIDGET (eil)->allocation.height && - y1 >= adj->value) - return GTK_VISIBILITY_FULL; - - return GTK_VISIBILITY_PARTIAL; -} - -/** - * e_icon_list_get_icon_at: - * @eil: An icon list. - * @x: X position in the icon list window. - * @y: Y position in the icon list window. - * - * Returns the index of the icon that is under the specified coordinates, which - * are relative to the icon list's window. If there is no icon in that - * position, -1 is returned. - */ -int -e_icon_list_get_icon_at (EIconList *eil, int x, int y) -{ - EIconListPrivate *priv; - double wx, wy; - double dx, dy; - int cx, cy; - int n; - GnomeCanvasItem *item; - double dist; - - g_return_val_if_fail (eil != NULL, -1); - g_return_val_if_fail (IS_EIL (eil), -1); - - priv = eil->_priv; - - dx = x; - dy = y; - - gnome_canvas_window_to_world (GNOME_CANVAS (eil), dx, dy, &wx, &wy); - gnome_canvas_w2c (GNOME_CANVAS (eil), wx, wy, &cx, &cy); - - for (n = 0; n < priv->icon_list->len; n++) { - Icon *icon = g_array_index(priv->icon_list, Icon*, n); - GnomeCanvasItem *image = GNOME_CANVAS_ITEM (icon->image); - GnomeCanvasItem *text = GNOME_CANVAS_ITEM (icon->text); - - if (wx >= image->x1 && wx <= image->x2 && wy >= image->y1 && wy <= image->y2) { - dist = (* GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (image)->klass)->point) ( - image, - wx, wy, - cx, cy, - &item); - - if ((int) (dist * GNOME_CANVAS (eil)->pixels_per_unit + 0.5) - <= GNOME_CANVAS (eil)->close_enough) - return n; - } - - if (wx >= text->x1 && wx <= text->x2 && wy >= text->y1 && wy <= text->y2) { - dist = (* GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (text)->klass)->point) ( - text, - wx, wy, - cx, cy, - &item); - - if ((int) (dist * GNOME_CANVAS (eil)->pixels_per_unit + 0.5) - <= GNOME_CANVAS (eil)->close_enough) - return n; - } - } - - return -1; -} - - -/** - * e_icon_list_get_num_icons: - * @eil: An icon list. - * - * Returns the number of icons in the icon list. - */ -guint -e_icon_list_get_num_icons (EIconList *eil) -{ - g_return_val_if_fail (E_IS_ICON_LIST (eil), 0); - - return eil->_priv->icons; -} - - -/** - * e_icon_list_get_selection: - * @eil: An icon list. - * - * Returns a list of integers with the indices of the currently selected icons. - */ -GList * -e_icon_list_get_selection (EIconList *eil) -{ - g_return_val_if_fail (E_IS_ICON_LIST (eil), NULL); - - return eil->_priv->selection; -} - - -/** - * e_icon_list_get_selection: - * @eil: An icon list. - * @idx: Index of an @icon. - * - * Returns the filename of the icon with index @idx. - */ -gchar * -e_icon_list_get_icon_filename (EIconList *eil, int idx) -{ - Icon *icon; - - g_return_val_if_fail (eil != NULL, NULL); - g_return_val_if_fail (IS_EIL (eil), NULL); - g_return_val_if_fail (idx >= 0 && idx < eil->_priv->icons, NULL); - - icon = g_array_index (eil->_priv->icon_list, Icon*, idx); - return icon->icon_filename; -} - - -/** - * e_icon_list_find_icon_from_filename: - * @eil: An icon list. - * @filename: Filename of an icon. - * - * Returns the index of the icon whose filename is @filename or -1 if - * there is no icon with this filename. - */ -int -e_icon_list_find_icon_from_filename (EIconList *eil, - const gchar *filename) -{ - EIconListPrivate *priv; - int n; - Icon *icon; - - g_return_val_if_fail (eil != NULL, -1); - g_return_val_if_fail (IS_EIL (eil), -1); - g_return_val_if_fail (filename != NULL, -1); - - priv = eil->_priv; - - for (n = 0; n < priv->icon_list->len; n++) { - icon = g_array_index(priv->icon_list, Icon*, n); - if (!strcmp (icon->icon_filename, filename)) - return n; - } - - return -1; -} - diff --git a/composer/e-icon-list.h b/composer/e-icon-list.h deleted file mode 100644 index 7cdaf6e85f..0000000000 --- a/composer/e-icon-list.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 1998, 1999 Free Software Foundation - * Copyright (C) 2000 Red Hat, Inc. - * All rights reserved. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/* - @NOTATION@ - */ - -/* GnomeIconList widget - scrollable icon list - * - * - * Authors: - * Federico Mena <federico@ximian.com> - * Miguel de Icaza <miguel@ximian.com> - */ - -#ifndef _E_ICON_LIST_H_ -#define _E_ICON_LIST_H_ - -#include <libgnome/gnome-defs.h> -#include <libgnomeui/gnome-canvas.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -BEGIN_GNOME_DECLS - -#define E_TYPE_ICON_LIST (e_icon_list_get_type ()) -#define E_ICON_LIST(obj) (GTK_CHECK_CAST ((obj), E_TYPE_ICON_LIST, EIconList)) -#define E_ICON_LIST_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_ICON_LIST, EIconListClass)) -#define E_IS_ICON_LIST(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_ICON_LIST)) -#define E_IS_ICON_LIST_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_ICON_LIST)) -#define E_ICON_LIST_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), E_TYPE_ICON_LIST, EIconListClass)) - -typedef struct _EIconList EIconList; -typedef struct _EIconListPrivate EIconListPrivate; -typedef struct _EIconListClass EIconListClass; - -typedef enum { - E_ICON_LIST_ICONS, - E_ICON_LIST_TEXT_BELOW, - E_ICON_LIST_TEXT_RIGHT -} EIconListMode; - -/* This structure has been converted to use public and private parts. To avoid - * breaking binary compatibility, the slots for private fields have been - * replaced with padding. Please remove these fields when gnome-libs has - * reached another major version and it is "fine" to break binary compatibility. - */ -struct _EIconList { - GnomeCanvas canvas; - - /*< private >*/ - EIconListPrivate * _priv; -}; - -struct _EIconListClass { - GnomeCanvasClass parent_class; - - void (*select_icon) (EIconList *gil, gint num, GdkEvent *event); - void (*unselect_icon) (EIconList *gil, gint num, GdkEvent *event); - gboolean (*text_changed) (EIconList *gil, gint num, const char *new_text); -}; - -enum { - E_ICON_LIST_IS_EDITABLE = 1 << 0, - E_ICON_LIST_STATIC_TEXT = 1 << 1 -}; - -guint e_icon_list_get_type (void) G_GNUC_CONST; - -GtkWidget *e_icon_list_new (guint icon_width, - int flags); -void e_icon_list_construct (EIconList *gil, - guint icon_width, - int flags); - - -/* To avoid excesive recomputes during insertion/deletion */ -void e_icon_list_freeze (EIconList *gil); -void e_icon_list_thaw (EIconList *gil); - - -void e_icon_list_insert (EIconList *gil, - int idx, - const char *icon_filename, - const char *text); -void e_icon_list_insert_pixbuf (EIconList *gil, - int idx, - GdkPixbuf *im, - const char *icon_filename, - const char *text); - -int e_icon_list_append (EIconList *gil, - const char *icon_filename, - const char *text); -int e_icon_list_append_pixbuf (EIconList *gil, - GdkPixbuf *im, - const char *icon_filename, - const char *text); - -void e_icon_list_clear (EIconList *gil); -void e_icon_list_remove (EIconList *gil, - int idx); - -guint e_icon_list_get_num_icons (EIconList *gil); - - -/* Managing the selection */ -void e_icon_list_set_selection_mode (EIconList *gil, - GtkSelectionMode mode); -void e_icon_list_select_icon (EIconList *gil, - int idx); -void e_icon_list_unselect_icon (EIconList *gil, - int idx); -int e_icon_list_unselect_all (EIconList *gil); -GList * e_icon_list_get_selection (EIconList *gil); - -/* Setting the spacing values */ -void e_icon_list_set_icon_width (EIconList *gil, - int w); -void e_icon_list_set_row_spacing (EIconList *gil, - int pixels); -void e_icon_list_set_col_spacing (EIconList *gil, - int pixels); -void e_icon_list_set_text_spacing (EIconList *gil, - int pixels); -void e_icon_list_set_icon_border (EIconList *gil, - int pixels); -void e_icon_list_set_separators (EIconList *gil, - const char *sep); -/* Icon filename. */ -gchar * e_icon_list_get_icon_filename (EIconList *gil, - int idx); -int e_icon_list_find_icon_from_filename (EIconList *gil, - const char *filename); - -/* Attaching information to the icons */ -void e_icon_list_set_icon_data (EIconList *gil, - int idx, gpointer data); -void e_icon_list_set_icon_data_full (EIconList *gil, - int idx, gpointer data, - GtkDestroyNotify destroy); -int e_icon_list_find_icon_from_data (EIconList *gil, - gpointer data); -gpointer e_icon_list_get_icon_data (EIconList *gil, - int idx); - -/* Visibility */ -void e_icon_list_moveto (EIconList *gil, - int idx, double yalign); -GtkVisibility e_icon_list_icon_is_visible (EIconList *gil, - int idx); - -int e_icon_list_get_icon_at (EIconList *gil, - int x, int y); - -int e_icon_list_get_items_per_line (EIconList *gil); - -END_GNOME_DECLS - -#endif /* _GNOME_ICON_LIST_H_ */ diff --git a/composer/e-msg-composer-attachment-bar.c b/composer/e-msg-composer-attachment-bar.c deleted file mode 100644 index 3e454cd8b8..0000000000 --- a/composer/e-msg-composer-attachment-bar.c +++ /dev/null @@ -1,820 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer-attachment-bar.c - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtksignal.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-util.h> -#include <libgnomeui/gnome-app.h> -#include <libgnomeui/gnome-app-helper.h> -#include <libgnomeui/gnome-popup-menu.h> -#include <glade/glade.h> -#include <libgnomevfs/gnome-vfs-mime-info.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk-pixbuf/gdk-pixbuf-loader.h> -#include <gdk-pixbuf/gnome-canvas-pixbuf.h> - -#include "e-msg-composer.h" -#include "e-msg-composer-select-file.h" -#include "e-msg-composer-attachment.h" -#include "e-msg-composer-attachment-bar.h" - -#include "e-icon-list.h" - -#include <gal/widgets/e-unicode.h> - -#include "camel/camel-data-wrapper.h" -#include "camel/camel-stream-fs.h" -#include "camel/camel-stream-mem.h" -#include "camel/camel-mime-part.h" - - -#define ICON_WIDTH 64 -#define ICON_SEPARATORS " /-_" -#define ICON_SPACING 2 -#define ICON_ROW_SPACING ICON_SPACING -#define ICON_COL_SPACING ICON_SPACING -#define ICON_BORDER 2 -#define ICON_TEXT_SPACING 2 - - -static EIconListClass *parent_class = NULL; - -struct _EMsgComposerAttachmentBarPrivate { - GList *attachments; - guint num_attachments; - - GtkWidget *context_menu; - GtkWidget *icon_context_menu; -}; - - -enum { - CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - - -static void update (EMsgComposerAttachmentBar *bar); - - -static gchar * -size_to_string (gulong size) -{ - gchar *size_string; - - /* FIXME: The following should probably go into a separate module, as - we might have to do the same thing in other places as well. Also, - I am not sure this will be OK for all the languages. */ - - if (size < 1e3L) { - if (size == 1) - size_string = g_strdup (_("1 byte")); - else - size_string = g_strdup_printf (_("%u bytes"), - (guint) size); - } else { - gdouble displayed_size; - - if (size < 1e6L) { - displayed_size = (gdouble) size / 1.0e3; - size_string = g_strdup_printf (_("%.1fK"), - displayed_size); - } else if (size < 1e9L) { - displayed_size = (gdouble) size / 1.0e6; - size_string = g_strdup_printf (_("%.1fM"), - displayed_size); - } else { - displayed_size = (gdouble) size / 1.0e9; - size_string = g_strdup_printf (_("%.1fG"), - displayed_size); - } - } - - return size_string; -} - -/* Attachment handling functions. */ - -static void -free_attachment_list (EMsgComposerAttachmentBar *bar) -{ - EMsgComposerAttachmentBarPrivate *priv; - GList *p; - - priv = bar->priv; - - for (p = priv->attachments; p != NULL; p = p->next) - gtk_object_unref (GTK_OBJECT (p->data)); -} - -static void -attachment_changed_cb (EMsgComposerAttachment *attachment, - gpointer data) -{ - update (E_MSG_COMPOSER_ATTACHMENT_BAR (data)); -} - -static void -add_common (EMsgComposerAttachmentBar *bar, - EMsgComposerAttachment *attachment) -{ - g_return_if_fail (attachment != NULL); - - gtk_signal_connect (GTK_OBJECT (attachment), "changed", - GTK_SIGNAL_FUNC (attachment_changed_cb), - bar); - - bar->priv->attachments = g_list_append (bar->priv->attachments, - attachment); - bar->priv->num_attachments++; - - update (bar); - - gtk_signal_emit (GTK_OBJECT (bar), signals[CHANGED]); -} - -static void -add_from_mime_part (EMsgComposerAttachmentBar *bar, - CamelMimePart *part) -{ - add_common (bar, e_msg_composer_attachment_new_from_mime_part (part)); -} - -static void -add_from_file (EMsgComposerAttachmentBar *bar, - const gchar *file_name, - const gchar *disposition) -{ - add_common (bar, e_msg_composer_attachment_new (file_name, disposition)); -} - -static void -remove_attachment (EMsgComposerAttachmentBar *bar, - EMsgComposerAttachment *attachment) -{ - bar->priv->attachments = g_list_remove (bar->priv->attachments, - attachment); - bar->priv->num_attachments--; - - gtk_object_unref (GTK_OBJECT (attachment)); - - gtk_signal_emit (GTK_OBJECT (bar), signals[CHANGED]); -} - - -/* Icon list contents handling. */ - -static GdkPixbuf * -pixbuf_for_mime_type (const char *mime_type) -{ - const char *icon_name; - char *filename = NULL; - GdkPixbuf *pixbuf; - - icon_name = gnome_vfs_mime_get_value (mime_type, "icon-filename"); - if (icon_name) { - if (*icon_name == '/') { - pixbuf = gdk_pixbuf_new_from_file (icon_name); - if (pixbuf) - return pixbuf; - } - - filename = gnome_pixmap_file (icon_name); - if (!filename) { - char *fm_icon; - - fm_icon = g_strdup_printf ("nautilus/%s", icon_name); - filename = gnome_pixmap_file (fm_icon); - if (!filename) { - fm_icon = g_strdup_printf ("mc/%s", icon_name); - filename = gnome_pixmap_file (fm_icon); - } - g_free (fm_icon); - } - } - - if (!filename) - filename = gnome_pixmap_file ("gnome-unknown.png"); - - pixbuf = gdk_pixbuf_new_from_file (filename); - g_free (filename); - - return pixbuf; -} - -static void -update (EMsgComposerAttachmentBar *bar) -{ - EMsgComposerAttachmentBarPrivate *priv; - EIconList *icon_list; - GList *p; - - priv = bar->priv; - icon_list = E_ICON_LIST (bar); - - e_icon_list_freeze (icon_list); - - e_icon_list_clear (icon_list); - - /* FIXME could be faster, but we don't care. */ - for (p = priv->attachments; p != NULL; p = p->next) { - EMsgComposerAttachment *attachment; - gchar *size_string, *label; - CamelContentType *content_type; - GdkPixbuf *pixbuf; - gboolean image; - char *desc; - - attachment = p->data; - content_type = camel_mime_part_get_content_type (attachment->body); - /* Get the image out of the attachment - and create a thumbnail for it */ - image = header_content_type_is (content_type, "image", "*"); - - if (image && attachment->pixbuf_cache == NULL) { - CamelDataWrapper *wrapper; - CamelStream *mstream; - GdkPixbufLoader *loader; - gboolean error = TRUE; - char tmp[4096]; - int t; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (attachment->body)); - mstream = camel_stream_mem_new (); - - camel_data_wrapper_write_to_stream (wrapper, mstream); - - camel_stream_reset (mstream); - - /* Stream image into pixbuf loader */ - loader = gdk_pixbuf_loader_new (); - do { - t = camel_stream_read (mstream, tmp, 4096); - if (t > 0) { - error = !gdk_pixbuf_loader_write (loader, - tmp, t); - if (error) { - break; - } - } else { - if (camel_stream_eos (mstream)) - break; - error = TRUE; - break; - } - - } while (!camel_stream_eos (mstream)); - - if (!error) { - int ratio, width, height; - - /* Shrink pixbuf */ - pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - if (width >= height) { - if (width > 48) { - ratio = width / 48; - width = 48; - height = height / ratio; - } - } else { - if (height > 48) { - ratio = height / 48; - height = 48; - width = width / ratio; - } - } - - attachment->pixbuf_cache = gdk_pixbuf_scale_simple - (pixbuf, - width, - height, - GDK_INTERP_BILINEAR); - } else { - g_warning ("GdkPixbufLoader Error"); - image = FALSE; - } - - /* Destroy everything */ - gdk_pixbuf_loader_close (loader); - gtk_object_destroy (GTK_OBJECT (loader)); - camel_stream_close (mstream); - } - - desc = e_utf8_to_gtk_string (GTK_WIDGET (icon_list), camel_mime_part_get_description (attachment->body)); - if (!desc || *desc == '\0') - desc = e_utf8_to_gtk_string (GTK_WIDGET (icon_list), - camel_mime_part_get_filename (attachment->body)); - - if (!desc) - desc = g_strdup (_("attachment")); - - if (attachment->size) { - size_string = size_to_string (attachment->size); - label = g_strdup_printf ("%s (%s)", desc, size_string); - g_free (size_string); - } else - label = g_strdup (desc); - - if (image) { - e_icon_list_append_pixbuf (icon_list, attachment->pixbuf_cache, NULL, label); - } else { - char *mime_type; - - mime_type = header_content_type_simple (content_type); - pixbuf = pixbuf_for_mime_type (mime_type); - g_free (mime_type); - e_icon_list_append_pixbuf (icon_list, pixbuf, - NULL, label); - if (pixbuf) - gdk_pixbuf_unref (pixbuf); - } - - g_free (desc); - g_free (label); - } - - e_icon_list_thaw (icon_list); -} - -static void -remove_selected (EMsgComposerAttachmentBar *bar) -{ - EIconList *icon_list; - EMsgComposerAttachment *attachment; - GList *attachment_list; - GList *p; - gint num; - - icon_list = E_ICON_LIST (bar); - - /* Weee! I am especially proud of this piece of cheesy code: it is - truly awful. But unless one attaches a huge number of files, it - will not be as greedy as intended. FIXME of course. */ - - attachment_list = NULL; - p = e_icon_list_get_selection (icon_list); - for (; p != NULL; p = p->next) { - num = GPOINTER_TO_INT (p->data); - attachment = E_MSG_COMPOSER_ATTACHMENT - (g_list_nth (bar->priv->attachments, num)->data); - attachment_list = g_list_prepend (attachment_list, attachment); - } - - for (p = attachment_list; p != NULL; p = p->next) - remove_attachment (bar, E_MSG_COMPOSER_ATTACHMENT (p->data)); - - g_list_free (attachment_list); - - update (bar); -} - -static void -edit_selected (EMsgComposerAttachmentBar *bar) -{ - EIconList *icon_list; - EMsgComposerAttachment *attachment; - GList *selection; - gint num; - - icon_list = E_ICON_LIST (bar); - - selection = e_icon_list_get_selection (icon_list); - num = GPOINTER_TO_INT (selection->data); - attachment = g_list_nth (bar->priv->attachments, num)->data; - - e_msg_composer_attachment_edit (attachment, GTK_WIDGET (bar)); -} - - -/* "Attach" dialog. */ - -static void -add_from_user (EMsgComposerAttachmentBar *bar) -{ - EMsgComposer *composer; - char *file_name; - gboolean is_inline = FALSE; - - composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (GTK_WIDGET (bar))); - - file_name = e_msg_composer_select_file_attachment (composer, &is_inline); - if (!file_name) - return; - - add_from_file (bar, file_name, is_inline ? "inline" : "attachment"); - - g_free (file_name); -} - - -/* Callbacks. */ - -static void -add_cb (GtkWidget *widget, - gpointer data) -{ - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); - - add_from_user (E_MSG_COMPOSER_ATTACHMENT_BAR (data)); -} - -static void -properties_cb (GtkWidget *widget, - gpointer data) -{ - EMsgComposerAttachmentBar *bar; - - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); - - bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); - edit_selected (data); -} - -static void -remove_cb (GtkWidget *widget, - gpointer data) -{ - EMsgComposerAttachmentBar *bar; - - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); - - bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); - remove_selected (bar); -} - - -/* Popup menu handling. */ - -static GnomeUIInfo icon_context_menu_info[] = { - GNOMEUIINFO_ITEM (N_("Remove"), - N_("Remove selected items from the attachment list"), - remove_cb, NULL), - GNOMEUIINFO_MENU_PROPERTIES_ITEM (properties_cb, NULL), - GNOMEUIINFO_END -}; - -static GtkWidget * -get_icon_context_menu (EMsgComposerAttachmentBar *bar) -{ - EMsgComposerAttachmentBarPrivate *priv; - - priv = bar->priv; - if (priv->icon_context_menu == NULL) - priv->icon_context_menu = gnome_popup_menu_new - (icon_context_menu_info); - - return priv->icon_context_menu; -} - -static void -popup_icon_context_menu (EMsgComposerAttachmentBar *bar, - gint num, - GdkEventButton *event) -{ - GtkWidget *menu; - - menu = get_icon_context_menu (bar); - gnome_popup_menu_do_popup (menu, NULL, NULL, event, bar); -} - -static GnomeUIInfo context_menu_info[] = { - GNOMEUIINFO_ITEM (N_("Add attachment..."), - N_("Attach a file to the message"), - add_cb, NULL), - GNOMEUIINFO_END -}; - -static GtkWidget * -get_context_menu (EMsgComposerAttachmentBar *bar) -{ - EMsgComposerAttachmentBarPrivate *priv; - - priv = bar->priv; - if (priv->context_menu == NULL) - priv->context_menu = gnome_popup_menu_new (context_menu_info); - - return priv->context_menu; -} - -static void -popup_context_menu (EMsgComposerAttachmentBar *bar, - GdkEventButton *event) -{ - GtkWidget *menu; - - menu = get_context_menu (bar); - gnome_popup_menu_do_popup (menu, NULL, NULL, event, bar); -} - - -/* GtkObject methods. */ - -static void -destroy (GtkObject *object) -{ - EMsgComposerAttachmentBar *bar; - - bar = E_MSG_COMPOSER_ATTACHMENT_BAR (object); - - free_attachment_list (bar); - - if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - - -/* GtkWidget methods. */ - -static gint -button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - EMsgComposerAttachmentBar *bar; - EIconList *icon_list; - gint icon_number; - - bar = E_MSG_COMPOSER_ATTACHMENT_BAR (widget); - icon_list = E_ICON_LIST (widget); - - if (event->button != 3) - return GTK_WIDGET_CLASS (parent_class)->button_press_event - (widget, event); - - icon_number = e_icon_list_get_icon_at (icon_list, - event->x, event->y); - - if (icon_number >= 0) { - e_icon_list_select_icon (icon_list, icon_number); - popup_icon_context_menu (bar, icon_number, event); - } else { - popup_context_menu (bar, event); - } - - return TRUE; -} - - -/* Initialization. */ - -static void -class_init (EMsgComposerAttachmentBarClass *class) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - EIconListClass *icon_list_class; - - object_class = GTK_OBJECT_CLASS (class); - widget_class = GTK_WIDGET_CLASS (class); - icon_list_class = E_ICON_LIST_CLASS (class); - - parent_class = gtk_type_class (e_icon_list_get_type ()); - - object_class->destroy = destroy; - - widget_class->button_press_event = button_press_event; - - /* Setup signals. */ - - signals[CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerAttachmentBarClass, - changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -init (EMsgComposerAttachmentBar *bar) -{ - EMsgComposerAttachmentBarPrivate *priv; - guint icon_size, icon_height; - GdkFont *font; - - priv = g_new (EMsgComposerAttachmentBarPrivate, 1); - - priv->attachments = NULL; - priv->context_menu = NULL; - priv->icon_context_menu = NULL; - - priv->num_attachments = 0; - - bar->priv = priv; - - /* FIXME partly hardcoded. We should compute height from the font, and - allow at least 2 lines for every item. */ - icon_size = ICON_WIDTH + ICON_SPACING + ICON_BORDER + ICON_TEXT_SPACING; - - font = GTK_WIDGET (bar)->style->font; - icon_height = icon_size + ((font->ascent + font->descent) * 2); - icon_size += 24; - - gtk_widget_set_usize (GTK_WIDGET (bar), icon_size * 4, icon_height); -} - - -GtkType -e_msg_composer_attachment_bar_get_type (void) -{ - static GtkType type = 0; - - if (type == 0) { - static const GtkTypeInfo info = { - "EMsgComposerAttachmentBar", - sizeof (EMsgComposerAttachmentBar), - sizeof (EMsgComposerAttachmentBarClass), - (GtkClassInitFunc) class_init, - (GtkObjectInitFunc) init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (e_icon_list_get_type (), &info); - } - - return type; -} - -GtkWidget * -e_msg_composer_attachment_bar_new (GtkAdjustment *adj) -{ - EMsgComposerAttachmentBar *new; - EIconList *icon_list; - - gdk_rgb_init (); - gtk_widget_push_visual (gdk_rgb_get_visual ()); - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); - new = gtk_type_new (e_msg_composer_attachment_bar_get_type ()); - gtk_widget_pop_visual (); - gtk_widget_pop_colormap (); - - icon_list = E_ICON_LIST (new); - - e_icon_list_construct (icon_list, ICON_WIDTH, 0); - - e_icon_list_set_separators (icon_list, ICON_SEPARATORS); - e_icon_list_set_row_spacing (icon_list, ICON_ROW_SPACING); - e_icon_list_set_col_spacing (icon_list, ICON_COL_SPACING); - e_icon_list_set_icon_border (icon_list, ICON_BORDER); - e_icon_list_set_text_spacing (icon_list, ICON_TEXT_SPACING); - e_icon_list_set_selection_mode (icon_list, GTK_SELECTION_MULTIPLE); - - return GTK_WIDGET (new); -} - -/* FIXME: is_8bit() and best_encoding() should really be shared - between e-msg-composer.c and this file. */ -static gboolean -is_8bit (const guchar *text) -{ - guchar *c; - - for (c = (guchar *) text; *c; c++) - if (*c > (guchar) 127) - return TRUE; - - return FALSE; -} - -static int -best_encoding (const guchar *text) -{ - guchar *ch; - int count = 0; - int total; - - for (ch = (guchar *) text; *ch; ch++) - if (*ch > (guchar) 127) - count++; - - total = (int) (ch - text); - - if ((float) count <= total * 0.17) - return CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE; - else - return CAMEL_MIME_PART_ENCODING_BASE64; -} - -static void -attach_to_multipart (CamelMultipart *multipart, - EMsgComposerAttachment *attachment, - const char *default_charset) -{ - CamelContentType *content_type; - - content_type = camel_mime_part_get_content_type (attachment->body); - - if (!header_content_type_is (content_type, "multipart", "*")) { - if (header_content_type_is (content_type, "text", "*")) { - CamelStream *stream; - GByteArray *array; - guchar *text; - - array = g_byte_array_new (); - stream = camel_stream_mem_new_with_byte_array (array); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (attachment->body), stream); - g_byte_array_append (array, "", 1); - text = array->data; - - if (is_8bit (text)) { - camel_mime_part_set_encoding (attachment->body, best_encoding (text)); - header_content_type_set_param (content_type, "charset", default_charset); - } else - camel_mime_part_set_encoding (attachment->body, CAMEL_MIME_PART_ENCODING_7BIT); - - camel_object_unref (CAMEL_OBJECT (stream)); - } else if (!header_content_type_is (content_type, "message", "*")) { - camel_mime_part_set_encoding (attachment->body, - CAMEL_MIME_PART_ENCODING_BASE64); - } - } - - camel_multipart_add_part (multipart, attachment->body); -} - -void -e_msg_composer_attachment_bar_to_multipart (EMsgComposerAttachmentBar *bar, - CamelMultipart *multipart, - const char *default_charset) -{ - EMsgComposerAttachmentBarPrivate *priv; - GList *p; - - g_return_if_fail (bar != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); - g_return_if_fail (multipart != NULL); - g_return_if_fail (CAMEL_IS_MULTIPART (multipart)); - - priv = bar->priv; - - for (p = priv->attachments; p != NULL; p = p->next) { - EMsgComposerAttachment *attachment; - - attachment = E_MSG_COMPOSER_ATTACHMENT (p->data); - attach_to_multipart (multipart, attachment, default_charset); - } -} - - -guint -e_msg_composer_attachment_bar_get_num_attachments (EMsgComposerAttachmentBar *bar) -{ - g_return_val_if_fail (bar != NULL, 0); - g_return_val_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar), 0); - - return bar->priv->num_attachments; -} - - -void -e_msg_composer_attachment_bar_attach (EMsgComposerAttachmentBar *bar, - const gchar *file_name) -{ - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); - - if (file_name == NULL) - add_from_user (bar); - else - add_from_file (bar, file_name, "attachment"); -} - -void -e_msg_composer_attachment_bar_attach_mime_part (EMsgComposerAttachmentBar *bar, - CamelMimePart *part) -{ - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); - - add_from_mime_part (bar, part); -} diff --git a/composer/e-msg-composer-attachment-bar.h b/composer/e-msg-composer-attachment-bar.h deleted file mode 100644 index 15774bb2fe..0000000000 --- a/composer/e-msg-composer-attachment-bar.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* msg-composer-attachment-bar.h - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifndef __E_MSG_COMPOSER_ATTACHMENT_BAR_H__ -#define __E_MSG_COMPOSER_ATTACHMENT_BAR_H__ - -#include "e-icon-list.h" -#include <camel/camel-multipart.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR \ - (e_msg_composer_attachment_bar_get_type ()) -#define E_MSG_COMPOSER_ATTACHMENT_BAR(obj) \ - (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR, EMsgComposerAttachmentBar)) -#define E_MSG_COMPOSER_ATTACHMENT_BAR_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR, EMsgComposerAttachmentBarClass)) -#define E_IS_MSG_COMPOSER_ATTACHMENT_BAR(obj) \ - (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR)) -#define E_IS_MSG_COMPOSER_ATTACHMENT_BAR_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT_BAR)) - - -typedef struct _EMsgComposerAttachmentBarPrivate EMsgComposerAttachmentBarPrivate; - -struct _EMsgComposerAttachmentBar { - EIconList parent; - - EMsgComposerAttachmentBarPrivate *priv; -}; -typedef struct _EMsgComposerAttachmentBar EMsgComposerAttachmentBar; - -struct _EMsgComposerAttachmentBarClass { - EIconListClass parent_class; - - void (* changed) (EMsgComposerAttachmentBar *bar); -}; -typedef struct _EMsgComposerAttachmentBarClass EMsgComposerAttachmentBarClass; - - -GtkType e_msg_composer_attachment_bar_get_type (void); -GtkWidget *e_msg_composer_attachment_bar_new (GtkAdjustment *adj); -void e_msg_composer_attachment_bar_to_multipart (EMsgComposerAttachmentBar *bar, CamelMultipart *multipart, - const char *default_charset); -guint e_msg_composer_attachment_bar_get_num_attachments (EMsgComposerAttachmentBar *bar); -void e_msg_composer_attachment_bar_attach (EMsgComposerAttachmentBar *bar, const gchar *file_name); -void e_msg_composer_attachment_bar_attach_mime_part (EMsgComposerAttachmentBar *bar, CamelMimePart *part); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __E_MSG_COMPOSER_ATTACHMENT_BAR_H__ */ diff --git a/composer/e-msg-composer-attachment.c b/composer/e-msg-composer-attachment.c deleted file mode 100644 index 1c03b0ff35..0000000000 --- a/composer/e-msg-composer-attachment.c +++ /dev/null @@ -1,444 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer-attachment.c - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -/* This is the object representing an email attachment. It is implemented as a - GtkObject to make it easier for the application to handle it. For example, - the "changed" signal is emitted whenever something changes in the - attachment. Also, this contains the code to let users edit the - attachment manually. */ - -#include <sys/stat.h> - -#include <gtk/gtknotebook.h> -#include <gtk/gtktogglebutton.h> -#include <camel/camel.h> -#include <gal/widgets/e-unicode.h> -#include <libgnomevfs/gnome-vfs-mime.h> - -#include "e-msg-composer.h" -#include "e-msg-composer-attachment.h" - - -enum { - CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - -static GtkObjectClass *parent_class = NULL; - - -static void -changed (EMsgComposerAttachment *attachment) -{ - gtk_signal_emit (GTK_OBJECT (attachment), signals[CHANGED]); -} - - -/* GtkObject methods. */ - -static void -destroy (GtkObject *object) -{ - EMsgComposerAttachment *attachment; - - attachment = E_MSG_COMPOSER_ATTACHMENT (object); - - camel_object_unref (CAMEL_OBJECT (attachment->body)); - if (attachment->pixbuf_cache != NULL) - gdk_pixbuf_unref (attachment->pixbuf_cache); -} - - -/* Signals. */ - -static void -real_changed (EMsgComposerAttachment *msg_composer_attachment) -{ - g_return_if_fail (msg_composer_attachment != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT (msg_composer_attachment)); -} - - -static void -class_init (EMsgComposerAttachmentClass *klass) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass*) klass; - - parent_class = gtk_type_class (gtk_object_get_type ()); - - object_class->destroy = destroy; - - signals[CHANGED] = gtk_signal_new ("changed", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET - (EMsgComposerAttachmentClass, - changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - klass->changed = real_changed; -} - -static void -init (EMsgComposerAttachment *msg_composer_attachment) -{ - msg_composer_attachment->editor_gui = NULL; - msg_composer_attachment->body = NULL; - msg_composer_attachment->size = 0; - msg_composer_attachment->pixbuf_cache = NULL; -} - -GtkType -e_msg_composer_attachment_get_type (void) -{ - static GtkType type = 0; - - if (type == 0) { - static const GtkTypeInfo info = { - "EMsgComposerAttachment", - sizeof (EMsgComposerAttachment), - sizeof (EMsgComposerAttachmentClass), - (GtkClassInitFunc) class_init, - (GtkObjectInitFunc) init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (gtk_object_get_type (), &info); - } - - return type; -} - - -/** - * e_msg_composer_attachment_new: - * @file_name: filename to attach - * @disposition: Content-Disposition of the attachment - * - * Return value: the new attachment, or %NULL on error - **/ -EMsgComposerAttachment * -e_msg_composer_attachment_new (const gchar *file_name, - const gchar *disposition) -{ - EMsgComposerAttachment *new; - CamelMimePart *part; - CamelDataWrapper *wrapper; - CamelStream *stream; - struct stat statbuf; - gchar *mime_type; - char *content_id; - char *filename; - - g_return_val_if_fail (file_name != NULL, NULL); - - if (stat (file_name, &statbuf) < 0) - return NULL; - - /* return if it's not a regular file */ - if (!S_ISREG (statbuf.st_mode)) - return NULL; - - stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0); - if (!stream) - return NULL; - wrapper = camel_data_wrapper_new (); - camel_data_wrapper_construct_from_stream (wrapper, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - mime_type = e_msg_composer_guess_mime_type (file_name); - if (mime_type) { - camel_data_wrapper_set_mime_type (wrapper, mime_type); - g_free (mime_type); - } else - camel_data_wrapper_set_mime_type (wrapper, "application/octet-stream"); - - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper); - camel_object_unref (CAMEL_OBJECT (wrapper)); - - camel_mime_part_set_disposition (part, disposition); - if (strchr (file_name, '/')) - filename = e_utf8_from_locale_string (strrchr (file_name, '/') + 1); - else - filename = e_utf8_from_locale_string (file_name); - - camel_mime_part_set_filename (part, filename); - g_free (filename); - - /* set the Content-Id */ - content_id = header_msgid_generate (); - camel_mime_part_set_content_id (part, content_id); - g_free (content_id); - - new = e_msg_composer_attachment_new_from_mime_part (part); - - new->size = statbuf.st_size; - new->guessed_type = TRUE; - - return new; -} - - -/** - * e_msg_composer_attachment_new_from_mime_part: - * @part: a CamelMimePart - * - * Return value: a new EMsgComposerAttachment based on the mime part - **/ -EMsgComposerAttachment * -e_msg_composer_attachment_new_from_mime_part (CamelMimePart *part) -{ - EMsgComposerAttachment *new; - - g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL); - - new = gtk_type_new (e_msg_composer_attachment_get_type ()); - - new->editor_gui = NULL; - new->body = part; - camel_object_ref (CAMEL_OBJECT (part)); - new->guessed_type = FALSE; - new->size = 0; - - return new; -} - - -/* The attachment property dialog. */ - -struct _DialogData { - GtkWidget *dialog; - GtkEntry *file_name_entry; - GtkEntry *description_entry; - GtkEntry *mime_type_entry; - GtkToggleButton *disposition_checkbox; - EMsgComposerAttachment *attachment; -}; -typedef struct _DialogData DialogData; - -static void -destroy_dialog_data (DialogData *data) -{ - g_free (data); -} - -/* - * fixme: I am converting EVERYTHING to/from UTF-8, although mime types - * are in ASCII. This is not strictly necessary, but we want to be - * consistent and possibly check for errors somewhere. - */ - -static void -update_mime_type (DialogData *data) -{ - const gchar *mime_type; - gchar *file_name; - - if (!data->attachment->guessed_type) - return; - - file_name = e_utf8_gtk_entry_get_text (data->file_name_entry); - mime_type = gnome_vfs_mime_type_from_name_or_default (file_name, NULL); - g_free (file_name); - - if (mime_type) - e_utf8_gtk_entry_set_text (data->mime_type_entry, mime_type); -} - -static void -set_entry (GladeXML *xml, - const gchar *widget_name, - const gchar *value) -{ - GtkEntry *entry; - - entry = GTK_ENTRY (glade_xml_get_widget (xml, widget_name)); - if (entry == NULL) - g_warning ("Entry for `%s' not found.", widget_name); - else - e_utf8_gtk_entry_set_text (entry, value ? value : ""); -} - -static void -connect_widget (GladeXML *gui, - const gchar *name, - const gchar *signal_name, - GtkSignalFunc func, - gpointer data) -{ - GtkWidget *widget; - - widget = glade_xml_get_widget (gui, name); - gtk_signal_connect (GTK_OBJECT (widget), signal_name, func, data); -} - -static void -close_cb (GtkWidget *widget, - gpointer data) -{ - EMsgComposerAttachment *attachment; - DialogData *dialog_data; - - dialog_data = (DialogData *) data; - attachment = dialog_data->attachment; - - gtk_widget_destroy (glade_xml_get_widget (attachment->editor_gui, - "dialog")); - gtk_object_unref (GTK_OBJECT (attachment->editor_gui)); - attachment->editor_gui = NULL; - - destroy_dialog_data (dialog_data); -} - -static void -ok_cb (GtkWidget *widget, - gpointer data) -{ - DialogData *dialog_data; - EMsgComposerAttachment *attachment; - gchar *str; - - dialog_data = (DialogData *) data; - attachment = dialog_data->attachment; - - str = e_utf8_gtk_entry_get_text (dialog_data->file_name_entry); - camel_mime_part_set_filename (attachment->body, str); - g_free (str); - - str = e_utf8_gtk_entry_get_text (dialog_data->description_entry); - camel_mime_part_set_description (attachment->body, str); - g_free (str); - - str = e_utf8_gtk_entry_get_text (dialog_data->mime_type_entry); - camel_mime_part_set_content_type (attachment->body, str); - - camel_data_wrapper_set_mime_type ( - camel_medium_get_content_object (CAMEL_MEDIUM (attachment->body)), str); - g_free (str); - - switch (gtk_toggle_button_get_active (dialog_data->disposition_checkbox)) { - case 0: - camel_mime_part_set_disposition (attachment->body, "attachment"); - break; - case 1: - camel_mime_part_set_disposition (attachment->body, "inline"); - break; - default: - /* Hmmmm? */ - break; - } - - changed (attachment); - close_cb (widget, data); -} - -static void -file_name_focus_out_cb (GtkWidget *widget, - GdkEventFocus *event, - gpointer data) -{ - DialogData *dialog_data; - - dialog_data = (DialogData *) data; - update_mime_type (dialog_data); -} - - -void -e_msg_composer_attachment_edit (EMsgComposerAttachment *attachment, - GtkWidget *parent) -{ - DialogData *dialog_data; - GladeXML *editor_gui; - - g_return_if_fail (attachment != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT (attachment)); - - if (attachment->editor_gui != NULL) { - GtkWidget *window; - - window = glade_xml_get_widget (attachment->editor_gui, - "dialog"); - gdk_window_show (window->window); - return; - } - - editor_gui = glade_xml_new (E_GLADEDIR "/e-msg-composer-attachment.glade", - NULL); - if (editor_gui == NULL) { - g_warning ("Cannot load `e-msg-composer-attachment.glade'"); - return; - } - - attachment->editor_gui = editor_gui; - - gtk_window_set_transient_for - (GTK_WINDOW (glade_xml_get_widget (editor_gui, "dialog")), - GTK_WINDOW (gtk_widget_get_toplevel (parent))); - - dialog_data = g_new (DialogData, 1); - dialog_data->attachment = attachment; - dialog_data->dialog = glade_xml_get_widget (editor_gui, "dialog"); - dialog_data->file_name_entry = GTK_ENTRY ( - glade_xml_get_widget (editor_gui, "file_name_entry")); - dialog_data->description_entry = GTK_ENTRY ( - glade_xml_get_widget (editor_gui, "description_entry")); - dialog_data->mime_type_entry = GTK_ENTRY ( - glade_xml_get_widget (editor_gui, "mime_type_entry")); - dialog_data->disposition_checkbox = GTK_TOGGLE_BUTTON ( - glade_xml_get_widget (editor_gui, "disposition_checkbox")); - - if (attachment != NULL) { - CamelContentType *content_type; - char *type; - const char *disposition; - - set_entry (editor_gui, "file_name_entry", - camel_mime_part_get_filename (attachment->body)); - set_entry (editor_gui, "description_entry", - camel_mime_part_get_description (attachment->body)); - content_type = camel_mime_part_get_content_type (attachment->body); - type = header_content_type_simple (content_type); - set_entry (editor_gui, "mime_type_entry", type); - g_free (type); - - disposition = camel_mime_part_get_disposition (attachment->body); - gtk_toggle_button_set_active (dialog_data->disposition_checkbox, - disposition && !g_strcasecmp (disposition, "inline")); - } - - connect_widget (editor_gui, "ok_button", "clicked", ok_cb, dialog_data); - connect_widget (editor_gui, "close_button", "clicked", close_cb, dialog_data); - - connect_widget (editor_gui, "file_name_entry", "focus_out_event", - file_name_focus_out_cb, dialog_data); -} diff --git a/composer/e-msg-composer-attachment.glade b/composer/e-msg-composer-attachment.glade deleted file mode 100644 index 5b585e2d5c..0000000000 --- a/composer/e-msg-composer-attachment.glade +++ /dev/null @@ -1,280 +0,0 @@ -<?xml version="1.0"?> -<GTK-Interface> - -<project> - <name>e-msg-composer-attachment</name> - <program_name>e-msg-composer-attachment</program_name> - <directory></directory> - <source_directory>src</source_directory> - <pixmaps_directory>pixmaps</pixmaps_directory> - <language>C</language> - <gnome_support>True</gnome_support> - <gettext_support>True</gettext_support> - <output_main_file>False</output_main_file> -</project> - -<widget> - <class>GnomeDialog</class> - <name>dialog</name> - <title>Attachment properties</title> - <type>GTK_WINDOW_TOPLEVEL</type> - <position>GTK_WIN_POS_NONE</position> - <modal>False</modal> - <allow_shrink>False</allow_shrink> - <allow_grow>False</allow_grow> - <auto_shrink>False</auto_shrink> - <auto_close>False</auto_close> - <hide_on_close>False</hide_on_close> - - <widget> - <class>GtkVBox</class> - <child_name>GnomeDialog:vbox</child_name> - <name>dialog-vbox1</name> - <homogeneous>False</homogeneous> - <spacing>8</spacing> - <child> - <padding>4</padding> - <expand>True</expand> - <fill>True</fill> - </child> - - <widget> - <class>GtkHButtonBox</class> - <child_name>GnomeDialog:action_area</child_name> - <name>dialog-action_area1</name> - <layout_style>GTK_BUTTONBOX_END</layout_style> - <spacing>8</spacing> - <child_min_width>85</child_min_width> - <child_min_height>27</child_min_height> - <child_ipad_x>7</child_ipad_x> - <child_ipad_y>0</child_ipad_y> - <child> - <padding>0</padding> - <expand>False</expand> - <fill>True</fill> - <pack>GTK_PACK_END</pack> - </child> - - <widget> - <class>GtkButton</class> - <name>ok_button</name> - <can_default>True</can_default> - <has_default>True</has_default> - <can_focus>True</can_focus> - <stock_button>GNOME_STOCK_BUTTON_OK</stock_button> - </widget> - - <widget> - <class>GtkButton</class> - <name>close_button</name> - <can_default>True</can_default> - <can_focus>True</can_focus> - <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button> - </widget> - </widget> - - <widget> - <class>GtkTable</class> - <name>table1</name> - <rows>4</rows> - <columns>2</columns> - <homogeneous>False</homogeneous> - <row_spacing>10</row_spacing> - <column_spacing>5</column_spacing> - <child> - <padding>0</padding> - <expand>True</expand> - <fill>True</fill> - </child> - - <widget> - <class>GtkEntry</class> - <name>description_entry</name> - <can_focus>True</can_focus> - <editable>True</editable> - <text_visible>True</text_visible> - <text_max_length>0</text_max_length> - <text></text> - <child> - <left_attach>1</left_attach> - <right_attach>2</right_attach> - <top_attach>1</top_attach> - <bottom_attach>2</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>True</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>True</xfill> - <yfill>False</yfill> - </child> - </widget> - - <widget> - <class>GtkHBox</class> - <name>hbox3</name> - <homogeneous>False</homogeneous> - <spacing>10</spacing> - <child> - <left_attach>1</left_attach> - <right_attach>2</right_attach> - <top_attach>0</top_attach> - <bottom_attach>1</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>True</xexpand> - <yexpand>True</yexpand> - <xshrink>True</xshrink> - <yshrink>True</yshrink> - <xfill>True</xfill> - <yfill>True</yfill> - </child> - - <widget> - <class>GtkEntry</class> - <name>file_name_entry</name> - <width>290</width> - <can_focus>True</can_focus> - <editable>True</editable> - <text_visible>True</text_visible> - <text_max_length>0</text_max_length> - <text></text> - <child> - <padding>0</padding> - <expand>True</expand> - <fill>True</fill> - </child> - </widget> - </widget> - - <widget> - <class>GtkEntry</class> - <name>mime_type_entry</name> - <sensitive>False</sensitive> - <can_focus>True</can_focus> - <editable>False</editable> - <text_visible>True</text_visible> - <text_max_length>0</text_max_length> - <text></text> - <child> - <left_attach>1</left_attach> - <right_attach>2</right_attach> - <top_attach>2</top_attach> - <bottom_attach>3</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>True</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>True</xfill> - <yfill>False</yfill> - </child> - </widget> - - <widget> - <class>GtkLabel</class> - <name>mime_label</name> - <label>MIME type:</label> - <justify>GTK_JUSTIFY_LEFT</justify> - <wrap>False</wrap> - <xalign>1</xalign> - <yalign>0.5</yalign> - <xpad>0</xpad> - <ypad>0</ypad> - <child> - <left_attach>0</left_attach> - <right_attach>1</right_attach> - <top_attach>2</top_attach> - <bottom_attach>3</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>False</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>True</xfill> - <yfill>False</yfill> - </child> - </widget> - - <widget> - <class>GtkLabel</class> - <name>description_label</name> - <label>Description:</label> - <justify>GTK_JUSTIFY_CENTER</justify> - <wrap>False</wrap> - <xalign>1</xalign> - <yalign>0.5</yalign> - <xpad>0</xpad> - <ypad>0</ypad> - <child> - <left_attach>0</left_attach> - <right_attach>1</right_attach> - <top_attach>1</top_attach> - <bottom_attach>2</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>False</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>True</xfill> - <yfill>False</yfill> - </child> - </widget> - - <widget> - <class>GtkLabel</class> - <name>filename_label</name> - <label>File name:</label> - <justify>GTK_JUSTIFY_CENTER</justify> - <wrap>False</wrap> - <xalign>1</xalign> - <yalign>0.5</yalign> - <xpad>0</xpad> - <ypad>0</ypad> - <child> - <left_attach>0</left_attach> - <right_attach>1</right_attach> - <top_attach>0</top_attach> - <bottom_attach>1</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>False</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>True</xfill> - <yfill>False</yfill> - </child> - </widget> - - <widget> - <class>GtkCheckButton</class> - <name>disposition_checkbox</name> - <can_focus>True</can_focus> - <label>Suggest automatic display of attachment</label> - <active>False</active> - <draw_indicator>True</draw_indicator> - <child> - <left_attach>0</left_attach> - <right_attach>2</right_attach> - <top_attach>3</top_attach> - <bottom_attach>4</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>False</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>True</xfill> - <yfill>False</yfill> - </child> - </widget> - </widget> - </widget> -</widget> - -</GTK-Interface> diff --git a/composer/e-msg-composer-attachment.h b/composer/e-msg-composer-attachment.h deleted file mode 100644 index e51db41d73..0000000000 --- a/composer/e-msg-composer-attachment.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer-attachment.h - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ -#ifndef __E_MSG_COMPOSER_ATTACHMENT_H__ -#define __E_MSG_COMPOSER_ATTACHMENT_H__ - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <glade/glade-xml.h> -#include <camel/camel-mime-part.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define E_TYPE_MSG_COMPOSER_ATTACHMENT (e_msg_composer_attachment_get_type ()) -#define E_MSG_COMPOSER_ATTACHMENT(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT, EMsgComposerAttachment)) -#define E_MSG_COMPOSER_ATTACHMENT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_ATTACHMENT, EMsgComposerAttachmentClass)) -#define E_IS_MSG_COMPOSER_ATTACHMENT(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT)) -#define E_IS_MSG_COMPOSER_ATTACHMENT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_ATTACHMENT)) - - -typedef struct _EMsgComposerAttachment EMsgComposerAttachment; -typedef struct _EMsgComposerAttachmentClass EMsgComposerAttachmentClass; - -struct _EMsgComposerAttachment { - GtkObject parent; - - GladeXML *editor_gui; - - CamelMimePart *body; - gboolean guessed_type; - gulong size; - - GdkPixbuf *pixbuf_cache; -}; - -struct _EMsgComposerAttachmentClass { - GtkObjectClass parent_class; - - void (*changed) (EMsgComposerAttachment *msg_composer_attachment); -}; - - -GtkType e_msg_composer_attachment_get_type (void); -EMsgComposerAttachment *e_msg_composer_attachment_new (const gchar *file_name, - const gchar *disposition); -EMsgComposerAttachment *e_msg_composer_attachment_new_from_mime_part (CamelMimePart *part); -void e_msg_composer_attachment_edit (EMsgComposerAttachment *attachment, - GtkWidget *parent); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __E_MSG_COMPOSER_ATTACHMENT_H__ */ diff --git a/composer/e-msg-composer-hdrs.c b/composer/e-msg-composer-hdrs.c deleted file mode 100644 index f27f32fe2d..0000000000 --- a/composer/e-msg-composer-hdrs.c +++ /dev/null @@ -1,969 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* msg-composer-hdrs.c - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <bonobo/bonobo-control.h> -#include <bonobo/bonobo-widget.h> - -#include <gtk/gtkmenuitem.h> -#include <gtk/gtkoptionmenu.h> -#include <gtk/gtktooltips.h> -#include <libgnomeui/gnome-uidefs.h> -#include <liboaf/liboaf.h> - -#include "Composer.h" - -#include <gtk/gtkmenuitem.h> -#include <gtk/gtkoptionmenu.h> -#include <gtk/gtktooltips.h> - -#include <gal/e-text/e-entry.h> -#include <gal/widgets/e-unicode.h> - -#include <camel/camel.h> -#include <e-destination.h> -#include "e-msg-composer-hdrs.h" -#include "mail/mail-config.h" -#include "addressbook/backend/ebook/e-book-util.h" - - -#define SELECT_NAMES_OAFID "OAFIID:GNOME_Evolution_Addressbook_SelectNames" - -/* Indexes in the GtkTable assigned to various items */ - -#define LINE_FROM 0 -#define LINE_REPLYTO 1 -#define LINE_TO 2 -#define LINE_CC 3 -#define LINE_BCC 4 -#define LINE_SUBJECT 5 - -typedef struct { - GtkWidget *label; - GtkWidget *entry; -} EMsgComposerHdrPair; - -struct _EMsgComposerHdrsPrivate { - GNOME_Evolution_Addressbook_SelectNames corba_select_names; - - /* The tooltips. */ - GtkTooltips *tooltips; - - GSList *from_options; - - /* Standard headers. */ - EMsgComposerHdrPair from, reply_to, to, cc, bcc, subject; -}; - - -static GtkTableClass *parent_class = NULL; - -enum { - SHOW_ADDRESS_DIALOG, - SUBJECT_CHANGED, - HDRS_CHANGED, - FROM_CHANGED, - LAST_SIGNAL -}; - -static gint signals[LAST_SIGNAL]; - - -static gboolean -setup_corba (EMsgComposerHdrs *hdrs) -{ - EMsgComposerHdrsPrivate *priv; - CORBA_Environment ev; - - priv = hdrs->priv; - - g_assert (priv->corba_select_names == CORBA_OBJECT_NIL); - - CORBA_exception_init (&ev); - - priv->corba_select_names = oaf_activate_from_id (SELECT_NAMES_OAFID, 0, NULL, &ev); - - /* OAF seems to be broken -- it can return a CORBA_OBJECT_NIL without - raising an exception in `ev'. */ - if (ev._major != CORBA_NO_EXCEPTION || priv->corba_select_names == CORBA_OBJECT_NIL) { - g_warning ("Cannot activate -- %s", SELECT_NAMES_OAFID); - CORBA_exception_free (&ev); - return FALSE; - } - - CORBA_exception_free (&ev); - - return TRUE; -} - -typedef struct { - EMsgComposerHdrs *hdrs; - char *string; -} EMsgComposerHdrsAndString; - -static void -e_msg_composer_hdrs_and_string_free(EMsgComposerHdrsAndString *emchas) -{ - if (emchas->hdrs) - gtk_object_unref(GTK_OBJECT(emchas->hdrs)); - g_free(emchas->string); -} - -static EMsgComposerHdrsAndString * -e_msg_composer_hdrs_and_string_create(EMsgComposerHdrs *hdrs, const char *string) -{ - EMsgComposerHdrsAndString *emchas; - - emchas = g_new(EMsgComposerHdrsAndString, 1); - emchas->hdrs = hdrs; - emchas->string = g_strdup(string); - if (emchas->hdrs) - gtk_object_ref(GTK_OBJECT(emchas->hdrs)); - - return emchas; -} - -static void -address_button_clicked_cb (GtkButton *button, - gpointer data) -{ - EMsgComposerHdrsAndString *emchas; - EMsgComposerHdrs *hdrs; - EMsgComposerHdrsPrivate *priv; - CORBA_Environment ev; - - emchas = data; - hdrs = emchas->hdrs; - priv = hdrs->priv; - - CORBA_exception_init (&ev); - - GNOME_Evolution_Addressbook_SelectNames_activateDialog ( - priv->corba_select_names, emchas->string, &ev); - - CORBA_exception_free (&ev); -} - -static void -from_changed (GtkWidget *item, gpointer data) -{ - EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (data); - - hdrs->account = gtk_object_get_data (GTK_OBJECT (item), "account"); - gtk_signal_emit (GTK_OBJECT (hdrs), signals [FROM_CHANGED]); -} - -static GtkWidget * -create_from_optionmenu (EMsgComposerHdrs *hdrs) -{ - GtkWidget *omenu, *menu, *first = NULL; - const GSList *accounts; - GtkWidget *item; - int i = 0, history = 0; - int default_account; - - omenu = gtk_option_menu_new (); - menu = gtk_menu_new (); - - default_account = mail_config_get_default_account_num (); - - accounts = mail_config_get_accounts (); - while (accounts) { - const MailConfigAccount *account; - char *label; - char *native_label; - - account = accounts->data; - - /* this should never ever fail */ - if (!account || !account->name || !account->id) { - g_assert_not_reached (); - continue; - } - - if (strcmp (account->name, account->id->address)) - label = g_strdup_printf ("%s <%s> (%s)", account->id->name, - account->id->address, account->name); - else - label = g_strdup_printf ("%s <%s>", account->id->name, account->id->address); - - - native_label = e_utf8_to_gtk_string (GTK_WIDGET (menu), label); - item = gtk_menu_item_new_with_label (native_label); - g_free (native_label); - g_free (label); - - gtk_object_set_data (GTK_OBJECT (item), "account", account_copy (account)); - gtk_signal_connect (GTK_OBJECT (item), "activate", - GTK_SIGNAL_FUNC (from_changed), hdrs); - - if (i == default_account) { - first = item; - history = i; - } - - /* this is so we can later set which one we want */ - hdrs->priv->from_options = g_slist_append (hdrs->priv->from_options, item); - - gtk_menu_append (GTK_MENU (menu), item); - gtk_widget_show (item); - - accounts = accounts->next; - i++; - } - - gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); - - if (first){ - gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), history); - gtk_signal_emit_by_name (GTK_OBJECT (first), "activate", hdrs); - } - - return omenu; -} - -static void -addressbook_entry_changed (BonoboListener *listener, - char *event_name, - CORBA_any *arg, - CORBA_Environment *ev, - gpointer user_data) -{ - EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (user_data); - - gtk_signal_emit (GTK_OBJECT (hdrs), signals[HDRS_CHANGED]); -} - -static GtkWidget * -create_addressbook_entry (EMsgComposerHdrs *hdrs, - const char *name) -{ - EMsgComposerHdrsPrivate *priv; - GNOME_Evolution_Addressbook_SelectNames corba_select_names; - Bonobo_Control corba_control; - GtkWidget *control_widget; - CORBA_Environment ev; - BonoboControlFrame *cf; - Bonobo_PropertyBag pb = CORBA_OBJECT_NIL; - - priv = hdrs->priv; - corba_select_names = priv->corba_select_names; - - CORBA_exception_init (&ev); - - GNOME_Evolution_Addressbook_SelectNames_addSection ( - corba_select_names, name, name, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - CORBA_exception_free (&ev); - return NULL; - } - - corba_control = - GNOME_Evolution_Addressbook_SelectNames_getEntryBySection ( - corba_select_names, name, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - CORBA_exception_free (&ev); - return NULL; - } - - CORBA_exception_free (&ev); - - control_widget = bonobo_widget_new_control_from_objref ( - corba_control, CORBA_OBJECT_NIL); - - cf = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_widget)); - pb = bonobo_control_frame_get_control_property_bag (cf, NULL); - - bonobo_event_source_client_add_listener ( - pb, addressbook_entry_changed, - "Bonobo/Property:change:entry_changed", - NULL, hdrs); - - return control_widget; -} - -static EMsgComposerHdrPair -header_new_recipient (EMsgComposerHdrs *hdrs, const gchar *name, const gchar *tip) -{ - EMsgComposerHdrsPrivate *priv; - EMsgComposerHdrPair ret; - - priv = hdrs->priv; - - ret.label = gtk_button_new_with_label (name); - GTK_OBJECT_UNSET_FLAGS (ret.label, GTK_CAN_FOCUS); - gtk_signal_connect_full ( - GTK_OBJECT (ret.label), "clicked", - GTK_SIGNAL_FUNC (address_button_clicked_cb), NULL, - e_msg_composer_hdrs_and_string_create(hdrs, name), - (GtkDestroyNotify) e_msg_composer_hdrs_and_string_free, - FALSE, FALSE); - - gtk_tooltips_set_tip ( - hdrs->priv->tooltips, ret.label, - _("Click here for the address book"), - NULL); - - ret.entry = create_addressbook_entry (hdrs, name); - - return ret; -} - -static void -entry_changed (GtkWidget *entry, EMsgComposerHdrs *hdrs) -{ - gchar *tmp; - gchar *subject; - - tmp = e_msg_composer_hdrs_get_subject (hdrs); - subject = e_utf8_to_gtk_string (GTK_WIDGET (entry), tmp); - - gtk_signal_emit (GTK_OBJECT (hdrs), signals[SUBJECT_CHANGED], subject); - g_free (tmp); - - gtk_signal_emit (GTK_OBJECT (hdrs), signals[HDRS_CHANGED]); -} - -static void -create_headers (EMsgComposerHdrs *hdrs) -{ - EMsgComposerHdrsPrivate *priv = hdrs->priv; - - /* - * From: - */ - priv->from.label = gtk_label_new (_("From:")); - priv->from.entry = create_from_optionmenu (hdrs); - - /* - * Reply-To: - */ - priv->reply_to.label = gtk_label_new (_("Reply-To:")); - priv->reply_to.entry = e_entry_new (); - gtk_object_set (GTK_OBJECT (priv->reply_to.entry), - "editable", TRUE, - "use_ellipsis", TRUE, - "allow_newlines", FALSE, - NULL); - - /* - * Subject: - */ - priv->subject.label = gtk_label_new (_("Subject:")); - priv->subject.entry = e_entry_new (); - gtk_object_set (GTK_OBJECT (priv->subject.entry), - "editable", TRUE, - "use_ellipsis", TRUE, - "allow_newlines", FALSE, - NULL); - gtk_signal_connect (GTK_OBJECT (priv->subject.entry), "changed", - GTK_SIGNAL_FUNC (entry_changed), hdrs); - - /* - * To: CC: and Bcc: - */ - priv->to = header_new_recipient ( - hdrs, _("To:"), - _("Enter the recipients of the message")); - - priv->cc = header_new_recipient ( - hdrs, _("Cc:"), - _("Enter the addresses that will receive a carbon copy of the message")); - - priv->bcc = header_new_recipient ( - hdrs, _("Bcc:"), - _("Enter the addresses that will receive a carbon copy of " - "the message without appearing in the recipient list of " - "the message.")); -} - -static void -attach_couple (EMsgComposerHdrs *hdrs, EMsgComposerHdrPair *pair, int line) -{ - int pad; - - if (GTK_IS_LABEL (pair->label)) - pad = GNOME_PAD; - else - pad = 2; - - gtk_table_attach ( - GTK_TABLE (hdrs), - pair->label, 0, 1, - line, line + 1, - GTK_FILL, GTK_FILL, pad, pad); - - gtk_table_attach ( - GTK_TABLE (hdrs), - pair->entry, 1, 2, - line, line + 1, - GTK_FILL | GTK_EXPAND, 0, 2, 2); -} - -static void -attach_headers (EMsgComposerHdrs *hdrs) -{ - EMsgComposerHdrsPrivate *p = hdrs->priv; - - attach_couple (hdrs, &p->from, LINE_FROM); - attach_couple (hdrs, &p->reply_to, LINE_REPLYTO); - attach_couple (hdrs, &p->to, LINE_TO); - attach_couple (hdrs, &p->cc, LINE_CC); - attach_couple (hdrs, &p->bcc, LINE_BCC); - attach_couple (hdrs, &p->subject, LINE_SUBJECT); -} - -static void -set_pair_visibility (EMsgComposerHdrs *h, EMsgComposerHdrPair *pair, gboolean visible) -{ - if (visible){ - gtk_widget_show (pair->label); - gtk_widget_show (pair->entry); - } else { - gtk_widget_hide (pair->label); - gtk_widget_hide (pair->entry); - } -} - -static void -headers_set_visibility (EMsgComposerHdrs *h, gint visible_flags) -{ - EMsgComposerHdrsPrivate *p = h->priv; - - set_pair_visibility (h, &p->from, visible_flags & E_MSG_COMPOSER_VISIBLE_FROM); - set_pair_visibility (h, &p->reply_to, visible_flags & E_MSG_COMPOSER_VISIBLE_REPLYTO); - set_pair_visibility (h, &p->cc, visible_flags & E_MSG_COMPOSER_VISIBLE_CC); - set_pair_visibility (h, &p->bcc, visible_flags & E_MSG_COMPOSER_VISIBLE_BCC); - set_pair_visibility (h, &p->subject, visible_flags & E_MSG_COMPOSER_VISIBLE_SUBJECT); -} - -void -e_msg_composer_set_hdrs_visible (EMsgComposerHdrs *hdrs, gint visible_flags) -{ - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - - headers_set_visibility (hdrs, visible_flags); - gtk_widget_queue_resize (GTK_WIDGET (hdrs)); -} - -static void -setup_headers (EMsgComposerHdrs *hdrs, gint visible_flags) -{ - create_headers (hdrs); - attach_headers (hdrs); - - /* - * To: is always visible - */ - gtk_widget_show (hdrs->priv->to.label); - gtk_widget_show (hdrs->priv->to.entry); - - headers_set_visibility (hdrs, visible_flags); -} - - -/* GtkObject methods. */ - -static void -destroy (GtkObject *object) -{ - EMsgComposerHdrs *hdrs; - EMsgComposerHdrsPrivate *priv; - GSList *l; - - hdrs = E_MSG_COMPOSER_HDRS (object); - priv = hdrs->priv; - - if (priv->corba_select_names != CORBA_OBJECT_NIL) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - CORBA_Object_release (priv->corba_select_names, &ev); - CORBA_exception_free (&ev); - } - - gtk_object_destroy (GTK_OBJECT (priv->tooltips)); - - l = priv->from_options; - while (l) { - MailConfigAccount *account; - GtkWidget *item = l->data; - - account = gtk_object_get_data (GTK_OBJECT (item), "account"); - account_destroy (account); - - l = l->next; - } - g_slist_free (priv->from_options); - - if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - - -static void -class_init (EMsgComposerHdrsClass *class) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (class); - object_class->destroy = destroy; - - parent_class = gtk_type_class (gtk_table_get_type ()); - - signals[SHOW_ADDRESS_DIALOG] = - gtk_signal_new ("show_address_dialog", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerHdrsClass, - show_address_dialog), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - signals[SUBJECT_CHANGED] = - gtk_signal_new ("subject_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerHdrsClass, - subject_changed), - gtk_marshal_NONE__STRING, - GTK_TYPE_NONE, - 1, GTK_TYPE_STRING); - - signals[HDRS_CHANGED] = - gtk_signal_new ("hdrs_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerHdrsClass, - hdrs_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - signals[FROM_CHANGED] = - gtk_signal_new ("from_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerHdrsClass, - from_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -init (EMsgComposerHdrs *hdrs) -{ - EMsgComposerHdrsPrivate *priv; - - priv = g_new0 (EMsgComposerHdrsPrivate, 1); - - priv->tooltips = gtk_tooltips_new (); - - hdrs->priv = priv; -} - - -GtkType -e_msg_composer_hdrs_get_type (void) -{ - static GtkType type = 0; - - if (type == 0) { - static const GtkTypeInfo info = { - "EMsgComposerHdrs", - sizeof (EMsgComposerHdrs), - sizeof (EMsgComposerHdrsClass), - (GtkClassInitFunc) class_init, - (GtkObjectInitFunc) init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (gtk_table_get_type (), &info); - } - - return type; -} - -GtkWidget * -e_msg_composer_hdrs_new (gint visible_flags) -{ - EMsgComposerHdrs *new; - EMsgComposerHdrsPrivate *priv; - - new = gtk_type_new (e_msg_composer_hdrs_get_type ()); - priv = new->priv; - - if (! setup_corba (new)) { - gtk_widget_destroy (GTK_WIDGET (new)); - return NULL; - } - - setup_headers (new, visible_flags); - - return GTK_WIDGET (new); -} - - -static void -set_recipients (CamelMimeMessage *msg, GtkWidget *entry_widget, const gchar *type) -{ - EDestination **destv; - CamelInternetAddress *addr; - char *string = NULL, *dest_str = NULL; - int i; - - bonobo_widget_get_property (BONOBO_WIDGET (entry_widget), "text", &string, NULL); - destv = e_destination_importv (string); - - g_message ("importv: [%s]", string); - - if (destv) { - dest_str = e_destination_get_address_textv (destv); - g_message ("destination is: %s", dest_str); - - /* dest_str has been utf8 encoded 2x by this point...not good */ - - if (dest_str && *dest_str) { - addr = camel_internet_address_new (); - camel_address_unformat (CAMEL_ADDRESS (addr), dest_str); - - /* TODO: In here, we could cross-reference the names with an alias book - or address book, it should be sufficient for unformat to do the parsing too */ - - camel_mime_message_set_recipients (msg, type, addr); - - camel_object_unref (CAMEL_OBJECT (addr)); - - g_free (dest_str); - } - - for (i = 0; destv[i]; i++) { - e_destination_touch (destv[i]); - gtk_object_unref (GTK_OBJECT (destv[i])); - } - g_free (destv); - } - - g_free (string); -} - -void -e_msg_composer_hdrs_to_message (EMsgComposerHdrs *hdrs, - CamelMimeMessage *msg) -{ - CamelInternetAddress *addr; - gchar *subject; - - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - g_return_if_fail (msg != NULL); - g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg)); - - subject = e_msg_composer_hdrs_get_subject (hdrs); - camel_mime_message_set_subject (msg, subject); - g_free (subject); - - addr = e_msg_composer_hdrs_get_from (hdrs); - camel_mime_message_set_from (msg, addr); - camel_object_unref (CAMEL_OBJECT (addr)); - - addr = e_msg_composer_hdrs_get_reply_to (hdrs); - if (addr) { - camel_mime_message_set_reply_to (msg, addr); - camel_object_unref (CAMEL_OBJECT (addr)); - } - - set_recipients (msg, hdrs->priv->to.entry, CAMEL_RECIPIENT_TYPE_TO); - set_recipients (msg, hdrs->priv->cc.entry, CAMEL_RECIPIENT_TYPE_CC); - set_recipients (msg, hdrs->priv->bcc.entry, CAMEL_RECIPIENT_TYPE_BCC); -} - - -static void -set_entry (BonoboWidget *bonobo_widget, - const GList *list) -{ - GString *string; - const GList *p; - - string = g_string_new (""); - for (p = list; p != NULL; p = p->next) { - if (string->str[0] != '\0') - g_string_append (string, ", "); - g_string_append (string, p->data); - } - - bonobo_widget_set_property (BONOBO_WIDGET (bonobo_widget), "text", string->str, NULL); - - g_string_free (string, TRUE); -} - - -/* FIXME: yea, this could be better... but it's doubtful it'll be used much */ -void -e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs, - const char *account_name) -{ - GtkOptionMenu *omenu; - GtkWidget *item; - GSList *l; - int i = 0; - int default_account = 0; - - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - - omenu = GTK_OPTION_MENU (hdrs->priv->from.entry); - - default_account = mail_config_get_default_account_num (); - - /* find the item that represents the account and activate it */ - l = hdrs->priv->from_options; - while (l) { - MailConfigAccount *account; - item = l->data; - - account = gtk_object_get_data (GTK_OBJECT (item), "account"); - if ((account_name && !strcmp (account_name, account->name)) || - (!account_name && i == default_account)) { - /* set the correct optionlist item */ - gtk_option_menu_set_history (omenu, i); - gtk_signal_emit_by_name (GTK_OBJECT (item), "activate", hdrs); - - return; - } - - l = l->next; - i++; - } -} - -void -e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs, - const char *reply_to) -{ - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - - bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->reply_to.entry), - "text", reply_to, NULL); -} - -/* FIXME: these shouldn't take GLists, they should take CamelInternetAddress's */ -void -e_msg_composer_hdrs_set_to (EMsgComposerHdrs *hdrs, - const GList *to_list) -{ - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - - set_entry (BONOBO_WIDGET (hdrs->priv->to.entry), to_list); -} - -void -e_msg_composer_hdrs_set_cc (EMsgComposerHdrs *hdrs, - const GList *cc_list) -{ - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - - set_entry (BONOBO_WIDGET (hdrs->priv->cc.entry), cc_list); -} - -void -e_msg_composer_hdrs_set_bcc (EMsgComposerHdrs *hdrs, - const GList *bcc_list) -{ - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - - set_entry (BONOBO_WIDGET (hdrs->priv->bcc.entry), bcc_list); -} - -void -e_msg_composer_hdrs_set_subject (EMsgComposerHdrs *hdrs, - const char *subject) -{ - g_return_if_fail (hdrs != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs)); - g_return_if_fail (subject != NULL); - - gtk_object_set (GTK_OBJECT (hdrs->priv->subject.entry), - "text", subject, - NULL); -} - - -CamelInternetAddress * -e_msg_composer_hdrs_get_from (EMsgComposerHdrs *hdrs) -{ - const MailConfigAccount *account; - CamelInternetAddress *addr; - - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - account = hdrs->account; - if (!account || !account->id) { - /* FIXME: perhaps we should try the default account? */ - return NULL; - } - - addr = camel_internet_address_new (); - camel_internet_address_add (addr, account->id->name, account->id->address); - - return addr; -} - -CamelInternetAddress * -e_msg_composer_hdrs_get_reply_to (EMsgComposerHdrs *hdrs) -{ - CamelInternetAddress *addr; - gchar *reply_to; - - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - gtk_object_get (GTK_OBJECT (hdrs->priv->reply_to.entry), - "text", &reply_to, NULL); - - if (!reply_to || *reply_to == '\0') { - g_free (reply_to); - return NULL; - } - - addr = camel_internet_address_new (); - if (camel_address_unformat (CAMEL_ADDRESS (addr), reply_to) == -1) { - g_free (reply_to); - camel_object_unref (CAMEL_OBJECT (addr)); - return NULL; - } - - g_free (reply_to); - - return addr; -} - -/* FIXME this is currently unused and broken. */ -GList * -e_msg_composer_hdrs_get_to (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - g_assert_not_reached (); - - return NULL; -} - -/* FIXME this is currently unused and broken. */ -GList * -e_msg_composer_hdrs_get_cc (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - g_assert_not_reached (); - - return NULL; -} - -/* FIXME this is currently unused and broken. */ -GList * -e_msg_composer_hdrs_get_bcc (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - g_assert_not_reached (); - - return NULL; -} - -char * -e_msg_composer_hdrs_get_subject (EMsgComposerHdrs *hdrs) -{ - gchar *subject; - - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - gtk_object_get (GTK_OBJECT (hdrs->priv->subject.entry), - "text", &subject, NULL); - - return subject; -} - - -GtkWidget * -e_msg_composer_hdrs_get_reply_to_entry (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - return hdrs->priv->reply_to.entry; -} - -GtkWidget * -e_msg_composer_hdrs_get_to_entry (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - return hdrs->priv->to.entry; -} - -GtkWidget * -e_msg_composer_hdrs_get_cc_entry (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - return hdrs->priv->cc.entry; -} - -GtkWidget * -e_msg_composer_hdrs_get_bcc_entry (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - return hdrs->priv->bcc.entry; -} - -GtkWidget * -e_msg_composer_hdrs_get_subject_entry (EMsgComposerHdrs *hdrs) -{ - g_return_val_if_fail (hdrs != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL); - - return hdrs->priv->subject.entry; -} diff --git a/composer/e-msg-composer-hdrs.h b/composer/e-msg-composer-hdrs.h deleted file mode 100644 index 42f8dee7d1..0000000000 --- a/composer/e-msg-composer-hdrs.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* msg-composer-hdrs.h - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifndef ___E_MSG_COMPOSER_HDRS_H__ -#define ___E_MSG_COMPOSER_HDRS_H__ - -#include <gtk/gtktable.h> -#include <camel/camel-mime-message.h> -#include <mail/mail-config.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define E_TYPE_MSG_COMPOSER_HDRS (e_msg_composer_hdrs_get_type ()) -#define E_MSG_COMPOSER_HDRS(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrs)) -#define E_MSG_COMPOSER_HDRS_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER_HDRS, EMsgComposerHdrsClass)) -#define E_IS_MSG_COMPOSER_HDRS(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER_HDRS)) -#define E_IS_MSG_COMPOSER_HDRS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER_HDRS)) - - -typedef struct _EMsgComposerHdrs EMsgComposerHdrs; -typedef struct _EMsgComposerHdrsClass EMsgComposerHdrsClass; -typedef struct _EMsgComposerHdrsPrivate EMsgComposerHdrsPrivate; - -struct _EMsgComposerHdrs { - GtkTable parent; - - EMsgComposerHdrsPrivate *priv; - - const MailConfigAccount *account; - - gboolean has_changed; -}; - -struct _EMsgComposerHdrsClass { - GtkTableClass parent_class; - - void (* show_address_dialog) (EMsgComposerHdrs *hdrs); - - void (* subject_changed) (EMsgComposerHdrs *hdrs, gchar *subject); - - void (* hdrs_changed) (EMsgComposerHdrs *hdrs); - - void (* from_changed) (EMsgComposerHdrs *hdrs); -}; - -typedef enum { - E_MSG_COMPOSER_VISIBLE_FROM = 1, - E_MSG_COMPOSER_VISIBLE_REPLYTO = 2, - E_MSG_COMPOSER_VISIBLE_CC = 4, - E_MSG_COMPOSER_VISIBLE_BCC = 8, - E_MSG_COMPOSER_VISIBLE_SUBJECT = 16 -} EMsgComposerHeaderVisibleFlags; - - -GtkType e_msg_composer_hdrs_get_type (void); -GtkWidget *e_msg_composer_hdrs_new (gint visible_flags); - -void e_msg_composer_hdrs_to_message (EMsgComposerHdrs *hdrs, - CamelMimeMessage *msg); - -void e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs, - const char *account_name); -void e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs, - const char *reply_to); -void e_msg_composer_hdrs_set_to (EMsgComposerHdrs *hdrs, - const GList *to_list); -void e_msg_composer_hdrs_set_cc (EMsgComposerHdrs *hdrs, - const GList *cc_list); -void e_msg_composer_hdrs_set_bcc (EMsgComposerHdrs *hdrs, - const GList *bcc_list); -void e_msg_composer_hdrs_set_subject (EMsgComposerHdrs *hdrs, - const char *subject); - -CamelInternetAddress *e_msg_composer_hdrs_get_from (EMsgComposerHdrs *hdrs); -CamelInternetAddress *e_msg_composer_hdrs_get_reply_to (EMsgComposerHdrs *hdrs); -GList *e_msg_composer_hdrs_get_to (EMsgComposerHdrs *hdrs); -GList *e_msg_composer_hdrs_get_cc (EMsgComposerHdrs *hdrs); -GList *e_msg_composer_hdrs_get_bcc (EMsgComposerHdrs *hdrs); -char *e_msg_composer_hdrs_get_subject (EMsgComposerHdrs *hdrs); - -GtkWidget *e_msg_composer_hdrs_get_reply_to_entry (EMsgComposerHdrs *hdrs); -GtkWidget *e_msg_composer_hdrs_get_to_entry (EMsgComposerHdrs *hdrs); -GtkWidget *e_msg_composer_hdrs_get_cc_entry (EMsgComposerHdrs *hdrs); -GtkWidget *e_msg_composer_hdrs_get_bcc_entry (EMsgComposerHdrs *hdrs); -GtkWidget *e_msg_composer_hdrs_get_subject_entry (EMsgComposerHdrs *hdrs); - -gint e_msg_composer_get_hdrs_visible (EMsgComposerHdrs *hdrs); -void e_msg_composer_set_hdrs_visible (EMsgComposerHdrs *hdrs, - gint flags); - -#ifdef _cplusplus -} -#endif /* _cplusplus */ - - -#endif /* __E_MSG_COMPOSER_HDRS_H__ */ diff --git a/composer/e-msg-composer-select-file.c b/composer/e-msg-composer-select-file.c deleted file mode 100644 index d44a0ec76f..0000000000 --- a/composer/e-msg-composer-select-file.c +++ /dev/null @@ -1,229 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer-select-file.c - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtkbox.h> -#include <gtk/gtkcheckbutton.h> -#include <gtk/gtkfilesel.h> -#include <gtk/gtkmain.h> -#include <gtk/gtksignal.h> -#include "e-msg-composer-select-file.h" - - -struct _FileSelectionInfo { - GtkWidget *widget; - GtkToggleButton *inline_checkbox; - char *selected_file; -}; -typedef struct _FileSelectionInfo FileSelectionInfo; - - -static void -confirm (FileSelectionInfo *info) -{ - const char *filename; - - filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (info->widget)); - info->selected_file = g_strdup (filename); - - gtk_widget_hide (info->widget); - - gtk_main_quit (); -} - -static void -cancel (FileSelectionInfo *info) -{ - g_assert (info->selected_file == NULL); - - gtk_widget_hide (info->widget); - - gtk_main_quit (); -} - - -/* Callbacks. */ - -static void -ok_clicked_cb (GtkWidget *widget, - void *data) -{ - FileSelectionInfo *info; - - info = (FileSelectionInfo *) data; - confirm (info); -} - -static void -cancel_clicked_cb (GtkWidget *widget, - void *data) -{ - FileSelectionInfo *info; - - info = (FileSelectionInfo *) data; - cancel (info); -} - -static int -delete_event_cb (GtkWidget *widget, - GdkEventAny *event, - void *data) -{ - FileSelectionInfo *info; - - info = (FileSelectionInfo *) data; - cancel (info); - - return TRUE; -} - - -/* Setup. */ - -static FileSelectionInfo * -create_file_selection (EMsgComposer *composer) -{ - FileSelectionInfo *info; - GtkWidget *widget; - GtkWidget *ok_button; - GtkWidget *cancel_button; - GtkWidget *inline_checkbox; - GtkWidget *box; - char *path; - - info = g_new (FileSelectionInfo, 1); - - widget = gtk_file_selection_new (NULL); - path = g_strdup_printf ("%s/", g_get_home_dir ()); - gtk_file_selection_set_filename (GTK_FILE_SELECTION (widget), path); - g_free (path); - gtk_window_set_wmclass (GTK_WINDOW (widget), "fileselection", - "Evolution:composer"); - ok_button = GTK_FILE_SELECTION (widget)->ok_button; - cancel_button = GTK_FILE_SELECTION (widget)->cancel_button; - - gtk_signal_connect (GTK_OBJECT (ok_button), - "clicked", GTK_SIGNAL_FUNC (ok_clicked_cb), info); - gtk_signal_connect (GTK_OBJECT (cancel_button), - "clicked", GTK_SIGNAL_FUNC (cancel_clicked_cb), info); - gtk_signal_connect (GTK_OBJECT (widget), "delete_event", - GTK_SIGNAL_FUNC (delete_event_cb), info); - - inline_checkbox = gtk_check_button_new_with_label (_("Suggest automatic display of attachment")); - box = gtk_widget_get_ancestor (GTK_FILE_SELECTION (widget)->selection_entry, GTK_TYPE_BOX); - gtk_box_pack_end (GTK_BOX (box), inline_checkbox, FALSE, FALSE, 4); - - info->widget = widget; - info->selected_file = NULL; - info->inline_checkbox = GTK_TOGGLE_BUTTON (inline_checkbox); - - return info; -} - -static void -file_selection_info_destroy_notify (void *data) -{ - FileSelectionInfo *info; - - info = (FileSelectionInfo *) data; - - if (info->widget != NULL) { - gtk_object_unref (GTK_OBJECT (info->widget)); - } - g_free (info->selected_file); - g_free (info); -} - - -static char * -select_file_internal (EMsgComposer *composer, - const char *title, - gboolean *inline_p) -{ - FileSelectionInfo *info; - char *retval; - - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); - - info = gtk_object_get_data (GTK_OBJECT (composer), - "e-msg-composer-file-selection-info"); - - if (info == NULL) { - info = create_file_selection (composer); - gtk_object_set_data_full (GTK_OBJECT (composer), - "e-msg-composer-file-selection-info", info, - file_selection_info_destroy_notify); - } - - if (GTK_WIDGET_VISIBLE (info->widget)) - return NULL; /* Busy! */ - - gtk_window_set_title (GTK_WINDOW (info->widget), title); - if (inline_p) - gtk_widget_show (GTK_WIDGET (info->inline_checkbox)); - else - gtk_widget_hide (GTK_WIDGET (info->inline_checkbox)); - gtk_widget_show (info->widget); - - GDK_THREADS_ENTER(); - gtk_main (); - GDK_THREADS_LEAVE(); - - retval = info->selected_file; - info->selected_file = NULL; - - if (inline_p) { - *inline_p = gtk_toggle_button_get_active (info->inline_checkbox); - gtk_toggle_button_set_active (info->inline_checkbox, FALSE); - } - - return retval; -} - -/** - * e_msg_composer_select_file: - * @composer: a composer - * @title: the title for the file selection dialog box - * - * This pops up a file selection dialog box with the given title - * and allows the user to select a file. - * - * Return value: the selected filename, or %NULL if the user - * cancelled. - **/ -char * -e_msg_composer_select_file (EMsgComposer *composer, - const char *title) -{ - return select_file_internal (composer, title, NULL); -} - -char * -e_msg_composer_select_file_attachment (EMsgComposer *composer, - gboolean *inline_p) -{ - return select_file_internal (composer, _("Attach a file"), inline_p); -} diff --git a/composer/e-msg-composer-select-file.h b/composer/e-msg-composer-select-file.h deleted file mode 100644 index d0df1732e6..0000000000 --- a/composer/e-msg-composer-select-file.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer-select-file.c - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifndef E_MSG_COMPOSER_SELECT_FILE_H -#define E_MSG_COMPOSER_SELECT_FILE_H - -#include "e-msg-composer.h" - -char *e_msg_composer_select_file (EMsgComposer *composer, - const char *title); - -char *e_msg_composer_select_file_attachment (EMsgComposer *composer, - gboolean *inline_p); - -#endif /* E_MSG_COMPOSER_SELECT_FILE_H */ diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c deleted file mode 100644 index 5ba7a5c838..0000000000 --- a/composer/e-msg-composer.c +++ /dev/null @@ -1,3516 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer.c - * - * Copyright (C) 1999 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Authors: - * Ettore Perazzoli (ettore@ximian.com) - * Jeffrey Stedfast (fejj@ximian.com) - * Miguel de Icaza (miguel@ximian.com) - * - */ - -/* - - TODO - - - Somehow users should be able to see if any file(s) are attached even when - the attachment bar is not shown. - - Should use EventSources to keep track of global changes made to configuration - values. Right now it ignores the problem olympically. Miguel. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> -#include <ctype.h> -#include <stdlib.h> -#include <dirent.h> -#include <libgnome/gnome-defs.h> -#include <libgnomeui/gnome-app.h> -#include <libgnomeui/gnome-uidefs.h> -#include <libgnomeui/gnome-dialog.h> -#include <libgnomeui/gnome-dialog-util.h> -#include <libgnomeui/gnome-stock.h> -#include <libgnomeui/gnome-window-icon.h> -#include <bonobo/bonobo-exception.h> -#include <bonobo/bonobo-moniker-util.h> -#include <bonobo/bonobo-object-client.h> -#include <bonobo/bonobo-stream-memory.h> -#include <bonobo/bonobo-ui-util.h> -#include <bonobo/bonobo-widget.h> -#include <libgnomevfs/gnome-vfs.h> - -#include <glade/glade.h> -#include <gal/widgets/e-gui-utils.h> -#include <gal/widgets/e-scroll-frame.h> -#include <gtkhtml/gtkhtml.h> - -#include "widgets/misc/e-charset-picker.h" - -#include "camel/camel.h" -#include "camel/camel-charset-map.h" -#include "camel/camel-session.h" - -#include "mail/mail.h" -#include "mail/mail-crypto.h" -#include "mail/mail-tools.h" -#include "mail/mail-ops.h" -#include "mail/mail-mt.h" -#include "mail/mail-session.h" - -#include "e-util/e-html-utils.h" - -#include "e-msg-composer.h" -#include "e-msg-composer-attachment-bar.h" -#include "e-msg-composer-hdrs.h" -#include "e-msg-composer-select-file.h" - -#include "evolution-shell-component-utils.h" - -#include "Editor.h" -#include "listener.h" - -#define GNOME_GTKHTML_EDITOR_CONTROL_ID "OAFIID:GNOME_GtkHTML_Editor" - - -#define DEFAULT_WIDTH 600 -#define DEFAULT_HEIGHT 500 - -enum { - SEND, - POSTPONE, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - DND_TYPE_MESSAGE_RFC822, - DND_TYPE_TEXT_URI_LIST, -}; - -static GtkTargetEntry drop_types[] = { - { "message/rfc822", 0, DND_TYPE_MESSAGE_RFC822 }, - { "text/uri-list", 0, DND_TYPE_TEXT_URI_LIST }, -}; - -static const int num_drop_types = sizeof (drop_types) / sizeof (drop_types[0]); - -static GnomeAppClass *parent_class = NULL; - -/* local prototypes */ -static GList *add_recipients (GList *list, const char *recips, gboolean decode); -static void free_recipients (GList *list); -static void handle_multipart (EMsgComposer *composer, CamelMultipart *multipart, int depth); -static void message_rfc822_dnd (EMsgComposer *composer, CamelStream *stream); - - -static GByteArray * -get_text (Bonobo_PersistStream persist, char *format) -{ - BonoboStream *stream; - BonoboStreamMem *stream_mem; - CORBA_Environment ev; - GByteArray *text; - - CORBA_exception_init (&ev); - - 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) { - g_warning ("Exception getting mail '%s'", - bonobo_exception_get_text (&ev)); - return NULL; - } - - CORBA_exception_free (&ev); - - stream_mem = BONOBO_STREAM_MEM (stream); - text = g_byte_array_new (); - g_byte_array_append (text, stream_mem->buffer, stream_mem->pos); - bonobo_object_unref (BONOBO_OBJECT(stream)); - - return text; -} - -#define LINE_LEN 72 - -static CamelMimePartEncodingType -best_encoding (GByteArray *buf, const char *charset) -{ - char *in, *out, outbuf[256], *ch; - size_t inlen, outlen; - int status, count = 0; - iconv_t cd; - - if (!charset) - return -1; - - cd = iconv_open (charset, "utf-8"); - g_return_val_if_fail (cd != (iconv_t)-1, -1); - - in = buf->data; - inlen = buf->len; - do { - out = outbuf; - outlen = sizeof (outbuf); - status = iconv (cd, &in, &inlen, &out, &outlen); - for (ch = out - 1; ch >= outbuf; ch--) { - if ((unsigned char)*ch > 127) - count++; - } - } while (status == -1 && errno == E2BIG); - iconv_close (cd); - - if (status == -1) - return -1; - - if (count == 0) - return CAMEL_MIME_PART_ENCODING_7BIT; - else if (count <= buf->len * 0.17) - return CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE; - else - return CAMEL_MIME_PART_ENCODING_BASE64; -} - -static const char * -best_charset (GByteArray *buf, const char *default_charset, CamelMimePartEncodingType *encoding) -{ - const char *charset; - - /* First try US-ASCII */ - *encoding = best_encoding (buf, "US-ASCII"); - if (*encoding == CAMEL_MIME_PART_ENCODING_7BIT) - return NULL; - - /* Next try the user-specified charset for this message */ - charset = default_charset; - *encoding = best_encoding (buf, charset); - if (*encoding != -1) - return charset; - - /* Now try the user's default charset from the mail config */ - charset = mail_config_get_default_charset (); - *encoding = best_encoding (buf, charset); - if (*encoding != -1) - return charset; - - /* Try to find something that will work */ - charset = camel_charset_best (buf->data, buf->len); - if (!charset) - *encoding = CAMEL_MIME_PART_ENCODING_7BIT; - else - *encoding = best_encoding (buf, charset); - return charset; -} - -static gboolean -clear_inline_images (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - g_free (value); - - return TRUE; -} - -void -e_msg_composer_clear_inlined_table (EMsgComposer *composer) -{ - g_hash_table_foreach_remove (composer->inline_images, clear_inline_images, NULL); -} - -static void -add_inlined_image (gpointer key, gpointer value, gpointer data) -{ - gchar *file_name = (gchar *) key; - gchar *cid = (gchar *) value; - gchar *mime_type; - CamelMultipart *multipart = (CamelMultipart *) data; - CamelStream *stream; - CamelDataWrapper *wrapper; - CamelMimePart *part; - struct stat statbuf; - - /* check for regular file */ - if (stat (file_name, &statbuf) < 0 || !S_ISREG (statbuf.st_mode)) - return; - - if (!(stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0))) - return; - - wrapper = camel_data_wrapper_new (); - camel_data_wrapper_construct_from_stream (wrapper, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - - mime_type = e_msg_composer_guess_mime_type (file_name); - camel_data_wrapper_set_mime_type (wrapper, mime_type ? mime_type : "application/octet-stream"); - g_free (mime_type); - - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper); - camel_object_unref (CAMEL_OBJECT (wrapper)); - - camel_mime_part_set_content_id (part, cid); - /* FIXME: should this use g_basename (file_name)? */ - camel_mime_part_set_filename (part, strchr (file_name, '/') ? strrchr (file_name, '/') + 1 : file_name); - camel_mime_part_set_encoding (part, CAMEL_MIME_PART_ENCODING_BASE64); - - camel_multipart_add_part (multipart, part); - camel_object_unref (CAMEL_OBJECT (part)); -} - -static void -add_inlined_images (EMsgComposer *composer, CamelMultipart *multipart) -{ - g_hash_table_foreach (composer->inline_images, add_inlined_image, multipart); -} - -/* This functions builds a CamelMimeMessage for the message that the user has - * composed in `composer'. - */ -static CamelMimeMessage * -build_message (EMsgComposer *composer) -{ - EMsgComposerAttachmentBar *attachment_bar = - E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar); - EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (composer->hdrs); - CamelMimeMessage *new; - GByteArray *data; - CamelDataWrapper *plain, *html, *current; - CamelMimePartEncodingType plain_encoding; - const char *charset; - CamelContentType *type; - CamelStream *stream; - CamelMultipart *body = NULL; - CamelMimePart *part; - CamelException ex; - int i; - - if (composer->persist_stream_interface == CORBA_OBJECT_NIL) - return NULL; - - new = camel_mime_message_new (); - e_msg_composer_hdrs_to_message (hdrs, new); - for (i = 0; i < composer->extra_hdr_names->len; i++) { - camel_medium_add_header (CAMEL_MEDIUM (new), - composer->extra_hdr_names->pdata[i], - composer->extra_hdr_values->pdata[i]); - } - - data = get_text (composer->persist_stream_interface, "text/plain"); - if (!data) { - /* The component has probably died */ - camel_object_unref (CAMEL_OBJECT (new)); - return NULL; - } - - /* FIXME: we may want to do better than this... */ - charset = best_charset (data, composer->charset, &plain_encoding); - type = header_content_type_new ("text", "plain"); - if (charset) - header_content_type_set_param (type, "charset", charset); - - plain = camel_data_wrapper_new (); - stream = camel_stream_mem_new_with_byte_array (data); - camel_data_wrapper_construct_from_stream (plain, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - camel_data_wrapper_set_mime_type_field (plain, type); - header_content_type_unref (type); - - if (composer->send_html) { - data = get_text (composer->persist_stream_interface, "text/html"); - if (!data) { - /* The component has probably died */ - camel_object_unref (CAMEL_OBJECT (new)); - camel_object_unref (CAMEL_OBJECT (plain)); - return NULL; - } - html = camel_data_wrapper_new (); - stream = camel_stream_mem_new_with_byte_array (data); - camel_data_wrapper_construct_from_stream (html, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - camel_data_wrapper_set_mime_type (html, "text/html; charset=utf-8"); - - /* Build the multipart/alternative */ - body = camel_multipart_new (); - camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (body), - "multipart/alternative"); - camel_multipart_set_boundary (body, NULL); - - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), plain); - camel_object_unref (CAMEL_OBJECT (plain)); - camel_mime_part_set_encoding (part, plain_encoding); - camel_multipart_add_part (body, part); - camel_object_unref (CAMEL_OBJECT (part)); - - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), html); - camel_object_unref (CAMEL_OBJECT (html)); - camel_multipart_add_part (body, part); - camel_object_unref (CAMEL_OBJECT (part)); - - /* If there are inlined images, construct a - * multipart/related containing the - * multipart/alternative and the images. - */ - if (g_hash_table_size (composer->inline_images)) { - CamelMultipart *html_with_images; - - html_with_images = camel_multipart_new (); - camel_data_wrapper_set_mime_type ( - CAMEL_DATA_WRAPPER (html_with_images), - "multipart/related; type=\"multipart/alternative\""); - camel_multipart_set_boundary (html_with_images, NULL); - - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (body)); - camel_object_unref (CAMEL_OBJECT (body)); - camel_multipart_add_part (html_with_images, part); - camel_object_unref (CAMEL_OBJECT (part)); - - add_inlined_images (composer, html_with_images); - current = CAMEL_DATA_WRAPPER (html_with_images); - } else - current = CAMEL_DATA_WRAPPER (body); - } else - current = plain; - - if (e_msg_composer_attachment_bar_get_num_attachments (attachment_bar)) { - CamelMultipart *multipart = camel_multipart_new (); - - /* Generate a random boundary. */ - camel_multipart_set_boundary (multipart, NULL); - - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), current); - if (current == plain) - camel_mime_part_set_encoding (part, plain_encoding); - camel_object_unref (CAMEL_OBJECT (current)); - camel_multipart_add_part (multipart, part); - camel_object_unref (CAMEL_OBJECT (part)); - - e_msg_composer_attachment_bar_to_multipart (attachment_bar, multipart, composer->charset); - - current = CAMEL_DATA_WRAPPER (multipart); - } - - if (composer->pgp_sign || composer->pgp_encrypt) { - part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (part), current); - if (current == plain) - camel_mime_part_set_encoding (part, plain_encoding); - camel_object_unref (CAMEL_OBJECT (current)); - - if (composer->pgp_sign) { - CamelInternetAddress *from = NULL; - const char *pgpid; - - camel_exception_init (&ex); - - if (hdrs->account && hdrs->account->pgp_key) { - pgpid = hdrs->account->pgp_key; - } else { - /* time for plan b */ - from = e_msg_composer_hdrs_get_from (hdrs); - camel_internet_address_get (from, 0, NULL, &pgpid); - } - - mail_crypto_pgp_mime_part_sign (&part, pgpid, CAMEL_CIPHER_HASH_SHA1, &ex); - - if (from) - camel_object_unref (CAMEL_OBJECT (from)); - - if (camel_exception_is_set (&ex)) - goto exception; - } - - if (composer->pgp_encrypt) { - /* FIXME: recipients should be an array of key ids rather than email addresses */ - const CamelInternetAddress *addr; - const char *address; - GPtrArray *recipients; - int i, len; - - camel_exception_init (&ex); - recipients = g_ptr_array_new (); - - /* check to see if we should encrypt to self */ - if (hdrs->account && hdrs->account->pgp_encrypt_to_self) { - CamelInternetAddress *from = NULL; - - if (hdrs->account->pgp_key) { - address = hdrs->account->pgp_key; - } else { - /* time for plan b */ - from = e_msg_composer_hdrs_get_from (hdrs); - camel_internet_address_get (from, 0, NULL, &address); - } - - g_ptr_array_add (recipients, g_strdup (address)); - - if (from) - camel_object_unref (CAMEL_OBJECT (from)); - } - - addr = camel_mime_message_get_recipients (new, CAMEL_RECIPIENT_TYPE_TO); - len = camel_address_length (CAMEL_ADDRESS (addr)); - for (i = 0; i < len; i++) { - camel_internet_address_get (addr, i, NULL, &address); - g_ptr_array_add (recipients, g_strdup (address)); - } - - addr = camel_mime_message_get_recipients (new, CAMEL_RECIPIENT_TYPE_CC); - len = camel_address_length (CAMEL_ADDRESS (addr)); - for (i = 0; i < len; i++) { - camel_internet_address_get (addr, i, NULL, &address); - g_ptr_array_add (recipients, g_strdup (address)); - } - - addr = camel_mime_message_get_recipients (new, CAMEL_RECIPIENT_TYPE_BCC); - len = camel_address_length (CAMEL_ADDRESS (addr)); - for (i = 0; i < len; i++) { - camel_internet_address_get (addr, i, NULL, &address); - g_ptr_array_add (recipients, g_strdup (address)); - } - - mail_crypto_pgp_mime_part_encrypt (&part, recipients, &ex); - for (i = 0; i < recipients->len; i++) - g_free (recipients->pdata[i]); - g_ptr_array_free (recipients, TRUE); - if (camel_exception_is_set (&ex)) - goto exception; - } - - current = camel_medium_get_content_object (CAMEL_MEDIUM (part)); - camel_object_ref (CAMEL_OBJECT (current)); - camel_object_unref (CAMEL_OBJECT (part)); - } - - camel_medium_set_content_object (CAMEL_MEDIUM (new), current); - if (current == plain) - camel_mime_part_set_encoding (CAMEL_MIME_PART (new), plain_encoding); - camel_object_unref (CAMEL_OBJECT (current)); - -#ifdef HAVE_NSS - if (composer->smime_sign) { - CamelInternetAddress *from = NULL; - CamelMimeMessage *smime_mesg; - const char *certname; - - camel_exception_init (&ex); - - if (hdrs->account && hdrs->account->smime_key) { - certname = hdrs->account->smime_key; - } else { - /* time for plan b */ - from = e_msg_composer_hdrs_get_from (hdrs); - camel_internet_address_get (from, 0, NULL, &certname); - } - - smime_mesg = mail_crypto_smime_sign (new, certname, TRUE, TRUE, &ex); - - if (from) - camel_object_unref (CAMEL_OBJECT (from)); - - if (camel_exception_is_set (&ex)) - goto exception; - - camel_object_unref (CAMEL_OBJECT (new)); - new = smime_mesg; - } - - if (composer->smime_encrypt) { - /* FIXME: we should try to get the preferred cert "nickname" for each recipient */ - const CamelInternetAddress *addr = NULL; - CamelInternetAddress *from = NULL; - CamelMimeMessage *smime_mesg; - const char *address; - GPtrArray *recipients; - int i, len; - - camel_exception_init (&ex); - recipients = g_ptr_array_new (); - - /* check to see if we should encrypt to self */ - if (hdrs->account && hdrs->account->smime_encrypt_to_self) { - if (hdrs->account->smime_key) { - address = hdrs->account->smime_key; - } else { - /* time for plan b */ - from = e_msg_composer_hdrs_get_from (hdrs); - camel_internet_address_get (from, 0, NULL, &address); - } - - g_ptr_array_add (recipients, g_strdup (address)); - - if (from) - camel_object_unref (CAMEL_OBJECT (addr)); - } - - addr = camel_mime_message_get_recipients (new, CAMEL_RECIPIENT_TYPE_TO); - len = camel_address_length (CAMEL_ADDRESS (addr)); - for (i = 0; i < len; i++) { - camel_internet_address_get (addr, i, NULL, &address); - g_ptr_array_add (recipients, g_strdup (address)); - } - - addr = camel_mime_message_get_recipients (new, CAMEL_RECIPIENT_TYPE_CC); - len = camel_address_length (CAMEL_ADDRESS (addr)); - for (i = 0; i < len; i++) { - camel_internet_address_get (addr, i, NULL, &address); - g_ptr_array_add (recipients, g_strdup (address)); - } - - addr = camel_mime_message_get_recipients (new, CAMEL_RECIPIENT_TYPE_BCC); - len = camel_address_length (CAMEL_ADDRESS (addr)); - for (i = 0; i < len; i++) { - camel_internet_address_get (addr, i, NULL, &address); - g_ptr_array_add (recipients, g_strdup (address)); - } - - from = e_msg_composer_hdrs_get_from (E_MSG_COMPOSER_HDRS (composer->hdrs)); - camel_internet_address_get (from, 0, NULL, &address); - - smime_mesg = mail_crypto_smime_encrypt (new, address, recipients, &ex); - - camel_object_unref (CAMEL_OBJECT (from)); - - for (i = 0; i < recipients->len; i++) - g_free (recipients->pdata[i]); - g_ptr_array_free (recipients, TRUE); - - if (camel_exception_is_set (&ex)) - goto exception; - - camel_object_unref (CAMEL_OBJECT (new)); - new = smime_mesg; - } - - /* FIXME: what about mail_crypto_smime_certsonly()?? */ - - /* FIXME: what about mail_crypto_smime_envelope()?? */ - -#endif /* HAVE_NSS */ - - return new; - - exception: - - if (part != CAMEL_MIME_PART (new)) - camel_object_unref (CAMEL_OBJECT (part)); - - camel_object_unref (CAMEL_OBJECT (new)); - - if (camel_exception_is_set (&ex)) { - GtkWidget *dialog; - - dialog = gnome_error_dialog_parented (camel_exception_get_description (&ex), - GTK_WINDOW (composer)); - gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); - camel_exception_clear (&ex); - } - - return NULL; -} - -static char * -read_file_content (gint fd) -{ - GByteArray *contents; - gchar buf[4096]; - gint n; - gchar *body; - - g_return_val_if_fail (fd > 0, NULL); - - contents = g_byte_array_new (); - while ((n = read (fd, buf, 4096)) > 0) { - g_byte_array_append (contents, buf, n); - } - g_byte_array_append (contents, "\0", 1); - - body = (n < 0) ? NULL : (gchar *)contents->data; - g_byte_array_free (contents, (n < 0)); - - return body; -} - -static char * -get_file_content (const gchar *file_name, gboolean convert, guint flags) -{ - gint fd; - char *raw; - char *html; - - fd = open (file_name, O_RDONLY); - if (fd == -1) { - char *msg; - - msg = g_strdup_printf (_("Could not open file %s:\n" - "%s"), file_name, g_strerror (errno)); - - gnome_error_dialog (msg); - g_free (msg); - return NULL; - } - - raw = read_file_content (fd); - - if (raw == NULL) { - char *msg; - - msg = g_strdup_printf (_("Error while reading file %s:\n" - "%s"), file_name, g_strerror (errno)); - - gnome_error_dialog (msg); - g_free (msg); - close (fd); - return NULL; - } - close (fd); - - html = convert ? e_text_to_html (raw, flags) : raw; - - if (convert) - g_free (raw); - - return html; -} - -char * -e_msg_composer_get_sig_file_content (const char *sigfile, gboolean in_html) -{ - if (!sigfile || !*sigfile) { - return NULL; - } - - return get_file_content (sigfile, !in_html, 0); -} - -static void -prepare_engine (EMsgComposer *composer) -{ - CORBA_Environment ev; - - g_assert (composer); - g_assert (E_IS_MSG_COMPOSER (composer)); - - /* printf ("prepare_engine\n"); */ - - CORBA_exception_init (&ev); - composer->editor_engine = (GNOME_GtkHTML_Editor_Engine) bonobo_object_client_query_interface - (bonobo_widget_get_server (BONOBO_WIDGET (composer->editor)), "IDL:GNOME/GtkHTML/Editor/Engine:1.0", &ev); - if (composer->editor_engine != CORBA_OBJECT_NIL) { - - /* printf ("trying set listener\n"); */ - composer->editor_listener = BONOBO_OBJECT (listener_new (composer)); - if (composer->editor_listener != CORBA_OBJECT_NIL) - GNOME_GtkHTML_Editor_Engine__set_listener (composer->editor_engine, - (GNOME_GtkHTML_Editor_Listener) - bonobo_object_dup_ref - (bonobo_object_corba_objref (composer->editor_listener), &ev), - &ev); - else - g_warning ("Can't establish Editor Listener\n"); - } else - g_warning ("Can't get Editor Engine\n"); - CORBA_exception_free (&ev); -} - -static gchar * -get_signature_html (EMsgComposer *composer) -{ - gboolean format_html = FALSE; - gchar *text, *html = NULL, *sig_file = NULL; - - if (E_MSG_COMPOSER_HDRS (composer->hdrs)->account->id) { - MailConfigIdentity *id; - - id = E_MSG_COMPOSER_HDRS (composer->hdrs)->account->id; - if (composer->send_html) { - if (id->has_html_signature) { - sig_file = id->html_signature; - format_html = TRUE; - } else - sig_file = id->signature; - } else - sig_file = id->signature; - } - - if (!sig_file) - return NULL; - - text = e_msg_composer_get_sig_file_content (sig_file, format_html); - if (text) { - html = g_strdup_printf ("<!--+GtkHTML:<DATA class=\"ClueFlow\" key=\"signature\" value=\"1\">-->" - "<TABLE WIDTH=\"100%%\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD>" - "%s%s%s%s" - "</TD></TR></TABLE>", - format_html ? "" : "<PRE>\n", - format_html || !strncmp ("-- \n", text, 3) ? "" : "--\n", - text, - format_html ? "" : "</PRE>\n"); - g_free (text); - text = html; - } - - return text; -} - -static void -set_editor_text (EMsgComposer *composer, const char *text) -{ - Bonobo_PersistStream persist; - BonoboStream *stream; - BonoboWidget *editor; - CORBA_Environment ev; - - editor = BONOBO_WIDGET (composer->editor); - - CORBA_exception_init (&ev); - persist = (Bonobo_PersistStream) bonobo_object_client_query_interface ( - bonobo_widget_get_server (editor), "IDL:Bonobo/PersistStream:1.0", &ev); - g_assert (persist != CORBA_OBJECT_NIL); - - stream = bonobo_stream_mem_create (text, strlen (text), - TRUE, FALSE); - Bonobo_PersistStream_load (persist, (Bonobo_Stream)bonobo_object_corba_objref (BONOBO_OBJECT (stream)), - "text/html", &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - /* FIXME. Some error message. */ - return; - } - if (ev._major != CORBA_SYSTEM_EXCEPTION) - CORBA_Object_release (persist, &ev); - - Bonobo_Unknown_unref (persist, &ev); - CORBA_exception_free (&ev); - bonobo_object_unref (BONOBO_OBJECT(stream)); -} - -static void -set_config (EMsgComposer *composer, char *key, int val) -{ - char *full_key; - - if (composer->config_db == CORBA_OBJECT_NIL) - return; - - full_key = g_strconcat ("/Mail/Composer/", key, NULL); - - bonobo_config_set_long (composer->config_db, full_key, val, NULL); - - g_free (full_key); -} - - -/* Commands. */ - -static void -show_attachments (EMsgComposer *composer, - gboolean show) -{ - if (show) { - gtk_widget_show (composer->attachment_scroll_frame); - gtk_widget_show (composer->attachment_bar); - } else { - gtk_widget_hide (composer->attachment_scroll_frame); - gtk_widget_hide (composer->attachment_bar); - } - - composer->attachment_bar_visible = show; - - /* Update the GUI. */ - -#if 0 - gtk_check_menu_item_set_active - (GTK_CHECK_MENU_ITEM - (glade_xml_get_widget (composer->menubar_gui, - "menu_view_attachments")), - show); -#endif - - /* XXX we should update the toggle toolbar item as well. At - this point, it is not a toggle because Glade is broken. */ -} - -static void -save (EMsgComposer *composer, - const char *file_name) -{ - CORBA_Environment ev; - char *my_file_name; - int fd; - - if (file_name != NULL) - my_file_name = g_strdup (file_name); - else - my_file_name = e_msg_composer_select_file (composer, _("Save as...")); - - if (my_file_name == NULL) - return; - - /* check to see if we already have the file */ - if ((fd = open (my_file_name, O_RDONLY | O_CREAT | O_EXCL)) == -1) { - GtkWidget *dialog, *label; - - dialog = gnome_dialog_new (_("Warning!"), GNOME_STOCK_BUTTON_YES, - GNOME_STOCK_BUTTON_NO, NULL); - label = gtk_label_new (_("File exists, overwrite?")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0); - - switch (gnome_dialog_run_and_close (GNOME_DIALOG (dialog))) { - case -1: - gtk_widget_destroy (dialog); - return; - case 1: - return; - default: - /* ie, the user hit "Yes" so just continue as normal */ - } - } else - close (fd); - - CORBA_exception_init (&ev); - - Bonobo_PersistFile_save (composer->persist_file_interface, my_file_name, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Error saving file: %s"), g_basename (file_name)); - } - - CORBA_exception_free (&ev); - - g_free (my_file_name); -} - -static void -load (EMsgComposer *composer, - const char *file_name) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - Bonobo_PersistFile_load (composer->persist_file_interface, file_name, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Error loading file: %s"), g_basename (file_name)); - - CORBA_exception_free (&ev); -} - -/* Exit dialog. (Displays a "Save composition to 'Drafts' before exiting?" warning before actually exiting.) */ - -enum { REPLY_YES = 0, REPLY_NO, REPLY_CANCEL }; - -struct _save_info { - EMsgComposer *composer; - int quitok; -}; - -static void -save_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info, int ok, void *data) -{ - struct _save_info *si = data; - - if (ok && si->quitok) - gtk_widget_destroy (GTK_WIDGET (si->composer)); - else - gtk_object_unref (GTK_OBJECT (si->composer)); - - g_free (info); - g_free (si); -} - -extern CamelFolder *drafts_folder; -extern char *default_drafts_folder_uri; - -static void -use_default_drafts_cb (gint reply, gpointer data) -{ - CamelFolder **folder = data; - - if (reply == 0) - *folder = drafts_folder; -} - -static void -save_folder (char *uri, CamelFolder *folder, gpointer data) -{ - CamelFolder **save = data; - - if (folder) { - *save = folder; - camel_object_ref (CAMEL_OBJECT (folder)); - } -} - -static void -save_draft (EMsgComposer *composer, int quitok) -{ - CamelMimeMessage *msg; - CamelMessageInfo *info; - const MailConfigAccount *account; - struct _save_info *si; - CamelFolder *folder = NULL; - - account = e_msg_composer_get_preferred_account (composer); - if (account && account->drafts_folder_uri && - strcmp (account->drafts_folder_uri, default_drafts_folder_uri) != 0) { - int id; - - id = mail_get_folder (account->drafts_folder_uri, save_folder, &folder); - mail_msg_wait (id); - - if (!folder) { - GtkWidget *dialog; - - dialog = gnome_ok_cancel_dialog_parented (_("Unable to open the drafts folder for this account.\n" - "Would you like to use the default drafts folder?"), - use_default_drafts_cb, &folder, GTK_WINDOW (composer)); - gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); - if (!folder) - return; - } - } else - folder = drafts_folder; - - msg = e_msg_composer_get_message_draft (composer); - - info = g_new0 (CamelMessageInfo, 1); - info->flags = CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_SEEN; - - si = g_malloc (sizeof (*si)); - si->composer = composer; - gtk_object_ref (GTK_OBJECT (composer)); - si->quitok = quitok; - - mail_append_mail (folder, msg, info, save_done, si); - camel_object_unref (CAMEL_OBJECT (msg)); -} - -#define AUTOSAVE_SEED ".evolution-composer.autosave-XXXXXX" -#define AUTOSAVE_INTERVAL 60000 - -typedef struct _AutosaveManager AutosaveManager; -struct _AutosaveManager { - GHashTable *table; - guint id; - gboolean ask; -}; - -static AutosaveManager *am = NULL; - -static gboolean -autosave_save_draft (EMsgComposer *composer) -{ - CamelMimeMessage *msg; - CamelStream *stream; - char *file; - gint fd; - gboolean success = TRUE; - - fd = composer->autosave_fd; - file = composer->autosave_file; - - if (fd == -1) { - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Error accessing file: %s"), file); - return FALSE; - } - - msg = e_msg_composer_get_message_draft (composer); - - if (msg == NULL) { - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Unable to retrieve message from editor")); - return FALSE; - } - - if (lseek (fd, (off_t)0, SEEK_SET) == -1) { - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Unable to seek on file: %s\n%s"), file, strerror(errno)); - return FALSE; - } - - if (ftruncate (fd, (off_t)0) == -1) { - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Unable to truncate file: %s\n%s"), file, strerror(errno)); - return FALSE; - } - - /* this does an lseek so we don't have to */ - stream = camel_stream_fs_new_with_fd(fd); - if (camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, stream) == -1 - || camel_stream_flush((CamelStream *)stream) == -1) { - e_notice (GTK_WINDOW (composer), GNOME_MESSAGE_BOX_ERROR, - _("Error autosaving message: %s\n %s"), file, strerror(errno)); - - success = FALSE; - } - /* set the fd to -1 in the stream so camel doesn't close it we want to keep it open */ - CAMEL_STREAM_FS (stream)->fd = -1; - camel_object_unref((CamelObject *)stream); - - return success; -} - -static EMsgComposer * -autosave_load_draft (const char *filename) -{ - CamelStream *stream; - CamelMimeMessage *msg; - EMsgComposer *composer; - - g_return_val_if_fail (filename != NULL, NULL); - - g_warning ("autosave load filename = \"%s\"", filename); - - stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0); - - if (stream == NULL) - return NULL; - - msg = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream); - unlink (filename); - - composer = e_msg_composer_new_with_message (msg); - if (composer) { - autosave_save_draft (composer); - - gtk_signal_connect (GTK_OBJECT (composer), "send", - GTK_SIGNAL_FUNC (composer_send_cb), NULL); - gtk_signal_connect (GTK_OBJECT (composer), "postpone", - GTK_SIGNAL_FUNC (composer_postpone_cb), NULL); - - gtk_widget_show (GTK_WIDGET (composer)); - } - - camel_object_unref ((CamelObject *)stream); - return composer; -} - -static gboolean -autosave_is_owned (AutosaveManager *am, const char *file) -{ - return g_hash_table_lookup (am->table, file) != NULL; -} - -static void -autosave_query_cb (gint reply, gpointer data) -{ - int *yes = data; - - *yes = !reply; -} - -static void -autosave_manager_query_load_orphans (AutosaveManager *am, EMsgComposer *composer) -{ - GtkWidget *dialog; - DIR *dir; - struct dirent *d; - GSList *match = NULL; - gint len = strlen (AUTOSAVE_SEED); - gint load = FALSE; - - dir = opendir (g_get_home_dir()); - if (!dir) { - return; - } - - while ((d = readdir (dir))) { - if ((!strncmp (d->d_name, AUTOSAVE_SEED, len - 6)) - && (strlen (d->d_name) == len) - && (!autosave_is_owned (am, d->d_name))) { - char *filename = g_strdup_printf ("%s/%s", g_get_home_dir(), d->d_name); - struct stat st; - - /* - * check if the file has any length, It is a valid case if it doesn't - * so we simply don't ask then. - */ - if (stat (filename, &st) < 0 || st.st_size == 0) { - unlink (filename); - g_free (filename); - continue; - } - match = g_slist_prepend (match, filename); - } - } - - if (match != NULL) { - dialog = gnome_question_dialog_parented (_("Evolution has found unsaved files from a previous session.\n" - "Would you like to attempt recovery?"), - autosave_query_cb, &load, GTK_WINDOW (composer)); - - gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); - } - - while (match != NULL) { - GSList *next = match->next; - char *filename = match->data; - EMsgComposer *composer; - - if (load) { - composer = autosave_load_draft (filename); - } else { - unlink (filename); - } - - g_free (filename); - g_slist_free_1 (match); - match = next; - } -} - -static void -autosave_run_foreach_cb (gpointer key, gpointer value, gpointer data) -{ - EMsgComposer *composer = E_MSG_COMPOSER (value); - - autosave_save_draft (composer); -} - -static gint -autosave_run (gpointer data) -{ - AutosaveManager *am = data; - - g_hash_table_foreach (am->table, (GHFunc)autosave_run_foreach_cb, am); - - return TRUE; -} - -static gboolean -autosave_init_file (EMsgComposer *composer) -{ - if (composer->autosave_file == NULL) { - composer->autosave_file = g_strdup_printf ("%s/%s", g_get_home_dir(), AUTOSAVE_SEED); - composer->autosave_fd = mkstemp (composer->autosave_file); - return TRUE; - } - return FALSE; -} -static void -autosave_manager_start (AutosaveManager *am) -{ - if (am->id == 0) - am->id = gtk_timeout_add (AUTOSAVE_INTERVAL, autosave_run, am); -} - -static void -autosave_manager_stop (AutosaveManager *am) -{ - if (am->id) { - gtk_timeout_remove (am->id); - am->id = 0; - } -} - -static AutosaveManager * -autosave_manager_new () -{ - AutosaveManager *am; - - am = g_new (AutosaveManager, 1); - am->table = g_hash_table_new (g_str_hash, g_str_equal); - am->id = 0; - am->ask = TRUE; - - return am; -} - -static void -autosave_manager_register (AutosaveManager *am, EMsgComposer *composer) -{ - char *key; - - g_return_if_fail (composer != NULL); - - if (autosave_init_file (composer)) { - key = g_basename (composer->autosave_file); - g_hash_table_insert (am->table, key, composer); - if (am->ask) { - /* keep recursion out of our bedrooms. */ - am->ask = FALSE; - autosave_manager_query_load_orphans (am, composer); - am->ask = TRUE; - } - - } - autosave_manager_start (am); -} - -static void -autosave_manager_unregister (AutosaveManager *am, EMsgComposer *composer) -{ - g_hash_table_remove (am->table, g_basename (composer->autosave_file)); - - /* only remove the file if we can successfully save it */ - /* FIXME this test could probably be more efficient */ - if (autosave_save_draft (composer)) { - unlink (composer->autosave_file); - } - close (composer->autosave_fd); - g_free (composer->autosave_file); - - if (g_hash_table_size (am->table) == 0) - autosave_manager_stop (am); -} - -static void -menu_file_save_draft_cb (BonoboUIComponent *uic, void *data, const char *path) -{ - save_draft (E_MSG_COMPOSER (data), FALSE); -} - -static void -exit_dialog_cb (int reply, EMsgComposer *composer) -{ - switch (reply) { - case REPLY_YES: - /* this has to be done async */ - save_draft(composer, TRUE); - break; - case REPLY_NO: - gtk_widget_destroy (GTK_WIDGET (composer)); - break; - case REPLY_CANCEL: - default: - } -} - -static void -do_exit (EMsgComposer *composer) -{ - GtkWidget *dialog; - gint button; - - if (composer->has_changed) { - dialog = gnome_message_box_new (_("This message has not been sent.\n\nDo you wish to save your changes?"), - GNOME_MESSAGE_BOX_QUESTION, - GNOME_STOCK_BUTTON_YES, /* Save */ - GNOME_STOCK_BUTTON_NO, /* Don't save */ - GNOME_STOCK_BUTTON_CANCEL, /* Cancel */ - NULL); - - gtk_window_set_title (GTK_WINDOW (dialog), _("Evolution")); - gnome_dialog_set_parent (GNOME_DIALOG (dialog), GTK_WINDOW (composer)); - gnome_dialog_set_default (GNOME_DIALOG (dialog), 0); - button = gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); - - exit_dialog_cb (button, composer); - } else { - gtk_widget_destroy (GTK_WIDGET (composer)); - } -} - -/* Menu callbacks. */ - -static void -menu_file_open_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - EMsgComposer *composer; - char *file_name; - - composer = E_MSG_COMPOSER (data); - - file_name = e_msg_composer_select_file (composer, _("Open file")); - if (file_name == NULL) - return; - - load (composer, file_name); - - g_free (file_name); -} - -static void -menu_file_save_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - EMsgComposer *composer; - CORBA_char *file_name; - CORBA_Environment ev; - - composer = E_MSG_COMPOSER (data); - - CORBA_exception_init (&ev); - - file_name = Bonobo_PersistFile_getCurrentFile (composer->persist_file_interface, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - save (composer, NULL); - } else { - save (composer, file_name); - CORBA_free (file_name); - } - CORBA_exception_free (&ev); -} - -static void -menu_file_save_as_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - - save (composer, NULL); -} - -static void -menu_file_send_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - if (camel_session_is_online (session)) - gtk_signal_emit (GTK_OBJECT (data), signals[SEND]); - else - gtk_signal_emit (GTK_OBJECT (data), signals[POSTPONE]); -} - -static void -menu_file_send_later_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - gtk_signal_emit (GTK_OBJECT (data), signals[POSTPONE]); -} - -static void -menu_file_close_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - do_exit (composer); -} - -static void -menu_file_add_attachment_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - - e_msg_composer_attachment_bar_attach - (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar), - NULL); -} - -static void -menu_edit_delete_all_cb (BonoboUIComponent *uic, void *data, const char *path) -{ - CORBA_Environment ev; - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - CORBA_exception_init (&ev); - - GNOME_GtkHTML_Editor_Engine_undo_begin (composer->editor_engine, "Delete all but signature", "Undelete all", &ev); - GNOME_GtkHTML_Editor_Engine_freeze (composer->editor_engine, &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "disable-selection", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "text-default-color", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "bold-off", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "italic-off", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "underline-off", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "strikeout-off", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "select-all", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "delete", &ev); - GNOME_GtkHTML_Editor_Engine_setParagraphData (composer->editor_engine, "signature", "0", &ev); - GNOME_GtkHTML_Editor_Engine_setParagraphData (composer->editor_engine, "orig", "0", &ev); - e_msg_composer_show_sig_file (composer); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "style-normal", &ev); - GNOME_GtkHTML_Editor_Engine_thaw (composer->editor_engine, &ev); - GNOME_GtkHTML_Editor_Engine_undo_end (composer->editor_engine, &ev); - - CORBA_exception_free (&ev); - printf ("delete all\n"); -} - -static void -menu_view_attachments_activate_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) - -{ - gboolean new_state; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - new_state = atoi (state); - - e_msg_composer_show_attachments (E_MSG_COMPOSER (user_data), new_state); -} - -static void -menu_file_insert_file_cb (BonoboUIComponent *uic, - void *data, - const char *path) -{ - EMsgComposer *composer; - char *file_name; - char *html; - CORBA_Environment ev; - - composer = E_MSG_COMPOSER (data); - - file_name = e_msg_composer_select_file (composer, _("Insert File")); - if (file_name == NULL) - return; - - html = get_file_content (file_name, TRUE, E_TEXT_TO_HTML_PRE); - if (html == NULL) - return; - - CORBA_exception_init (&ev); - GNOME_GtkHTML_Editor_Engine_freeze (composer->editor_engine, &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "cursor-position-save", &ev); - GNOME_GtkHTML_Editor_Engine_undo_begin (composer->editor_engine, "Insert file", "Uninsert file", &ev); - if (!GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (composer->editor_engine, &ev)) - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "insert-paragraph", &ev); - GNOME_GtkHTML_Editor_Engine_insertHTML (composer->editor_engine, html, &ev); - GNOME_GtkHTML_Editor_Engine_undo_end (composer->editor_engine, &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "cursor-position-restore", &ev); - GNOME_GtkHTML_Editor_Engine_thaw (composer->editor_engine, &ev); - CORBA_exception_free (&ev); - - g_free (html); -} - -static void -menu_format_html_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) - -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_send_html (E_MSG_COMPOSER (user_data), atoi (state)); -} - -static void -menu_security_pgp_sign_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer composer) - -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_pgp_sign (E_MSG_COMPOSER (composer), atoi (state)); -} - -static void -menu_security_pgp_encrypt_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer composer) - -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_pgp_encrypt (E_MSG_COMPOSER (composer), atoi (state)); -} - -static void -menu_security_smime_sign_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer composer) - -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_smime_sign (E_MSG_COMPOSER (composer), atoi (state)); -} - -static void -menu_security_smime_encrypt_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer composer) - -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_smime_encrypt (E_MSG_COMPOSER (composer), atoi (state)); -} - - -static void -menu_view_from_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_view_from (E_MSG_COMPOSER (user_data), atoi (state)); -} - -static void -menu_view_replyto_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_view_replyto (E_MSG_COMPOSER (user_data), atoi (state)); -} - -static void -menu_view_bcc_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_view_bcc (E_MSG_COMPOSER (user_data), atoi (state)); -} - -static void -menu_view_cc_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - e_msg_composer_set_view_cc (E_MSG_COMPOSER (user_data), atoi (state)); -} - -static void -menu_changed_charset_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) -{ - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - if (atoi (state)) { - /* Charset menu names are "Charset-%s" where %s is the charset name */ - g_free (E_MSG_COMPOSER (user_data)->charset); - E_MSG_COMPOSER (user_data)->charset = g_strdup (path + strlen ("Charset-")); - } -} - - -static BonoboUIVerb verbs [] = { - - BONOBO_UI_VERB ("FileOpen", menu_file_open_cb), - BONOBO_UI_VERB ("FileSave", menu_file_save_cb), - BONOBO_UI_VERB ("FileSaveAs", menu_file_save_as_cb), - BONOBO_UI_VERB ("FileSaveDraft", menu_file_save_draft_cb), - BONOBO_UI_VERB ("FileClose", menu_file_close_cb), - - BONOBO_UI_VERB ("FileInsertFile", menu_file_insert_file_cb), - BONOBO_UI_VERB ("FileAttach", menu_file_add_attachment_cb), - - BONOBO_UI_VERB ("FileSend", menu_file_send_cb), - BONOBO_UI_VERB ("FileSendLater", menu_file_send_later_cb), - - BONOBO_UI_VERB ("DeleteAll", menu_edit_delete_all_cb), - - BONOBO_UI_VERB_END -}; - -static EPixmap pixcache [] = { - E_PIXMAP ("/Toolbar/FileAttach", "buttons/add-attachment.png"), - - E_PIXMAP_END -}; - -static void -setup_ui (EMsgComposer *composer) -{ - BonoboUIContainer *container; - gboolean hide_smime; - - container = bonobo_ui_container_new (); - bonobo_ui_container_set_win (container, BONOBO_WINDOW (composer)); - - composer->uic = bonobo_ui_component_new ("evolution-message-composer"); - bonobo_ui_component_set_container ( - composer->uic, bonobo_object_corba_objref (BONOBO_OBJECT (container))); - - bonobo_ui_component_add_verb_list_with_data ( - composer->uic, verbs, composer); - - bonobo_ui_component_freeze (composer->uic, NULL); - - bonobo_ui_util_set_ui (composer->uic, EVOLUTION_DATADIR, - "evolution-message-composer.xml", - "evolution-message-composer"); - - e_pixmaps_update (composer->uic, pixcache); - - e_charset_picker_bonobo_ui_populate (composer->uic, NULL, - menu_changed_charset_cb, - composer); - - if (!camel_session_is_online (session)) { - /* Move the accelerator from Send to Send Later */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/FileSend", - "accel", NULL, NULL); - bonobo_ui_component_set_prop ( - composer->uic, "/commands/FileSendLater", - "accel", "*Ctrl*Return", NULL); - } - - /* Format -> HTML */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/FormatHtml", - "state", composer->send_html ? "1" : "0", NULL); - bonobo_ui_component_add_listener ( - composer->uic, "FormatHtml", - menu_format_html_cb, composer); - - /* View/From */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewFrom", - "state", composer->view_from ? "1" : "0", NULL); - bonobo_ui_component_add_listener ( - composer->uic, "ViewFrom", - menu_view_from_cb, composer); - - /* View/ReplyTo */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewReplyTo", - "state", composer->view_replyto ? "1" : "0", NULL); - bonobo_ui_component_add_listener ( - composer->uic, "ViewReplyTo", - menu_view_replyto_cb, composer); - - /* View/BCC */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewBCC", - "state", composer->view_bcc ? "1" : "0", NULL); - bonobo_ui_component_add_listener ( - composer->uic, "ViewBCC", - menu_view_bcc_cb, composer); - - /* View/CC */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewCC", - "state", composer->view_cc ? "1" : "0", NULL); - bonobo_ui_component_add_listener ( - composer->uic, "ViewCC", - menu_view_cc_cb, composer); - - /* Security -> PGP Sign */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/SecurityPGPSign", - "state", composer->pgp_sign ? "1" : "0", NULL); - - bonobo_ui_component_add_listener ( - composer->uic, "SecurityPGPSign", - menu_security_pgp_sign_cb, composer); - - /* Security -> PGP Encrypt */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/SecurityPGPEncrypt", - "state", composer->pgp_encrypt ? "1" : "0", NULL); - - bonobo_ui_component_add_listener ( - composer->uic, "SecurityPGPEncrypt", - menu_security_pgp_encrypt_cb, composer); - -#ifdef HAVE_NSS - hide_smime = FALSE; -#else - hide_smime = TRUE; -#endif - - /* Security -> S/MIME Sign */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/SecuritySMimeSign", - "state", composer->smime_sign ? "1" : "0", NULL); - bonobo_ui_component_set_prop ( - composer->uic, "/commands/SecuritySMimeSign", - "hidden", hide_smime ? "1" : "0", NULL); - - bonobo_ui_component_add_listener ( - composer->uic, "SecuritySMimeSign", - menu_security_smime_sign_cb, composer); - - /* Security -> S/MIME Encrypt */ - bonobo_ui_component_set_prop ( - composer->uic, "/commands/SecuritySMimeEncrypt", - "state", composer->smime_encrypt ? "1" : "0", NULL); - bonobo_ui_component_set_prop ( - composer->uic, "/commands/SecuritySMimeEncrypt", - "hidden", hide_smime ? "1" : "0", NULL); - - bonobo_ui_component_add_listener ( - composer->uic, "SecuritySMimeEncrypt", - menu_security_smime_encrypt_cb, composer); - - /* View -> Attachments */ - bonobo_ui_component_add_listener ( - composer->uic, "ViewAttach", - menu_view_attachments_activate_cb, composer); - - bonobo_ui_component_thaw (composer->uic, NULL); -} - - -/* Miscellaneous callbacks. */ - -static void -attachment_bar_changed_cb (EMsgComposerAttachmentBar *bar, - void *data) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - - if (e_msg_composer_attachment_bar_get_num_attachments (bar) > 0) - e_msg_composer_show_attachments (composer, TRUE); - else - e_msg_composer_show_attachments (composer, FALSE); - - /* Mark the composer as changed so it prompts about unsaved changes on close */ - e_msg_composer_set_changed (composer); -} - -static void -subject_changed_cb (EMsgComposerHdrs *hdrs, - gchar *subject, - void *data) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - - if (strlen (subject)) - gtk_window_set_title (GTK_WINDOW (composer), subject); - else - gtk_window_set_title (GTK_WINDOW (composer), - _("Compose a message")); - g_free (subject); -} - -static void -hdrs_changed_cb (EMsgComposerHdrs *hdrs, - void *data) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - - /* Mark the composer as changed so it prompts about unsaved changes on close */ - e_msg_composer_set_changed (composer); -} - -static void -from_changed_cb (EMsgComposerHdrs *hdrs, - void *data) -{ - EMsgComposer *composer; - - composer = E_MSG_COMPOSER (data); - - e_msg_composer_show_sig_file (composer); -} - - -/* GtkObject methods. */ - -static void -composer_shutdown (GtkObject *object) -{ - /* When destroy() is called, the contents of the window - * (including the remote editor control) will already have - * been destroyed, so we have to do this here. - */ - autosave_manager_unregister (am, E_MSG_COMPOSER (object)); - if (GTK_OBJECT_CLASS (parent_class)->shutdown != NULL) - (* GTK_OBJECT_CLASS (parent_class)->shutdown) (object); -} - -static void -destroy (GtkObject *object) -{ - EMsgComposer *composer; - CORBA_Environment ev; - - composer = E_MSG_COMPOSER (object); - - CORBA_exception_init (&ev); - - if (composer->config_db) { - Bonobo_ConfigDatabase_sync (composer->config_db, &ev); - bonobo_object_release_unref (composer->config_db, NULL); - } - composer->config_db = NULL; - - if (composer->uic) - bonobo_object_unref (BONOBO_OBJECT (composer->uic)); - composer->uic = NULL; - - /* FIXME? I assume the Bonobo widget will get destroyed - normally? */ - - if (composer->address_dialog != NULL) - gtk_widget_destroy (composer->address_dialog); - if (composer->hdrs != NULL) - gtk_widget_destroy (composer->hdrs); - - if (composer->extra_hdr_names) { - int i; - - for (i = 0; i < composer->extra_hdr_names->len; i++) { - g_free (composer->extra_hdr_names->pdata[i]); - g_free (composer->extra_hdr_values->pdata[i]); - } - g_ptr_array_free (composer->extra_hdr_names, TRUE); - g_ptr_array_free (composer->extra_hdr_values, TRUE); - } - - e_msg_composer_clear_inlined_table (composer); - g_hash_table_destroy (composer->inline_images); - - g_free (composer->charset); - - CORBA_exception_init (&ev); - - if (composer->persist_stream_interface != CORBA_OBJECT_NIL) { - Bonobo_Unknown_unref (composer->persist_stream_interface, &ev); - CORBA_Object_release (composer->persist_stream_interface, &ev); - } - - if (composer->persist_file_interface != CORBA_OBJECT_NIL) { - Bonobo_Unknown_unref (composer->persist_file_interface, &ev); - CORBA_Object_release (composer->persist_file_interface, &ev); - } - - if (composer->editor_engine != CORBA_OBJECT_NIL) { - Bonobo_Unknown_unref (composer->editor_engine, &ev); - CORBA_Object_release (composer->editor_engine, &ev); - } - - CORBA_exception_free (&ev); - - if (composer->editor_listener) - bonobo_object_unref (composer->editor_listener); - - if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - - -/* GtkWidget methods. */ - -static int -delete_event (GtkWidget *widget, - GdkEventAny *event) -{ - do_exit (E_MSG_COMPOSER (widget)); - - return TRUE; -} - -static void -message_rfc822_dnd (EMsgComposer *composer, CamelStream *stream) -{ - CamelMimeParser *mp; - CamelException *ex; - - mp = camel_mime_parser_new (); - camel_mime_parser_scan_from (mp, TRUE); - camel_mime_parser_init_with_stream (mp, stream); - - ex = camel_exception_new (); - - while (camel_mime_parser_step (mp, 0, 0) == HSCAN_FROM) { - CamelMimeMessage *message; - - message = camel_mime_message_new (); - if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (message), mp) == -1) { - camel_object_unref (CAMEL_OBJECT (message)); - break; - } - - e_msg_composer_attachment_bar_attach_mime_part (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar), - CAMEL_MIME_PART (message)); - camel_object_unref (CAMEL_OBJECT (message)); - camel_exception_clear (ex); - - /* skip over the FROM_END state */ - camel_mime_parser_step (mp, 0, 0); - } - - camel_object_unref (CAMEL_OBJECT (mp)); - camel_exception_free (ex); -} - -static void -drag_data_received (EMsgComposer *composer, GdkDragContext *context, - gint x, gint y, GtkSelectionData *selection, - guint info, guint time) -{ - gchar *tmp, *filename, **filenames; - CamelStream *stream; - CamelURL *url; - int i; - - switch (info) { - case DND_TYPE_MESSAGE_RFC822: - /* write the message(s) out to a CamelStream so we can use it */ - stream = camel_stream_mem_new (); - camel_stream_write (stream, selection->data, selection->length); - camel_stream_reset (stream); - - message_rfc822_dnd (composer, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - break; - case DND_TYPE_TEXT_URI_LIST: - tmp = g_strndup (selection->data, selection->length); - filenames = g_strsplit (tmp, "\n", 0); - g_free (tmp); - - for (i = 0; filenames[i] != NULL; i++) { - filename = g_strstrip (filenames[i]); - - url = camel_url_new (filename, NULL); - g_free (filename); - filename = url->path; - url->path = NULL; - camel_url_free (url); - - e_msg_composer_attachment_bar_attach - (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar), - filename); - - g_free (filename); - } - - g_free (filenames); - break; - default: - break; - } -} - - -static void -class_init (EMsgComposerClass *klass) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = GTK_OBJECT_CLASS (klass); - widget_class = GTK_WIDGET_CLASS (klass); - - object_class->shutdown = composer_shutdown; - object_class->destroy = destroy; - - widget_class->delete_event = delete_event; - - parent_class = gtk_type_class (bonobo_window_get_type ()); - - signals[SEND] = - gtk_signal_new ("send", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerClass, send), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - signals[POSTPONE] = - gtk_signal_new ("postpone", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMsgComposerClass, postpone), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -init (EMsgComposer *composer) -{ - composer->uic = NULL; - - composer->hdrs = NULL; - composer->extra_hdr_names = g_ptr_array_new (); - composer->extra_hdr_values = g_ptr_array_new (); - - composer->editor = NULL; - - composer->address_dialog = NULL; - - composer->attachment_bar = NULL; - composer->attachment_scroll_frame = NULL; - - composer->persist_file_interface = CORBA_OBJECT_NIL; - composer->persist_stream_interface = CORBA_OBJECT_NIL; - - composer->editor_engine = CORBA_OBJECT_NIL; - composer->inline_images = g_hash_table_new (g_str_hash, g_str_equal); - - composer->attachment_bar_visible = FALSE; - composer->send_html = FALSE; - composer->pgp_sign = FALSE; - composer->pgp_encrypt = FALSE; - composer->smime_sign = FALSE; - composer->smime_encrypt = FALSE; - - composer->has_changed = FALSE; - - composer->charset = NULL; - composer->autosave_file = NULL; - composer->autosave_fd = -1; - - if (am == NULL) { - am = autosave_manager_new (); - } - autosave_manager_register (am, composer); -} - - -GtkType -e_msg_composer_get_type (void) -{ - static GtkType type = 0; - - if (type == 0) { - static const GtkTypeInfo info = { - "EMsgComposer", - sizeof (EMsgComposer), - sizeof (EMsgComposerClass), - (GtkClassInitFunc) class_init, - (GtkObjectInitFunc) init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (bonobo_window_get_type (), &info); - } - - return type; -} - -static void -load_from_config_db (EMsgComposer *composer) -{ - Bonobo_ConfigDatabase db = composer->config_db; - - composer->view_from = bonobo_config_get_long_with_default (db, - "Mail/Composer/ViewFrom", 1, NULL); - composer->view_replyto = bonobo_config_get_long_with_default (db, - "Mail/Composer/ViewReplyTo", 0, NULL); - composer->view_bcc = bonobo_config_get_long_with_default (db, - "Mail/Composer/ViewBCC", 0, NULL); - composer->view_cc = bonobo_config_get_long_with_default (db, - "Mail/Composer/ViewCC", 1, NULL); - composer->view_subject = bonobo_config_get_long_with_default (db, - "Mail/Composer/ViewSubject", 1, NULL); -} - -static void -e_msg_composer_load_config (EMsgComposer *composer) -{ - Bonobo_ConfigDatabase db; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - db = bonobo_get_object ( "wombat:", "Bonobo/ConfigDatabase", &ev); - - if (ev._major == CORBA_NO_EXCEPTION && db != CORBA_OBJECT_NIL){ - composer->config_db = db; - load_from_config_db (composer); - } else - composer->config_db = CORBA_OBJECT_NIL; - - CORBA_exception_free (&ev); -} - -static gint -e_msg_composer_get_visible_flags (EMsgComposer *composer) -{ - int flags = 0; - - if (composer->view_from) - flags |= E_MSG_COMPOSER_VISIBLE_FROM; - if (composer->view_replyto) - flags |= E_MSG_COMPOSER_VISIBLE_REPLYTO; - if (composer->view_cc) - flags |= E_MSG_COMPOSER_VISIBLE_CC; - if (composer->view_bcc) - flags |= E_MSG_COMPOSER_VISIBLE_BCC; - if (composer->view_subject) - flags |= E_MSG_COMPOSER_VISIBLE_SUBJECT; - - /* - * Until we have a GUI way, lets make sure that - * even if the user screws up, we will do the right - * thing (screws up == edit the config file manually - * and screw up). - */ - flags |= E_MSG_COMPOSER_VISIBLE_SUBJECT; - return flags; -} - -/** - * e_msg_composer_construct: - * @composer: A message composer widget - * - * Construct @composer. - **/ -void -e_msg_composer_construct (EMsgComposer *composer) -{ - GtkWidget *vbox; - BonoboObject *editor_server; - gint vis; - - g_return_if_fail (gtk_main_level () > 0); - - gtk_window_set_default_size (GTK_WINDOW (composer), - DEFAULT_WIDTH, DEFAULT_HEIGHT); - gnome_window_icon_set_from_file (GTK_WINDOW (composer), EVOLUTION_DATADIR - "/images/evolution/compose-message.png"); - bonobo_window_construct (BONOBO_WINDOW (composer), "e-msg-composer", - _("Compose a message")); - - /* DND support */ - gtk_drag_dest_set (GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL, - drop_types, num_drop_types, GDK_ACTION_COPY); - gtk_signal_connect (GTK_OBJECT (composer), "drag_data_received", - GTK_SIGNAL_FUNC (drag_data_received), NULL); - e_msg_composer_load_config (composer); - - setup_ui (composer); - - vbox = gtk_vbox_new (FALSE, 0); - - vis = e_msg_composer_get_visible_flags (composer); - composer->hdrs = e_msg_composer_hdrs_new (vis); - - gtk_box_pack_start (GTK_BOX (vbox), composer->hdrs, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (composer->hdrs), "subject_changed", - GTK_SIGNAL_FUNC (subject_changed_cb), composer); - gtk_signal_connect (GTK_OBJECT (composer->hdrs), "hdrs_changed", - GTK_SIGNAL_FUNC (hdrs_changed_cb), composer); - gtk_signal_connect (GTK_OBJECT (composer->hdrs), "from_changed", - GTK_SIGNAL_FUNC (from_changed_cb), composer); - gtk_widget_show (composer->hdrs); - - /* Editor component. */ - composer->editor = bonobo_widget_new_control ( - GNOME_GTKHTML_EDITOR_CONTROL_ID, - bonobo_ui_component_get_container (composer->uic)); - - if (!composer->editor) - return; - - /* let the editor know which mode we are in */ - bonobo_widget_set_property (BONOBO_WIDGET (composer->editor), - "FormatHTML", composer->send_html, - NULL); - - editor_server = BONOBO_OBJECT (bonobo_widget_get_server (BONOBO_WIDGET (composer->editor))); - - composer->persist_file_interface - = bonobo_object_query_interface (editor_server, "IDL:Bonobo/PersistFile:1.0"); - composer->persist_stream_interface - = bonobo_object_query_interface (editor_server, "IDL:Bonobo/PersistStream:1.0"); - - gtk_box_pack_start (GTK_BOX (vbox), composer->editor, TRUE, TRUE, 0); - - /* Attachment editor, wrapped into an EScrollFrame. We don't - show it for now. */ - - composer->attachment_scroll_frame = e_scroll_frame_new (NULL, NULL); - e_scroll_frame_set_shadow_type (E_SCROLL_FRAME (composer->attachment_scroll_frame), - GTK_SHADOW_IN); - e_scroll_frame_set_policy (E_SCROLL_FRAME (composer->attachment_scroll_frame), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - - composer->attachment_bar = e_msg_composer_attachment_bar_new (NULL); - GTK_WIDGET_SET_FLAGS (composer->attachment_bar, GTK_CAN_FOCUS); - gtk_container_add (GTK_CONTAINER (composer->attachment_scroll_frame), - composer->attachment_bar); - gtk_box_pack_start (GTK_BOX (vbox), - composer->attachment_scroll_frame, - FALSE, FALSE, GNOME_PAD_SMALL); - - gtk_signal_connect (GTK_OBJECT (composer->attachment_bar), "changed", - GTK_SIGNAL_FUNC (attachment_bar_changed_cb), composer); - - bonobo_window_set_contents (BONOBO_WINDOW (composer), vbox); - gtk_widget_show (vbox); - - /* If we show this widget earlier, we lose network transparency. i.e. the - component appears on the machine evo is running on, ignoring any DISPLAY - variable. */ - gtk_widget_show (composer->editor); - - e_msg_composer_show_attachments (composer, FALSE); - - /* Set focus on the `To:' field. - - gtk_widget_grab_focus (e_msg_composer_hdrs_get_to_entry (E_MSG_COMPOSER_HDRS (composer->hdrs))); - GTK_WIDGET_SET_FLAGS (composer->editor, GTK_CAN_FOCUS); - gtk_window_set_focus (GTK_WINDOW (composer), composer->editor); */ - gtk_widget_grab_focus (composer->editor); -} - -static EMsgComposer * -create_composer (void) -{ - EMsgComposer *new; - - new = gtk_type_new (E_TYPE_MSG_COMPOSER); - e_msg_composer_construct (new); - if (!new->editor) { - e_notice (GTK_WINDOW (new), GNOME_MESSAGE_BOX_ERROR, - _("Could not create composer window.")); - gtk_object_unref (GTK_OBJECT (new)); - return NULL; - } - prepare_engine (new); - - return new; -} - -/** - * e_msg_composer_new: - * - * Create a new message composer widget. - * - * Return value: A pointer to the newly created widget - **/ -EMsgComposer * -e_msg_composer_new (void) -{ - EMsgComposer *new; - - new = create_composer (); - if (new) - set_editor_text (new, ""); - - return new; -} - -/** - * e_msg_composer_new_with_sig_file: - * - * Create a new message composer widget. Sets the signature file. - * - * Return value: A pointer to the newly created widget - **/ -EMsgComposer * -e_msg_composer_new_with_sig_file () -{ - EMsgComposer *new; - - new = create_composer (); - if (new) { - e_msg_composer_set_send_html (new, mail_config_get_send_html ()); - set_editor_text (new, ""); - } - - return new; -} - -static void -handle_multipart_alternative (EMsgComposer *composer, CamelMultipart *multipart) -{ - /* Find the text/html part and set the composer body to it's contents */ - int i, nparts; - - nparts = camel_multipart_get_number (multipart); - - for (i = 0; i < nparts; i++) { - CamelContentType *content_type; - CamelMimePart *mime_part; - - mime_part = camel_multipart_get_part (multipart, i); - content_type = camel_mime_part_get_content_type (mime_part); - - if (header_content_type_is (content_type, "text", "html")) { - CamelDataWrapper *contents; - char *text, *final_text; - gboolean is_html; - - contents = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - text = mail_get_message_body (contents, FALSE, &is_html); - if (text) { - if (is_html) - final_text = g_strdup (text); - else - final_text = e_text_to_html (text, E_TEXT_TO_HTML_CONVERT_NL | - E_TEXT_TO_HTML_CONVERT_SPACES); - g_free (text); - - e_msg_composer_set_body_text (composer, final_text); - } - - return; - } - } -} - -static void -handle_multipart (EMsgComposer *composer, CamelMultipart *multipart, int depth) -{ - int i, nparts; - - nparts = camel_multipart_get_number (multipart); - - for (i = 0; i < nparts; i++) { - CamelContentType *content_type; - CamelMimePart *mime_part; - - mime_part = camel_multipart_get_part (multipart, i); - content_type = camel_mime_part_get_content_type (mime_part); - - if (header_content_type_is (content_type, "multipart", "alternative")) { - /* this structure contains the body */ - CamelDataWrapper *wrapper; - CamelMultipart *mpart; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - mpart = CAMEL_MULTIPART (wrapper); - - handle_multipart_alternative (composer, mpart); - } else if (header_content_type_is (content_type, "multipart", "*")) { - /* another layer of multipartness... */ - CamelDataWrapper *wrapper; - CamelMultipart *mpart; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - mpart = CAMEL_MULTIPART (wrapper); - - handle_multipart (composer, mpart, depth + 1); - } else if (depth == 0 && i == 0) { - /* Since the first part is not multipart/alternative, then this must be the body */ - CamelDataWrapper *contents; - char *text, *final_text; - gboolean is_html; - - contents = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - text = mail_get_message_body (contents, FALSE, &is_html); - if (text) { - if (is_html) - final_text = g_strdup (text); - else - final_text = e_text_to_html (text, E_TEXT_TO_HTML_CONVERT_NL | - E_TEXT_TO_HTML_CONVERT_SPACES); - g_free (text); - - e_msg_composer_set_body_text (composer, final_text); - } - } else { - /* this is a leaf of the tree, so attach it */ - e_msg_composer_attach (composer, mime_part); - } - } -} - -/* FIXME: are there any other headers?? */ -/* This is a list of headers that we DO NOT want to append to the - * extra_hdr_* arrays. - * - * Note: a '*' char can be used for a simple wilcard match. - * is_special_header() will use g_strNcasecmp() with the first '*' - * char being the end of the match string. If no '*' is present, then - * it will be assumed that the header must be an exact match. - */ -static char *special_headers[] = { - "Subject", - "Date", - "From", - "To", - "Cc", - "Bcc", - "Received", - "Message-Id", - "X-Evolution*", - "Content-*", - "MIME-Version", - NULL -}; - -static gboolean -is_special_header (const char *hdr_name) -{ - int i; - - for (i = 0; special_headers[i]; i++) { - char *p; - - if ((p = strchr (special_headers[i], '*'))) { - if (!g_strncasecmp (special_headers[i], hdr_name, p - special_headers[i])) - return TRUE; - } else { - if (!g_strcasecmp (special_headers[i], hdr_name)) - return TRUE; - } - } - - return FALSE; -} - -/** - * e_msg_composer_new_with_message: - * - * Create a new message composer widget. - * - * Return value: A pointer to the newly created widget - **/ -EMsgComposer * -e_msg_composer_new_with_message (CamelMimeMessage *msg) -{ - const CamelInternetAddress *to, *cc, *bcc; - GList *To = NULL, *Cc = NULL, *Bcc = NULL; - const char *format, *subject, *account_name; - CamelContentType *content_type; - struct _header_raw *headers; - EMsgComposer *new; - guint len, i; - - g_return_val_if_fail (gtk_main_level () > 0, NULL); - - new = create_composer (); - if (!new) - return NULL; - - subject = camel_mime_message_get_subject (msg); - - to = camel_mime_message_get_recipients (msg, CAMEL_RECIPIENT_TYPE_TO); - cc = camel_mime_message_get_recipients (msg, CAMEL_RECIPIENT_TYPE_CC); - bcc = camel_mime_message_get_recipients (msg, CAMEL_RECIPIENT_TYPE_BCC); - - len = CAMEL_ADDRESS (to)->addresses->len; - for (i = 0; i < len; i++) { - const char *name, *addr; - - if (camel_internet_address_get (to, i, &name, &addr)) { - To = g_list_append (To, camel_internet_address_format_address (name, addr)); - } - } - - len = CAMEL_ADDRESS (cc)->addresses->len; - for (i = 0; i < len; i++) { - const char *name, *addr; - - if (camel_internet_address_get (cc, i, &name, &addr)) { - Cc = g_list_append (Cc, camel_internet_address_format_address (name, addr)); - } - } - - len = CAMEL_ADDRESS (bcc)->addresses->len; - for (i = 0; i < len; i++) { - const char *name, *addr; - - if (camel_internet_address_get (bcc, i, &name, &addr)) { - Bcc = g_list_append (Bcc, camel_internet_address_format_address (name, addr)); - } - } - - /* Restore the Account preference */ - account_name = camel_medium_get_header (CAMEL_MEDIUM (msg), "X-Evolution-Account"); - if (account_name) { - while (*account_name && isspace ((unsigned) *account_name)) - account_name++; - camel_medium_remove_header (CAMEL_MEDIUM (msg), "X-Evolution-Account"); - } - - e_msg_composer_set_headers (new, account_name, To, Cc, Bcc, subject); - - free_recipients (To); - free_recipients (Cc); - free_recipients (Bcc); - - /* Restore the format editing preference */ - format = camel_medium_get_header (CAMEL_MEDIUM (msg), "X-Evolution-Format"); - if (format) { - while (*format && isspace ((unsigned) *format)) - format++; - - if (!g_strcasecmp (format, "text/html")) - e_msg_composer_set_send_html (new, TRUE); - else - e_msg_composer_set_send_html (new, FALSE); - - camel_medium_remove_header (CAMEL_MEDIUM (msg), "X-Evolution-Format"); - } - - /* Remove any other X-Evolution-* headers that may have been set */ - if (camel_medium_get_header (CAMEL_MEDIUM (msg), "X-Evolution-Transport")) - camel_medium_remove_header (CAMEL_MEDIUM (msg), "X-Evolution-Transport"); - if (camel_medium_get_header (CAMEL_MEDIUM (msg), "X-Evolution-Source")) - camel_medium_remove_header (CAMEL_MEDIUM (msg), "X-Evolution-Source"); - - /* set extra headers */ - headers = CAMEL_MIME_PART (msg)->headers; - while (headers) { - if (!is_special_header (headers->name)) { - g_ptr_array_add (new->extra_hdr_names, g_strdup (headers->name)); - g_ptr_array_add (new->extra_hdr_values, g_strdup (headers->value)); - } - - headers = headers->next; - } - - content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (msg)); - if (header_content_type_is (content_type, "multipart", "alternative")) { - /* multipart/alternative contains the text/plain and text/html versions of the message body */ - CamelDataWrapper *wrapper; - CamelMultipart *multipart; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (msg))); - multipart = CAMEL_MULTIPART (wrapper); - - handle_multipart_alternative (new, multipart); - } else if (header_content_type_is (content_type, "multipart", "*")) { - /* there must be attachments... */ - CamelDataWrapper *wrapper; - CamelMultipart *multipart; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (msg))); - multipart = CAMEL_MULTIPART (wrapper); - - handle_multipart (new, multipart, 0); - } else { - /* We either have a text/plain or a text/html part */ - CamelDataWrapper *contents; - char *text, *final_text; - gboolean is_html; - - contents = camel_medium_get_content_object (CAMEL_MEDIUM (msg)); - text = mail_get_message_body (contents, FALSE, &is_html); - if (text) { - if (is_html) - final_text = g_strdup (text); - else - final_text = e_text_to_html (text, E_TEXT_TO_HTML_CONVERT_NL | - E_TEXT_TO_HTML_CONVERT_SPACES); - g_free (text); - - e_msg_composer_set_body_text (new, final_text); - } - } - - return new; -} - -#if 0 -static GList * -add_recipients (GList *list, const char *recips, gboolean decode) -{ - int len; - char *addr; - - while (*recips) { - len = strcspn (recips, ","); - if (len) { - addr = g_strndup (recips, len); - if (decode) - camel_url_decode (addr); - list = g_list_append (list, addr); - } - recips += len; - if (*recips == ',') - recips++; - } - - return list; -} -#endif - -static GList * -add_recipients (GList *list, const char *recips, gboolean decode) -{ - CamelInternetAddress *cia; - const char *name, *addr; - int num, i; - - cia = camel_internet_address_new (); - if (decode) - num = camel_address_decode (CAMEL_ADDRESS (cia), recips); - else - num = camel_address_unformat (CAMEL_ADDRESS (cia), recips); - - for (i = 0; i < num; i++) { - if (camel_internet_address_get (cia, i, &name, &addr)) { - char *str; - - str = camel_internet_address_format_address (name, addr); - list = g_list_append (list, str); - } - } - - return list; -} - -static void -free_recipients (GList *list) -{ - GList *l; - - for (l = list; l; l = l->next) - g_free (l->data); - g_list_free (list); -} - -/** - * e_msg_composer_new_from_url: - * @url: a mailto URL - * - * Create a new message composer widget, and fill in fields as - * defined by the provided URL. - **/ -EMsgComposer * -e_msg_composer_new_from_url (const char *url) -{ - EMsgComposer *composer; - EMsgComposerHdrs *hdrs; - GList *to = NULL, *cc = NULL, *bcc = NULL; - char *subject = NULL, *body = NULL; - const char *p, *header; - int len, clen; - char *content; - - g_return_val_if_fail (g_strncasecmp (url, "mailto:", 7) == 0, NULL); - - composer = e_msg_composer_new (); - if (!composer) - return NULL; - - /* Parse recipients (everything after ':' until '?' or eos. */ - p = url + 7; - len = strcspn (p, "?,"); - if (len) { - content = g_strndup (p, len); - to = add_recipients (to, content, TRUE); - g_free (content); - } - - p += len; - if (*p == '?') { - p++; - - while (*p) { - len = strcspn (p, "=&"); - - /* If it's malformed, give up. */ - if (p[len] != '=') - break; - - header = p; - p += len + 1; - - clen = strcspn (p, "&"); - content = g_strndup (p, clen); - camel_url_decode (content); - - if (!g_strncasecmp (header, "to", len)) - to = add_recipients (to, content, FALSE); - else if (!g_strncasecmp (header, "cc", len)) - cc = add_recipients (cc, content, FALSE); - else if (!g_strncasecmp (header, "bcc", len)) - bcc = add_recipients (bcc, content, FALSE); - else if (!g_strncasecmp (header, "subject", len)) - subject = g_strdup (content); - else if (!g_strncasecmp (header, "body", len)) - body = g_strdup (content); - - g_free (content); - p += clen; - if (*p == '&') { - p++; - if (!strcmp (p, "amp;")) - p += 4; - } - } - } - - hdrs = E_MSG_COMPOSER_HDRS (composer->hdrs); - e_msg_composer_hdrs_set_to (hdrs, to); - free_recipients (to); - e_msg_composer_hdrs_set_cc (hdrs, cc); - free_recipients (cc); - e_msg_composer_hdrs_set_bcc (hdrs, bcc); - free_recipients (bcc); - if (subject) { - e_msg_composer_hdrs_set_subject (hdrs, subject); - g_free (subject); - } - - if (body) { - char *htmlbody = e_text_to_html (body, E_TEXT_TO_HTML_PRE); - set_editor_text (composer, htmlbody); - g_free (htmlbody); - } - - return composer; -} - -/** - * e_msg_composer_show_attachments: - * @composer: A message composer widget - * @show: A boolean specifying whether the attachment bar should be shown or - * not - * - * If @show is %FALSE, hide the attachment bar. Otherwise, show it. - **/ -void -e_msg_composer_show_attachments (EMsgComposer *composer, - gboolean show) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - show_attachments (composer, show); -} - -/** - * e_msg_composer_set_headers: - * @composer: a composer object - * @from: the name of the account the user will send from, - * or %NULL for the default account - * @to: the values for the "To" header - * @cc: the values for the "Cc" header - * @bcc: the values for the "Bcc" header - * @subject: the value for the "Subject" header - * - * Sets the headers in the composer to the given values. - **/ -void -e_msg_composer_set_headers (EMsgComposer *composer, - const char *from, - const GList *to, - const GList *cc, - const GList *bcc, - const char *subject) -{ - EMsgComposerHdrs *hdrs; - - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - hdrs = E_MSG_COMPOSER_HDRS (composer->hdrs); - - e_msg_composer_hdrs_set_from_account (hdrs, from); - e_msg_composer_hdrs_set_to (hdrs, to); - e_msg_composer_hdrs_set_cc (hdrs, cc); - e_msg_composer_hdrs_set_bcc (hdrs, bcc); - e_msg_composer_hdrs_set_subject (hdrs, subject); -} - - -/** - * e_msg_composer_set_body_text: - * @composer: a composer object - * @text: the HTML text to initialize the editor with - * - * Loads the given HTML text into the editor. - **/ -void -e_msg_composer_set_body_text (EMsgComposer *composer, const char *text) -{ - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - set_editor_text (composer, text); -} - - -/** - * e_msg_composer_add_header: - * @composer: a composer object - * @name: the header name - * @value: the header value - * - * Adds a header with @name and @value to the message. This header - * may not be displayed by the composer, but will be included in - * the message it outputs. - **/ -void -e_msg_composer_add_header (EMsgComposer *composer, const char *name, - const char *value) -{ - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - g_return_if_fail (name != NULL); - g_return_if_fail (value != NULL); - - g_ptr_array_add (composer->extra_hdr_names, g_strdup (name)); - g_ptr_array_add (composer->extra_hdr_values, g_strdup (value)); -} - - -/** - * e_msg_composer_attach: - * @composer: a composer object - * @attachment: the CamelMimePart to attach - * - * Attaches @attachment to the message being composed in the composer. - **/ -void -e_msg_composer_attach (EMsgComposer *composer, CamelMimePart *attachment) -{ - EMsgComposerAttachmentBar *bar; - - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - g_return_if_fail (CAMEL_IS_MIME_PART (attachment)); - - bar = E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar); - e_msg_composer_attachment_bar_attach_mime_part (bar, attachment); -} - - -/** - * e_msg_composer_get_message: - * @composer: A message composer widget - * - * Retrieve the message edited by the user as a CamelMimeMessage. The - * CamelMimeMessage object is created on the fly; subsequent calls to this - * function will always create new objects from scratch. - * - * Return value: A pointer to the new CamelMimeMessage object - **/ -CamelMimeMessage * -e_msg_composer_get_message (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); - - return build_message (composer); -} - -CamelMimeMessage * -e_msg_composer_get_message_draft (EMsgComposer *composer) -{ - CamelMimeMessage *msg; - const MailConfigAccount *account; - gint old_send_html; - - /* always save drafts as HTML to preserve formatting */ - old_send_html = composer->send_html; - composer->send_html = TRUE; - msg = e_msg_composer_get_message (composer); - composer->send_html = old_send_html; - - /* Attach whether this message was written in HTML */ - camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Format", - composer->send_html ? "text/html" : "text/plain"); - - /* Attach account info to the draft. */ - account = e_msg_composer_get_preferred_account (composer); - if (account && account->name) - camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Account", account->name); - - return msg; -} - - - -static void -delete_old_signature (EMsgComposer *composer) -{ - CORBA_Environment ev; - - /* printf ("delete_old_signature\n"); */ - CORBA_exception_init (&ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "cursor-bod", &ev); - if (GNOME_GtkHTML_Editor_Engine_searchByData (composer->editor_engine, 1, "ClueFlow", "signature", "1", &ev)) { - /* printf ("found\n"); */ - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "select-paragraph", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "delete", &ev); - /* selection-move-right doesn't succeed means that we are already on the end of document */ - /* if (!rv) - break; */ - GNOME_GtkHTML_Editor_Engine_setParagraphData (composer->editor_engine, "signature", "0", &ev); - } else - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "insert-paragraph", &ev); - CORBA_exception_free (&ev); -} - -/** - * e_msg_composer_show_sig: - * @composer: A message composer widget - * - * Set a signature - **/ -void -e_msg_composer_show_sig_file (EMsgComposer *composer) -{ - CORBA_Environment ev; - gchar *html; - - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - /* printf ("set sig '%s' '%s'\n", sig_file, composer->sig_file); */ - - composer->in_signature_insert = TRUE; - CORBA_exception_init (&ev); - GNOME_GtkHTML_Editor_Engine_freeze (composer->editor_engine, &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "cursor-position-save", &ev); - GNOME_GtkHTML_Editor_Engine_undo_begin (composer->editor_engine, "Set signature", "Reset signature", &ev); - - delete_old_signature (composer); - html = get_signature_html (composer); - if (html) { - if (!GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (composer->editor_engine, &ev)) - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "insert-paragraph", &ev); - /* printf ("insert %s\n", html); */ - GNOME_GtkHTML_Editor_Engine_setParagraphData (composer->editor_engine, "orig", "0", &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "indent-zero", &ev); - GNOME_GtkHTML_Editor_Engine_insertHTML (composer->editor_engine, html, &ev); - g_free (html); - } - GNOME_GtkHTML_Editor_Engine_undo_end (composer->editor_engine, &ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "cursor-position-restore", &ev); - GNOME_GtkHTML_Editor_Engine_thaw (composer->editor_engine, &ev); - CORBA_exception_free (&ev); - composer->in_signature_insert = FALSE; -} - -/** - * e_msg_composer_set_send_html: - * @composer: A message composer widget - * @send_html: Whether the composer should have the "Send HTML" flag set - * - * Set the status of the "Send HTML" toggle item. The user can override it. - **/ -void -e_msg_composer_set_send_html (EMsgComposer *composer, - gboolean send_html) -{ - CORBA_Environment ev; - - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if (composer->send_html && send_html) - return; - if (! composer->send_html && ! send_html) - return; - - composer->send_html = send_html; - - CORBA_exception_init (&ev); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "block-redraw", &ev); - bonobo_ui_component_set_prop ( - composer->uic, "/commands/FormatHtml", - "state", composer->send_html ? "1" : "0", NULL); - - /* let the editor know which mode we are in */ - bonobo_widget_set_property (BONOBO_WIDGET (composer->editor), "FormatHTML", - composer->send_html, NULL); - - set_config (composer, "FormatHTML", composer->send_html); - e_msg_composer_show_sig_file (composer); - GNOME_GtkHTML_Editor_Engine_runCommand (composer->editor_engine, "unblock-redraw", &ev); - CORBA_exception_free (&ev); -} - -/** - * e_msg_composer_get_send_html: - * @composer: A message composer widget - * - * Get the status of the "Send HTML mail" flag. - * - * Return value: The status of the "Send HTML mail" flag. - **/ -gboolean -e_msg_composer_get_send_html (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->send_html; -} - - -/** - * e_msg_composer_get_preferred_account: - * @composer: composer - * - * Returns the user-specified account (from field). - */ -const MailConfigAccount * -e_msg_composer_get_preferred_account (EMsgComposer *composer) -{ - EMsgComposerHdrs *hdrs; - - g_return_val_if_fail (composer != NULL, NULL); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); - - hdrs = E_MSG_COMPOSER_HDRS (composer->hdrs); - - return hdrs->account; -} - - -/** - * e_msg_composer_set_pgp_sign: - * @composer: A message composer widget - * @send_html: Whether the composer should have the "PGP Sign" flag set - * - * Set the status of the "PGP Sign" toggle item. The user can override it. - **/ -void -e_msg_composer_set_pgp_sign (EMsgComposer *composer, gboolean pgp_sign) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if (composer->pgp_sign && pgp_sign) - return; - if (!composer->pgp_sign && !pgp_sign) - return; - - composer->pgp_sign = pgp_sign; - - bonobo_ui_component_set_prop (composer->uic, "/commands/SecurityPGPSign", - "state", composer->pgp_sign ? "1" : "0", NULL); -} - -/** - * e_msg_composer_get_pgp_sign: - * @composer: A message composer widget - * - * Get the status of the "PGP Sign" flag. - * - * Return value: The status of the "PGP Sign" flag. - **/ -gboolean -e_msg_composer_get_pgp_sign (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->pgp_sign; -} - - -/** - * e_msg_composer_set_pgp_encrypt: - * @composer: A message composer widget - * @send_html: Whether the composer should have the "PGP Encrypt" flag set - * - * Set the status of the "PGP Encrypt" toggle item. The user can override it. - **/ -void -e_msg_composer_set_pgp_encrypt (EMsgComposer *composer, gboolean pgp_encrypt) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if (composer->pgp_encrypt && pgp_encrypt) - return; - if (!composer->pgp_encrypt && !pgp_encrypt) - return; - - composer->pgp_encrypt = pgp_encrypt; - - bonobo_ui_component_set_prop (composer->uic, "/commands/SecurityPGPEncrypt", - "state", composer->pgp_encrypt ? "1" : "0", NULL); -} - - -/** - * e_msg_composer_get_pgp_encrypt: - * @composer: A message composer widget - * - * Get the status of the "PGP Encrypt" flag. - * - * Return value: The status of the "PGP Encrypt" flag. - **/ -gboolean -e_msg_composer_get_pgp_encrypt (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->pgp_encrypt; -} - - -/** - * e_msg_composer_set_smime_sign: - * @composer: A message composer widget - * @send_html: Whether the composer should have the "S/MIME Sign" flag set - * - * Set the status of the "S/MIME Sign" toggle item. The user can override it. - **/ -void -e_msg_composer_set_smime_sign (EMsgComposer *composer, gboolean smime_sign) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if (composer->smime_sign && smime_sign) - return; - if (!composer->smime_sign && !smime_sign) - return; - - composer->smime_sign = smime_sign; - - bonobo_ui_component_set_prop (composer->uic, "/commands/SecuritySMimeSign", - "state", composer->smime_sign ? "1" : "0", NULL); -} - -/** - * e_msg_composer_get_smime_sign: - * @composer: A message composer widget - * - * Get the status of the "S/MIME Sign" flag. - * - * Return value: The status of the "S/MIME Sign" flag. - **/ -gboolean -e_msg_composer_get_smime_sign (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->smime_sign; -} - - -/** - * e_msg_composer_set_smime_encrypt: - * @composer: A message composer widget - * @send_html: Whether the composer should have the "S/MIME Encrypt" flag set - * - * Set the status of the "S/MIME Encrypt" toggle item. The user can override it. - **/ -void -e_msg_composer_set_smime_encrypt (EMsgComposer *composer, gboolean smime_encrypt) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if (composer->smime_encrypt && smime_encrypt) - return; - if (!composer->smime_encrypt && !smime_encrypt) - return; - - composer->smime_encrypt = smime_encrypt; - - bonobo_ui_component_set_prop (composer->uic, "/commands/SecuritySMimeEncrypt", - "state", composer->smime_encrypt ? "1" : "0", NULL); -} - - -/** - * e_msg_composer_get_smime_encrypt: - * @composer: A message composer widget - * - * Get the status of the "S/MIME Encrypt" flag. - * - * Return value: The status of the "S/MIME Encrypt" flag. - **/ -gboolean -e_msg_composer_get_smime_encrypt (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->smime_encrypt; -} - - -/** - * e_msg_composer_set_view_bcc: - * @composer: A message composer widget - * @state: whether to show or hide the bcc view - * - * Controls the state of the BCC display - */ -void -e_msg_composer_set_view_bcc (EMsgComposer *composer, gboolean view_bcc) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if ((composer->view_bcc && view_bcc) || - (!composer->view_bcc && !view_bcc)) - return; - - composer->view_bcc = view_bcc; - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewBCC", - "state", composer->view_bcc ? "1" : "0", NULL); - set_config (composer, "ViewBCC", composer->view_bcc); - e_msg_composer_set_hdrs_visible - (E_MSG_COMPOSER_HDRS (composer->hdrs), - e_msg_composer_get_visible_flags (composer)); - -} - -/** - * e_msg_composer_get_view_bcc: - * @composer: A message composer widget - * - * Get the status of the "View BCC header" flag. - * - * Return value: The status of the "View BCC header" flag. - **/ -gboolean -e_msg_composer_get_view_bcc (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->view_bcc; -} - -/** - * e_msg_composer_set_view_cc: - * @composer: A message composer widget - * @state: whether to show or hide the cc view - * - * Controls the state of the CC display - */ -void -e_msg_composer_set_view_cc (EMsgComposer *composer, gboolean view_cc) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if ((composer->view_cc && view_cc) || - (!composer->view_cc && !view_cc)) - return; - - composer->view_cc = view_cc; - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewCC", - "state", composer->view_cc ? "1" : "0", NULL); - set_config (composer, "ViewCC", composer->view_cc); - e_msg_composer_set_hdrs_visible - (E_MSG_COMPOSER_HDRS (composer->hdrs), - e_msg_composer_get_visible_flags (composer)); -} - -/** - * e_msg_composer_get_view_cc: - * @composer: A message composer widget - * - * Get the status of the "View CC header" flag. - * - * Return value: The status of the "View CC header" flag. - **/ -gboolean -e_msg_composer_get_view_cc (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->view_cc; -} - -/** - * e_msg_composer_set_view_from: - * @composer: A message composer widget - * @state: whether to show or hide the From selector - * - * Controls the state of the From selector - */ -void -e_msg_composer_set_view_from (EMsgComposer *composer, gboolean view_from) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if ((composer->view_from && view_from) || - (!composer->view_from && !view_from)) - return; - - composer->view_from = view_from; - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewFrom", - "state", composer->view_from ? "1" : "0", NULL); - set_config (composer, "ViewFrom", composer->view_from); - e_msg_composer_set_hdrs_visible - (E_MSG_COMPOSER_HDRS (composer->hdrs), - e_msg_composer_get_visible_flags (composer)); -} - -/** - * e_msg_composer_get_view_from: - * @composer: A message composer widget - * - * Get the status of the "View From header" flag. - * - * Return value: The status of the "View From header" flag. - **/ -gboolean -e_msg_composer_get_view_from (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->view_from; -} - -/** - * e_msg_composer_set_view_from: - * @composer: A message composer widget - * @state: whether to show or hide the From selector - * - * Controls the state of the From selector - */ -void -e_msg_composer_set_view_replyto (EMsgComposer *composer, gboolean view_replyto) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - if ((composer->view_replyto && view_replyto) || - (!composer->view_replyto && !view_replyto)) - return; - - composer->view_replyto = view_replyto; - bonobo_ui_component_set_prop ( - composer->uic, "/commands/ViewReplyTo", - "state", composer->view_replyto ? "1" : "0", NULL); - set_config (composer, "ViewReplyTo", composer->view_replyto); - e_msg_composer_set_hdrs_visible - (E_MSG_COMPOSER_HDRS (composer->hdrs), - e_msg_composer_get_visible_flags (composer)); -} - -/** - * e_msg_composer_get_view_replyto: - * @composer: A message composer widget - * - * Get the status of the "View Reply-To header" flag. - * - * Return value: The status of the "View Reply-To header" flag. - **/ -gboolean -e_msg_composer_get_view_replyto (EMsgComposer *composer) -{ - g_return_val_if_fail (composer != NULL, FALSE); - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); - - return composer->view_replyto; -} - -/** - * e_msg_composer_guess_mime_type: - * @file_name: filename - * - * Returns the guessed mime type of the file given by #file_name. - **/ -gchar * -e_msg_composer_guess_mime_type (const gchar *file_name) -{ - GnomeVFSFileInfo info; - GnomeVFSResult result; - - result = gnome_vfs_get_file_info (file_name, &info, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE | - GNOME_VFS_FILE_INFO_FOLLOW_LINKS); - if (result == GNOME_VFS_OK) { - gchar *type; - - type = g_strdup (gnome_vfs_file_info_get_mime_type (&info)); - gnome_vfs_file_info_unref (&info); - return type; - } else - return NULL; -} - -/** - * e_msg_composer_set_changed: - * @composer: An EMsgComposer object. - * - * Mark the composer as changed, so before the composer gets destroyed - * the user will be prompted about unsaved changes. - **/ -void -e_msg_composer_set_changed (EMsgComposer *composer) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - composer->has_changed = TRUE; -} - -/** - * e_msg_composer_unset_changed: - * @composer: An EMsgComposer object. - * - * Mark the composer as unchanged, so no prompt about unsaved changes - * will appear before destroying the composer. - **/ -void -e_msg_composer_unset_changed (EMsgComposer *composer) -{ - g_return_if_fail (composer != NULL); - g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - - composer->has_changed = FALSE; -} diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h deleted file mode 100644 index 11ab45cdd8..0000000000 --- a/composer/e-msg-composer.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-msg-composer.h - * - * Copyright (C) 1999, 2000 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifndef ___E_MSG_COMPOSER_H__ -#define ___E_MSG_COMPOSER_H__ - -typedef struct _EMsgComposer EMsgComposer; -typedef struct _EMsgComposerClass EMsgComposerClass; - -#include <bonobo/bonobo-win.h> -#include <bonobo/bonobo-ui-component.h> -#include <bonobo-conf/bonobo-config-database.h> - -#include "e-msg-composer-attachment-bar.h" -#include "e-msg-composer-hdrs.h" -#include "Editor.h" - -#include <mail/mail-config.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - - -#define E_TYPE_MSG_COMPOSER (e_msg_composer_get_type ()) -#define E_MSG_COMPOSER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MSG_COMPOSER, EMsgComposer)) -#define E_MSG_COMPOSER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER, EMsgComposerClass)) -#define E_IS_MSG_COMPOSER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MSG_COMPOSER)) -#define E_IS_MSG_COMPOSER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER)) - - - -struct _EMsgComposer { - BonoboWindow parent; - - BonoboUIComponent *uic; - - GtkWidget *hdrs; - GPtrArray *extra_hdr_names, *extra_hdr_values; - - GtkWidget *editor; - - GtkWidget *attachment_bar; - GtkWidget *attachment_scroll_frame; - - GtkWidget *address_dialog; - - Bonobo_PersistFile persist_file_interface; - Bonobo_PersistStream persist_stream_interface; - GNOME_GtkHTML_Editor_Engine editor_engine; - BonoboObject *editor_listener; - GHashTable *inline_images; - - Bonobo_ConfigDatabase config_db; - - char *charset; - - char *autosave_file; - int autosave_fd; - - gboolean attachment_bar_visible : 1; - gboolean send_html : 1; - gboolean pgp_sign : 1; - gboolean pgp_encrypt : 1; - gboolean smime_sign : 1; - gboolean smime_encrypt : 1; - gboolean view_from : 1; - gboolean view_replyto : 1; - gboolean view_bcc : 1; - gboolean view_cc : 1; - gboolean view_subject : 1; - gboolean has_changed : 1; - - gboolean in_signature_insert : 1; -}; - -struct _EMsgComposerClass { - BonoboWindowClass parent_class; - - void (* send) (EMsgComposer *composer); - void (* postpone) (EMsgComposer *composer); -}; - - -GtkType e_msg_composer_get_type (void); -void e_msg_composer_construct (EMsgComposer *composer); -EMsgComposer *e_msg_composer_new (void); -EMsgComposer *e_msg_composer_new_with_sig_file (void); -EMsgComposer *e_msg_composer_new_with_message (CamelMimeMessage *msg); -EMsgComposer *e_msg_composer_new_from_url (const char *url); -void e_msg_composer_show_attachments (EMsgComposer *composer, - gboolean show); -void e_msg_composer_set_headers (EMsgComposer *composer, - const char *from, - const GList *to, - const GList *cc, - const GList *bcc, - const char *subject); -void e_msg_composer_set_body_text (EMsgComposer *composer, - const char *text); -void e_msg_composer_add_header (EMsgComposer *composer, - const char *name, - const char *value); -void e_msg_composer_attach (EMsgComposer *composer, - CamelMimePart *attachment); -CamelMimeMessage *e_msg_composer_get_message (EMsgComposer *composer); -CamelMimeMessage *e_msg_composer_get_message_draft (EMsgComposer *composer); -void e_msg_composer_show_sig_file (EMsgComposer *composer); -gboolean e_msg_composer_get_send_html (EMsgComposer *composer); -void e_msg_composer_set_send_html (EMsgComposer *composer, - gboolean send_html); -gboolean e_msg_composer_get_view_from (EMsgComposer *composer); -void e_msg_composer_set_view_from (EMsgComposer *composer, - gboolean view_from); - -gboolean e_msg_composer_get_view_replyto (EMsgComposer *composer); -void e_msg_composer_set_view_replyto (EMsgComposer *composer, - gboolean view_replyto); - -gboolean e_msg_composer_get_view_bcc (EMsgComposer *composer); -void e_msg_composer_set_view_bcc (EMsgComposer *composer, - gboolean view_bcc); -gboolean e_msg_composer_get_view_cc (EMsgComposer *composer); -void e_msg_composer_set_view_cc (EMsgComposer *composer, - gboolean view_cc); - -const MailConfigAccount *e_msg_composer_get_preferred_account (EMsgComposer *composer); - -void e_msg_composer_clear_inlined_table (EMsgComposer *composer); -gchar * e_msg_composer_guess_mime_type (const gchar *file_name); - -void e_msg_composer_set_changed (EMsgComposer *composer); -void e_msg_composer_unset_changed (EMsgComposer *composer); - -/* PGP */ -void e_msg_composer_set_pgp_sign (EMsgComposer *composer, - gboolean pgp_sign); -gboolean e_msg_composer_get_pgp_sign (EMsgComposer *composer); -void e_msg_composer_set_pgp_encrypt (EMsgComposer *composer, - gboolean pgp_encrypt); -gboolean e_msg_composer_get_pgp_encrypt (EMsgComposer *composer); - -/* S/MIME */ -void e_msg_composer_set_smime_sign (EMsgComposer *composer, - gboolean smime_sign); -gboolean e_msg_composer_get_smime_sign (EMsgComposer *composer); -void e_msg_composer_set_smime_encrypt (EMsgComposer *composer, - gboolean smime_encrypt); -gboolean e_msg_composer_get_smime_encrypt (EMsgComposer *composer); -gchar * e_msg_composer_get_sig_file_content (const char *sigfile, - gboolean in_html); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ___E_MSG_COMPOSER_H__ */ diff --git a/composer/evolution-composer.c b/composer/evolution-composer.c deleted file mode 100644 index 6dfddf1202..0000000000 --- a/composer/evolution-composer.c +++ /dev/null @@ -1,380 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* evolution-composer.c - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Dan Winship <danw@ximian.com> - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtksignal.h> -#include <bonobo/bonobo-item-handler.h> -#include <bonobo/bonobo-generic-factory.h> -#include <gal/util/e-util.h> -#include <gal/widgets/e-gui-utils.h> -#include <camel/camel.h> -#include "evolution-composer.h" -#include "mail/mail-config.h" - -#define PARENT_TYPE BONOBO_OBJECT_TYPE -static BonoboObjectClass *parent_class = NULL; - -static void (*send_cb) (EMsgComposer *, gpointer); -static void (*postpone_cb) (EMsgComposer *, gpointer); - -/* CORBA interface implementation. */ - -static POA_GNOME_Evolution_Composer__vepv Composer_vepv; - -static GList * -corba_recipientlist_to_glist (const GNOME_Evolution_Composer_RecipientList *cl) -{ - GNOME_Evolution_Composer_Recipient *recip; - GList *gl = NULL; - char *str; - int i; - - for (i = cl->_length - 1; i >= 0; i--) { - recip = &(cl->_buffer[i]); - - /* Let's copy this code into yet another place! */ - if (*recip->name) { - str = camel_internet_address_format_address (recip->name, recip->address); - } else - str = g_strdup (recip->address); - - gl = g_list_prepend (gl, str); - } - - return gl; -} - -static void -free_recipient_glist (GList *gl) -{ - GList *tmp; - - while (gl) { - tmp = gl->next; - g_free (gl->data); - g_list_free_1 (gl); - gl = tmp; - } -} - -static void -impl_Composer_set_headers (PortableServer_Servant servant, - const GNOME_Evolution_Composer_RecipientList *to, - const GNOME_Evolution_Composer_RecipientList *cc, - const GNOME_Evolution_Composer_RecipientList *bcc, - const CORBA_char *subject, - CORBA_Environment *ev) -{ - BonoboObject *bonobo_object; - EvolutionComposer *composer; - GList *gto, *gcc, *gbcc; - - bonobo_object = bonobo_object_from_servant (servant); - composer = EVOLUTION_COMPOSER (bonobo_object); - - gto = corba_recipientlist_to_glist (to); - gcc = corba_recipientlist_to_glist (cc); - gbcc = corba_recipientlist_to_glist (bcc); - - e_msg_composer_set_headers (composer->composer, NULL, gto, gcc, gbcc, - subject); - - free_recipient_glist (gto); - free_recipient_glist (gcc); - free_recipient_glist (gbcc); -} - -static void -impl_Composer_set_body_text (PortableServer_Servant servant, - const CORBA_char *text, - CORBA_Environment *ev) -{ - BonoboObject *bonobo_object; - EvolutionComposer *composer; - - bonobo_object = bonobo_object_from_servant (servant); - composer = EVOLUTION_COMPOSER (bonobo_object); - - e_msg_composer_set_body_text (composer->composer, text); -} - -static void -impl_Composer_attach_MIME (PortableServer_Servant servant, - const CORBA_char *data, - CORBA_Environment *ev) -{ - BonoboObject *bonobo_object; - EvolutionComposer *composer; - CamelMimePart *attachment; - CamelStream *mem_stream; - int status; - - bonobo_object = bonobo_object_from_servant (servant); - composer = EVOLUTION_COMPOSER (bonobo_object); - - mem_stream = camel_stream_mem_new_with_buffer (data, strlen (data)); - attachment = camel_mime_part_new (); - status = camel_data_wrapper_construct_from_stream ( - CAMEL_DATA_WRAPPER (attachment), mem_stream); - camel_object_unref (CAMEL_OBJECT (mem_stream)); - - if (status == -1) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Composer_CouldNotParse, - NULL); - return; - } - - e_msg_composer_attach (composer->composer, attachment); - camel_object_unref (CAMEL_OBJECT (attachment)); -} - -static void -impl_Composer_attach_data (PortableServer_Servant servant, - const CORBA_char *content_type, - const CORBA_char *filename, - const CORBA_char *description, - const CORBA_boolean show_inline, - const GNOME_Evolution_Composer_AttachmentData *data, - CORBA_Environment *ev) -{ - BonoboObject *bonobo_object; - EvolutionComposer *composer; - CamelMimePart *attachment; - - bonobo_object = bonobo_object_from_servant (servant); - composer = EVOLUTION_COMPOSER (bonobo_object); - - attachment = camel_mime_part_new (); - camel_mime_part_set_content (attachment, data->_buffer, data->_length, - content_type); - - if (*filename) - camel_mime_part_set_filename (attachment, filename); - if (*description) - camel_mime_part_set_description (attachment, description); - camel_mime_part_set_disposition (attachment, show_inline ? - "inline" : "attachment"); - - e_msg_composer_attach (composer->composer, attachment); - camel_object_unref (CAMEL_OBJECT (attachment)); -} - -static void -impl_Composer_show (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - BonoboObject *bonobo_object; - EvolutionComposer *composer; - - bonobo_object = bonobo_object_from_servant (servant); - composer = EVOLUTION_COMPOSER (bonobo_object); - - gtk_widget_show (GTK_WIDGET (composer->composer)); -} - -static void -impl_Composer_send (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - BonoboObject *bonobo_object; - EvolutionComposer *composer; - - bonobo_object = bonobo_object_from_servant (servant); - composer = EVOLUTION_COMPOSER (bonobo_object); - - send_cb (composer->composer, NULL); -} - -POA_GNOME_Evolution_Composer__epv * -evolution_composer_get_epv (void) -{ - POA_GNOME_Evolution_Composer__epv *epv; - - epv = g_new0 (POA_GNOME_Evolution_Composer__epv, 1); - epv->setHeaders = impl_Composer_set_headers; - epv->setBodyText = impl_Composer_set_body_text; - epv->attachMIME = impl_Composer_attach_MIME; - epv->attachData = impl_Composer_attach_data; - epv->show = impl_Composer_show; - epv->send = impl_Composer_send; - - return epv; -} - - -/* GtkObject stuff */ - -static void -destroy (GtkObject *object) -{ - EvolutionComposer *composer = EVOLUTION_COMPOSER (object); - - if (composer->composer) - gtk_object_unref (GTK_OBJECT (composer->composer)); - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -static void -class_init (EvolutionComposerClass *klass) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS (klass); - object_class->destroy = destroy; - - parent_class = gtk_type_class (bonobo_object_get_type ()); - - Composer_vepv.Bonobo_Unknown_epv = bonobo_object_get_epv (); - Composer_vepv.GNOME_Evolution_Composer_epv = evolution_composer_get_epv (); -} - -static void -init (EvolutionComposer *composer) -{ - const MailConfigAccount *account; - - account = mail_config_get_default_account (); - composer->composer = e_msg_composer_new_with_sig_file (); - - gtk_signal_connect (GTK_OBJECT (composer->composer), "send", - GTK_SIGNAL_FUNC (send_cb), NULL); - gtk_signal_connect (GTK_OBJECT (composer->composer), "postpone", - GTK_SIGNAL_FUNC (postpone_cb), NULL); -} - -#if 0 -static Bonobo_ItemContainer_ObjectNames * -enum_objects (BonoboItemHandler *handler, gpointer data, CORBA_Environment *ev) -{ -} -#endif - -static Bonobo_Unknown -get_object (BonoboItemHandler *h, const char *item_name, gboolean only_if_exists, - gpointer data, CORBA_Environment *ev) -{ - EvolutionComposer *composer = data; - GSList *options, *l; - - options = bonobo_item_option_parse (item_name); - for (l = options; l; l = l->next){ - BonoboItemOption *option = l->data; - - if (strcmp (option->key, "visible") == 0){ - gboolean show = 1; - - if (option->value) - show = atoi (option->value); - - if (show) - gtk_widget_show (GTK_WIDGET (composer->composer)); - else - gtk_widget_hide (GTK_WIDGET (composer->composer)); - } - } - return bonobo_object_dup_ref ( - BONOBO_OBJECT (composer)->corba_objref, ev); -} - -void -evolution_composer_construct (EvolutionComposer *composer, - GNOME_Evolution_Composer corba_object) -{ - BonoboObject *item_handler; - - g_return_if_fail (composer != NULL); - g_return_if_fail (EVOLUTION_IS_COMPOSER (composer)); - g_return_if_fail (corba_object != CORBA_OBJECT_NIL); - - bonobo_object_construct (BONOBO_OBJECT (composer), corba_object); - - item_handler = BONOBO_OBJECT ( - bonobo_item_handler_new (NULL, get_object, composer)); - bonobo_object_add_interface (BONOBO_OBJECT (composer), BONOBO_OBJECT (item_handler)); -} - -EvolutionComposer * -evolution_composer_new (void) -{ - EvolutionComposer *new; - POA_GNOME_Evolution_Composer *servant; - CORBA_Environment ev; - GNOME_Evolution_Composer corba_object; - - servant = (POA_GNOME_Evolution_Composer *) g_new0 (BonoboObjectServant, 1); - servant->vepv = &Composer_vepv; - - CORBA_exception_init (&ev); - POA_GNOME_Evolution_Composer__init ((PortableServer_Servant) servant, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_free (servant); - CORBA_exception_free (&ev); - return NULL; - } - CORBA_exception_free (&ev); - - new = gtk_type_new (evolution_composer_get_type ()); - corba_object = bonobo_object_activate_servant (BONOBO_OBJECT (new), - servant); - evolution_composer_construct (new, corba_object); - - return new; -} - -E_MAKE_TYPE (evolution_composer, "EvolutionComposer", EvolutionComposer, class_init, init, PARENT_TYPE) - - -#define GNOME_EVOLUTION_MAIL_COMPOSER_FACTORY_ID "OAFIID:GNOME_Evolution_Mail_ComposerFactory" - -static BonoboObject * -factory_fn (BonoboGenericFactory *factory, void *closure) -{ - if (!mail_config_is_configured ()) { - e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, - _("Could not create composer window, because you " - "have not yet\nconfigured any identities in the " - "mail component.")); - return NULL; - } - return BONOBO_OBJECT (evolution_composer_new ()); -} - -void -evolution_composer_factory_init (void (*send) (EMsgComposer *, gpointer), - void (*postpone) (EMsgComposer *, gpointer)) -{ - if (bonobo_generic_factory_new (GNOME_EVOLUTION_MAIL_COMPOSER_FACTORY_ID, - factory_fn, NULL) == NULL) { - e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, - _("Cannot initialize Evolution's composer.")); - exit (1); - } - - send_cb = send; - postpone_cb = postpone; -} diff --git a/composer/evolution-composer.h b/composer/evolution-composer.h deleted file mode 100644 index 9791a262fd..0000000000 --- a/composer/evolution-composer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* evolution-composer.h - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Dan Winship - */ - -#ifndef __EVOLUTION_COMPOSER_H__ -#define __EVOLUTION_COMPOSER_H__ - -#include <bonobo/bonobo-object.h> - -#include "Composer.h" -#include "e-msg-composer.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EVOLUTION_TYPE_COMPOSER (evolution_composer_get_type ()) -#define EVOLUTION_COMPOSER(obj) (GTK_CHECK_CAST ((obj), EVOLUTION_TYPE_COMPOSER, EvolutionComposer)) -#define EVOLUTION_COMPOSER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_COMPOSER, EvolutionComposerClass)) -#define EVOLUTION_IS_COMPOSER(obj) (GTK_CHECK_TYPE ((obj), EVOLUTION_TYPE_COMPOSER)) -#define EVOLUTION_IS_COMPOSER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_COMPOSER)) - -typedef struct _EvolutionComposer EvolutionComposer; -typedef struct _EvolutionComposerClass EvolutionComposerClass; - -struct _EvolutionComposer { - BonoboObject parent; - - EMsgComposer *composer; -}; - -struct _EvolutionComposerClass { - BonoboObjectClass parent_class; -}; - -POA_GNOME_Evolution_Composer__epv *evolution_composer_get_epv (void); - -GtkType evolution_composer_get_type (void); -void evolution_composer_construct (EvolutionComposer *, - GNOME_Evolution_Composer); -EvolutionComposer *evolution_composer_new (void); - -void evolution_composer_factory_init (void (*send) (EMsgComposer *, gpointer), - void (*postpone) (EMsgComposer *, gpointer)); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __EVOLUTION_COMPOSER_H__ */ diff --git a/composer/listener.c b/composer/listener.c deleted file mode 100644 index c3cc8f4e76..0000000000 --- a/composer/listener.c +++ /dev/null @@ -1,253 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* This file is part of gnome-spell bonobo component - - Copyright (C) 2000 Ximian, Inc. - Authors: Radek Doulik <rodo@ximian.com> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <bonobo/bonobo-arg.h> -#include <bonobo/bonobo-object.h> - -#include "listener.h" - -static BonoboObjectClass *listener_parent_class; -static POA_GNOME_GtkHTML_Editor_Listener__vepv listener_vepv; - -inline static EditorListener * -listener_from_servant (PortableServer_Servant servant) -{ - return EDITOR_LISTENER (bonobo_object_from_servant (servant)); -} - -static CORBA_any * -get_any_null () -{ - CORBA_any *rv; - - rv = CORBA_any__alloc (); - rv->_type = TC_null; - - return rv; -} - -static gchar * -resolve_image_url (EditorListener *l, gchar *url) -{ - gchar *cid = NULL; - - printf ("resolve_image_url %s\n", url); - - if (!strncmp (url, "file:", 5)) { - gchar *id; - - id = (gchar *) g_hash_table_lookup (l->composer->inline_images, url + 5); - if (!id) { - id = header_msgid_generate (); - g_hash_table_insert (l->composer->inline_images, g_strdup (url + 5), id); - } - cid = g_strconcat ("cid:", id, NULL); - printf ("resolved to %s\n", cid); - } - - return cid; -} - -static void -reply_indent (EditorListener *l, CORBA_Environment * ev) -{ - if (!GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (l->composer->editor_engine, ev)) { - if (GNOME_GtkHTML_Editor_Engine_isPreviousParagraphEmpty (l->composer->editor_engine, ev)) - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "cursor-backward", ev); - else { - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "insert-paragraph", ev); - return; - } - - } - - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "style-normal", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "indent-zero", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "cursor-position-save", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "select-paragraph-extended", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "text-default-color", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "italic-off", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "disable-selection", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (l->composer->editor_engine, "cursor-position-restore", ev); -} - -static void -clear_signature (GNOME_GtkHTML_Editor_Engine e, CORBA_Environment * ev) -{ - if (GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (e, ev)) - GNOME_GtkHTML_Editor_Engine_setParagraphData (e, "signature", "0", ev); - else if (GNOME_GtkHTML_Editor_Engine_isPreviousParagraphEmpty (e, ev) - && GNOME_GtkHTML_Editor_Engine_runCommand (e, "cursor-backward", ev)) { - GNOME_GtkHTML_Editor_Engine_setParagraphData (e, "signature", "0", ev); - GNOME_GtkHTML_Editor_Engine_runCommand (e, "cursor-forward", ev); - } -} - -static CORBA_any * -impl_event (PortableServer_Servant _servant, - const CORBA_char * name, const CORBA_any * arg, - CORBA_Environment * ev) -{ - EditorListener *l = listener_from_servant (_servant); - CORBA_any *rv = NULL; - - /* printf ("impl_event\n"); */ - - if (!strcmp (name, "command")) { - if (!l->composer->in_signature_insert) { - CORBA_char *orig, *signature; - /* FIXME check for insert-paragraph command */ - orig = GNOME_GtkHTML_Editor_Engine_getParagraphData (l->composer->editor_engine, "orig", ev); - if (ev->_major == CORBA_NO_EXCEPTION) { - if (orig && *orig == '1') - reply_indent (l, ev); - GNOME_GtkHTML_Editor_Engine_setParagraphData (l->composer->editor_engine, "orig", "0", ev); - } - signature = GNOME_GtkHTML_Editor_Engine_getParagraphData (l->composer->editor_engine, "signature", ev); - if (ev->_major == CORBA_NO_EXCEPTION) { - if (signature && *signature == '1') - clear_signature (l->composer->editor_engine, ev); - } - } - } else if (!strcmp (name, "image_url")) { - gchar *url; - - if ((url = resolve_image_url (l, BONOBO_ARG_GET_STRING (arg)))) { - rv = bonobo_arg_new (TC_string); - BONOBO_ARG_SET_STRING (rv, url); - /* printf ("new url: %s\n", url); */ - g_free (url); - } - } - - return rv ? rv : get_any_null (); -} - -POA_GNOME_GtkHTML_Editor_Listener__epv * -listener_get_epv (void) -{ - POA_GNOME_GtkHTML_Editor_Listener__epv *epv; - - epv = g_new0 (POA_GNOME_GtkHTML_Editor_Listener__epv, 1); - - epv->event = impl_event; - - return epv; -} - -static void -init_listener_corba_class (void) -{ - listener_vepv.Bonobo_Unknown_epv = bonobo_object_get_epv (); - listener_vepv.GNOME_GtkHTML_Editor_Listener_epv = listener_get_epv (); -} - -static void -listener_class_init (EditorListenerClass *klass) -{ - listener_parent_class = gtk_type_class (bonobo_object_get_type ()); - - init_listener_corba_class (); -} - -GtkType -listener_get_type (void) -{ - static GtkType type = 0; - - if (!type){ - GtkTypeInfo info = { - "EditorListener", - sizeof (EditorListener), - sizeof (EditorListenerClass), - (GtkClassInitFunc) listener_class_init, - (GtkObjectInitFunc) NULL, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; - - type = gtk_type_unique (bonobo_object_get_type (), &info); - } - - return type; -} - -EditorListener * -listener_construct (EditorListener *listener, GNOME_GtkHTML_Editor_Listener corba_listener) -{ - g_return_val_if_fail (listener != NULL, NULL); - g_return_val_if_fail (IS_EDITOR_LISTENER (listener), NULL); - g_return_val_if_fail (corba_listener != CORBA_OBJECT_NIL, NULL); - - if (!bonobo_object_construct (BONOBO_OBJECT (listener), (CORBA_Object) corba_listener)) - return NULL; - - return listener; -} - -static GNOME_GtkHTML_Editor_Listener -create_listener (BonoboObject *listener) -{ - POA_GNOME_GtkHTML_Editor_Listener *servant; - CORBA_Environment ev; - - servant = (POA_GNOME_GtkHTML_Editor_Listener *) g_new0 (BonoboObjectServant, 1); - servant->vepv = &listener_vepv; - - CORBA_exception_init (&ev); - POA_GNOME_GtkHTML_Editor_Listener__init ((PortableServer_Servant) servant, &ev); - ORBIT_OBJECT_KEY(servant->_private)->object = NULL; - - if (ev._major != CORBA_NO_EXCEPTION){ - g_free (servant); - CORBA_exception_free (&ev); - return CORBA_OBJECT_NIL; - } - - CORBA_exception_free (&ev); - - return (GNOME_GtkHTML_Editor_Listener) bonobo_object_activate_servant (listener, servant); -} - -EditorListener * -listener_new (EMsgComposer *composer) -{ - EditorListener *listener; - GNOME_GtkHTML_Editor_Listener corba_listener; - - listener = gtk_type_new (EDITOR_LISTENER_TYPE); - listener->composer = composer; - - corba_listener = create_listener (BONOBO_OBJECT (listener)); - - if (corba_listener == CORBA_OBJECT_NIL) { - bonobo_object_unref (BONOBO_OBJECT (listener)); - return NULL; - } - - return listener_construct (listener, corba_listener); -} diff --git a/composer/listener.h b/composer/listener.h deleted file mode 100644 index 72e2cb697a..0000000000 --- a/composer/listener.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* This file is part of gnome-spell bonobo component - - Copyright (C) 2000 Ximian, Inc. - Authors: Radek Doulik <rodo@ximian.com> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifndef LISTENER_H_ -#define LISTENER_H_ - -#include <libgnome/gnome-defs.h> -#include <bonobo/bonobo-object.h> -#include "Editor.h" -#include "e-msg-composer.h" - -BEGIN_GNOME_DECLS - -#define EDITOR_LISTENER_TYPE (listener_get_type ()) -#define EDITOR_LISTENER(o) (GTK_CHECK_CAST ((o), EDITOR_LISTENER_TYPE, EditorListener)) -#define EDITOR_LISTENER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), EDITOR_LISTENER_TYPE, EditorListenerClass)) -#define IS_EDITOR_LISTENER(o) (GTK_CHECK_TYPE ((o), EDITOR_LISTENER_TYPE)) -#define IS_EDITOR_LISTENER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), EDITOR_LISTENER_TYPE)) - -typedef struct { - BonoboObject parent; - EMsgComposer *composer; -} EditorListener; - -typedef struct { - BonoboObjectClass parent_class; -} EditorListenerClass; - -GtkType listener_get_type (void); -EditorListener *listener_construct (EditorListener *listener, - GNOME_GtkHTML_Editor_Listener corba_listener); -EditorListener *listener_new (EMsgComposer *composer); -POA_GNOME_GtkHTML_Editor_Listener__epv *listener_get_epv (void); - -END_GNOME_DECLS - -#endif /* LISTENER_H_ */ |