/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* e-summary.c * * Authors: Iain Holmes * * Copyright (C) 2000 Helix Code, 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. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "e-summary.h" #include "e-summary-factory.h" #include "e-summary-util.h" #include "e-summary-url.h" #include #include #include #define PARENT_TYPE (gtk_vbox_get_type ()) #define STORAGE_TYPE "fs" #define IID_FILE "oaf.id" #define DATA_FILE "data" /* From component-factory.c */ extern char *evolution_dir; static GtkObjectClass *e_summary_parent_class; struct _ESummaryPrivate { GNOME_Evolution_Shell shell; GNOME_Evolution_ShellView shell_view_interface; GtkWidget *html_scroller; GtkWidget *html; guint idle; GtkHTMLStream *stream; gboolean grabbed; GList *window_list; char *header; int header_len; char *footer; int footer_len; }; static gboolean on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, ESummary *summary); static void e_summary_save_state (ESummary *esummary, const char *path); static void e_summary_load_state (ESummary *esummary, const char *path); /* GtkObject methods */ static void e_summary_destroy (GtkObject *object) { ESummary *esummary = E_SUMMARY (object); ESummaryPrivate *priv; GList *l; char *prefix; priv = esummary->private; if (priv == NULL) return; prefix = g_concat_dir_and_file (evolution_dir, "config/"); e_summary_save_state (esummary, prefix); g_free (prefix); e_summary_prefs_free (esummary->prefs); for (l = priv->window_list; l; l = l->next) e_summary_window_free (l->data); g_list_free (priv->window_list); g_free (priv->header); g_free (priv->footer); g_free (esummary->private); esummary->private = NULL; e_summary_parent_class->destroy (object); } static void e_summary_class_init (GtkObjectClass *object_class) { object_class->destroy = e_summary_destroy; e_summary_parent_class = gtk_type_class (PARENT_TYPE); } static void e_summary_start_load (ESummary *esummary) { ESummaryPrivate *priv; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; priv->stream = gtk_html_begin (GTK_HTML (priv->html)); /* HTML hacks */ /* Hack to stop page returning to the top */ GTK_HTML (priv->html)->engine->newPage = FALSE; /* Hack to make the border width of the page 0 */ GTK_HTML (priv->html)->engine->leftBorder = 0; GTK_HTML (priv->html)->engine->rightBorder = 0; GTK_HTML (priv->html)->engine->topBorder = 0; GTK_HTML (priv->html)->engine->bottomBorder = 0; } static void load_default_header (ESummary *esummary) { ESummaryPrivate *priv; char *def = "" "
" "
" "
" "Submit a bug report" "

"; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; g_return_if_fail (priv->stream != NULL); gtk_html_write (GTK_HTML (priv->html), priv->stream, def, strlen (def)); } static void load_default_footer (ESummary *esummary) { ESummaryPrivate *priv; char *footer = "

All Executive Summary comments to Iain Holmes (iain@helixcode.com)

"; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; gtk_html_write (GTK_HTML (priv->html), priv->stream, footer, strlen (footer)); } static void e_summary_end_load (ESummary *esummary) { ESummaryPrivate *priv; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; gtk_html_end (GTK_HTML (priv->html), priv->stream, GTK_HTML_STREAM_OK); priv->stream = NULL; } static void e_summary_init (ESummary *esummary) { GdkColor bgcolour = {0, 0xdfff, 0xdfff, 0xffff}; ESummaryPrivate *priv; esummary->prefs = NULL; esummary->tmp_prefs = NULL; esummary->private = g_new0 (ESummaryPrivate, 1); priv = esummary->private; priv->window_list = NULL; priv->idle = 0; /* HTML widget */ priv->html_scroller = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->html_scroller), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); priv->html = gtk_html_new (); gtk_html_set_editable (GTK_HTML (priv->html), FALSE); gtk_html_set_default_content_type (GTK_HTML (priv->html), "text/html; charset=utf-8"); gtk_html_set_default_background_color (GTK_HTML (priv->html), &bgcolour); gtk_signal_connect (GTK_OBJECT (priv->html), "url-requested", GTK_SIGNAL_FUNC (e_summary_url_request), esummary); gtk_signal_connect (GTK_OBJECT (priv->html), "object-requested", GTK_SIGNAL_FUNC (on_object_requested), esummary); gtk_signal_connect (GTK_OBJECT (priv->html), "link-clicked", GTK_SIGNAL_FUNC (e_summary_url_click), esummary); gtk_signal_connect (GTK_OBJECT (priv->html), "on-url", GTK_SIGNAL_FUNC (e_summary_url_over), esummary); gtk_container_add (GTK_CONTAINER (priv->html_scroller), priv->html); gtk_widget_show_all (priv->html_scroller); e_summary_queue_rebuild (esummary); /* Pack stuff */ gtk_box_pack_start (GTK_BOX (esummary), priv->html_scroller, TRUE, TRUE, 0); } E_MAKE_TYPE (e_summary, "ESummary", ESummary, e_summary_class_init, e_summary_init, PARENT_TYPE); GtkWidget * e_summary_new (const GNOME_Evolution_Shell shell) { ESummary *esummary; ESummaryPrivate *priv; char *path; esummary = gtk_type_new (e_summary_get_type ()); priv = esummary->private; priv->shell = shell; /* Restore services */ path = g_concat_dir_and_file (evolution_dir, "config"); e_summary_load_state (esummary, path); g_free (path); return GTK_WIDGET (esummary); } #if 0 static void control_unrealize (GtkHTMLEmbedded *eb, GtkWidget *widget) { g_print ("Removing\n"); } static void being_unrealized (GtkWidget *widget, GtkHTMLEmbedded *eb) { g_warning ("Widget is being unrealized"); gtk_container_remove (GTK_CONTAINER (eb), widget); } static void being_realized (GtkWidget *widget, gpointer user_data) { gdk_window_ref (widget->window); } #endif static gboolean on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, ESummary *esummary) { #if 0 static GtkWidget *widget = NULL; int id; if (sscanf (eb->classid, "cid:%d", &id) != 1) { g_warning ("Could not get the view id: eb->classid = %s", eb->classid); return FALSE; } if (widget == NULL || !GTK_IS_WIDGET (widget)) { g_print ("Create new\n"); widget = executive_summary_component_view_get_widget (view); /* widget = gtk_button_new_with_label ("Hello?"); */ gtk_signal_connect (GTK_OBJECT (widget), "realize", GTK_SIGNAL_FUNC (being_realized), NULL); gtk_signal_connect (GTK_OBJECT (widget), "unrealize", GTK_SIGNAL_FUNC (being_unrealized), eb); g_print ("New widget: %p\n", GTK_BIN (widget)->child); } else { g_print ("No new\n"); } if (widget == NULL) { g_warning ("View %d has no GtkWidget.", id); return FALSE; } gtk_signal_connect (GTK_OBJECT (eb), "unrealize", GTK_SIGNAL_FUNC (control_unrealize), widget); gtk_widget_show_all (widget); gtk_widget_ref (widget); if (widget->parent == NULL) gtk_container_add (GTK_CONTAINER (eb), widget); #endif return TRUE; } /* Generates the window controls and works out if they should be disabled or not */ static char * make_control_html (ESummaryWindow *window, int row, int col, int numwindows) { char *html, *tmp; int id = GPOINTER_TO_INT (window); gboolean config; config = TRUE; if (window->propertycontrol == CORBA_OBJECT_NIL) config = FALSE; html = g_strdup_printf ("
" "" "
", id); tmp = html; if (!config) { html = g_strdup_printf ("%s" "
", tmp); } else { html = g_strdup_printf ("%s" "" "", tmp, id); } g_free (tmp); return html; } static void e_summary_display_window_title (ESummary *esummary, ESummaryWindow *window, int row, int col, int numwindows) { ESummaryPrivate *priv; char *title_html; char *control_html; char *title_colour[2] = {"bac1b6", "cdd1c7"}; priv = esummary->private; control_html = make_control_html (window, row, col, numwindows); title_html = g_strdup_printf ("" "" "
" "" "%s%s
", title_colour[col % 2], window->icon, window->title, control_html); g_free (control_html); gtk_html_write (GTK_HTML (priv->html), priv->stream, title_html, strlen (title_html)); g_free (title_html); } static void e_summary_display_window (ESummary *esummary, ESummaryWindow *window, int row, int col, int numwindows) { ESummaryPrivate *priv; char *footer = ""; char *header; char *colour[2] = {"e6e8e4", "edeeeb"}; priv = esummary->private; header = g_strdup_printf ("", colour[col % 2]); gtk_html_write (GTK_HTML (priv->html), priv->stream, header, strlen (header)); g_free (header); if (window->html != CORBA_OBJECT_NIL) { char *html = NULL; CORBA_Environment ev; CORBA_exception_init (&ev); html = GNOME_Evolution_Summary_HTMLView_getHtml (window->html, &ev); if (ev._major != CORBA_NO_EXCEPTION) { CORBA_exception_free (&ev); g_warning ("Cannot get HTML."); if (html) CORBA_free (html); } else { CORBA_exception_free (&ev); gtk_html_write (GTK_HTML (priv->html), priv->stream, html, strlen (html)); CORBA_free (html); } } else { #if 0 char *body_cid; body_cid = g_strdup_printf ("", id); gtk_html_write (GTK_HTML (priv->html), priv->stream, body_cid, strlen (body_cid)); g_free (body_cid); #endif } gtk_html_write (GTK_HTML (priv->html), priv->stream, footer, strlen (footer)); } static int e_summary_rebuild_page (ESummary *esummary) { ESummaryPrivate *priv; GList *windows; char *service_table = ""; char *tmp; int numwindows, numrows; int i, j, k; int columns; g_return_val_if_fail (esummary != NULL, FALSE); g_return_val_if_fail (IS_E_SUMMARY (esummary), FALSE); priv = esummary->private; if (priv->idle == 0) { g_warning ("esummary->private->idle == 0! This means that " "e_summary_rebuild_page was called by itself and " "not queued. You should use e_summary_queue_rebuild " "instead."); return FALSE; } /* If there is a selection, don't redraw the page so that the selection isn't cleared */ if (GTK_HTML (priv->html)->in_selection == TRUE || html_engine_is_selection_active (GTK_HTML (priv->html)->engine) == TRUE) return FALSE; gtk_layout_freeze (GTK_LAYOUT (priv->html)); e_summary_start_load (esummary); if (priv->header == NULL || *priv->header == '\0') { load_default_header (esummary); } else { gtk_html_write (GTK_HTML (priv->html), priv->stream, priv->header, priv->header_len); } /* Load the start of the services */ tmp = g_strdup_printf (service_table, esummary->prefs->columns); gtk_html_write (GTK_HTML (priv->html), priv->stream, tmp, strlen (tmp)); g_free (tmp); /* Load each of the services */ numwindows = g_list_length (priv->window_list); columns = esummary->prefs->columns; windows = priv->window_list; if (numwindows % columns == 0) numrows = numwindows / columns; else numrows = numwindows / columns + 1; for (i = 0; i < numrows; i++) { GList *window = windows; /* Do the same row twice: Once for the title, once for the contents */ for (j = 0; j < 2; j++) { int limit; gtk_html_write (GTK_HTML (priv->html), priv->stream, "", 4); /* For each window on row i */ limit = MIN (columns, (numwindows - (i * columns))); for (k = 0; k < limit; k++) { if (window == NULL) break; if (j == 0) { e_summary_display_window_title (esummary, window->data, k, k, numwindows); } else { e_summary_display_window (esummary, window->data, k, k, numwindows); } if (window != NULL) window = window->next; if (window == NULL) break; } gtk_html_write (GTK_HTML (priv->html), priv->stream, "", 5); if (j == 0) window = windows; else { if (window) windows = window; else break; } } } gtk_html_write (GTK_HTML (priv->html), priv->stream, "
", 13); if (priv->footer == NULL || *priv->footer == '\0') { load_default_footer (esummary); } else { gtk_html_write (GTK_HTML (priv->html), priv->stream, priv->footer, priv->footer_len); } e_summary_end_load (esummary); gtk_layout_thaw (GTK_LAYOUT (priv->html)); priv->idle = 0; return FALSE; } /* This is the function that should be called instead of e_summary_queue_rebuild. This prevents multiple rebuilds happening together. */ void e_summary_queue_rebuild (ESummary *esummary) { ESummaryPrivate *priv; priv = esummary->private; if (priv->idle != 0) return; priv->idle = g_idle_add ((GSourceFunc) e_summary_rebuild_page, esummary); } static void listener_event (BonoboListener *listener, char *event_name, BonoboArg *event_data, CORBA_Environment *ev, gpointer user_data) { ESummaryWindow *window = (ESummaryWindow *) user_data; if (strcmp (event_name, "Bonobo/Property:change:window_title") == 0) { if (window->title != NULL) g_free (window->title); window->title = g_strdup (BONOBO_ARG_GET_STRING (event_data)); e_summary_queue_rebuild (window->esummary); } else if (strcmp (event_name, "Bonobo/Property:change:window_icon") == 0) { if (window->icon != NULL) g_free (window->icon); window->icon = g_strdup (BONOBO_ARG_GET_STRING (event_data)); e_summary_queue_rebuild (window->esummary); } else if (strcmp (event_name, EXECUTIVE_SUMMARY_HTML_VIEW_HTML_CHANGED) == 0) { e_summary_queue_rebuild (window->esummary); } return; } ESummaryWindow * e_summary_add_service (ESummary *esummary, GNOME_Evolution_Summary_Component component, const char *iid) { ESummaryWindow *window; ESummaryPrivate *priv; Bonobo_Unknown unknown = CORBA_OBJECT_NIL; Bonobo_Listener listener; CORBA_Environment ev; g_return_val_if_fail (esummary != NULL, NULL); g_return_val_if_fail (IS_E_SUMMARY (esummary), NULL); g_return_val_if_fail (component != CORBA_OBJECT_NIL, NULL); priv = esummary->private; window = g_new0 (ESummaryWindow, 1); window->component = component; window->iid = g_strdup (iid); window->esummary = esummary; /* See what interfaces our component supports */ CORBA_exception_init (&ev); unknown = Bonobo_Unknown_queryInterface (component, "IDL:Bonobo/Control:1.0", &ev); window->control = (Bonobo_Control) unknown; unknown = Bonobo_Unknown_queryInterface (component, "IDL:GNOME/Evolution/Summary/HTMLView:1.0", &ev); window->html = (GNOME_Evolution_Summary_HTMLView) unknown; /* Check at least one of the above interfaces was supported */ if (window->html == CORBA_OBJECT_NIL && window->control == CORBA_OBJECT_NIL) { CORBA_Environment ev2; g_warning ("This component does not support either" "Bonobo/Control:1.0 or GNOME/Evolution/Summary/HTMLView:1.0"); CORBA_exception_init (&ev2); CORBA_Object_release (component, &ev2); CORBA_exception_free (&ev2); g_free (window); return NULL; } unknown = Bonobo_Unknown_queryInterface (component, "IDL:Bonobo/PropertyBag:1.0", &ev); window->propertybag = (Bonobo_PropertyBag) unknown; window->event_source = Bonobo_Unknown_queryInterface(window->propertybag, "IDL:Bonobo/EventSource:1.0", &ev); if (window->event_source == CORBA_OBJECT_NIL) { g_warning ("There is no Bonobo::EventSource interface"); /* FIXME: Free whatever objects exist */ g_free (window); return NULL; } window->listener = bonobo_listener_new (NULL, NULL); gtk_signal_connect (GTK_OBJECT (window->listener), "event_notify", GTK_SIGNAL_FUNC (listener_event), window); listener = bonobo_object_corba_objref (BONOBO_OBJECT (window->listener)); window->listener_id = Bonobo_EventSource_addListener (window->event_source, listener, &ev); unknown = Bonobo_Unknown_queryInterface (component, "IDL:Bonobo/PersistStream:1.0", &ev); window->persiststream = (Bonobo_PersistStream) unknown; unknown = Bonobo_Unknown_queryInterface (component, "IDL:Bonobo/PropertyControl:1.0", &ev); window->propertycontrol = (Bonobo_PropertyControl) unknown; /* Cache the title and icon */ window->title = bonobo_property_bag_client_get_value_string (window->propertybag, "window_title", NULL); g_print ("title: %s\n", window->title); window->icon = bonobo_property_bag_client_get_value_string (window->propertybag, "window_icon", NULL); g_print ("icon: %s\n", window->icon); CORBA_exception_free (&ev); priv->window_list = g_list_append (priv->window_list, window); return window; } ESummaryWindow * e_summary_embed_service_from_id (ESummary *esummary, const char *obj_id) { GNOME_Evolution_Summary_Component component; ExecutiveSummaryComponentFactoryClient *client; ESummaryWindow *window; client = executive_summary_component_factory_client_new (obj_id); component = executive_summary_component_factory_client_create_view (client); /* Don't need the client any more */ bonobo_object_unref (BONOBO_OBJECT (client)); window = e_summary_add_service (esummary, component, obj_id); e_summary_queue_rebuild (esummary); return window; } void e_summary_window_free (ESummaryWindow *window) { CORBA_Environment ev; g_return_if_fail (window != NULL); g_free (window->iid); g_free (window->icon); g_free (window->title); CORBA_exception_init (&ev); if (window->control != CORBA_OBJECT_NIL) { bonobo_object_release_unref (window->control, &ev); } if (window->event_source != CORBA_OBJECT_NIL) { Bonobo_EventSource_removeListener (window->event_source, window->listener_id, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("CORBA ERROR: %s", CORBA_exception_id (&ev)); } bonobo_object_release_unref (window->event_source, &ev); } bonobo_object_release_unref (window->propertybag, &ev); bonobo_object_release_unref (window->persiststream, &ev); bonobo_object_release_unref (window->propertycontrol, &ev); bonobo_object_unref (BONOBO_OBJECT (window->listener)); bonobo_object_release_unref (window->html, &ev); bonobo_object_release_unref (window->component, &ev); CORBA_exception_free (&ev); g_free (window); } void e_summary_remove_window (ESummary *esummary, ESummaryWindow *window) { ESummaryPrivate *priv; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); g_return_if_fail (window != NULL); priv = esummary->private; priv->window_list = g_list_remove (priv->window_list, window); e_summary_window_free (window); } void e_summary_set_shell_view_interface (ESummary *esummary, GNOME_Evolution_ShellView svi) { ESummaryPrivate *priv; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); g_return_if_fail (svi != CORBA_OBJECT_NIL); priv = esummary->private; priv->shell_view_interface = svi; } /* Wrappers for GNOME_Evolution_ShellView */ void e_summary_set_message (ESummary *esummary, const char *message, gboolean busy) { ESummaryPrivate *priv; GNOME_Evolution_ShellView svi; CORBA_Environment ev; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; svi = priv->shell_view_interface; if (svi == NULL) return; CORBA_exception_init (&ev); if (message != NULL) GNOME_Evolution_ShellView_setMessage (svi, message, busy, &ev); else GNOME_Evolution_ShellView_setMessage (svi, "", busy, &ev); CORBA_exception_free (&ev); } void e_summary_unset_message (ESummary *esummary) { ESummaryPrivate *priv; GNOME_Evolution_ShellView svi; CORBA_Environment ev; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; svi = priv->shell_view_interface; if (svi == NULL) return; CORBA_exception_init (&ev); GNOME_Evolution_ShellView_unsetMessage (svi, &ev); CORBA_exception_free (&ev); } void e_summary_change_current_view (ESummary *esummary, const char *uri) { ESummaryPrivate *priv; GNOME_Evolution_ShellView svi; CORBA_Environment ev; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; svi = priv->shell_view_interface; if (svi == NULL) return; CORBA_exception_init (&ev); GNOME_Evolution_ShellView_changeCurrentView (svi, uri, &ev); CORBA_exception_free (&ev); } void e_summary_set_title (ESummary *esummary, const char *title) { ESummaryPrivate *priv; GNOME_Evolution_ShellView svi; CORBA_Environment ev; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; svi = priv->shell_view_interface; if (svi == NULL) return; CORBA_exception_init (&ev); GNOME_Evolution_ShellView_setTitle (svi, title, &ev); CORBA_exception_free (&ev); } static void e_summary_load_page (ESummary *esummary) { ESummaryPrivate *priv; GnomeVFSHandle *handle = NULL; GnomeVFSResult result; GtkWidget *toplevel; GString *string; char *str, *comment; char *filename; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; /* Pass NULL to reset the page to the default */ if ((esummary->prefs->page) == NULL || *(esummary->prefs->page) == '\0') { filename = g_concat_dir_and_file (EVOLUTION_DATADIR, "/evolution/summary.html"); } else { filename = g_strdup (esummary->prefs->page); } toplevel = gtk_widget_get_toplevel (GTK_WIDGET (esummary)); string = g_string_new (""); result = gnome_vfs_open (&handle, filename, GNOME_VFS_OPEN_READ); if (result != GNOME_VFS_OK) { e_notice (GTK_WINDOW (toplevel), GNOME_MESSAGE_BOX_WARNING, _("Cannot open the HTML file:\n%s"), filename); g_free (filename); return; } g_free (filename); while (1) { char buffer[4096]; GnomeVFSFileSize size; memset (buffer, 0x00, 4096); result = gnome_vfs_read (handle, buffer, 4096, &size); if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) { e_notice (GTK_WINDOW (toplevel), GNOME_MESSAGE_BOX_WARNING, _("Error reading data:\n%s"), gnome_vfs_result_to_string (result)); gnome_vfs_close (handle); return; } if (size == 0) break; /* EOF */ string = g_string_append (string, buffer); } gnome_vfs_close (handle); str = string->str; g_string_free (string, FALSE); comment = strstr (str, ""); if (comment == NULL) { e_notice (NULL, GNOME_MESSAGE_BOX_WARNING, _("File does not have a place for the services.\n")); g_free (str); return; } if (priv->header != NULL) g_free (priv->header); priv->header = g_strndup (str, comment - str); priv->header_len = strlen (priv->header); if (priv->footer != NULL) g_free (priv->footer); priv->footer = g_strdup (comment); priv->footer_len = strlen (priv->footer); g_free (str); } static char * load_component_id_stream_read (Bonobo_Stream stream, CORBA_Environment *ev) { Bonobo_Stream_iobuf *buffer; GString *str; char *ans; str = g_string_sized_new (256); #define READ_CHUNK_SIZE 65536 do { int i; Bonobo_Stream_read (stream, READ_CHUNK_SIZE, &buffer, ev); if (ev->_major != CORBA_NO_EXCEPTION) return NULL; /* FIXME: make better PLEASE!!!*/ for (i = 0; i < buffer->_length; i++) g_string_append_c (str, buffer->_buffer[i]); if (buffer->_length <= 0) break; CORBA_free (buffer); } while (1); #undef READ_CHUNK_SIZE CORBA_free (buffer); ans = str->str; g_string_free (str, FALSE); return ans; } static char * load_component_id (Bonobo_Storage corba_storage, CORBA_Environment *ev) { Bonobo_Stream corba_stream; char *iid; corba_stream = Bonobo_Storage_openStream (corba_storage, IID_FILE, Bonobo_Storage_READ, ev); if (ev->_major != CORBA_NO_EXCEPTION) return NULL; if (corba_stream) { iid = load_component_id_stream_read (corba_stream, ev); Bonobo_Unknown_unref (corba_stream, ev); CORBA_Object_release (corba_stream, ev); } else { g_warning ("Cannot find `%s'", IID_FILE); return NULL; } return iid; } static void load_component (ESummary *esummary, BonoboStorage *storage, int index) { char *curdir; char *iid; Bonobo_Storage corba_subdir; Bonobo_Storage corba_storage; ESummaryWindow *window; CORBA_Environment ev; curdir = g_strdup_printf ("%08d", index); corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage)); CORBA_exception_init (&ev); corba_subdir = Bonobo_Storage_openStorage (corba_storage, curdir, Bonobo_Storage_READ, &ev); if (corba_subdir == CORBA_OBJECT_NIL) { g_free (curdir); return; } iid = load_component_id (corba_subdir, &ev); if (iid) { Bonobo_Stream corba_stream; window = e_summary_embed_service_from_id (esummary, iid); if (window) { if (window->persiststream) { corba_stream = Bonobo_Storage_openStream (corba_subdir, DATA_FILE, Bonobo_Storage_READ | Bonobo_Storage_CREATE, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_print ("Gah"); return; } Bonobo_PersistStream_load (window->persiststream, corba_stream, "", &ev); if (ev._major != CORBA_NO_EXCEPTION) g_warning ("Could not load `%s'", iid); bonobo_object_release_unref (corba_stream, &ev); } } g_free (iid); } bonobo_object_release_unref (corba_subdir, &ev); CORBA_exception_free (&ev); g_free (curdir); } void e_summary_reconfigure (ESummary *esummary) { e_summary_load_page (esummary); e_summary_queue_rebuild (esummary); } static void e_summary_load_state (ESummary *esummary, const char *path) { char *fullpath; BonoboStorage *storage; Bonobo_Storage corba_storage; Bonobo_Storage_DirectoryList *list; CORBA_Environment ev; int i; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); fullpath = g_strdup_printf ("%s/Executive-Summary", path); storage = bonobo_storage_open (STORAGE_TYPE, fullpath, Bonobo_Storage_READ | Bonobo_Storage_WRITE, 0664); if (storage != NULL) { CORBA_exception_init (&ev); corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage)); list = Bonobo_Storage_listContents (corba_storage, "/", 0, &ev); if (list) { for (i = 0; i < list->_length; i++) load_component (esummary, storage, i); CORBA_free (list); } bonobo_object_unref (BONOBO_OBJECT (storage)); CORBA_exception_free (&ev); } g_free (fullpath); /* Load the preferences */ if (esummary->prefs != NULL) e_summary_prefs_free (esummary->prefs); esummary->prefs = e_summary_prefs_load (path); e_summary_reconfigure (esummary); } static void save_component (BonoboStorage *storage, ESummaryWindow *window, int index) { char *curdir = g_strdup_printf ("%08d", index); Bonobo_Storage corba_storage; Bonobo_Storage corba_subdir; CORBA_Environment ev; corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage)); CORBA_exception_init (&ev); corba_subdir = Bonobo_Storage_openStorage (corba_storage, curdir, Bonobo_Storage_CREATE| Bonobo_Storage_WRITE| Bonobo_Storage_READ, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("Cannot create '%s'", curdir); g_free (curdir); } else { Bonobo_Stream corba_stream; g_free (curdir); corba_stream = Bonobo_Storage_openStream (corba_subdir, IID_FILE, Bonobo_Storage_CREATE| Bonobo_Storage_READ| Bonobo_Storage_WRITE, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("EEK: %s", CORBA_exception_id (&ev)); if (corba_subdir != CORBA_OBJECT_NIL) bonobo_object_release_unref (corba_subdir, &ev); CORBA_exception_free (&ev); return; } bonobo_stream_client_write_string (corba_stream, window->iid, TRUE, &ev); bonobo_object_release_unref (corba_stream, &ev); corba_stream = Bonobo_Storage_openStream (corba_subdir, DATA_FILE, Bonobo_Storage_CREATE, &ev); if (window->persiststream != CORBA_OBJECT_NIL) { Bonobo_PersistStream_save (window->persiststream, corba_stream, "", &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("Unable to save %s", window->iid); } } bonobo_object_release_unref (corba_stream, &ev); } if (corba_subdir != CORBA_OBJECT_NIL) bonobo_object_release_unref (corba_subdir, &ev); CORBA_exception_free (&ev); } static void e_summary_save_state (ESummary *esummary, const char *path) { ESummaryPrivate *priv; BonoboStorage *storage; Bonobo_Storage corba_storage; CORBA_Environment ev; GList *windows; char *fullpath; int i; g_return_if_fail (esummary != NULL); g_return_if_fail (IS_E_SUMMARY (esummary)); priv = esummary->private; fullpath = g_strdup_printf("%s/Executive-Summary", path); g_print ("fullpath: %s\n", fullpath); e_summary_rm_dir (fullpath); storage = bonobo_storage_open (STORAGE_TYPE, fullpath, Bonobo_Storage_READ | Bonobo_Storage_WRITE | Bonobo_Storage_CREATE, 0660); g_return_if_fail (storage); CORBA_exception_init (&ev); corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (storage)); i = 0; for (windows = priv->window_list; windows; windows = windows->next) { save_component (storage, windows->data, i); g_print ("IID: %s\n", ((ESummaryWindow *)windows->data)->iid); i++; } Bonobo_Storage_commit (corba_storage, &ev); CORBA_exception_free (&ev); bonobo_object_unref (BONOBO_OBJECT (storage)); e_summary_prefs_save (esummary->prefs, path); g_free (fullpath); } void e_summary_window_move_left (ESummary *esummary, ESummaryWindow *window) { ESummaryPrivate *priv; GList *win_item, *grandparent; int position; priv = esummary->private; /* Need to cache this location */ win_item = g_list_find (priv->window_list, window); /* Find the item 2 previous. */ if (win_item->prev == NULL) return; /* Item was first, can't be moved left */ grandparent = win_item->prev->prev; /* Remove it from the list */ priv->window_list = g_list_remove_link (priv->window_list, win_item); /* Insert it after the grandparent */ position = g_list_position (priv->window_list, grandparent); priv->window_list = g_list_insert (priv->window_list, win_item->data, position + 1); g_list_free_1 (win_item); } void e_summary_window_move_right (ESummary *esummary, ESummaryWindow *window) { ESummaryPrivate *priv; GList *win_item, *child; int position; priv = esummary->private; win_item = g_list_find (priv->window_list, window); if (win_item->next == NULL) return; child = win_item->next; priv->window_list = g_list_remove_link (priv->window_list, win_item); position = g_list_position (priv->window_list, child); priv->window_list = g_list_insert (priv->window_list, win_item->data, position + 1); g_list_free_1 (win_item); } void e_summary_window_move_up (ESummary *esummary, ESummaryWindow *window) { ESummaryPrivate *priv; GList *win_item; int position; priv = esummary->private; win_item = g_list_find (priv->window_list, window); position = g_list_position (priv->window_list, win_item); priv->window_list = g_list_remove_link (priv->window_list, win_item); priv->window_list = g_list_insert (priv->window_list, win_item->data, position - 3); g_list_free_1 (win_item); } void e_summary_window_move_down (ESummary *esummary, ESummaryWindow *window) { ESummaryPrivate *priv; GList *win_item; int position; priv = esummary->private; win_item = g_list_find (priv->window_list, window); position = g_list_position (priv->window_list, win_item); priv->window_list = g_list_remove_link (priv->window_list, win_item); priv->window_list = g_list_insert (priv->window_list, win_item->data, position + 3); }