]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/gpdf.cc
f0237c76646302dfb62b5eb74595884147053c28
[evince.git] / pdf / xpdf / gpdf.cc
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * test-container.c
4  *
5  * A simple program to act as a test container for embeddable
6  * components.
7  *
8  * Authors:
9  *    Nat Friedman (nat@gnome-support.com)
10  *    Miguel de Icaza (miguel@gnu.org)
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stddef.h>
16 #include <string.h>
17 extern "C" {
18 #define GString G_String
19 #include <gnome.h>
20 #include <libgnorba/gnorba.h>
21 #include <gdk/gdkprivate.h>
22 #include <gdk/gdkx.h>
23 #include <bonobo/gnome-bonobo.h>
24 #undef  GString 
25 }
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include "gtypes.h"
29 #include "GString.h"
30 #include "parseargs.h"
31 #include "gfile.h"
32 #include "gmem.h"
33 #include "Object.h"
34 #include "Stream.h"
35 #include "Array.h"
36 #include "Dict.h"
37 #include "XRef.h"
38 #include "Catalog.h"
39 #include "Page.h"
40 #include "Link.h"
41 #include "PDFDoc.h"
42 #include "GOutputDev.h"
43 #include "PSOutputDev.h"
44 #include "TextOutputDev.h"
45 #include "Params.h"
46 #include "Error.h"
47 #include "config.h"
48
49 CORBA_Environment ev;
50 CORBA_ORB orb;
51 poptContext ctx;
52 gint  gpdf_debug=1;
53
54 const struct poptOption gpdf_popt_options [] = {
55   { "debug", '\0', POPT_ARG_INT, &gpdf_debug, 0,
56     N_("Enables some debugging functions"), N_("LEVEL") },
57   { NULL, '\0', 0, NULL, 0 }
58 };
59
60 /*
61  * A handle to some Embeddables and their ClientSites so we can add
62  * views to existing components.
63  */
64 GnomeObjectClient *text_obj;
65 GnomeClientSite *text_client_site;
66
67 GnomeObjectClient *image_png_obj;
68 GnomeClientSite   *image_client_site;
69
70 /*
71  * The currently active view.  We keep track of this
72  * so we can deactivate it when a new view is activated.
73  */
74 GnomeViewFrame *active_view_frame;
75
76 char *server_goadid = "gnome_xpdf_viewer";
77
78 typedef struct {
79         GtkWidget *app;
80         GnomeContainer *container;
81         GtkWidget *box;
82         GnomeUIHandler *uih;
83         gboolean contains_pdf;
84 } Application;
85
86 /* List of applications */
87 GList *apps = NULL;
88
89 static Application * application_new (void);
90
91 static void
92 application_destroy (Application *app)
93 {
94         apps = g_list_remove (apps, app);
95         gtk_widget_destroy (app->app);
96         g_free (app);
97         if (!apps)
98                 gtk_main_quit ();
99 }
100
101 static void
102 applications_destroy ()
103 {
104         while (apps)
105                 application_destroy ((Application *)apps->data);
106 }
107
108 static GnomeObjectClient *
109 launch_server (GnomeClientSite *client_site, GnomeContainer *container, char *goadid)
110 {
111         GnomeObjectClient *object_server;
112         
113         gnome_container_add (container, GNOME_OBJECT (client_site));
114
115         printf ("Launching...\n");
116         object_server = gnome_object_activate_with_goad_id (NULL, goadid, GOAD_ACTIVATE_SHLIB, NULL);
117         printf ("Return: %p\n", object_server);
118         if (!object_server){
119                 g_warning (_("Can not activate object_server\n"));
120                 return NULL;
121         }
122
123         if (!gnome_client_site_bind_embeddable (client_site, object_server)){
124                 g_warning (_("Can not bind object server to client_site\n"));
125                 return NULL;
126         }
127
128         return object_server;
129 }
130
131 static GnomeObjectClient *
132 launch_server_moniker (GnomeClientSite *client_site, GnomeContainer *container, char *moniker)
133 {
134         GnomeObjectClient *object_server;
135         
136         gnome_container_add (container, GNOME_OBJECT (client_site));
137
138         printf ("Launching moniker %s...\n", moniker);
139         object_server = gnome_object_activate (moniker, GOAD_ACTIVATE_SHLIB);
140         printf ("Return: %p\n", object_server);
141         if (!object_server){
142                 g_warning (_("Can not activate object_server\n"));
143                 return NULL;
144         }
145
146         if (!gnome_client_site_bind_embeddable (client_site, object_server)){
147                 g_warning (_("Can not bind object server to client_site\n"));
148                 return NULL;
149         }
150
151         return object_server;
152 }
153
154 /*
155  * This function is called when the user double clicks on a View in
156  * order to activate it.
157  */
158 static gint
159 user_activation_request_cb (GnomeViewFrame *view_frame)
160 {
161         /*
162          * If there is already an active View, deactivate it.
163          */
164         if (active_view_frame != NULL) {
165                 /*
166                  * This just sends a notice to the embedded View that
167                  * it is being deactivated.  We will also forcibly
168                  * cover it so that it does not receive any Gtk
169                  * events.
170                  */
171                 gnome_view_frame_view_deactivate (active_view_frame);
172
173                 /*
174                  * Here we manually cover it if it hasn't acquiesced.
175                  * If it has consented to be deactivated, then it will
176                  * already have notified us that it is inactive, and
177                  * we will have covered it and set active_view_frame
178                  * to NULL.  Which is why this check is here.
179                  */
180                 if (active_view_frame != NULL)
181                         gnome_view_frame_set_covered (active_view_frame, TRUE);
182                                                                              
183                 active_view_frame = NULL;
184         }
185
186         /*
187          * Activate the View which the user clicked on.  This just
188          * sends a request to the embedded View to activate itself.
189          * When it agrees to be activated, it will notify its
190          * ViewFrame, and our view_activated_cb callback will be
191          * called.
192          *
193          * We do not uncover the View here, because it may not wish to
194          * be activated, and so we wait until it notifies us that it
195          * has been activated to uncover it.
196          */
197         gnome_view_frame_view_activate (view_frame);
198
199         return FALSE;
200 }                                                                               
201
202 /*
203  * Gets called when the View notifies the ViewFrame that it would like
204  * to be activated or deactivated.
205  */
206 static gint
207 view_activated_cb (GnomeViewFrame *view_frame, gboolean activated)
208 {
209
210         if (activated) {
211                 /*
212                  * If the View is requesting to be activated, then we
213                  * check whether or not there is already an active
214                  * View.
215                  */
216                 if (active_view_frame != NULL) {
217                         g_warning ("View requested to be activated but there is already "
218                                    "an active View!\n");
219                         return FALSE;
220                 }
221
222                 /*
223                  * Otherwise, uncover it so that it can receive
224                  * events, and set it as the active View.
225                  */
226                 gnome_view_frame_set_covered (view_frame, FALSE);
227                 active_view_frame = view_frame;
228         } else {
229                 /*
230                  * If the View is asking to be deactivated, always
231                  * oblige.  We may have already deactivated it (see
232                  * user_activation_request_cb), but there's no harm in
233                  * doing it again.  There is always the possibility
234                  * that a View will ask to be deactivated when we have
235                  * not told it to deactivate itself, and that is
236                  * why we cover the view here.
237                  */
238                 gnome_view_frame_set_covered (view_frame, TRUE);
239
240                 if (view_frame == active_view_frame)
241                         active_view_frame = NULL;
242         }                                                                       
243
244         return FALSE;
245 }                                                                               
246
247 static GnomeViewFrame *
248 add_view (Application *app,
249           GnomeClientSite *client_site, GnomeObjectClient *server) 
250 {
251         GnomeViewFrame *view_frame;
252         GtkWidget *view_widget;
253         
254         view_frame = gnome_client_site_embeddable_new_view (client_site);
255
256         gtk_signal_connect (GTK_OBJECT (view_frame), "user_activate",
257                             GTK_SIGNAL_FUNC (user_activation_request_cb), NULL);
258         gtk_signal_connect (GTK_OBJECT (view_frame), "view_activated",
259                             GTK_SIGNAL_FUNC (view_activated_cb), NULL);
260
261         gnome_view_frame_set_ui_handler (view_frame, app->uih);
262
263         view_widget = gnome_view_frame_get_wrapper (view_frame);
264
265         gtk_box_pack_start (GTK_BOX (app->box), view_widget, TRUE, TRUE, 0);
266         gtk_widget_show_all (app->box);
267
268         return view_frame;
269 } /* add_view */
270
271 static GnomeObjectClient *
272 add_cmd (Application *app, char *server_goadid,
273          GnomeClientSite **client_site)
274 {
275         GnomeObjectClient *server;
276         
277         *client_site = gnome_client_site_new (app->container);
278
279         server = launch_server (*client_site, app->container, server_goadid);
280         if (server == NULL)
281                 return NULL;
282
283         add_view (app, *client_site, server);
284         return server;
285 }
286
287 static void
288 open_pdf (Application *app, const char *name)
289 {
290         GnomeObjectClient *object;
291         GnomeStream *stream;
292         GNOME_PersistStream persist;
293
294         object = add_cmd (app, "bonobo-object:image-x-pdf", &image_client_site);
295         if (object == NULL) {
296                 gnome_error_dialog (_("Could not launch bonobo object."));
297                 return;
298         }
299
300         image_png_obj = object;
301
302         persist = GNOME_Unknown_query_interface (
303                 gnome_object_corba_objref (GNOME_OBJECT (object)),
304                 "IDL:GNOME/PersistStream:1.0", &ev);
305
306         if (ev._major != CORBA_NO_EXCEPTION ||
307             persist == CORBA_OBJECT_NIL) {
308                 gnome_error_dialog ("Panic: component is well broken.");
309                 return;
310         }
311         
312         stream = gnome_stream_fs_open (name, GNOME_Storage_READ);
313
314         if (stream == NULL) {
315                 char *err = g_strconcat (_("Could not open "), name, NULL);
316                 gnome_error_dialog_parented (err, GTK_WINDOW(app->app));
317                 g_free (err);
318                 return;
319         }
320         
321         GNOME_PersistStream_load (persist,
322              (GNOME_Stream) gnome_object_corba_objref (GNOME_OBJECT (stream)), &ev);
323
324         GNOME_Unknown_unref (persist, &ev);
325         CORBA_Object_release (persist, &ev);
326         app->contains_pdf = TRUE;
327 }
328
329 static void
330 set_ok (GtkWidget *widget, gboolean *dialog_result)
331 {
332         *dialog_result = TRUE;
333         gtk_main_quit ();
334 }
335
336 static guint
337 file_dialog_delete_event (GtkWidget *widget, GdkEventAny *event)
338 {
339         gtk_main_quit ();
340         return TRUE;
341 }
342
343 static void
344 file_open_cmd (GtkWidget *widget, Application *app)
345 {
346         GtkFileSelection *fsel;
347         gboolean accepted = FALSE;
348
349         fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Load file")));
350         gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
351
352         gtk_window_set_transient_for (GTK_WINDOW (fsel),
353                                       GTK_WINDOW (app->app));
354
355         /* Connect the signals for Ok and Cancel */
356         gtk_signal_connect (GTK_OBJECT (fsel->ok_button), "clicked",
357                             GTK_SIGNAL_FUNC (set_ok), &accepted);
358         gtk_signal_connect (GTK_OBJECT (fsel->cancel_button), "clicked",
359                             GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
360         gtk_window_set_position (GTK_WINDOW (fsel), GTK_WIN_POS_MOUSE);
361
362         /*
363          * Make sure that we quit the main loop if the window is destroyed 
364          */
365         gtk_signal_connect (GTK_OBJECT (fsel), "delete_event",
366                             GTK_SIGNAL_FUNC (file_dialog_delete_event), NULL);
367
368         /* Run the dialog */
369         gtk_widget_show (GTK_WIDGET (fsel));
370         gtk_grab_add (GTK_WIDGET (fsel));
371         gtk_main ();
372
373         if (accepted) {
374                 char *name = gtk_file_selection_get_filename (fsel);
375
376                 if (name [strlen (name)-1] != '/') {
377                         if (app->contains_pdf)
378                                 app = application_new ();
379                         char *fname = g_strdup (name);
380                         open_pdf (app, fname);
381                         g_free (fname);
382                 } else {
383                         GtkWidget *dialog;
384                         dialog = gnome_message_box_new ("Can't open a directory",
385                                                         GNOME_MESSAGE_BOX_ERROR,
386                                                         GNOME_STOCK_BUTTON_OK, NULL);
387                         gnome_dialog_set_parent (GNOME_DIALOG (dialog),
388                                                  GTK_WINDOW (app->app));
389                         gnome_dialog_run (GNOME_DIALOG (dialog));
390                 }
391         }
392
393         gtk_widget_destroy (GTK_WIDGET (fsel));
394 }
395
396 static void
397 close_cmd (GtkWidget *widget, Application *app)
398 {
399         application_destroy (app);
400 }
401
402 static void
403 exit_cmd (void)
404 {
405         applications_destroy ();
406 }
407
408 static GnomeUIInfo container_file_menu [] = {
409         GNOMEUIINFO_MENU_OPEN_ITEM (file_open_cmd, NULL),
410         GNOMEUIINFO_SEPARATOR,
411         GNOMEUIINFO_MENU_CLOSE_ITEM(close_cmd, NULL),
412         GNOMEUIINFO_SEPARATOR,
413         GNOMEUIINFO_MENU_EXIT_ITEM (exit_cmd, NULL),
414         GNOMEUIINFO_END
415 };
416
417 static GnomeUIInfo container_main_menu [] = {
418         GNOMEUIINFO_MENU_FILE_TREE (container_file_menu),
419         GNOMEUIINFO_END
420 };
421
422 static Application *
423 application_new (void)
424 {
425         Application *app;
426         GnomeUIHandlerMenuItem *menu_list;
427
428         app = g_new0 (Application, 1);
429         app->app = gnome_app_new ("gpdf",
430                                   "GNOME PDF viewer");
431         app->container = GNOME_CONTAINER (gnome_container_new ());
432         app->contains_pdf = FALSE;
433
434         app->box = gtk_vbox_new (FALSE, 0);
435         gtk_widget_show (app->box);
436         gnome_app_set_contents (GNOME_APP (app->app), app->box);
437
438         /*
439          * Create the menus.
440          */
441         app->uih = gnome_ui_handler_new ();
442
443         gnome_ui_handler_set_app (app->uih, GNOME_APP (app->app));
444         gnome_ui_handler_create_menubar (app->uih);
445
446         menu_list = gnome_ui_handler_menu_parse_uiinfo_list_with_data (container_main_menu, app);
447         gnome_ui_handler_menu_add_list (app->uih, "/", menu_list);
448         gnome_ui_handler_menu_free_list (menu_list);
449
450 /*      gnome_ui_handler_create_toolbar (app->uih, "Common");
451         gnome_ui_handler_toolbar_new_item (app->uih,
452                                            "/Common/item 1",
453                                            "Container-added Item 1", "I am the container.  Hear me roar.",
454                                            0, GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0, 0,
455                                            NULL, NULL);*/
456
457         gtk_widget_show (app->app);
458
459         apps = g_list_append (apps, app);
460         return app;
461 }
462
463 int
464 main (int argc, char *argv [])
465 {
466         Application *app;
467         char **view_files = NULL;
468
469         if (argc != 1){
470                 server_goadid = argv [1];
471         }
472         
473         CORBA_exception_init (&ev);
474         
475         gnome_CORBA_init_with_popt_table ("PDFViewer", "0.0.1",
476                                           &argc, argv,
477                                           gpdf_popt_options, 0, &ctx,
478                                           GNORBA_INIT_SERVER_FUNC, &ev);
479         orb = gnome_CORBA_ORB ();
480         
481         if (bonobo_init (orb, NULL, NULL) == FALSE)
482                 g_error (_("Can not bonobo_init\n"));
483
484         app = application_new ();
485
486         view_files = poptGetArgs (ctx);
487
488         /* Load files */
489         if (view_files) {
490                 int i;
491                 for (i = 0; view_files[i]; i++) {
492                         if (app->contains_pdf)
493                                 app = application_new ();
494                         open_pdf (app, view_files[i]);
495                 }
496         }
497
498         poptFreeContext (ctx);
499
500         gtk_main ();
501
502         CORBA_exception_free (&ev);
503         
504         return 0;
505 }