]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/gpdf.cc
Clean some redundant code.
[evince.git] / pdf / xpdf / gpdf.cc
index f0237c76646302dfb62b5eb74595884147053c28..69c1ab2294951dec91f31e70f11cf0bba324d66d 100644 (file)
@@ -1,15 +1,10 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * test-container.c
+ * PDF viewer Bonobo container.
  *
- * A simple program to act as a test container for embeddable
- * components.
+ * Author:
+ *   Michael Meeks <michael@imaginator.com>
  *
- * Authors:
- *    Nat Friedman (nat@gnome-support.com)
- *    Miguel de Icaza (miguel@gnu.org)
  */
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -46,10 +41,8 @@ extern "C" {
 #include "Error.h"
 #include "config.h"
 
-CORBA_Environment ev;
-CORBA_ORB orb;
 poptContext ctx;
-gint  gpdf_debug=1;
+gint  gpdf_debug=0;
 
 const struct poptOption gpdf_popt_options [] = {
   { "debug", '\0', POPT_ARG_INT, &gpdf_debug, 0,
@@ -57,449 +50,552 @@ const struct poptOption gpdf_popt_options [] = {
   { NULL, '\0', 0, NULL, 0 }
 };
 
+typedef struct _Component Component;
+typedef struct _Container Container;
+/* NB. there is a 1 to 1 Container -> Component mapping, this
+   is due to how much MDI sucks; unutterably */
+struct _Container {
+  GnomeContainer    *container;
+  GnomeUIHandler    *uih;
+  
+  GnomeViewFrame    *active_view_frame;
+  
+  GtkWidget        *app;
+  GtkScrolledWindow *scroll;
+  GtkWidget        *view_widget;
+  Component         *component;
+};
+
+struct  _Component {
+       Container         *container;
+
+       GnomeClientSite   *client_site;
+       GnomeViewFrame    *view_frame;
+       GnomeObjectClient *server;
+};
+
+GList *containers = NULL;
 /*
- * A handle to some Embeddables and their ClientSites so we can add
- * views to existing components.
+ * Static prototypes.
  */
-GnomeObjectClient *text_obj;
-GnomeClientSite *text_client_site;
-
-GnomeObjectClient *image_png_obj;
-GnomeClientSite   *image_client_site;
+extern "C" {
+  static Container *container_new       (const char *fname);
+  static void       container_destroy   (Container *cont);
+  static void       container_open_cmd  (GtkWidget *widget, Container *container);
+  static void       container_close_cmd (GtkWidget *widget, Container *container);
+  static void       container_exit_cmd  (void);
+  static void       container_about_cmd (GtkWidget *widget, Container *container);
+  static Component *container_activate_component (Container *container, char *component_goad_id);
+}
 
 /*
- * The currently active view.  We keep track of this
- * so we can deactivate it when a new view is activated.
+ * The menus.
  */
-GnomeViewFrame *active_view_frame;
+static GnomeUIInfo container_file_menu [] = {
+       GNOMEUIINFO_MENU_OPEN_ITEM (container_open_cmd, NULL),
+       GNOMEUIINFO_SEPARATOR,
+       GNOMEUIINFO_MENU_CLOSE_ITEM(container_close_cmd, NULL),
+       GNOMEUIINFO_SEPARATOR,
+       GNOMEUIINFO_MENU_EXIT_ITEM (container_exit_cmd, NULL),
+       GNOMEUIINFO_END
+};
 
-char *server_goadid = "gnome_xpdf_viewer";
+static GnomeUIInfo container_help_menu [] = {
+        GNOMEUIINFO_MENU_ABOUT_ITEM(container_about_cmd, NULL),
+       GNOMEUIINFO_END
+};
 
-typedef struct {
-       GtkWidget *app;
-       GnomeContainer *container;
-       GtkWidget *box;
-       GnomeUIHandler *uih;
-       gboolean contains_pdf;
-} Application;
+static GnomeUIInfo container_main_menu [] = {
+       GNOMEUIINFO_MENU_FILE_TREE (container_file_menu),
+       GNOMEUIINFO_MENU_HELP_TREE (container_help_menu),
+       GNOMEUIINFO_END
+};
 
-/* List of applications */
-GList *apps = NULL;
+static GnomeUIInfo container_toolbar [] = {
+       GNOMEUIINFO_ITEM_STOCK (
+               N_("Open"), N_("Opens an existing workbook"),
+               container_open_cmd, GNOME_STOCK_PIXMAP_OPEN),
 
-static Application * application_new (void);
+       GNOMEUIINFO_SEPARATOR,
+       GNOMEUIINFO_END
+};
+
+extern "C" {
+  static gboolean
+  open_pdf (Container *container, const char *name)
+  {
+    GnomeObjectClient *object;
+    GnomeStream *stream;
+    GNOME_PersistStream persist;
+    Component *comp;
+    CORBA_Environment ev;
+
+    g_return_val_if_fail (container != NULL, FALSE);
+    g_return_val_if_fail (container->view_widget == NULL, FALSE);
+
+    comp = container_activate_component (container, "bonobo-object:application-x-pdf");
+    if (!comp || !(object = comp->server)) {
+      gnome_error_dialog (_("Could not launch bonobo object."));
+      return FALSE;
+    }
+    
+    CORBA_exception_init (&ev);
+    persist = GNOME_Unknown_query_interface (
+      gnome_object_corba_objref (GNOME_OBJECT (object)),
+      "IDL:GNOME/PersistStream:1.0", &ev);
+    
+    if (ev._major != CORBA_NO_EXCEPTION ||
+       persist == CORBA_OBJECT_NIL) {
+      gnome_error_dialog ("Panic: component is well broken.");
+      return FALSE;
+    }
+    
+    stream = gnome_stream_fs_open (name, GNOME_Storage_READ);
+    
+    if (stream == NULL) {
+      char *err = g_strconcat (_("Could not open "), name, NULL);
+      gnome_error_dialog_parented (err, GTK_WINDOW(container->app));
+      g_free (err);
+      return FALSE;
+    }
+    
+    GNOME_PersistStream_load (persist,
+                             (GNOME_Stream) gnome_object_corba_objref (GNOME_OBJECT (stream)), &ev);
+
+    GNOME_Unknown_unref (persist, &ev);
+    CORBA_Object_release (persist, &ev);
+    CORBA_exception_free (&ev);
+
+/*    gnome_view_frame_view_do_verb (comp->view_frame, "ZoomFit"); */
+    return TRUE;
+  }
+  
+  static void
+  set_ok (GtkWidget *widget, gboolean *dialog_result)
+  {
+    *dialog_result = TRUE;
+    gtk_main_quit ();
+  }
+  
+  static guint
+  file_dialog_delete_event (GtkWidget *widget, GdkEventAny *event)
+  {
+    gtk_main_quit ();
+    return TRUE;
+  }
+  
+  static void
+  container_open_cmd (GtkWidget *widget, Container *container)
+  {
+    GtkFileSelection *fsel;
+    gboolean accepted = FALSE;
+    
+    fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Load file")));
+    gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
+    
+    gtk_window_set_transient_for (GTK_WINDOW (fsel),
+                                 GTK_WINDOW (container->app));
+    
+    /* Connect the signals for Ok and Cancel */
+    gtk_signal_connect (GTK_OBJECT (fsel->ok_button), "clicked",
+                       GTK_SIGNAL_FUNC (set_ok), &accepted);
+    gtk_signal_connect (GTK_OBJECT (fsel->cancel_button), "clicked",
+                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+    gtk_window_set_position (GTK_WINDOW (fsel), GTK_WIN_POS_MOUSE);
+    
+    /*
+     * Make sure that we quit the main loop if the window is destroyed 
+     */
+    gtk_signal_connect (GTK_OBJECT (fsel), "delete_event",
+                       GTK_SIGNAL_FUNC (file_dialog_delete_event), NULL);
+    
+    /* Run the dialog */
+    gtk_widget_show (GTK_WIDGET (fsel));
+    gtk_grab_add (GTK_WIDGET (fsel));
+    gtk_main ();
+    
+    if (accepted) {
+      char *name = gtk_file_selection_get_filename (fsel);
+      
+      if (name [strlen (name)-1] != '/') {
+       char *fname = g_strdup (name);
+       if (container->view_widget) /* any sort of MDI sucks :-] */
+         container = container_new (fname);
+       else {
+         if (!open_pdf (container, fname))
+           container_destroy (container);
+       }
+       g_free (fname);
+      } else {
+       GtkWidget *dialog;
+       dialog = gnome_message_box_new ("Can't open a directory",
+                                       GNOME_MESSAGE_BOX_ERROR,
+                                       GNOME_STOCK_BUTTON_OK, NULL);
+       gnome_dialog_set_parent (GNOME_DIALOG (dialog),
+                                GTK_WINDOW (container->app));
+       gnome_dialog_run (GNOME_DIALOG (dialog));
+      }
+    }
+    
+    gtk_widget_destroy (GTK_WIDGET (fsel));
+  }
+
+  static void 
+  component_destroy (Component *component)
+  {
+    CORBA_Environment ev;
+    g_return_if_fail (component != NULL);
+
+    CORBA_exception_init (&ev);
+    
+    if (component->server)
+      GNOME_Unknown_unref (
+       gnome_object_corba_objref (GNOME_OBJECT (component->server)), &ev);
+    component->server = NULL;
+
+    CORBA_exception_free (&ev);
+  }
+
+  static void
+  container_destroy (Container *cont)
+  {
+    containers = g_list_remove (containers, cont);
+    if (cont->app)
+      gtk_widget_destroy (cont->app);
+    
+    if (cont->component)
+      component_destroy (cont->component);
+    cont->component = NULL;
+    
+    cont->app = NULL;
+    
+    g_free (cont);
+    if (!containers)
+      gtk_main_quit ();
+  }
+  
+  static void
+  container_close_cmd (GtkWidget *widget, Container *cont)
+  {
+    container_destroy (cont);
+  }
+  
+  static void
+  container_exit_cmd (void)
+  {
+    while (containers)
+      container_destroy ((Container *)containers->data);
+  }
 
-static void
-application_destroy (Application *app)
-{
-       apps = g_list_remove (apps, app);
-       gtk_widget_destroy (app->app);
-       g_free (app);
-       if (!apps)
-               gtk_main_quit ();
-}
 
 static void
-applications_destroy ()
+container_about_cmd (GtkWidget *widget, Container *container)
 {
-       while (apps)
-               application_destroy ((Application *)apps->data);
+  GtkWidget *about;
+  int i;
+
+  const gchar *authors[] = {
+    N_("Derek B. Noonburg, main author"),
+    N_("Michael Meeks, GNOME port maintainer."),
+    N_("Miguel de Icaza."),
+    N_("Nat Friedman."),
+    NULL
+  };
+  
+#ifdef ENABLE_NLS
+  for (i = 0; authors[i] != NULL; i++)
+    authors [i] = _(authors [i]);
+#endif
+  
+  about = gnome_about_new (_("GPDF"), VERSION,
+                          _("(C) 1996-1999 Derek B. Noonburg."),
+                          authors, NULL, NULL);
+  
+  gnome_dialog_set_parent (GNOME_DIALOG (about), GTK_WINDOW (container->app));
+  gnome_dialog_set_close (GNOME_DIALOG (about), TRUE);
+  gtk_widget_show (about);
 }
-
-static GnomeObjectClient *
-launch_server (GnomeClientSite *client_site, GnomeContainer *container, char *goadid)
-{
-       GnomeObjectClient *object_server;
-       
-       gnome_container_add (container, GNOME_OBJECT (client_site));
-
-       printf ("Launching...\n");
-       object_server = gnome_object_activate_with_goad_id (NULL, goadid, GOAD_ACTIVATE_SHLIB, NULL);
-       printf ("Return: %p\n", object_server);
-       if (!object_server){
-               g_warning (_("Can not activate object_server\n"));
-               return NULL;
-       }
-
-       if (!gnome_client_site_bind_embeddable (client_site, object_server)){
-               g_warning (_("Can not bind object server to client_site\n"));
-               return NULL;
-       }
-
-       return object_server;
 }
 
-static GnomeObjectClient *
-launch_server_moniker (GnomeClientSite *client_site, GnomeContainer *container, char *moniker)
+static void
+container_set_view (Container *container, Component *component)
 {
-       GnomeObjectClient *object_server;
-       
-       gnome_container_add (container, GNOME_OBJECT (client_site));
-
-       printf ("Launching moniker %s...\n", moniker);
-       object_server = gnome_object_activate (moniker, GOAD_ACTIVATE_SHLIB);
-       printf ("Return: %p\n", object_server);
-       if (!object_server){
-               g_warning (_("Can not activate object_server\n"));
-               return NULL;
-       }
-
-       if (!gnome_client_site_bind_embeddable (client_site, object_server)){
-               g_warning (_("Can not bind object server to client_site\n"));
-               return NULL;
-       }
-
-       return object_server;
-}
+       GnomeViewFrame *view_frame;
+       GtkWidget *view_widget;
 
-/*
- * This function is called when the user double clicks on a View in
- * order to activate it.
- */
-static gint
-user_activation_request_cb (GnomeViewFrame *view_frame)
-{
        /*
-        * If there is already an active View, deactivate it.
+        * Create the remote view and the local ViewFrame.
         */
-        if (active_view_frame != NULL) {
-               /*
-                * This just sends a notice to the embedded View that
-                * it is being deactivated.  We will also forcibly
-                * cover it so that it does not receive any Gtk
-                * events.
-                */
-                gnome_view_frame_view_deactivate (active_view_frame);
-
-               /*
-                * Here we manually cover it if it hasn't acquiesced.
-                * If it has consented to be deactivated, then it will
-                * already have notified us that it is inactive, and
-                * we will have covered it and set active_view_frame
-                * to NULL.  Which is why this check is here.
-                */
-               if (active_view_frame != NULL)
-                       gnome_view_frame_set_covered (active_view_frame, TRUE);
-                                                                            
-               active_view_frame = NULL;
-       }
+       view_frame = gnome_client_site_new_view (component->client_site);
+       component->view_frame = view_frame;
 
-        /*
-        * Activate the View which the user clicked on.  This just
-        * sends a request to the embedded View to activate itself.
-        * When it agrees to be activated, it will notify its
-        * ViewFrame, and our view_activated_cb callback will be
-        * called.
-        *
-        * We do not uncover the View here, because it may not wish to
-        * be activated, and so we wait until it notifies us that it
-        * has been activated to uncover it.
+       /*
+        * Set the GnomeUIHandler for this ViewFrame.  That way, the
+        * embedded component can get access to our UIHandler server
+        * so that it can merge menu and toolbar items when it gets
+        * activated.
         */
-        gnome_view_frame_view_activate (view_frame);
-
-        return FALSE;
-}                                                                               
-
-/*
- * Gets called when the View notifies the ViewFrame that it would like
- * to be activated or deactivated.
- */
-static gint
-view_activated_cb (GnomeViewFrame *view_frame, gboolean activated)
-{
-
-        if (activated) {
-               /*
-                * If the View is requesting to be activated, then we
-                * check whether or not there is already an active
-                * View.
-                */
-               if (active_view_frame != NULL) {
-                       g_warning ("View requested to be activated but there is already "
-                                  "an active View!\n");
-                       return FALSE;
-               }
-
-               /*
-                * Otherwise, uncover it so that it can receive
-                * events, and set it as the active View.
-                */
-               gnome_view_frame_set_covered (view_frame, FALSE);
-                active_view_frame = view_frame;
-        } else {
-               /*
-                * If the View is asking to be deactivated, always
-                * oblige.  We may have already deactivated it (see
-                * user_activation_request_cb), but there's no harm in
-                * doing it again.  There is always the possibility
-                * that a View will ask to be deactivated when we have
-                * not told it to deactivate itself, and that is
-                * why we cover the view here.
-                */
-               gnome_view_frame_set_covered (view_frame, TRUE);
-
-               if (view_frame == active_view_frame)
-                       active_view_frame = NULL;
-        }                                                                       
-
-        return FALSE;
-}                                                                               
-
-static GnomeViewFrame *
-add_view (Application *app,
-         GnomeClientSite *client_site, GnomeObjectClient *server) 
-{
-       GnomeViewFrame *view_frame;
-       GtkWidget *view_widget;
-       
-       view_frame = gnome_client_site_embeddable_new_view (client_site);
-
-       gtk_signal_connect (GTK_OBJECT (view_frame), "user_activate",
-                           GTK_SIGNAL_FUNC (user_activation_request_cb), NULL);
-       gtk_signal_connect (GTK_OBJECT (view_frame), "view_activated",
-                           GTK_SIGNAL_FUNC (view_activated_cb), NULL);
-
-       gnome_view_frame_set_ui_handler (view_frame, app->uih);
+       gnome_view_frame_set_ui_handler (view_frame, container->uih);
 
+       /*
+        * Embed the view frame into the application.
+        */
        view_widget = gnome_view_frame_get_wrapper (view_frame);
+       container->view_widget = view_widget;
+       container->component   = component;
 
-       gtk_box_pack_start (GTK_BOX (app->box), view_widget, TRUE, TRUE, 0);
-       gtk_widget_show_all (app->box);
-
-       return view_frame;
-} /* add_view */
-
-static GnomeObjectClient *
-add_cmd (Application *app, char *server_goadid,
-        GnomeClientSite **client_site)
-{
-       GnomeObjectClient *server;
-       
-       *client_site = gnome_client_site_new (app->container);
+       /*
+        * Show the component.
+        */
+       gtk_scrolled_window_add_with_viewport (container->scroll, view_widget);
 
-       server = launch_server (*client_site, app->container, server_goadid);
-       if (server == NULL)
-               return NULL;
+       /*
+        * Activate it ( get it to merge menus etc. )
+        */
+       gnome_view_frame_view_activate (view_frame);
 
-       add_view (app, *client_site, server);
-       return server;
+       gtk_widget_show_all (GTK_WIDGET (container->scroll));
 }
 
-static void
-open_pdf (Application *app, const char *name)
+static GnomeObjectClient *
+container_launch_component (GnomeClientSite *client_site,
+                           GnomeContainer *container,
+                           char *component_goad_id)
 {
-       GnomeObjectClient *object;
-       GnomeStream *stream;
-       GNOME_PersistStream persist;
-
-       object = add_cmd (app, "bonobo-object:image-x-pdf", &image_client_site);
-       if (object == NULL) {
-               gnome_error_dialog (_("Could not launch bonobo object."));
-               return;
-       }
-
-       image_png_obj = object;
+       GnomeObjectClient *object_server;
 
-       persist = GNOME_Unknown_query_interface (
-               gnome_object_corba_objref (GNOME_OBJECT (object)),
-               "IDL:GNOME/PersistStream:1.0", &ev);
+       /*
+        * Launch the component.
+        */
+       object_server = gnome_object_activate_with_goad_id (
+               NULL, component_goad_id, GOAD_ACTIVATE_SHLIB, NULL);
 
-        if (ev._major != CORBA_NO_EXCEPTION ||
-           persist == CORBA_OBJECT_NIL) {
-               gnome_error_dialog ("Panic: component is well broken.");
-                return;
-       }
-       
-       stream = gnome_stream_fs_open (name, GNOME_Storage_READ);
+       if (object_server == NULL)
+               return NULL;
 
-       if (stream == NULL) {
-               char *err = g_strconcat (_("Could not open "), name, NULL);
-               gnome_error_dialog_parented (err, GTK_WINDOW(app->app));
-               g_free (err);
-               return;
+       /*
+        * Bind it to the local ClientSite.  Every embedded component
+        * has a local GnomeClientSite object which serves as a
+        * container-side point of contact for the embeddable.  The
+        * container talks to the embeddable through its ClientSite
+        */
+       if (!gnome_client_site_bind_embeddable (client_site, object_server)) {
+               gnome_object_unref (GNOME_OBJECT (object_server));
+               return NULL;
        }
-       
-       GNOME_PersistStream_load (persist,
-            (GNOME_Stream) gnome_object_corba_objref (GNOME_OBJECT (stream)), &ev);
 
-       GNOME_Unknown_unref (persist, &ev);
-       CORBA_Object_release (persist, &ev);
-       app->contains_pdf = TRUE;
-}
+       /*
+        * The GnomeContainer object maintains a list of the
+        * ClientSites which it manages.  Here we add the new
+        * ClientSite to that list.
+        */
+       gnome_container_add (container, GNOME_OBJECT (client_site));
 
-static void
-set_ok (GtkWidget *widget, gboolean *dialog_result)
-{
-       *dialog_result = TRUE;
-       gtk_main_quit ();
+       return object_server;
 }
 
-static guint
-file_dialog_delete_event (GtkWidget *widget, GdkEventAny *event)
-{
-       gtk_main_quit ();
-       return TRUE;
+extern "C" {
+  static Component *
+  container_activate_component (Container *container, char *component_goad_id)
+  {
+    Component *component;
+    GnomeClientSite *client_site;
+    GnomeObjectClient *server;
+    
+    /*
+     * The ClientSite is the container-side point of contact for
+     * the Embeddable.  So there is a one-to-one correspondence
+     * between GnomeClientSites and GnomeEmbeddables.  */
+    client_site = gnome_client_site_new (container->container);
+    
+    /*
+     * A GnomeObjectClient is a simple wrapper for a remote
+     * GnomeObject (a server supporting GNOME::Unknown).
+     */
+    server = container_launch_component (client_site, container->container,
+                                        component_goad_id);
+    if (server == NULL) {
+      char *error_msg;
+      
+      error_msg = g_strdup_printf (_("Could not launch Embeddable %s!"),
+                                  component_goad_id);
+      gnome_warning_dialog (error_msg);
+      g_free (error_msg);
+      
+      return NULL;
+    }
+    
+    /*
+     * Create the internal data structure which we will use to
+     * keep track of this component.
+     */
+    component = g_new0 (Component, 1);
+    component->container = container;
+    component->client_site = client_site;
+    component->server = server;
+    
+    container_set_view (container, component);
+
+    return component;
+  }
+  
+  static void
+  filenames_dropped (GtkWidget * widget,
+                    GdkDragContext   *context,
+                    gint              x,
+                    gint              y,
+                    GtkSelectionData *selection_data,
+                    guint             info,
+                    guint             time,
+                    Container        *container)
+  {
+    GList *names, *tmp_list;
+    
+    names = gnome_uri_list_extract_filenames ((char *)selection_data->data);
+    tmp_list = names;
+    
+    while (tmp_list) {
+      const char *fname = (const char *)tmp_list->data;
+
+      if (fname) {
+       if (container->view_widget)
+         container = container_new (fname);
+       else
+         open_pdf (container, fname);
+      }
+
+      tmp_list = g_list_next (tmp_list);
+    }
+  }
 }
 
 static void
-file_open_cmd (GtkWidget *widget, Application *app)
+container_create_menus (Container *container)
 {
-       GtkFileSelection *fsel;
-       gboolean accepted = FALSE;
-
-       fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Load file")));
-       gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
-
-       gtk_window_set_transient_for (GTK_WINDOW (fsel),
-                                     GTK_WINDOW (app->app));
+       GnomeUIHandlerMenuItem *menu_list;
 
-       /* Connect the signals for Ok and Cancel */
-       gtk_signal_connect (GTK_OBJECT (fsel->ok_button), "clicked",
-                           GTK_SIGNAL_FUNC (set_ok), &accepted);
-       gtk_signal_connect (GTK_OBJECT (fsel->cancel_button), "clicked",
-                           GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
-       gtk_window_set_position (GTK_WINDOW (fsel), GTK_WIN_POS_MOUSE);
+       gnome_ui_handler_create_menubar (container->uih);
 
        /*
-        * Make sure that we quit the main loop if the window is destroyed 
+        * Create the basic menus out of UIInfo structures.
         */
-       gtk_signal_connect (GTK_OBJECT (fsel), "delete_event",
-                           GTK_SIGNAL_FUNC (file_dialog_delete_event), NULL);
-
-       /* Run the dialog */
-       gtk_widget_show (GTK_WIDGET (fsel));
-       gtk_grab_add (GTK_WIDGET (fsel));
-       gtk_main ();
-
-       if (accepted) {
-               char *name = gtk_file_selection_get_filename (fsel);
-
-               if (name [strlen (name)-1] != '/') {
-                       if (app->contains_pdf)
-                               app = application_new ();
-                       char *fname = g_strdup (name);
-                       open_pdf (app, fname);
-                       g_free (fname);
-               } else {
-                       GtkWidget *dialog;
-                       dialog = gnome_message_box_new ("Can't open a directory",
-                                                       GNOME_MESSAGE_BOX_ERROR,
-                                                       GNOME_STOCK_BUTTON_OK, NULL);
-                       gnome_dialog_set_parent (GNOME_DIALOG (dialog),
-                                                GTK_WINDOW (app->app));
-                       gnome_dialog_run (GNOME_DIALOG (dialog));
-               }
-       }
-
-       gtk_widget_destroy (GTK_WIDGET (fsel));
+       menu_list = gnome_ui_handler_menu_parse_uiinfo_list_with_data (container_main_menu, container);
+       gnome_ui_handler_menu_add_list (container->uih, "/", menu_list);
+       gnome_ui_handler_menu_free_list (menu_list);
 }
 
 static void
-close_cmd (GtkWidget *widget, Application *app)
+container_create_toolbar (Container *container)
 {
-       application_destroy (app);
+       GnomeUIHandlerToolbarItem *toolbar;
+
+       gnome_ui_handler_create_toolbar (container->uih, "pdf");
+       toolbar = gnome_ui_handler_toolbar_parse_uiinfo_list_with_data (container_toolbar, container);
+       gnome_ui_handler_toolbar_add_list (container->uih, "/", toolbar);
+       gnome_ui_handler_toolbar_free_list (toolbar);
 }
 
-static void
-exit_cmd (void)
+static Container *
+container_new (const char *fname)
 {
-       applications_destroy ();
-}
+       Container *container;
+       static GtkTargetEntry drag_types[] =
+       {
+         { "text/uri-list", 0, 0 },
+       };
+       static gint n_drag_types = sizeof (drag_types) / sizeof (drag_types [0]);
+       
+       container = g_new0 (Container, 1);
 
-static GnomeUIInfo container_file_menu [] = {
-       GNOMEUIINFO_MENU_OPEN_ITEM (file_open_cmd, NULL),
-       GNOMEUIINFO_SEPARATOR,
-       GNOMEUIINFO_MENU_CLOSE_ITEM(close_cmd, NULL),
-       GNOMEUIINFO_SEPARATOR,
-       GNOMEUIINFO_MENU_EXIT_ITEM (exit_cmd, NULL),
-       GNOMEUIINFO_END
-};
+       container->app  = gnome_app_new ("pdf-viewer",
+                                        "GNOME PDF viewer");
 
-static GnomeUIInfo container_main_menu [] = {
-       GNOMEUIINFO_MENU_FILE_TREE (container_file_menu),
-       GNOMEUIINFO_END
-};
+       gtk_drag_dest_set (container->app,
+                          GTK_DEST_DEFAULT_ALL,
+                          drag_types, n_drag_types,
+                          GDK_ACTION_COPY);
 
-static Application *
-application_new (void)
-{
-       Application *app;
-       GnomeUIHandlerMenuItem *menu_list;
+       gtk_signal_connect (GTK_OBJECT(container->app),
+                           "drag_data_received",
+                           GTK_SIGNAL_FUNC(filenames_dropped), (gpointer)container);
 
-       app = g_new0 (Application, 1);
-       app->app = gnome_app_new ("gpdf",
-                                 "GNOME PDF viewer");
-       app->container = GNOME_CONTAINER (gnome_container_new ());
-       app->contains_pdf = FALSE;
+       gtk_window_set_default_size (GTK_WINDOW (container->app), 600, 600);
+       gtk_window_set_policy (GTK_WINDOW (container->app), TRUE, TRUE, FALSE);
 
-       app->box = gtk_vbox_new (FALSE, 0);
-       gtk_widget_show (app->box);
-       gnome_app_set_contents (GNOME_APP (app->app), app->box);
+       container->container   = gnome_container_new ();
+       container->view_widget = NULL;
+       container->scroll = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL));
+       gtk_scrolled_window_set_policy (container->scroll, GTK_POLICY_AUTOMATIC,
+                                       GTK_POLICY_AUTOMATIC);
+       gnome_app_set_contents (GNOME_APP (container->app), GTK_WIDGET (container->scroll));
 
        /*
-        * Create the menus.
+        * Create the GnomeUIHandler object which will be used to
+        * create the container's menus and toolbars.  The UIHandler
+        * also creates a CORBA server which embedded components use
+        * to do menu/toolbar merging.
         */
-       app->uih = gnome_ui_handler_new ();
+       container->uih = gnome_ui_handler_new ();
+       gnome_ui_handler_set_app (container->uih, GNOME_APP (container->app));
 
-       gnome_ui_handler_set_app (app->uih, GNOME_APP (app->app));
-       gnome_ui_handler_create_menubar (app->uih);
+       container_create_menus   (container);
+       container_create_toolbar (container);
 
-       menu_list = gnome_ui_handler_menu_parse_uiinfo_list_with_data (container_main_menu, app);
-       gnome_ui_handler_menu_add_list (app->uih, "/", menu_list);
-       gnome_ui_handler_menu_free_list (menu_list);
+       gtk_widget_show_all (container->app);
 
-/*     gnome_ui_handler_create_toolbar (app->uih, "Common");
-       gnome_ui_handler_toolbar_new_item (app->uih,
-                                          "/Common/item 1",
-                                          "Container-added Item 1", "I am the container.  Hear me roar.",
-                                          0, GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0, 0,
-                                          NULL, NULL);*/
+       if (fname)
+         if (!open_pdf (container, fname)) {
+           container_destroy (container);
+           return NULL;
+         }
 
-       gtk_widget_show (app->app);
+       containers = g_list_append (containers, container);
 
-       apps = g_list_append (apps, app);
-       return app;
+       gtk_widget_show_all (container->app);
+
+       return container;
 }
 
 int
-main (int argc, char *argv [])
+main (int argc, char **argv)
 {
-       Application *app;
-       char **view_files = NULL;
-
-       if (argc != 1){
-               server_goadid = argv [1];
-       }
-       
-       CORBA_exception_init (&ev);
-       
-       gnome_CORBA_init_with_popt_table ("PDFViewer", "0.0.1",
-                                         &argc, argv,
-                                         gpdf_popt_options, 0, &ctx,
-                                         GNORBA_INIT_SERVER_FUNC, &ev);
-       orb = gnome_CORBA_ORB ();
-       
-       if (bonobo_init (orb, NULL, NULL) == FALSE)
-               g_error (_("Can not bonobo_init\n"));
-
-       app = application_new ();
-
-       view_files = poptGetArgs (ctx);
-
-       /* Load files */
-       if (view_files) {
-               int i;
-               for (i = 0; view_files[i]; i++) {
-                       if (app->contains_pdf)
-                               app = application_new ();
-                       open_pdf (app, view_files[i]);
-               }
-       }
-
-       poptFreeContext (ctx);
-
-       gtk_main ();
-
-       CORBA_exception_free (&ev);
+  CORBA_Environment ev;
+  CORBA_ORB         orb;
+  char            **view_files = NULL;
+  gboolean          loaded;
+  int               i;
+  
+  CORBA_exception_init (&ev);
+  
+  gnome_CORBA_init_with_popt_table ("PDFViewer", "0.0.1",
+                                   &argc, argv,
+                                   gpdf_popt_options, 0, &ctx,
+                                   GNORBA_INIT_SERVER_FUNC, &ev);
+
+  CORBA_exception_free (&ev);
+
+  orb = gnome_CORBA_ORB ();
+
+  if (bonobo_init (orb, NULL, NULL) == FALSE)
+    g_error (_("Could not initialize Bonobo!\n"));
+  bonobo_activate ();
+
+  view_files = poptGetArgs (ctx);
+
+  /* Load files */
+  i = 0;
+  loaded = FALSE;
+  if (view_files) {
+    for (i = 0; view_files[i]; i++)
+      if (container_new (view_files[i]))
+       loaded = TRUE;
+  }
+  if ((i == 0) || !loaded)
+    container_new (NULL);
+  
+  poptFreeContext (ctx);
+
+  gtk_main ();
        
-       return 0;
+  return 0;
 }