]> www.fi.muni.cz Git - evince.git/blob - bonobo-image-x-pdf.cc
c4f2ead593751803edd1539a8f02bb94bc4cb24a
[evince.git] / bonobo-image-x-pdf.cc
1 /*
2  * image/x-pdf BonoboObject.
3  *
4  * Author:
5  *   Michael Meeks <michael@imaginator.com>
6  *
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stddef.h>
11 #include <string.h>
12 #include <config.h>
13 extern "C" {
14 #define GString G_String
15 #include <gnome.h>
16 #include <libgnorba/gnorba.h>
17 #include <bonobo/gnome-bonobo.h>
18 #undef  GString 
19 }
20 #include "gtypes.h"
21 #include "GString.h"
22 #include "parseargs.h"
23 #include "gfile.h"
24 #include "gmem.h"
25 #include "Object.h"
26 #include "Stream.h"
27 #include "Array.h"
28 #include "Dict.h"
29 #include "XRef.h"
30 #include "Catalog.h"
31 #include "Page.h"
32 #include "Link.h"
33 #include "PDFDoc.h"
34 #include "GOutputDev.h"
35 #include "PSOutputDev.h"
36 #include "TextOutputDev.h"
37 #include "Params.h"
38 #include "Error.h"
39 #include "config.h"
40 #include "BonoboStream.h"
41
42 #define PDF_DEBUG 0
43
44 GBool printCommands = gFalse;
45
46 /*
47  * Number of servers running on the system
48  * when the count reaches zero, we unregister from the
49  * Name Server and we shut down.
50  */
51 static int embeddable_servers = 0;
52
53 /*
54  * Our embeddable factory
55  */
56 static GnomeEmbeddableFactory *factory;
57         
58 /* This lock protects the global PDF 'xref' variable */
59 GMutex       *xref_lock;
60
61 /*
62  * BonoboObject data
63  */
64 typedef struct {
65   GnomeEmbeddable *embeddable;
66
67   PDFDoc       *pdf;
68   XRef         *xref; /* Ugly global XRef hack fix */
69
70   BonoboStream *pdf_stream;
71   GNOME_Stream  bonobo_stream;
72
73   GList *views;
74 } bed_t;
75
76 /*
77  * View data
78  */
79 typedef struct {
80   GnomeView            *view;
81   bed_t *bed;
82
83   double                scale;
84   GtkWidget            *drawing_area;
85   GdkPixmap            *pixmap;
86   GdkWindow            *win;
87   GOutputDev           *out;
88   GdkColor              paper;
89   gint                  w, h;
90   gdouble               zoom;
91   gint                  page;
92 } view_data_t;
93
94 static inline void
95 xref_do_lock (bed_t *bed)
96 {
97   g_return_if_fail (bed != NULL);
98
99   g_mutex_lock (xref_lock);
100   xref = bed->xref; /* Ugly global XRef hack fix */
101 }
102
103 static inline void
104 xref_do_unlock (bed_t *bed)
105 {
106   xref = NULL;
107   g_mutex_unlock (xref_lock);
108 }
109
110
111 extern "C" {
112   static void realize_drawing_areas (bed_t *bed);
113   static void setup_pixmap (bed_t *doc, view_data_t *view, GdkWindow *window);
114 }
115
116 static void
117 redraw_view (view_data_t *view_data, GdkRectangle *rect)
118 {
119   gint width, height;
120   bed_t *bed = view_data->bed;
121
122   g_return_if_fail (view_data->pixmap != NULL);
123
124   /*
125    * Do not draw outside the region that we know how to display
126    */
127   if (rect->x > view_data->w)
128     return;
129   
130   if (rect->y > view_data->h)
131     return;
132
133   /*
134    * Clip the draw region
135    */
136   if (rect->x + rect->width > view_data->w)
137     rect->width = view_data->w - rect->x;
138   
139   if (rect->y + rect->height > view_data->h)
140     rect->height = view_data->h - rect->y;
141   
142   /*
143    * Draw the exposed region.
144    */
145   gdk_draw_pixmap (view_data->drawing_area->window,
146                    view_data->drawing_area->style->white_gc,
147                    view_data->pixmap,
148                    rect->x, rect->y,
149                    rect->x, rect->y,
150                    rect->width,
151                    rect->height);
152 }
153
154 static void
155 configure_size (view_data_t *view_data)
156 {
157   gtk_widget_set_usize (
158     view_data->drawing_area,
159     view_data->w,
160     view_data->h);
161 }
162
163 static void
164 render_page (view_data_t *view_data)
165 {
166   setup_pixmap (view_data->bed, view_data,
167                 view_data->win);
168
169   xref_do_lock (view_data->bed);
170   view_data->out->startDoc();
171   view_data->bed->pdf->displayPage (view_data->out,
172                                     view_data->page, view_data->zoom,
173                                     0, gTrue);
174   xref_do_unlock (view_data->bed);
175 }
176
177 static void
178 redraw_view_all (view_data_t *view_data)
179 {
180   GdkRectangle rect;
181   g_return_if_fail (view_data != NULL);
182
183 #if PDF_DEBUG > 0
184   printf ("Redraw view of page %d\n", view_data->page);
185 #endif
186   render_page (view_data);
187   rect.x = 0;
188   rect.y = 0;
189   rect.width  = view_data->w;
190   rect.height = view_data->h;
191   redraw_view (view_data, &rect);
192   gtk_widget_queue_draw (GTK_WIDGET (view_data->drawing_area));
193 }
194
195 static void
196 redraw_all (bed_t *bed)
197 {
198         GList *l;
199         
200         for (l = bed->views; l; l = l->next) {
201           GdkRectangle rect;
202           view_data_t *view_data = (view_data_t *)l->data;
203           redraw_view_all (view_data);
204         }
205 }
206
207 static int
208 save_image (GnomePersistStream *ps, GNOME_Stream stream, void *data)
209 {
210   g_warning ("Unimplemented");
211   return -1;
212 }
213
214 /*
215  * different size ?
216  */
217 static gboolean
218 setup_size (bed_t *doc, view_data_t *view_data)
219 {
220   int      w, h;
221   gboolean same;
222
223   if (!doc || !view_data || !doc->pdf) {
224     view_data->w = 320;
225     view_data->h = 200;
226     return FALSE;
227   }
228   xref_do_lock (view_data->bed);
229   w = (int)((doc->pdf->getPageWidth  (view_data->page)
230              * view_data->zoom) / 72.0);
231   h = (int)((doc->pdf->getPageHeight (view_data->page)
232              * view_data->zoom) / 72.0);
233   xref_do_unlock (view_data->bed);
234   
235   if (view_data->w == w && view_data->h == h)
236     same = TRUE;
237   else
238     same = FALSE;
239   view_data->w = w;
240   view_data->h = h;
241
242   return same;
243 }
244
245 static void
246 bed_free_data (bed_t *bed)
247 {
248   g_return_if_fail (bed != NULL);
249
250   xref_do_lock (bed);
251   if (bed->pdf)
252     delete bed->pdf;
253   bed->pdf = NULL;
254   xref_do_unlock (bed);
255
256   if (bed->pdf_stream)
257     delete (bed->pdf_stream);
258   bed->pdf_stream = NULL;
259   
260   if (bed->bonobo_stream) {
261     CORBA_Environment ev;
262     CORBA_exception_init (&ev);
263     CORBA_Object_release (bed->bonobo_stream, &ev);
264     bed->bonobo_stream = NULL;
265     CORBA_exception_free (&ev);
266   }
267 }
268
269 /*
270  * Loads a PDF from a GNOME_Stream
271  */
272 static int
273 load_image_from_stream (GnomePersistStream *ps, GNOME_Stream stream, void *data)
274 {
275         bed_t *bed = (bed_t *)data;
276         CORBA_long length;
277         GNOME_Stream_iobuf *buffer;
278         CORBA_Environment ev;
279         guint lp;
280         #define CHUNK 512
281         FILE *hack;
282         char *name;
283         Object obj;
284
285         if (bed->pdf || bed->pdf_stream ||
286             bed->bonobo_stream) {
287           g_warning ("Won't overwrite pre-existing stream: you wierdo");
288           return 0;
289         }
290         CORBA_exception_init (&ev);
291
292         /* We need this for later */
293         CORBA_Object_duplicate (stream, &ev);
294         bed->bonobo_stream = stream;
295         g_return_val_if_fail (ev._major == CORBA_NO_EXCEPTION, 0);
296
297 #if PDF_DEBUG > 0
298         printf ("Loading PDF from persiststream\n");
299 #endif
300         xref_do_lock (bed);
301         obj.initNull();
302         bed->pdf_stream = new BonoboStream (stream, 0, -1, &obj);
303         bed->pdf = new PDFDoc (bed->pdf_stream);
304         bed->xref = xref; /* Ugly global XRef hack fix */
305         xref = NULL;
306                                               
307 #if PDF_DEBUG > 0
308         printf ("Done load\n");
309 #endif
310         if (!(bed->pdf->isOk())) {
311           g_warning ("Duff pdf data\n");
312           bed_free_data (bed);
313         }
314         if (!bed->pdf->getCatalog()) {
315           g_warning ("Duff pdf catalog\n");
316           bed_free_data (bed);
317         }
318         xref_do_unlock (bed);
319
320         realize_drawing_areas (bed);
321         redraw_all (bed);
322
323         CORBA_exception_free (&ev);
324         return 0;
325 }
326
327 extern "C" {
328
329   static void
330   destroy_view (GnomeView *view, view_data_t *view_data)
331   {
332     view_data->bed->views = g_list_remove (view_data->bed->views, view_data);
333     gtk_object_unref (GTK_OBJECT (view_data->drawing_area));
334     
335     g_free (view_data);
336   }
337
338   static void
339   destroy_embed (GnomeView *view, bed_t *bed)
340   {
341     CORBA_Environment ev;
342
343     printf ("Destroying embedded component\n");
344
345     while (bed->views)
346       destroy_view (NULL, (view_data_t *)bed->views->data);
347
348     bed_free_data (bed);
349     g_free (bed);
350
351     embeddable_servers--;
352
353     if (embeddable_servers == 0){
354       gnome_object_unref (GNOME_OBJECT (factory));
355       gtk_main_quit ();
356     }
357   }
358
359   static void
360   setup_pixmap (bed_t *doc, view_data_t *view_data, GdkWindow *window)
361   {
362     GdkGCValues  gcValues;
363     GdkGC       *strokeGC;
364     PDFDoc      *pdf;
365     int          w, h;
366     GdkPixmap   *pixmap = NULL;
367     
368     g_return_if_fail (doc != NULL);
369     g_return_if_fail (doc->pdf != NULL);
370     g_return_if_fail (view_data != NULL);
371     
372     pdf = doc->pdf;
373
374     if (setup_size (doc, view_data) &&
375         view_data->pixmap) {
376 #if PDF_DEBUG > 0
377       printf ("No need to re-init output device\n");
378 #endif
379       return;
380     }
381
382     w = view_data->w;
383     h = view_data->h;
384
385     pixmap = gdk_pixmap_new (window, w, h, -1);
386     
387     gdk_color_white (gtk_widget_get_default_colormap(), &view_data->paper);
388     view_data->out = new GOutputDev (pixmap, view_data->paper, window);
389     
390     gdk_color_white (gtk_widget_get_default_colormap (), &gcValues.foreground);
391     gdk_color_black (gtk_widget_get_default_colormap (), &gcValues.background);
392     gcValues.line_width = 1;
393     gcValues.line_style = GDK_LINE_SOLID;
394     strokeGC = gdk_gc_new_with_values (
395       pixmap, &gcValues, 
396       (enum GdkGCValuesMask)(GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_LINE_WIDTH | GDK_GC_LINE_STYLE));
397     
398     gdk_draw_rectangle (pixmap, strokeGC,
399                         TRUE, 0, 0,
400                         w, h);
401     
402     view_data->pixmap = pixmap;
403     configure_size (view_data);
404   }
405
406   static gboolean
407   view_is_good (view_data_t *view_data)
408   {
409     if (!view_data ||
410         !view_data->bed ||
411         !view_data->bed->pdf)
412       return FALSE;
413
414     return TRUE;
415   }
416
417   static gboolean
418   first_page (view_data_t *view_data)
419   {
420     g_return_val_if_fail (view_is_good (view_data), FALSE);
421     if (view_data->page != 1) {
422       view_data->page = 1;
423       return TRUE;
424     } else
425       return FALSE;
426   }
427
428   static gboolean
429   last_page (view_data_t *view_data)
430   {
431     g_return_val_if_fail (view_is_good (view_data), FALSE);
432     if (view_data->page < view_data->bed->pdf->getNumPages()) {
433       view_data->page = view_data->bed->pdf->getNumPages();
434       return TRUE;
435     } else
436       return FALSE;
437   }
438
439   static gboolean
440   next_page (view_data_t *view_data)
441   {
442     g_return_val_if_fail (view_is_good (view_data), FALSE);
443     if (view_data->page < view_data->bed->pdf->getNumPages()) {
444       view_data->page++;
445       return TRUE;
446     } else
447       return FALSE;
448   }
449
450   static gboolean
451   prev_page (view_data_t *view_data)
452   {
453     g_return_val_if_fail (view_is_good (view_data), FALSE);
454     if (view_data->page > 1) {
455       view_data->page--;
456       return TRUE;
457     } else
458       return FALSE;
459   }
460
461   static void
462   page_first_cb (GnomeUIHandler *uih, void *data, char *path)
463   {
464     first_page ((view_data_t *)data);
465     redraw_view_all ((view_data_t *)data);
466   }
467   
468   static void
469   page_next_cb  (GnomeUIHandler *uih, void *data, char *path)
470   {
471     next_page ((view_data_t *)data);
472     redraw_view_all ((view_data_t *)data);
473   }
474   
475   static void
476   page_prev_cb  (GnomeUIHandler *uih, void *data, char *path)
477   {
478     prev_page ((view_data_t *)data);
479     redraw_view_all ((view_data_t *)data);
480   }
481
482   static void
483   page_last_cb  (GnomeUIHandler *uih, void *data, char *path)
484   {
485     last_page ((view_data_t *)data);
486     redraw_view_all ((view_data_t *)data);
487   }
488 }
489
490 static void
491 view_create_menus (view_data_t *view_data)
492 {
493   GNOME_UIHandler remote_uih;
494   GnomeView *view = view_data->view;
495   GnomeUIHandler *uih;
496   
497   uih = gnome_view_get_ui_handler (view);
498   remote_uih = gnome_view_get_remote_ui_handler (view);
499   
500   if (remote_uih == CORBA_OBJECT_NIL) {
501     g_warning ("server has no UI hander");
502     return;
503   }
504   
505   gnome_ui_handler_set_container (uih, remote_uih);
506
507   gnome_ui_handler_menu_new_subtree (uih, "/Page",
508                                      N_("Page..."),
509                                      N_("Set the currently displayed page"),
510                                      1,
511                                      GNOME_UI_HANDLER_PIXMAP_NONE, NULL,
512                                      0, (GdkModifierType)0);
513
514   gnome_ui_handler_menu_new_item (uih, "/Page/First",
515                                   N_("First"), N_("View the first page"), -1,
516                                   GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
517                                   (GdkModifierType)0, page_first_cb, (gpointer)view_data);
518                                  
519   gnome_ui_handler_menu_new_item (uih, "/Page/Prev",
520                                   N_("Previous"), N_("View the previous page"), -1,
521                                   GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
522                                   (GdkModifierType)0, page_prev_cb, (gpointer)view_data);
523                                  
524   gnome_ui_handler_menu_new_item (uih, "/Page/Next",
525                                   N_("Next"), N_("View the next page"), -1,
526                                   GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
527                                   (GdkModifierType)0, page_next_cb, (gpointer)view_data);
528                                  
529   gnome_ui_handler_menu_new_item (uih, "/Page/Last",
530                                   N_("Last"), N_("View the last page"), -1,
531                                   GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0,
532                                   (GdkModifierType)0, page_last_cb, (gpointer)view_data);
533
534   gnome_ui_handler_toolbar_new_item (uih, "/First", 
535                                      N_("First"), N_("View the first page"), -1,
536                                      GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_FIRST,
537                                      0, (GdkModifierType)0, page_first_cb, (gpointer)view_data);
538   gnome_ui_handler_toolbar_new_item (uih, "/Prev",
539                                      N_("Previous"), N_("View the previous page"), -1,
540                                      GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_BACK,
541                                      0, (GdkModifierType)0, page_prev_cb, (gpointer)view_data);
542   gnome_ui_handler_toolbar_new_item (uih, "/Next",
543                                      N_("Next"), N_("View the next page"), -1,
544                                      GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_FORWARD,
545                                      0, (GdkModifierType)0, page_next_cb, (gpointer)view_data);
546   gnome_ui_handler_toolbar_new_item (uih, "/Last",
547                                      N_("Last"), N_("View the last page"), -1,
548                                      GNOME_UI_HANDLER_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_LAST,
549                                      0, (GdkModifierType)0, page_last_cb, (gpointer)view_data);
550 }
551
552 /*
553  * When this view is deactivated, we must remove our menu items.
554  */
555 static void
556 view_remove_menus (view_data_t *view_data)
557 {
558         GnomeView *view = view_data->view;
559         GnomeUIHandler *uih;
560
561         uih = gnome_view_get_ui_handler (view);
562
563         gnome_ui_handler_unset_container (uih);
564 }
565
566 extern "C" {
567
568   static void
569   drawing_area_realize (GtkWidget *drawing_area, view_data_t *view_data)
570   {
571     g_return_if_fail (view_data != NULL);
572     g_return_if_fail (drawing_area != NULL);
573
574     view_data->win = gtk_widget_get_parent_window (drawing_area);
575   }
576
577   static int
578   drawing_area_exposed (GtkWidget *widget, GdkEventExpose *event, view_data_t *view_data)
579   {
580     if (!view_data ||
581         !view_data->bed->pdf)
582       return TRUE;
583     
584     redraw_view (view_data, &event->area);
585     
586     return TRUE;
587   }
588
589   static void
590   view_activate (GnomeView *view, gboolean activate, gpointer data)
591   {
592     view_data_t *view_data = (view_data_t *) data;
593     g_return_if_fail (view != NULL);
594     g_return_if_fail (view_data != NULL);
595     
596     gnome_view_activate_notify (view, activate);
597     
598 #if PDF_DEBUG > 0
599     printf ("View change activation to %d\n", activate);
600 #endif
601     /*
602      * If we were just activated, we merge in our menu entries.
603      * If we were just deactivated, we remove them.
604      */
605     if (activate)
606       view_create_menus (view_data);
607     else
608       view_remove_menus (view_data);
609   }
610
611   static void
612   view_size_query (GnomeView *view, int *desired_width, int *desired_height,
613                    gpointer data)
614   {
615     view_data_t *view_data = (view_data_t *) data;
616     
617     g_return_if_fail (view_data != NULL);
618
619     *desired_width  = view_data->w;
620     *desired_height = view_data->h;
621   }
622
623   static void
624   view_zoom_query (GnomeView *view, gdouble new_zoom, gpointer data)
625   {
626     view_data_t *view_data = (view_data_t *) data;
627
628     g_return_if_fail (view_data != NULL);
629
630     /* The rational behind this is that the _entire_ page is allocated
631        regardless of viewport size, so you _really_ don't want it too big ! */
632     g_return_if_fail (new_zoom > 10.0);
633     g_return_if_fail (new_zoom < 180.0);
634
635     view_data->zoom = new_zoom;
636     redraw_view_all (view_data);
637   }
638
639   static void
640   realize_drawing_areas (bed_t *bed)
641   {
642     GList *l;
643     
644     for (l = bed->views; l; l = l->next) {
645       view_data_t *view_data = (view_data_t *)l->data;
646       g_return_if_fail (view_data->win);
647       render_page (view_data);
648       configure_size (view_data);
649     }  
650   }
651
652   static void
653   view_switch_page (GnomeView *view, const char *verb_name, void *user_data)
654   {
655     view_data_t  *view_data = (view_data_t *) user_data;
656     GdkRectangle  rect;
657     gboolean      changed = FALSE;
658
659     if (!g_strcasecmp (verb_name, "firstpage")) {
660       changed = first_page (view_data);
661     } else if (!g_strcasecmp (verb_name, "prevpage")) {
662       changed = prev_page (view_data);
663     } else if (!g_strcasecmp (verb_name, "nextpage")) {
664       changed = next_page (view_data);
665     } else if (!g_strcasecmp (verb_name, "lastpage")) {
666       changed = last_page (view_data);
667     } else
668       g_warning ("Unknown verb");
669
670     if (changed) {
671       render_page (view_data);
672       redraw_view (view_data, &rect);
673       gtk_widget_queue_draw (GTK_WIDGET (view_data->drawing_area));
674     }
675   }
676 }
677
678 static GnomeView *
679 view_factory (GnomeEmbeddable *embeddable,
680               const GNOME_ViewFrame view_frame,
681               void *data)
682 {
683         GnomeView *view;
684         GnomeUIHandler *uih;
685         bed_t *bed = (bed_t *)data;
686         view_data_t *view_data = g_new (view_data_t, 1);
687
688 #if PDF_DEBUG > 0
689         printf ("Created new bonobo object view %p\n", view_data);
690 #endif
691         
692         view_data->scale  = 1.0;
693         view_data->bed    = bed;
694         view_data->drawing_area = gtk_drawing_area_new ();
695         view_data->pixmap = NULL;
696         view_data->win    = NULL;
697         view_data->out    = NULL;
698         view_data->w      = 320;
699         view_data->h      = 320;
700         view_data->zoom   = 43.0; /* 86.0; Must be small for demos :-) */
701         view_data->page   = 1;
702
703         gtk_signal_connect (
704                 GTK_OBJECT (view_data->drawing_area),
705                 "realize",
706                 GTK_SIGNAL_FUNC (drawing_area_realize), view_data);
707
708         gtk_signal_connect (
709                 GTK_OBJECT (view_data->drawing_area),
710                 "expose_event",
711                 GTK_SIGNAL_FUNC (drawing_area_exposed), view_data);
712
713         gtk_widget_show (view_data->drawing_area);
714
715         setup_size (bed, view_data);
716
717         view = gnome_view_new (view_data->drawing_area);
718         view_data->view = view;
719
720         gtk_signal_connect (
721                 GTK_OBJECT (view), "destroy",
722                 GTK_SIGNAL_FUNC (destroy_view), view_data);
723
724         /* UI handling */
725         uih = gnome_ui_handler_new ();
726         gnome_view_set_ui_handler (view, uih);
727
728         gtk_signal_connect (GTK_OBJECT (view), "view_activate",
729                             GTK_SIGNAL_FUNC (view_activate), view_data);
730
731         gtk_signal_connect (GTK_OBJECT (view), "size_query",
732                             GTK_SIGNAL_FUNC (view_size_query), view_data);
733
734         gtk_signal_connect (GTK_OBJECT (view), "set_zoom_factor",
735                             GTK_SIGNAL_FUNC (view_zoom_query), view_data);
736
737         bed->views = g_list_prepend (bed->views, view_data);
738
739         /* Verb handling */
740         gnome_view_register_verb (view, "FirstPage",
741                                   view_switch_page, view_data);
742         gnome_view_register_verb (view, "PrevPage",
743                                   view_switch_page, view_data);
744         gnome_view_register_verb (view, "NextPage",
745                                   view_switch_page, view_data);
746         gnome_view_register_verb (view, "LastPage",
747                                   view_switch_page, view_data);
748
749         return view;
750 }
751
752 static GnomeObject *
753 embeddable_factory (GnomeEmbeddableFactory *This, void *data)
754 {
755         GnomeEmbeddable *embeddable;
756         GnomePersistStream *stream;
757         bed_t *bed = (bed_t *)data;
758
759         bed = g_new0 (bed_t, 1);
760         if (!bed)
761                 return NULL;
762
763 #if PDF_DEBUG > 0
764         printf ("Created new bonobo object %p\n", bed);
765 #endif
766         /*
767          * Creates the BonoboObject server
768          */
769         embeddable = gnome_embeddable_new (view_factory, bed);
770         if (embeddable == NULL){
771                 g_free (bed);
772                 return NULL;
773         }
774
775         bed->pdf = NULL;
776
777         /*
778          * Interface GNOME::PersistStream 
779          */
780         stream = gnome_persist_stream_new ("bonobo-object:image-x-pdf",
781                                            load_image_from_stream,
782                                            save_image,
783                                            bed);
784         if (stream == NULL) {
785                 gtk_object_unref (GTK_OBJECT (embeddable));
786                 g_free (bed);
787                 return NULL;
788         }
789
790         bed->embeddable = embeddable;
791
792         /*
793          * Bind the interfaces
794          */
795         gnome_object_add_interface (GNOME_OBJECT (embeddable),
796                                     GNOME_OBJECT (stream));
797         gtk_signal_connect (
798           GTK_OBJECT (embeddable), "destroy",
799           GTK_SIGNAL_FUNC (destroy_embed), bed);
800
801         embeddable_servers++;
802
803         /* Setup some verbs */
804         gnome_embeddable_add_verb (embeddable,
805                                    "FirstPage",
806                                    _("_First page"),
807                                    _("goto the first page"));
808         gnome_embeddable_add_verb (embeddable,
809                                    "PrevPage",
810                                    _("_Previous page"),
811                                    _("goto the previous page"));
812         gnome_embeddable_add_verb (embeddable,
813                                    "NextPage",
814                                    _("_Next page"),
815                                    _("goto the next page"));
816         gnome_embeddable_add_verb (embeddable,
817                                    "LastPage",
818                                    _("_Last page"),
819                                    _("goto the last page"));
820         
821         return (GnomeObject *) embeddable;
822 }
823
824 static gboolean
825 init_bonobo_image_x_pdf_factory (void)
826 {
827         factory = gnome_embeddable_factory_new (
828                 "bonobo-object-factory:image-x-pdf",
829                 embeddable_factory, NULL);
830
831         if (factory == NULL)
832                 return FALSE;
833         else
834                 return TRUE;
835 }
836
837 static void
838 init_server_factory (int argc, char **argv)
839 {
840   CORBA_Environment ev;
841
842   CORBA_exception_init (&ev);
843
844   gnome_CORBA_init_with_popt_table (
845     "bonobo-image-x-pdf", "1.0",
846     &argc, argv, NULL, 0, NULL, GNORBA_INIT_SERVER_FUNC, &ev);
847   
848   if (bonobo_init (CORBA_OBJECT_NIL, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE)
849     g_error (_("I could not initialize Bonobo"));
850
851   CORBA_exception_free (&ev);
852 }
853
854 int
855 main (int argc, char *argv [])
856 {
857   g_thread_init (NULL);
858   xref_lock = g_mutex_new ();
859   
860   init_server_factory (argc, argv);
861   if (!init_bonobo_image_x_pdf_factory ()) {
862     fprintf (stderr, "Could not initialize the Bonobo PDF factory\n"
863                      "probably a server is already running?");
864     exit (1);
865   }
866   
867   errorInit ();
868   
869   initParams (xpdfConfigFile); /* Init font path */
870   
871   gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
872   gtk_widget_set_default_visual (gdk_rgb_get_visual ());
873
874   bonobo_main ();
875
876   freeParams ();
877   g_mutex_free (xref_lock);
878   
879   return 0;
880 }
881