]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/XPDFViewer.cc
Import of Xpdf 2.03
[evince.git] / pdf / xpdf / XPDFViewer.cc
1 //========================================================================
2 //
3 // XPDFViewer.cc
4 //
5 // Copyright 2002-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <X11/cursorfont.h>
19 #ifdef HAVE_X11_XPM_H
20 #include <X11/xpm.h>
21 #endif
22 #if defined(__sgi) && (XmVERSION <= 1)
23 #define Object XtObject
24 #include <Sgm/HPanedW.h>
25 #undef Object
26 #endif
27 #include "gmem.h"
28 #include "gfile.h"
29 #include "GString.h"
30 #include "GList.h"
31 #include "Error.h"
32 #include "GlobalParams.h"
33 #include "PDFDoc.h"
34 #include "ErrorCodes.h"
35 #include "Outline.h"
36 #include "UnicodeMap.h"
37 #ifndef DISABLE_OUTLINE
38 #define Object XtObject
39 #include "XPDFTree.h"
40 #undef Object
41 #endif
42 #include "XPDFApp.h"
43 #include "XPDFViewer.h"
44 #include "XPixmapOutputDev.h"
45 #include "PSOutputDev.h"
46 #include "config.h"
47
48 // these macro defns conflict with xpdf's Object class
49 #ifdef LESSTIF_VERSION
50 #undef XtDisplay
51 #undef XtScreen
52 #undef XtWindow
53 #undef XtParent
54 #undef XtIsRealized
55 #endif
56
57 #if XmVERSION <= 1
58 #define XmSET   True
59 #define XmUNSET False
60 #endif
61
62 //------------------------------------------------------------------------
63 // GUI includes
64 //------------------------------------------------------------------------
65
66 #include "xpdfIcon.xpm"
67 #include "leftArrow.xbm"
68 #include "leftArrowDis.xbm"
69 #include "dblLeftArrow.xbm"
70 #include "dblLeftArrowDis.xbm"
71 #include "rightArrow.xbm"
72 #include "rightArrowDis.xbm"
73 #include "dblRightArrow.xbm"
74 #include "dblRightArrowDis.xbm"
75 #include "backArrow.xbm"
76 #include "backArrowDis.xbm"
77 #include "forwardArrow.xbm"
78 #include "forwardArrowDis.xbm"
79 #include "find.xbm"
80 #include "findDis.xbm"
81 #include "print.xbm"
82 #include "printDis.xbm"
83 #include "about.xbm"
84 #include "about-text.h"
85
86 //------------------------------------------------------------------------
87
88 struct ZoomMenuInfo {
89   char *label;
90   double zoom;
91 };
92
93 static ZoomMenuInfo zoomMenuInfo[nZoomMenuItems] = {
94   { "400%",      400 },
95   { "200%",      200 },
96   { "150%",      150 },
97   { "125%",      125 },
98   { "100%",      100 },
99   { "50%",        50 },
100   { "25%",        25 },
101   { "12.5%",      12.5 },
102   { "fit page",  zoomPage },
103   { "fit width", zoomWidth }
104 };
105
106 #define maxZoomIdx   0
107 #define defZoomIdx   3
108 #define minZoomIdx   7
109 #define zoomPageIdx  8
110 #define zoomWidthIdx 9
111
112 //------------------------------------------------------------------------
113
114 XPDFViewer::XPDFViewer(XPDFApp *appA, GString *fileName,
115                        int pageA, GString *destName,
116                        GString *ownerPassword, GString *userPassword) {
117   LinkDest *dest;
118   int pg;
119   double z;
120   GString *dir;
121
122   app = appA;
123   win = NULL;
124   core = NULL;
125   password = NULL;
126   ok = gFalse;
127 #ifndef DISABLE_OUTLINE
128   outlineLabels = NULL;
129   outlineLabelsLength = outlineLabelsSize = 0;
130 #endif
131
132   // do Motif-specific initialization and create the window;
133   // this also creates the core object
134   initWindow();
135   initAboutDialog();
136   initOpenDialog();
137   initFindDialog();
138   initSaveAsDialog();
139   initPrintDialog();
140   initPasswordDialog();
141
142   dest = NULL; // make gcc happy
143   pg = pageA; // make gcc happy
144
145   if (fileName) {
146     if (loadFile(fileName, ownerPassword, userPassword)) {
147       getPageAndDest(pageA, destName, &pg, &dest);
148 #ifndef DISABLE_OUTLINE
149       if (!app->getFullScreen() &&
150           core->getDoc()->getOutline()->getItems() &&
151           core->getDoc()->getOutline()->getItems()->getLength() > 0) {
152         XtVaSetValues(outlineScroll, XmNwidth, 175, NULL);
153       }
154 #endif
155       if (pg > 0) {
156         core->resizeToPage(pg);
157       }
158       dir = makePathAbsolute(grabPath(fileName->getCString()));
159       setOpenDialogDir(dir->getCString());
160       setSaveAsDialogDir(dir->getCString());
161       delete dir;
162     } else {
163       return;
164     }
165   }
166
167   // map the window -- we do this after calling resizeToPage to avoid
168   // an annoying on-screen resize
169   mapWindow();
170
171   // display the first page
172   z = app->getFullScreen() ? zoomPage : core->getZoom();
173   if (dest) {
174     displayDest(dest, z, core->getRotate(), gTrue);
175     delete dest;
176   } else {
177     displayPage(pg, z, core->getRotate(), gTrue, gTrue);
178   }
179
180   ok = gTrue;
181 }
182
183 XPDFViewer::~XPDFViewer() {
184   delete core;
185   XmFontListFree(aboutBigFont);
186   XmFontListFree(aboutVersionFont);
187   XmFontListFree(aboutFixedFont);
188   closeWindow();
189 #ifndef DISABLE_OUTLINE
190   if (outlineLabels) {
191     gfree(outlineLabels);
192   }
193 #endif
194   if (password) {
195     delete password;
196   }
197 }
198
199 void XPDFViewer::open(GString *fileName, int pageA, GString *destName) {
200   LinkDest *dest;
201   int pg;
202   double z;
203
204   if (!core->getDoc() || fileName->cmp(core->getDoc()->getFileName())) {
205     if (!loadFile(fileName, NULL, NULL)) {
206       return;
207     }
208   }
209   getPageAndDest(pageA, destName, &pg, &dest);
210   z = app->getFullScreen() ? zoomPage : core->getZoom();
211   if (dest) {
212     displayDest(dest, z, core->getRotate(), gTrue);
213     delete dest;
214   } else {
215     displayPage(pg, z, core->getRotate(), gTrue, gTrue);
216   }
217 }
218
219 void XPDFViewer::clear() {
220   char *title;
221   XmString s;
222
223   core->clear();
224
225   // set up title, number-of-pages display
226   title = app->getTitle() ? app->getTitle()->getCString()
227                           : (char *)xpdfAppName;
228   XtVaSetValues(win, XmNtitle, title, XmNiconName, title, NULL);
229   s = XmStringCreateLocalized("");
230   XtVaSetValues(pageNumText, XmNlabelString, s, NULL);
231   XmStringFree(s);
232   s = XmStringCreateLocalized(" of 0");
233   XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL);
234   XmStringFree(s);
235
236   // disable buttons
237   XtVaSetValues(prevTenPageBtn, XmNsensitive, False, NULL);
238   XtVaSetValues(prevPageBtn, XmNsensitive, False, NULL);
239   XtVaSetValues(nextTenPageBtn, XmNsensitive, False, NULL);
240   XtVaSetValues(nextPageBtn, XmNsensitive, False, NULL);
241
242   // remove the old outline
243 #ifndef DISABLE_OUTLINE
244   setupOutline();
245 #endif
246 }
247
248 //------------------------------------------------------------------------
249 // load / display
250 //------------------------------------------------------------------------
251
252 GBool XPDFViewer::loadFile(GString *fileName, GString *ownerPassword,
253                            GString *userPassword) {
254   return core->loadFile(fileName, ownerPassword, userPassword) == errNone;
255 }
256
257 void XPDFViewer::reloadFile() {
258   int pg;
259
260   if (!core->getDoc()) {
261     return;
262   }
263   pg = core->getPageNum();
264   loadFile(core->getDoc()->getFileName());
265   if (pg > core->getDoc()->getNumPages()) {
266     pg = core->getDoc()->getNumPages();
267   }
268   displayPage(pg, core->getZoom(), core->getRotate(), gFalse, gFalse);
269 }
270
271 void XPDFViewer::displayPage(int pageA, double zoomA, int rotateA,
272                              GBool scrollToTop, GBool addToHist) {
273   core->displayPage(pageA, zoomA, rotateA, scrollToTop, addToHist);
274 }
275
276 void XPDFViewer::displayDest(LinkDest *dest, double zoomA, int rotateA,
277                              GBool addToHist) {
278   core->displayDest(dest, zoomA, rotateA, addToHist);
279 }
280
281 void XPDFViewer::getPageAndDest(int pageA, GString *destName,
282                                 int *pageOut, LinkDest **destOut) {
283   Ref pageRef;
284
285   // find the page number for a named destination
286   *pageOut = pageA;
287   *destOut = NULL;
288   if (destName && (*destOut = core->getDoc()->findDest(destName))) {
289     if ((*destOut)->isPageRef()) {
290       pageRef = (*destOut)->getPageRef();
291       *pageOut = core->getDoc()->findPage(pageRef.num, pageRef.gen);
292     } else {
293       *pageOut = (*destOut)->getPageNum();
294     }
295   }
296
297   if (*pageOut <= 0) {
298     *pageOut = 1;
299   }
300   if (*pageOut > core->getDoc()->getNumPages()) {
301     *pageOut = core->getDoc()->getNumPages();
302   }
303 }
304
305 //------------------------------------------------------------------------
306 // password dialog
307 //------------------------------------------------------------------------
308
309 GString *XPDFViewer::reqPasswordCbk(void *data, GBool again) {
310   XPDFViewer *viewer = (XPDFViewer *)data;
311
312   viewer->getPassword(again);
313   return viewer->password;
314 }
315
316 //------------------------------------------------------------------------
317 // actions
318 //------------------------------------------------------------------------
319
320 void XPDFViewer::actionCbk(void *data, char *action) {
321   XPDFViewer *viewer = (XPDFViewer *)data;
322
323   if (!strcmp(action, "Quit")) {
324     viewer->app->quit();
325   }
326 }
327
328 //------------------------------------------------------------------------
329 // keyboard/mouse input
330 //------------------------------------------------------------------------
331
332 void XPDFViewer::keyPressCbk(void *data, char *s, KeySym key,
333                              Guint modifiers) {
334   XPDFViewer *viewer = (XPDFViewer *)data;
335   int z;
336
337   if (s[0]) {
338     switch (s[0]) {
339     case 'O':
340     case 'o':
341       viewer->mapOpenDialog(gFalse);
342       break;
343     case 'R':
344     case 'r':
345       viewer->reloadFile();
346       break;
347     case 'F':
348     case 'f':
349     case '\006':                // ctrl-F
350       if (viewer->core->getDoc()) {
351         XtManageChild(viewer->findDialog);
352       }
353       break;
354     case '\007':                // ctrl-G
355       if (viewer->core->getDoc()) {
356         viewer->doFind(gTrue);
357       }
358       break;
359     case '\020':                // ctrl-P
360       if (viewer->core->getDoc()) {
361         XtManageChild(viewer->printDialog);
362       }
363       break;
364     case 'N':
365     case 'n':
366       viewer->core->gotoNextPage(1, !(modifiers & Mod5Mask));
367       break;
368     case 'P':
369     case 'p':
370       viewer->core->gotoPrevPage(1, !(modifiers & Mod5Mask), gFalse);
371       break;
372     case ' ':
373       if (viewer->app->getFullScreen()) {
374         viewer->core->gotoNextPage(1, gTrue);
375       } else {
376         viewer->core->scrollPageDown();
377       }
378       break;
379     case '\b':                  // bs
380     case '\177':                // del
381       if (viewer->app->getFullScreen()) {
382         viewer->core->gotoPrevPage(1, gTrue, gFalse);
383       } else {
384         viewer->core->scrollPageUp();
385       }
386       break;
387     case 'v':
388       viewer->core->goForward();
389       break;
390     case 'b':
391       viewer->core->goBackward();
392       break;
393     case 'g':
394       if (!viewer->app->getFullScreen()) {
395         XmTextFieldSetSelection(
396             viewer->pageNumText, 0,
397             strlen(XmTextFieldGetString(viewer->pageNumText)),
398             XtLastTimestampProcessed(viewer->display));
399         XmProcessTraversal(viewer->pageNumText, XmTRAVERSE_CURRENT);
400       }
401       break;
402     case 'h':                   // vi-style left
403       if (!viewer->app->getFullScreen() && viewer->app->getViKeys()) {
404         viewer->core->scrollLeft();
405       }
406       break;
407     case 'l':                   // vi-style right
408       if (!viewer->app->getFullScreen() && viewer->app->getViKeys()) {
409         viewer->core->scrollRight();
410       }
411       break;
412     case 'k':                   // vi-style up
413       if (!viewer->app->getFullScreen() && viewer->app->getViKeys()) {
414         viewer->core->scrollUp();
415       }
416       break;
417     case 'j':                   // vi-style down
418       if (!viewer->app->getFullScreen() && viewer->app->getViKeys()) {
419         viewer->core->scrollDown();
420       }
421       break;
422     case '0':
423       if (!viewer->app->getFullScreen() &&
424           viewer->core->getZoom() != defZoom) {
425         viewer->setZoomIdx(defZoomIdx);
426         viewer->displayPage(viewer->core->getPageNum(), defZoom,
427                             viewer->core->getRotate(), gTrue, gFalse);
428       }
429       break;
430     case '+':
431       if (!viewer->app->getFullScreen()) {
432         z = viewer->getZoomIdx();
433         if (z <= minZoomIdx && z > maxZoomIdx) {
434           --z;
435           viewer->setZoomIdx(z);
436           viewer->displayPage(viewer->core->getPageNum(),
437                               zoomMenuInfo[z].zoom,
438                               viewer->core->getRotate(), gTrue, gFalse);
439         }
440       }
441       break;
442     case '-':
443       if (!viewer->app->getFullScreen()) {
444         z = viewer->getZoomIdx();
445         if (z < minZoomIdx && z >= maxZoomIdx) {
446           ++z;
447           viewer->setZoomIdx(z);
448           viewer->displayPage(viewer->core->getPageNum(),
449                               zoomMenuInfo[z].zoom,
450                               viewer->core->getRotate(), gTrue, gFalse);
451         }
452       }
453       break;
454     case 'z':
455       if (!viewer->app->getFullScreen() &&
456           viewer->core->getZoom() != zoomPage) {
457         viewer->setZoomIdx(zoomPageIdx);
458         viewer->displayPage(viewer->core->getPageNum(), zoomPage,
459                             viewer->core->getRotate(), gTrue, gFalse);
460       }
461       break;
462     case 'w':
463       if (!viewer->app->getFullScreen() &&
464           viewer->core->getZoom() != zoomWidth) {
465         viewer->setZoomIdx(zoomWidthIdx);
466         viewer->displayPage(viewer->core->getPageNum(), zoomWidth,
467                             viewer->core->getRotate(), gTrue, gFalse);
468       }
469       break;
470     case '\014':                // ^L
471       viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(),
472                           viewer->core->getRotate(), gFalse, gFalse);
473       break;
474     case '\027':                // ^W
475       viewer->app->close(viewer, gFalse);
476       break;
477     case '?':
478       XtManageChild(viewer->aboutDialog);
479       break;
480     case 'Q':
481     case 'q':
482       viewer->app->quit();
483       break;
484     }
485   }
486 }
487
488 void XPDFViewer::mouseCbk(void *data, XEvent *event) {
489   XPDFViewer *viewer = (XPDFViewer *)data;
490
491   if (event->type == ButtonPress && event->xbutton.button == 3) {
492     XmMenuPosition(viewer->popupMenu, &event->xbutton);
493     XtManageChild(viewer->popupMenu);
494
495     // this is magic (taken from DDD) - weird things happen if this
496     // call isn't made (this is done in two different places, in hopes
497     // of squashing this stupid bug)
498     XtUngrabButton(viewer->core->getDrawAreaWidget(), AnyButton, AnyModifier);
499   }
500 }
501
502 //------------------------------------------------------------------------
503 // GUI code: main window
504 //------------------------------------------------------------------------
505
506 void XPDFViewer::initWindow() {
507   Widget btn, label, lastBtn, zoomWidget;
508 #ifndef DISABLE_OUTLINE
509   Widget clipWin;
510 #endif
511   Colormap colormap;
512   XColor xcol;
513   Arg args[20];
514   int n;
515   char *title;
516   XmString s, s2, emptyString;
517   int i;
518
519   display = XtDisplay(app->getAppShell());
520   screenNum = XScreenNumberOfScreen(XtScreen(app->getAppShell()));
521
522   // private colormap
523   if (app->getInstallCmap()) {
524     XtVaGetValues(app->getAppShell(), XmNcolormap, &colormap, NULL);
525     // ensure that BlackPixel and WhitePixel are reserved in the
526     // new colormap
527     xcol.red = xcol.green = xcol.blue = 0;
528     XAllocColor(display, colormap, &xcol);
529     xcol.red = xcol.green = xcol.blue = 65535;
530     XAllocColor(display, colormap, &xcol);
531     colormap = XCopyColormapAndFree(display, colormap);
532   }
533
534   // top-level window
535   n = 0;
536   title = app->getTitle() ? app->getTitle()->getCString()
537                           : (char *)xpdfAppName;
538   XtSetArg(args[n], XmNtitle, title); ++n;
539   XtSetArg(args[n], XmNiconName, title); ++n;
540   XtSetArg(args[n], XmNminWidth, 100); ++n;
541   XtSetArg(args[n], XmNminHeight, 100); ++n;
542   XtSetArg(args[n], XmNbaseWidth, 0); ++n;
543   XtSetArg(args[n], XmNbaseHeight, 0); ++n;
544   XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); ++n;
545   if (app->getFullScreen()) {
546     XtSetArg(args[n], XmNmwmDecorations, 0); ++n;
547     XtSetArg(args[n], XmNgeometry, "+0+0"); ++n;
548   } else if (app->getGeometry()) {
549     XtSetArg(args[n], XmNgeometry, app->getGeometry()->getCString()); ++n;
550   }
551   win = XtCreatePopupShell("win", topLevelShellWidgetClass,
552                            app->getAppShell(), args, n);
553   if (app->getInstallCmap()) {
554     XtVaSetValues(win, XmNcolormap, colormap, NULL);
555   }
556   XmAddWMProtocolCallback(win, XInternAtom(display, "WM_DELETE_WINDOW", False),
557                           &closeMsgCbk, this);
558
559   // form
560   n = 0;
561   form = XmCreateForm(win, "form", args, n);
562   XtManageChild(form);
563
564   // toolbar
565   n = 0;
566   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
567   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
568   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
569   toolBar = XmCreateForm(form, "toolBar", args, n);
570   XtManageChild(toolBar);
571
572   // create an empty string -- this is used for buttons that will get
573   // pixmaps later
574   emptyString = XmStringCreateLocalized("");
575
576   // page movement buttons
577   n = 0;
578   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
579   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
580   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
581   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
582   XtSetArg(args[n], XmNsensitive, False); ++n;
583   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
584   backBtn = XmCreatePushButton(toolBar, "back", args, n);
585   XtManageChild(backBtn);
586   XtAddCallback(backBtn, XmNactivateCallback,
587                 &backCbk, (XtPointer)this);
588   n = 0;
589   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
590   XtSetArg(args[n], XmNleftWidget, backBtn); ++n;
591   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
592   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
593   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
594   XtSetArg(args[n], XmNsensitive, False); ++n;
595   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
596   prevTenPageBtn = XmCreatePushButton(toolBar, "prevTenPage", args, n);
597   XtManageChild(prevTenPageBtn);
598   XtAddCallback(prevTenPageBtn, XmNactivateCallback,
599                 &prevTenPageCbk, (XtPointer)this);
600   n = 0;
601   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
602   XtSetArg(args[n], XmNleftWidget, prevTenPageBtn); ++n;
603   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
604   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
605   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
606   XtSetArg(args[n], XmNsensitive, False); ++n;
607   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
608   prevPageBtn = XmCreatePushButton(toolBar, "prevPage", args, n);
609   XtManageChild(prevPageBtn);
610   XtAddCallback(prevPageBtn, XmNactivateCallback,
611                 &prevPageCbk, (XtPointer)this);
612   n = 0;
613   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
614   XtSetArg(args[n], XmNleftWidget, prevPageBtn); ++n;
615   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
616   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
617   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
618   XtSetArg(args[n], XmNsensitive, False); ++n;
619   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
620   nextPageBtn = XmCreatePushButton(toolBar, "nextPage", args, n);
621   XtManageChild(nextPageBtn);
622   XtAddCallback(nextPageBtn, XmNactivateCallback,
623                 &nextPageCbk, (XtPointer)this);
624   n = 0;
625   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
626   XtSetArg(args[n], XmNleftWidget, nextPageBtn); ++n;
627   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
628   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
629   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
630   XtSetArg(args[n], XmNsensitive, False); ++n;
631   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
632   nextTenPageBtn = XmCreatePushButton(toolBar, "nextTenPage", args, n);
633   XtManageChild(nextTenPageBtn);
634   XtAddCallback(nextTenPageBtn, XmNactivateCallback,
635                 &nextTenPageCbk, (XtPointer)this);
636   n = 0;
637   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
638   XtSetArg(args[n], XmNleftWidget, nextTenPageBtn); ++n;
639   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
640   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
641   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
642   XtSetArg(args[n], XmNsensitive, False); ++n;
643   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
644   forwardBtn = XmCreatePushButton(toolBar, "forward", args, n);
645   XtManageChild(forwardBtn);
646   XtAddCallback(forwardBtn, XmNactivateCallback,
647                 &forwardCbk, (XtPointer)this);
648
649   // page number display
650   n = 0;
651   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
652   XtSetArg(args[n], XmNleftWidget, forwardBtn); ++n;
653   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
654   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
655   s = XmStringCreateLocalized("Page ");
656   XtSetArg(args[n], XmNlabelString, s); ++n;
657   label = XmCreateLabel(toolBar, "pageLabel", args, n);
658   XmStringFree(s);
659   XtManageChild(label);
660   n = 0;
661   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
662   XtSetArg(args[n], XmNleftWidget, label); ++n;
663   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
664   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
665   XtSetArg(args[n], XmNmarginWidth, 3); ++n;
666   XtSetArg(args[n], XmNmarginHeight, 3); ++n;
667   XtSetArg(args[n], XmNcolumns, 5); ++n;
668   pageNumText = XmCreateTextField(toolBar, "pageNum", args, n);
669   XtManageChild(pageNumText);
670   XtAddCallback(pageNumText, XmNactivateCallback,
671                 &pageNumCbk, (XtPointer)this);
672   n = 0;
673   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
674   XtSetArg(args[n], XmNleftWidget, pageNumText); ++n;
675   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
676   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
677   s = XmStringCreateLocalized(" of 00000");
678   XtSetArg(args[n], XmNlabelString, s); ++n;
679   XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); ++n;
680   XtSetArg(args[n], XmNrecomputeSize, False); ++n;
681   pageCountLabel = XmCreateLabel(toolBar, "pageCountLabel", args, n);
682   XmStringFree(s);
683   XtManageChild(pageCountLabel);
684   s = XmStringCreateLocalized(" of 0");
685   XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL);
686   XmStringFree(s);
687
688   // zoom menu
689 #if USE_COMBO_BOX
690   XmString st[nZoomMenuItems];
691   n = 0;
692   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
693   XtSetArg(args[n], XmNleftWidget, pageCountLabel); ++n;
694   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
695   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
696   XtSetArg(args[n], XmNmarginWidth, 0); ++n;
697   XtSetArg(args[n], XmNmarginHeight, 0); ++n;
698   XtSetArg(args[n], XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); ++n;
699   XtSetArg(args[n], XmNpositionMode, XmONE_BASED); ++n;
700   XtSetArg(args[n], XmNcolumns, 7); ++n;
701   for (i = 0; i < nZoomMenuItems; ++i) {
702     st[i] = XmStringCreateLocalized(zoomMenuInfo[i].label);
703   }
704   XtSetArg(args[n], XmNitems, st); ++n;
705   XtSetArg(args[n], XmNitemCount, nZoomMenuItems); ++n;
706   zoomComboBox = XmCreateComboBox(toolBar, "zoomComboBox", args, n);
707   for (i = 0; i < nZoomMenuItems; ++i) {
708     XmStringFree(st[i]);
709   }
710   XtAddCallback(zoomComboBox, XmNselectionCallback,
711                 &zoomComboBoxCbk, (XtPointer)this);
712   XtManageChild(zoomComboBox);
713   zoomWidget = zoomComboBox;
714 #else
715   Widget menuPane;
716   char buf[16];
717   n = 0;
718   menuPane = XmCreatePulldownMenu(toolBar, "zoomMenuPane", args, n);
719   for (i = 0; i < nZoomMenuItems; ++i) {
720     n = 0;
721     s = XmStringCreateLocalized(zoomMenuInfo[i].label);
722     XtSetArg(args[n], XmNlabelString, s); ++n;
723     XtSetArg(args[n], XmNuserData, (XtPointer)i); ++n;
724     sprintf(buf, "zoom%d", i);
725     btn = XmCreatePushButton(menuPane, buf, args, n);
726     XmStringFree(s);
727     XtManageChild(btn);
728     XtAddCallback(btn, XmNactivateCallback,
729                   &zoomMenuCbk, (XtPointer)this);
730     zoomMenuBtns[i] = btn;
731   }
732   n = 0;
733   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
734   XtSetArg(args[n], XmNleftWidget, pageCountLabel); ++n;
735   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
736   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
737   XtSetArg(args[n], XmNmarginWidth, 0); ++n;
738   XtSetArg(args[n], XmNmarginHeight, 0); ++n;
739   XtSetArg(args[n], XmNsubMenuId, menuPane); ++n;
740   zoomMenu = XmCreateOptionMenu(toolBar, "zoomMenu", args, n);
741   XtManageChild(zoomMenu);
742   zoomWidget = zoomMenu;
743 #endif
744
745   // find/print/about buttons
746   n = 0;
747   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
748   XtSetArg(args[n], XmNleftWidget, zoomWidget); ++n;
749   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
750   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
751   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
752   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
753   findBtn = XmCreatePushButton(toolBar, "find", args, n);
754   XtManageChild(findBtn);
755   XtAddCallback(findBtn, XmNactivateCallback,
756                 &findCbk, (XtPointer)this);
757   n = 0;
758   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
759   XtSetArg(args[n], XmNleftWidget, findBtn); ++n;
760   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
761   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
762   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
763   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
764   printBtn = XmCreatePushButton(toolBar, "print", args, n);
765   XtManageChild(printBtn);
766   XtAddCallback(printBtn, XmNactivateCallback,
767                 &printCbk, (XtPointer)this);
768   n = 0;
769   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
770   XtSetArg(args[n], XmNleftWidget, printBtn); ++n;
771   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
772   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
773   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
774   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
775   aboutBtn = XmCreatePushButton(toolBar, "about", args, n);
776   XtManageChild(aboutBtn);
777   XtAddCallback(aboutBtn, XmNactivateCallback,
778                 &aboutCbk, (XtPointer)this);
779   lastBtn = aboutBtn;
780
781   // quit button
782   n = 0;
783   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
784   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
785   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
786   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
787   s = XmStringCreateLocalized("Quit");
788   XtSetArg(args[n], XmNlabelString, s); ++n;
789   quitBtn = XmCreatePushButton(toolBar, "quit", args, n);
790   XmStringFree(s);
791   XtManageChild(quitBtn);
792   XtAddCallback(quitBtn, XmNactivateCallback,
793                 &quitCbk, (XtPointer)this);
794
795   // link label
796   n = 0;
797   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
798   XtSetArg(args[n], XmNleftWidget, lastBtn); ++n;
799   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
800   XtSetArg(args[n], XmNrightWidget, quitBtn); ++n;
801   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
802   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
803   s = XmStringCreateLocalized("");
804   XtSetArg(args[n], XmNlabelString, s); ++n;
805   XtSetArg(args[n], XmNrecomputeSize, True); ++n;
806   XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); ++n;
807   linkLabel = XmCreateLabel(toolBar, "linkLabel", args, n);
808   XmStringFree(s);
809   XtManageChild(linkLabel);
810
811 #ifndef DISABLE_OUTLINE
812   if (app->getFullScreen()) {
813 #endif
814
815     // core
816     core = new XPDFCore(win, form, app->getPaperColor(),
817                         app->getFullScreen(), app->getReverseVideo(),
818                         app->getInstallCmap(), app->getRGBCubeSize());
819     core->setUpdateCbk(&updateCbk, this);
820     core->setActionCbk(&actionCbk, this);
821     core->setKeyPressCbk(&keyPressCbk, this);
822     core->setMouseCbk(&mouseCbk, this);
823     core->setReqPasswordCbk(&reqPasswordCbk, this);
824     n = 0;
825     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
826     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
827     XtSetArg(args[n], XmNbottomWidget, toolBar); ++n;
828     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
829     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
830     XtSetValues(core->getWidget(), args, n);
831
832 #ifndef DISABLE_OUTLINE
833   } else {
834
835     // paned window
836     n = 0;
837     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
838     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
839     XtSetArg(args[n], XmNbottomWidget, toolBar); ++n;
840     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
841     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
842     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
843 #if defined(__sgi) && (XmVERSION <= 1)
844     panedWin = SgCreateHorzPanedWindow(form, "panedWin", args, n);
845 #else
846     panedWin = XmCreatePanedWindow(form, "panedWin", args, n);
847 #endif
848     XtManageChild(panedWin);
849
850     // scrolled window for outline container
851     n = 0;
852     XtSetArg(args[n], XmNpositionIndex, 0); ++n;
853     XtSetArg(args[n], XmNallowResize, True); ++n;
854     XtSetArg(args[n], XmNpaneMinimum, 1); ++n;
855     XtSetArg(args[n], XmNpaneMaximum, 10000); ++n;
856 #if !(defined(__sgi) && (XmVERSION <= 1))
857     XtSetArg(args[n], XmNwidth, 1); ++n;
858 #endif
859     XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n;
860     outlineScroll = XmCreateScrolledWindow(panedWin, "outlineScroll", args, n);
861     XtManageChild(outlineScroll);
862     XtVaGetValues(outlineScroll, XmNclipWindow, &clipWin, NULL);
863     XtVaSetValues(clipWin, XmNbackground, app->getPaperColor(), NULL);
864
865     // outline tree
866     n = 0;
867     XtSetArg(args[n], XmNbackground, app->getPaperColor()); ++n;
868     outlineTree = XPDFCreateTree(outlineScroll, "outlineTree", args, n);
869     XtManageChild(outlineTree);
870     XtAddCallback(outlineTree, XPDFNselectionCallback, &outlineSelectCbk,
871                   (XtPointer)this);
872
873     // core
874     core = new XPDFCore(win, panedWin, app->getPaperColor(),
875                         app->getFullScreen(), app->getReverseVideo(),
876                         app->getInstallCmap(), app->getRGBCubeSize());
877     core->setUpdateCbk(&updateCbk, this);
878     core->setActionCbk(&actionCbk, this);
879     core->setKeyPressCbk(&keyPressCbk, this);
880     core->setMouseCbk(&mouseCbk, this);
881     core->setReqPasswordCbk(&reqPasswordCbk, this);
882     n = 0;
883     XtSetArg(args[n], XmNpositionIndex, 1); ++n;
884     XtSetArg(args[n], XmNallowResize, True); ++n;
885     XtSetArg(args[n], XmNpaneMinimum, 1); ++n;
886     XtSetArg(args[n], XmNpaneMaximum, 10000); ++n;
887     XtSetValues(core->getWidget(), args, n);
888   }
889 #endif
890
891   // set the zoom menu to match the initial zoom setting
892   setZoomVal(core->getZoom());
893
894   // set traversal order
895   XtVaSetValues(core->getDrawAreaWidget(),
896                 XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
897   XtVaSetValues(backBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
898                 NULL);
899   XtVaSetValues(prevTenPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
900                 NULL);
901   XtVaSetValues(prevPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
902                 NULL);
903   XtVaSetValues(nextPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
904                 NULL);
905   XtVaSetValues(nextTenPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
906                 NULL);
907   XtVaSetValues(forwardBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
908                 NULL);
909   XtVaSetValues(pageNumText, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
910                 NULL);
911   XtVaSetValues(zoomWidget, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
912                 NULL);
913   XtVaSetValues(findBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
914                 NULL);
915   XtVaSetValues(printBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
916                 NULL);
917   XtVaSetValues(aboutBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
918                 NULL);
919   XtVaSetValues(quitBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
920                 NULL);
921
922   // popup menu
923   n = 0;
924 #if XmVersion < 1002
925   // older versions of Motif need this, newer ones choke on it,
926   // sometimes not displaying the menu at all, maybe depending on the
927   // state of the NumLock key (taken from DDD)
928   XtSetArg(args[n], XmNmenuPost, "<Btn3Down>"); ++n;
929 #endif
930   popupMenu = XmCreatePopupMenu(core->getDrawAreaWidget(), "popupMenu",
931                                 args, n);
932   n = 0;
933   s = XmStringCreateLocalized("Open...");
934   XtSetArg(args[n], XmNlabelString, s); ++n;
935   s2 = XmStringCreateLocalized("O");
936   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
937   btn = XmCreatePushButton(popupMenu, "open", args, n);
938   XmStringFree(s);
939   XmStringFree(s2);
940   XtManageChild(btn);
941   XtAddCallback(btn, XmNactivateCallback,
942                 &openCbk, (XtPointer)this);
943   n = 0;
944   s = XmStringCreateLocalized("Open in new window...");
945   XtSetArg(args[n], XmNlabelString, s); ++n;
946   btn = XmCreatePushButton(popupMenu, "openInNewWindow", args, n);
947   XmStringFree(s);
948   XtManageChild(btn);
949   XtAddCallback(btn, XmNactivateCallback,
950                 &openInNewWindowCbk, (XtPointer)this);
951   n = 0;
952   s = XmStringCreateLocalized("Reload");
953   XtSetArg(args[n], XmNlabelString, s); ++n;
954   s2 = XmStringCreateLocalized("R");
955   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
956   btn = XmCreatePushButton(popupMenu, "reload", args, n);
957   XmStringFree(s);
958   XmStringFree(s2);
959   XtManageChild(btn);
960   XtAddCallback(btn, XmNactivateCallback,
961                 &reloadCbk, (XtPointer)this);
962   n = 0;
963   s = XmStringCreateLocalized("Save as...");
964   XtSetArg(args[n], XmNlabelString, s); ++n;
965   btn = XmCreatePushButton(popupMenu, "saveAs", args, n);
966   XmStringFree(s);
967   XtManageChild(btn);
968   XtAddCallback(btn, XmNactivateCallback,
969                 &saveAsCbk, (XtPointer)this);
970   n = 0;
971   btn = XmCreateSeparator(popupMenu, "sep1", args, n);
972   XtManageChild(btn);
973   n = 0;
974   s = XmStringCreateLocalized("Rotate counterclockwise");
975   XtSetArg(args[n], XmNlabelString, s); ++n;
976   btn = XmCreatePushButton(popupMenu, "rotateCCW", args, n);
977   XmStringFree(s);
978   XtManageChild(btn);
979   XtAddCallback(btn, XmNactivateCallback,
980                 &rotateCCWCbk, (XtPointer)this);
981   n = 0;
982   s = XmStringCreateLocalized("Rotate clockwise");
983   XtSetArg(args[n], XmNlabelString, s); ++n;
984   btn = XmCreatePushButton(popupMenu, "rotateCW", args, n);
985   XmStringFree(s);
986   XtManageChild(btn);
987   XtAddCallback(btn, XmNactivateCallback,
988                 &rotateCWCbk, (XtPointer)this);
989   n = 0;
990   btn = XmCreateSeparator(popupMenu, "sep2", args, n);
991   XtManageChild(btn);
992   n = 0;
993   s = XmStringCreateLocalized("Close");
994   XtSetArg(args[n], XmNlabelString, s); ++n;
995   s2 = XmStringCreateLocalized("Ctrl+W");
996   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
997   btn = XmCreatePushButton(popupMenu, "close", args, n);
998   XmStringFree(s);
999   XmStringFree(s2);
1000   XtManageChild(btn);
1001   XtAddCallback(btn, XmNactivateCallback,
1002                 &closeCbk, (XtPointer)this);
1003   n = 0;
1004   s = XmStringCreateLocalized("Quit");
1005   XtSetArg(args[n], XmNlabelString, s); ++n;
1006   s2 = XmStringCreateLocalized("Q");
1007   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
1008   btn = XmCreatePushButton(popupMenu, "quit", args, n);
1009   XmStringFree(s);
1010   XmStringFree(s2);
1011   XtManageChild(btn);
1012   XtAddCallback(btn, XmNactivateCallback,
1013                 &quitCbk, (XtPointer)this);
1014
1015   // this is magic (taken from DDD) - weird things happen if this
1016   // call isn't made
1017   XtUngrabButton(core->getDrawAreaWidget(), AnyButton, AnyModifier);
1018
1019   XmStringFree(emptyString);
1020 }
1021
1022 void XPDFViewer::mapWindow() {
1023 #ifdef HAVE_X11_XPM_H
1024   Pixmap iconPixmap;
1025 #endif
1026   int depth;
1027   Pixel fg, bg, arm;
1028
1029   // show the window
1030   XtPopup(win, XtGrabNone);
1031   core->takeFocus();
1032
1033   // create the icon
1034 #ifdef HAVE_X11_XPM_H
1035   if (XpmCreatePixmapFromData(display, XtWindow(win), xpdfIcon,
1036                               &iconPixmap, NULL, NULL) == XpmSuccess) {
1037     XtVaSetValues(win, XmNiconPixmap, iconPixmap, NULL);
1038   }
1039 #endif
1040
1041   // set button bitmaps (must be done after the window is mapped)
1042   XtVaGetValues(backBtn, XmNdepth, &depth,
1043                 XmNforeground, &fg, XmNbackground, &bg,
1044                 XmNarmColor, &arm, NULL);
1045   XtVaSetValues(backBtn, XmNlabelType, XmPIXMAP,
1046                 XmNlabelPixmap,
1047                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1048                                             (char *)backArrow_bits,
1049                                             backArrow_width,
1050                                             backArrow_height,
1051                                             fg, bg, depth),
1052                 XmNarmPixmap,
1053                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1054                                             (char *)backArrow_bits,
1055                                             backArrow_width,
1056                                             backArrow_height,
1057                                             fg, arm, depth),
1058                 XmNlabelInsensitivePixmap,
1059                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1060                                             (char *)backArrowDis_bits,
1061                                             backArrowDis_width,
1062                                             backArrowDis_height,
1063                                             fg, bg, depth),
1064                 NULL);
1065   XtVaSetValues(prevTenPageBtn, XmNlabelType, XmPIXMAP,
1066                 XmNlabelPixmap,
1067                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1068                                             (char *)dblLeftArrow_bits,
1069                                             dblLeftArrow_width,
1070                                             dblLeftArrow_height,
1071                                             fg, bg, depth),
1072                 XmNarmPixmap,
1073                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1074                                             (char *)dblLeftArrow_bits,
1075                                             dblLeftArrow_width,
1076                                             dblLeftArrow_height,
1077                                             fg, arm, depth),
1078                 XmNlabelInsensitivePixmap,
1079                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1080                                             (char *)dblLeftArrowDis_bits,
1081                                             dblLeftArrowDis_width,
1082                                             dblLeftArrowDis_height,
1083                                             fg, bg, depth),
1084                 NULL);
1085   XtVaSetValues(prevPageBtn, XmNlabelType, XmPIXMAP,
1086                 XmNlabelPixmap,
1087                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1088                                             (char *)leftArrow_bits,
1089                                             leftArrow_width,
1090                                             leftArrow_height,
1091                                             fg, bg, depth),
1092                 XmNarmPixmap,
1093                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1094                                             (char *)leftArrow_bits,
1095                                             leftArrow_width,
1096                                             leftArrow_height,
1097                                             fg, arm, depth),
1098                 XmNlabelInsensitivePixmap,
1099                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1100                                             (char *)leftArrowDis_bits,
1101                                             leftArrowDis_width,
1102                                             leftArrowDis_height,
1103                                             fg, bg, depth),
1104                 NULL);
1105   XtVaSetValues(nextPageBtn, XmNlabelType, XmPIXMAP,
1106                 XmNlabelPixmap,
1107                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1108                                             (char *)rightArrow_bits,
1109                                             rightArrow_width,
1110                                             rightArrow_height,
1111                                             fg, bg, depth),
1112                 XmNarmPixmap,
1113                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1114                                             (char *)rightArrow_bits,
1115                                             rightArrow_width,
1116                                             rightArrow_height,
1117                                             fg, arm, depth),
1118                 XmNlabelInsensitivePixmap,
1119                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1120                                             (char *)rightArrowDis_bits,
1121                                             rightArrowDis_width,
1122                                             rightArrowDis_height,
1123                                             fg, bg, depth),
1124                 NULL);
1125   XtVaSetValues(nextTenPageBtn, XmNlabelType, XmPIXMAP,
1126                 XmNlabelPixmap,
1127                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1128                                             (char *)dblRightArrow_bits,
1129                                             dblRightArrow_width,
1130                                             dblRightArrow_height,
1131                                             fg, bg, depth),
1132                 XmNarmPixmap,
1133                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1134                                             (char *)dblRightArrow_bits,
1135                                             dblRightArrow_width,
1136                                             dblRightArrow_height,
1137                                             fg, arm, depth),
1138                 XmNlabelInsensitivePixmap,
1139                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1140                                             (char *)dblRightArrowDis_bits,
1141                                             dblRightArrowDis_width,
1142                                             dblRightArrowDis_height,
1143                                             fg, bg, depth),
1144                 NULL);
1145   XtVaSetValues(forwardBtn, XmNlabelType, XmPIXMAP,
1146                 XmNlabelPixmap,
1147                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1148                                             (char *)forwardArrow_bits,
1149                                             forwardArrow_width,
1150                                             forwardArrow_height,
1151                                             fg, bg, depth),
1152                 XmNarmPixmap,
1153                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1154                                             (char *)forwardArrow_bits,
1155                                             forwardArrow_width,
1156                                             forwardArrow_height,
1157                                             fg, arm, depth),
1158                 XmNlabelInsensitivePixmap,
1159                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1160                                             (char *)forwardArrowDis_bits,
1161                                             forwardArrowDis_width,
1162                                             forwardArrowDis_height,
1163                                             fg, bg, depth),
1164                 NULL);
1165   XtVaSetValues(findBtn, XmNlabelType, XmPIXMAP,
1166                 XmNlabelPixmap,
1167                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1168                                             (char *)find_bits,
1169                                             find_width,
1170                                             find_height,
1171                                             fg, bg, depth),
1172                 XmNarmPixmap,
1173                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1174                                             (char *)find_bits,
1175                                             find_width,
1176                                             find_height,
1177                                             fg, arm, depth),
1178                 XmNlabelInsensitivePixmap,
1179                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1180                                             (char *)findDis_bits,
1181                                             findDis_width,
1182                                             findDis_height,
1183                                             fg, bg, depth),
1184                 NULL);
1185   XtVaSetValues(printBtn, XmNlabelType, XmPIXMAP,
1186                 XmNlabelPixmap,
1187                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1188                                             (char *)print_bits,
1189                                             print_width,
1190                                             print_height,
1191                                             fg, bg, depth),
1192                 XmNarmPixmap,
1193                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1194                                             (char *)print_bits,
1195                                             print_width,
1196                                             print_height,
1197                                             fg, arm, depth),
1198                 XmNlabelInsensitivePixmap,
1199                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1200                                             (char *)printDis_bits,
1201                                             printDis_width,
1202                                             printDis_height,
1203                                             fg, bg, depth),
1204                 NULL);
1205   XtVaSetValues(aboutBtn, XmNlabelType, XmPIXMAP,
1206                 XmNlabelPixmap,
1207                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1208                                             (char *)about_bits,
1209                                             about_width,
1210                                             about_height,
1211                                             fg, bg, depth),
1212                 XmNarmPixmap,
1213                 XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
1214                                             (char *)about_bits,
1215                                             about_width,
1216                                             about_height,
1217                                             fg, arm, depth),
1218                 NULL);
1219 }
1220
1221 void XPDFViewer::closeWindow() {
1222   XtPopdown(win);
1223   XtDestroyWidget(win);
1224 }
1225
1226 int XPDFViewer::getZoomIdx() {
1227 #if USE_COMBO_BOX
1228   int z;
1229
1230   XtVaGetValues(zoomComboBox, XmNselectedPosition, &z, NULL);
1231   return z - 1;
1232 #else
1233   Widget w;
1234   int i;
1235
1236   XtVaGetValues(zoomMenu, XmNmenuHistory, &w, NULL);
1237   for (i = 0; i < nZoomMenuItems; ++i) {
1238     if (w == zoomMenuBtns[i]) {
1239       return i;
1240     }
1241   }
1242   // this should never happen
1243   return 0;
1244 #endif
1245 }
1246
1247 void XPDFViewer::setZoomIdx(int idx) {
1248 #if USE_COMBO_BOX
1249   XtVaSetValues(zoomComboBox, XmNselectedPosition, idx + 1, NULL);
1250 #else
1251   XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[idx], NULL);
1252 #endif
1253 }
1254
1255 void XPDFViewer::setZoomVal(double z) {
1256 #if USE_COMBO_BOX
1257   char buf[32];
1258   XmString s;
1259   int i;
1260
1261   for (i = 0; i < nZoomMenuItems; ++i) {
1262     if (z == zoomMenuInfo[i].zoom) {
1263       XtVaSetValues(zoomComboBox, XmNselectedPosition, i + 1, NULL);
1264       return;
1265     }
1266   }
1267   sprintf(buf, "%d", (int)z);
1268   s = XmStringCreateLocalized(buf);
1269   XtVaSetValues(zoomComboBox, XmNselectedItem, s, NULL);
1270   XmStringFree(s);
1271 #else
1272   int i;
1273
1274   for (i = 0; i < nZoomMenuItems; ++i) {
1275     if (z == zoomMenuInfo[i].zoom) {
1276       XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[i], NULL);
1277       return;
1278     }
1279   }
1280   for (i = maxZoomIdx; i < minZoomIdx; ++i) {
1281     if (z > zoomMenuInfo[i].zoom) {
1282       break;
1283     }
1284   }
1285   XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[i], NULL);
1286 #endif
1287 }
1288
1289 void XPDFViewer::prevPageCbk(Widget widget, XtPointer ptr,
1290                              XtPointer callData) {
1291   XPDFViewer *viewer = (XPDFViewer *)ptr;
1292
1293   viewer->core->gotoPrevPage(1, gTrue, gFalse);
1294   viewer->core->takeFocus();
1295 }
1296
1297 void XPDFViewer::prevTenPageCbk(Widget widget, XtPointer ptr,
1298                                 XtPointer callData) {
1299   XPDFViewer *viewer = (XPDFViewer *)ptr;
1300
1301   viewer->core->gotoPrevPage(10, gTrue, gFalse);
1302   viewer->core->takeFocus();
1303 }
1304
1305 void XPDFViewer::nextPageCbk(Widget widget, XtPointer ptr,
1306                              XtPointer callData) {
1307   XPDFViewer *viewer = (XPDFViewer *)ptr;
1308
1309   viewer->core->gotoNextPage(1, gTrue);
1310   viewer->core->takeFocus();
1311 }
1312
1313 void XPDFViewer::nextTenPageCbk(Widget widget, XtPointer ptr,
1314                                 XtPointer callData) {
1315   XPDFViewer *viewer = (XPDFViewer *)ptr;
1316
1317   viewer->core->gotoNextPage(10, gTrue);
1318   viewer->core->takeFocus();
1319 }
1320
1321 void XPDFViewer::backCbk(Widget widget, XtPointer ptr,
1322                          XtPointer callData) {
1323   XPDFViewer *viewer = (XPDFViewer *)ptr;
1324
1325   viewer->core->goBackward();
1326   viewer->core->takeFocus();
1327 }
1328
1329 void XPDFViewer::forwardCbk(Widget widget, XtPointer ptr,
1330                             XtPointer callData) {
1331   XPDFViewer *viewer = (XPDFViewer *)ptr;
1332
1333   viewer->core->goForward();
1334   viewer->core->takeFocus();
1335 }
1336
1337 #if USE_COMBO_BOX
1338
1339 void XPDFViewer::zoomComboBoxCbk(Widget widget, XtPointer ptr,
1340                                  XtPointer callData) {
1341   XPDFViewer *viewer = (XPDFViewer *)ptr;
1342   XmComboBoxCallbackStruct *data = (XmComboBoxCallbackStruct *)callData;
1343   double z;
1344   char *s;
1345   XmStringContext context;
1346   XmStringCharSet charSet;
1347   XmStringDirection dir;
1348   Boolean sep;
1349
1350   z = viewer->core->getZoom();
1351   if (data->item_position == 0) {
1352     XmStringInitContext(&context, data->item_or_text);
1353     if (XmStringGetNextSegment(context, &s, &charSet, &dir, &sep)) {
1354       z = atof(s);
1355       if (z <= 1) {
1356         z = defZoom;
1357       }
1358       XtFree(charSet);
1359       XtFree(s);
1360     }
1361     XmStringFreeContext(context);
1362   } else {
1363     z = zoomMenuInfo[data->item_position - 1].zoom;
1364   }
1365   // only redraw if this was triggered by an event; otherwise
1366   // the caller is responsible for doing the redraw
1367   if (z != viewer->core->getZoom() && data->event) {
1368     viewer->displayPage(viewer->core->getPageNum(), z,
1369                         viewer->core->getRotate(), gTrue, gFalse);
1370   }
1371   viewer->core->takeFocus();
1372 }
1373
1374 #else // USE_COMBO_BOX
1375
1376 void XPDFViewer::zoomMenuCbk(Widget widget, XtPointer ptr,
1377                              XtPointer callData) {
1378   XPDFViewer *viewer = (XPDFViewer *)ptr;
1379   XmPushButtonCallbackStruct *data = (XmPushButtonCallbackStruct *)callData;
1380   XtPointer userData;
1381   double z;
1382
1383   XtVaGetValues(widget, XmNuserData, &userData, NULL);
1384   z = zoomMenuInfo[(int)userData].zoom;
1385   // only redraw if this was triggered by an event; otherwise
1386   // the caller is responsible for doing the redraw
1387   if (z != viewer->core->getZoom() && data->event) {
1388     viewer->displayPage(viewer->core->getPageNum(), z,
1389                         viewer->core->getRotate(), gTrue, gFalse);
1390   }
1391   viewer->core->takeFocus();
1392 }
1393
1394 #endif // USE_COMBO_BOX
1395
1396 void XPDFViewer::findCbk(Widget widget, XtPointer ptr,
1397                          XtPointer callData) {
1398   XPDFViewer *viewer = (XPDFViewer *)ptr;
1399
1400   if (!viewer->core->getDoc()) {
1401     return;
1402   }
1403   XtManageChild(viewer->findDialog);
1404 }
1405
1406 void XPDFViewer::printCbk(Widget widget, XtPointer ptr,
1407                           XtPointer callData) {
1408   XPDFViewer *viewer = (XPDFViewer *)ptr;
1409
1410   if (!viewer->core->getDoc()) {
1411     return;
1412   }
1413   XtManageChild(viewer->printDialog);
1414 }
1415
1416 void XPDFViewer::aboutCbk(Widget widget, XtPointer ptr,
1417                           XtPointer callData) {
1418   XPDFViewer *viewer = (XPDFViewer *)ptr;
1419
1420   XtManageChild(viewer->aboutDialog);
1421 }
1422
1423 void XPDFViewer::quitCbk(Widget widget, XtPointer ptr,
1424                          XtPointer callData) {
1425   XPDFViewer *viewer = (XPDFViewer *)ptr;
1426
1427   viewer->app->quit();
1428 }
1429
1430 void XPDFViewer::openCbk(Widget widget, XtPointer ptr,
1431                          XtPointer callData) {
1432   XPDFViewer *viewer = (XPDFViewer *)ptr;
1433
1434   viewer->mapOpenDialog(gFalse);
1435 }
1436
1437 void XPDFViewer::openInNewWindowCbk(Widget widget, XtPointer ptr,
1438                                     XtPointer callData) {
1439   XPDFViewer *viewer = (XPDFViewer *)ptr;
1440
1441   viewer->mapOpenDialog(gTrue);
1442 }
1443
1444 void XPDFViewer::reloadCbk(Widget widget, XtPointer ptr,
1445                          XtPointer callData) {
1446   XPDFViewer *viewer = (XPDFViewer *)ptr;
1447
1448   viewer->reloadFile();
1449 }
1450
1451 void XPDFViewer::saveAsCbk(Widget widget, XtPointer ptr,
1452                            XtPointer callData) {
1453   XPDFViewer *viewer = (XPDFViewer *)ptr;
1454
1455   if (!viewer->core->getDoc()) {
1456     return;
1457   }
1458   viewer->mapSaveAsDialog();
1459 }
1460
1461 void XPDFViewer::rotateCCWCbk(Widget widget, XtPointer ptr,
1462                               XtPointer callData) {
1463   XPDFViewer *viewer = (XPDFViewer *)ptr;
1464   int r;
1465
1466   r = viewer->core->getRotate();
1467   r = (r == 0) ? 270 : r - 90;
1468   viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(),
1469                       r, gTrue, gFalse);
1470 }
1471
1472 void XPDFViewer::rotateCWCbk(Widget widget, XtPointer ptr,
1473                              XtPointer callData) {
1474   XPDFViewer *viewer = (XPDFViewer *)ptr;
1475   int r;
1476
1477   r = viewer->core->getRotate();
1478   r = (r == 270) ? 0 : r + 90;
1479   viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(),
1480                       r, gTrue, gFalse);
1481 }
1482
1483 void XPDFViewer::closeCbk(Widget widget, XtPointer ptr,
1484                           XtPointer callData) {
1485   XPDFViewer *viewer = (XPDFViewer *)ptr;
1486
1487   viewer->app->close(viewer, gFalse);
1488 }
1489
1490 void XPDFViewer::closeMsgCbk(Widget widget, XtPointer ptr,
1491                              XtPointer callData) {
1492   XPDFViewer *viewer = (XPDFViewer *)ptr;
1493
1494   viewer->app->close(viewer, gTrue);
1495 }
1496
1497 void XPDFViewer::pageNumCbk(Widget widget, XtPointer ptr,
1498                             XtPointer callData) {
1499   XPDFViewer *viewer = (XPDFViewer *)ptr;
1500   char *s, *p;
1501   int pg;
1502   char buf[20];
1503
1504   if (!viewer->core->getDoc()) {
1505     goto err;
1506   }
1507   s = XmTextFieldGetString(viewer->pageNumText);
1508   for (p = s; *p; ++p) {
1509     if (!isdigit(*p)) {
1510       goto err;
1511     }
1512   }
1513   pg = atoi(s);
1514   if (pg < 1 || pg > viewer->core->getDoc()->getNumPages()) {
1515     goto err;
1516   }
1517   viewer->displayPage(pg, viewer->core->getZoom(),
1518                       viewer->core->getRotate(), gFalse, gTrue);
1519   viewer->core->takeFocus();
1520   return;
1521
1522  err:
1523   XBell(viewer->display, 0);
1524   sprintf(buf, "%d", viewer->core->getPageNum());
1525   XmTextFieldSetString(viewer->pageNumText, buf);
1526 }
1527
1528 void XPDFViewer::updateCbk(void *data, GString *fileName,
1529                            int pageNum, int numPages, char *linkString) {
1530   XPDFViewer *viewer = (XPDFViewer *)data;
1531   GString *title;
1532   char buf[20];
1533   XmString s;
1534
1535   if (fileName) {
1536     if (!(title = viewer->app->getTitle())) {
1537       title = (new GString(xpdfAppName))->append(": ")->append(fileName);
1538     }
1539     XtVaSetValues(viewer->win, XmNtitle, title->getCString(),
1540                   XmNiconName, title->getCString(), NULL);
1541     if (!viewer->app->getTitle()) {
1542       delete title;
1543     }
1544 #ifndef DISABLE_OUTLINE
1545     if (!viewer->app->getFullScreen()) {
1546       viewer->setupOutline();
1547     }
1548 #endif
1549     viewer->setupPrintDialog();
1550   }
1551
1552   if (pageNum >= 0) {
1553     s = XmStringCreateLocalized("");
1554     XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL);
1555     XmStringFree(s);
1556     sprintf(buf, "%d", pageNum);
1557     XmTextFieldSetString(viewer->pageNumText, buf);
1558     XtVaSetValues(viewer->prevTenPageBtn, XmNsensitive,
1559                   pageNum > 1, NULL);
1560     XtVaSetValues(viewer->prevPageBtn, XmNsensitive,
1561                   pageNum > 1, NULL);
1562     XtVaSetValues(viewer->nextTenPageBtn, XmNsensitive,
1563                   pageNum < viewer->core->getDoc()->getNumPages(), NULL);
1564     XtVaSetValues(viewer->nextPageBtn, XmNsensitive,
1565                   pageNum < viewer->core->getDoc()->getNumPages(), NULL);
1566     XtVaSetValues(viewer->backBtn, XmNsensitive,
1567                   viewer->core->canGoBack(), NULL);
1568     XtVaSetValues(viewer->forwardBtn, XmNsensitive,
1569                   viewer->core->canGoForward(), NULL);
1570   }
1571
1572   if (numPages >= 0) {
1573     sprintf(buf, " of %d", numPages);
1574     s = XmStringCreateLocalized(buf);
1575     XtVaSetValues(viewer->pageCountLabel, XmNlabelString, s, NULL);
1576     XmStringFree(s);
1577   }
1578
1579   if (linkString) {
1580     s = XmStringCreateLocalized(linkString);
1581     XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL);
1582     XmStringFree(s);
1583   }
1584 }
1585
1586
1587 //------------------------------------------------------------------------
1588 // GUI code: outline
1589 //------------------------------------------------------------------------
1590
1591 #ifndef DISABLE_OUTLINE
1592
1593 void XPDFViewer::setupOutline() {
1594   GList *items;
1595   UnicodeMap *uMap;
1596   GString *enc;
1597   int i;
1598
1599   // unmanage and destroy the old labels
1600   if (outlineLabels) {
1601     XtUnmanageChildren(outlineLabels, outlineLabelsLength);
1602     for (i = 0; i < outlineLabelsLength; ++i) {
1603       XtDestroyWidget(outlineLabels[i]);
1604     }
1605     gfree(outlineLabels);
1606     outlineLabels = NULL;
1607     outlineLabelsLength = outlineLabelsSize = 0;
1608   }
1609
1610   if (core->getDoc()) {
1611
1612     // create the new labels
1613     items = core->getDoc()->getOutline()->getItems();
1614     if (items && items->getLength() > 0) {
1615       enc = new GString("Latin1");
1616       uMap = globalParams->getUnicodeMap(enc);
1617       delete enc;
1618       setupOutlineItems(items, NULL, uMap);
1619       uMap->decRefCnt();
1620     }
1621
1622     // manage the new labels
1623     XtManageChildren(outlineLabels, outlineLabelsLength);
1624   }
1625 }
1626
1627 void XPDFViewer::setupOutlineItems(GList *items, Widget parent,
1628                                    UnicodeMap *uMap) {
1629   OutlineItem *item;
1630   GList *kids;
1631   Widget label;
1632   Arg args[20];
1633   GString *title;
1634   char buf[8];
1635   XmString s;
1636   int i, j, n;
1637
1638   for (i = 0; i < items->getLength(); ++i) {
1639     item = (OutlineItem *)items->get(i);
1640     title = new GString();
1641     for (j = 0; j < item->getTitleLength(); ++j) {
1642       n = uMap->mapUnicode(item->getTitle()[j], buf, sizeof(buf));
1643       title->append(buf, n);
1644     }
1645     n = 0;
1646     XtSetArg(args[n], XPDFNentryPosition, i); ++n;
1647     if (parent) {
1648       XtSetArg(args[n], XPDFNentryParent, parent); ++n;
1649     }
1650     XtSetArg(args[n], XPDFNentryExpanded, item->isOpen()); ++n;
1651     s = XmStringCreateLocalized(title->getCString());
1652     delete title;
1653     XtSetArg(args[n], XmNlabelString, s); ++n;
1654     XtSetArg(args[n], XmNuserData, item); ++n;
1655     XtSetArg(args[n], XmNmarginWidth, 0); ++n;
1656     XtSetArg(args[n], XmNmarginHeight, 2); ++n;
1657     XtSetArg(args[n], XmNshadowThickness, 0); ++n;
1658     XtSetArg(args[n], XmNforeground,
1659              app->getReverseVideo() ? WhitePixel(display, screenNum)
1660                                     : BlackPixel(display, screenNum)); ++n;
1661     XtSetArg(args[n], XmNbackground, app->getPaperColor()); ++n;
1662     label = XmCreateLabelGadget(outlineTree, "label", args, n);
1663     XmStringFree(s);
1664     if (outlineLabelsLength == outlineLabelsSize) {
1665       outlineLabelsSize += 64;
1666       outlineLabels = (Widget *)grealloc(outlineLabels,
1667                                          outlineLabelsSize * sizeof(Widget *));
1668     }
1669     outlineLabels[outlineLabelsLength++] = label;
1670     item->open();
1671     if ((kids = item->getKids())) {
1672       setupOutlineItems(kids, label, uMap);
1673     }
1674   }
1675 }
1676
1677 void XPDFViewer::outlineSelectCbk(Widget widget, XtPointer ptr,
1678                                   XtPointer callData) {
1679   XPDFViewer *viewer = (XPDFViewer *)ptr;
1680   XPDFTreeSelectCallbackStruct *data =
1681       (XPDFTreeSelectCallbackStruct *)callData;
1682   OutlineItem *item;
1683
1684   XtVaGetValues(data->selectedItem, XmNuserData, &item, NULL);
1685   if (item) {
1686     viewer->core->doAction(item->getAction());
1687   }
1688   viewer->core->takeFocus();
1689 }
1690
1691 #endif // !DISABLE_OUTLINE
1692
1693 //------------------------------------------------------------------------
1694 // GUI code: "about" dialog
1695 //------------------------------------------------------------------------
1696
1697 void XPDFViewer::initAboutDialog() {
1698   Widget scrolledWin, col, label, sep, closeBtn;
1699   Arg args[20];
1700   int n, i;
1701   XmString s;
1702   char buf[20];
1703
1704   //----- dialog
1705   n = 0;
1706   s = XmStringCreateLocalized(xpdfAppName ": About");
1707   XtSetArg(args[n], XmNdialogTitle, s); ++n;
1708   XtSetArg(args[n], XmNwidth, 450); ++n;
1709   XtSetArg(args[n], XmNheight, 300); ++n;
1710   aboutDialog = XmCreateFormDialog(win, "aboutDialog", args, n);
1711   XmStringFree(s);
1712
1713   //----- "close" button
1714   n = 0;
1715   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1716   XtSetArg(args[n], XmNrightOffset, 4); ++n;
1717   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1718   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
1719   closeBtn = XmCreatePushButton(aboutDialog, "Close", args, n);
1720   XtManageChild(closeBtn);
1721   n = 0;
1722   XtSetArg(args[n], XmNdefaultButton, closeBtn); ++n;
1723   XtSetArg(args[n], XmNcancelButton, closeBtn); ++n;
1724   XtSetValues(aboutDialog, args, n);
1725
1726   //----- scrolled window and RowColumn
1727   n = 0;
1728   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1729   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
1730   XtSetArg(args[n], XmNbottomWidget, closeBtn); ++n;
1731   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1732   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1733   XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n;
1734   scrolledWin = XmCreateScrolledWindow(aboutDialog, "scrolledWin", args, n);
1735   XtManageChild(scrolledWin);
1736   n = 0;
1737   XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n;
1738   XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n;
1739   col = XmCreateRowColumn(scrolledWin, "col", args, n);
1740   XtManageChild(col);
1741
1742   //----- fonts
1743   aboutBigFont =
1744     createFontList("-*-times-bold-i-normal--20-*-*-*-*-*-iso8859-1");
1745   aboutVersionFont =
1746     createFontList("-*-times-medium-r-normal--16-*-*-*-*-*-iso8859-1");
1747   aboutFixedFont =
1748     createFontList("-*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1");
1749
1750   //----- heading
1751   n = 0;
1752   s = XmStringCreateLocalized("Xpdf");
1753   XtSetArg(args[n], XmNlabelString, s); ++n;
1754   XtSetArg(args[n], XmNfontList, aboutBigFont); ++n;
1755   label = XmCreateLabel(col, "h0", args, n);
1756   XmStringFree(s);
1757   XtManageChild(label);
1758   n = 0;
1759   s = XmStringCreateLocalized("Version " xpdfVersion);
1760   XtSetArg(args[n], XmNlabelString, s); ++n;
1761   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
1762   label = XmCreateLabel(col, "h1", args, n);
1763   XmStringFree(s);
1764   XtManageChild(label);
1765   n = 0;
1766   s = XmStringCreateLocalized(xpdfCopyright);
1767   XtSetArg(args[n], XmNlabelString, s); ++n;
1768   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
1769   label = XmCreateLabel(col, "h2", args, n);
1770   XmStringFree(s);
1771   XtManageChild(label);
1772   n = 0;
1773   s = XmStringCreateLocalized(" ");
1774   XtSetArg(args[n], XmNlabelString, s); ++n;
1775   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
1776   label = XmCreateLabel(col, "h3", args, n);
1777   XmStringFree(s);
1778   XtManageChild(label);
1779   n = 0;
1780   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
1781   sep = XmCreateSeparator(col, "sep", args, n);
1782   XtManageChild(sep);
1783   n = 0;
1784   s = XmStringCreateLocalized(" ");
1785   XtSetArg(args[n], XmNlabelString, s); ++n;
1786   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
1787   label = XmCreateLabel(col, "h4", args, n);
1788   XmStringFree(s);
1789   XtManageChild(label);
1790   n = 0;
1791
1792   //----- text
1793   for (i = 0; aboutWinText[i]; ++i) {
1794     n = 0;
1795     s = XmStringCreateLocalized(aboutWinText[i]);
1796     XtSetArg(args[n], XmNlabelString, s); ++n;
1797     XtSetArg(args[n], XmNfontList, aboutFixedFont); ++n;
1798     sprintf(buf, "t%d", i);
1799     label = XmCreateLabel(col, buf, args, n);
1800     XtManageChild(label);
1801     XmStringFree(s);
1802   }
1803 }
1804
1805 //------------------------------------------------------------------------
1806 // GUI code: "open" dialog
1807 //------------------------------------------------------------------------
1808
1809 void XPDFViewer::initOpenDialog() {
1810   Arg args[20];
1811   int n;
1812   XmString s1, s2, s3;
1813
1814   n = 0;
1815   s1 = XmStringCreateLocalized("Open");
1816   XtSetArg(args[n], XmNokLabelString, s1); ++n;
1817   s2 = XmStringCreateLocalized("*.[Pp][Dd][Ff]");
1818   XtSetArg(args[n], XmNpattern, s2); ++n;
1819   s3 = XmStringCreateLocalized(xpdfAppName ": Open");
1820   XtSetArg(args[n], XmNdialogTitle, s3); ++n;
1821   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
1822   XtSetArg(args[n], XmNautoUnmanage, True); ++n;
1823   openDialog = XmCreateFileSelectionDialog(win, "openDialog", args, n);
1824   XmStringFree(s1);
1825   XmStringFree(s2);
1826   XmStringFree(s3);
1827   XtUnmanageChild(XmFileSelectionBoxGetChild(openDialog,
1828                                              XmDIALOG_HELP_BUTTON));
1829   XtAddCallback(openDialog, XmNokCallback,
1830                 &openOkCbk, (XtPointer)this);
1831 }
1832
1833 void XPDFViewer::setOpenDialogDir(char *dir) {
1834   XmString s;
1835
1836   s = XmStringCreateLocalized(dir);
1837   XtVaSetValues(openDialog, XmNdirectory, s, NULL);
1838   XmStringFree(s);
1839 }
1840
1841 void XPDFViewer::mapOpenDialog(GBool openInNewWindowA) {
1842   openInNewWindow = openInNewWindowA;
1843   XmFileSelectionDoSearch(openDialog, NULL);
1844   XtManageChild(openDialog);
1845 }
1846
1847 void XPDFViewer::openOkCbk(Widget widget, XtPointer ptr,
1848                            XtPointer callData) {
1849   XPDFViewer *viewer = (XPDFViewer *)ptr;
1850   XmFileSelectionBoxCallbackStruct *data =
1851     (XmFileSelectionBoxCallbackStruct *)callData;
1852   char *fileName;
1853   XmStringContext context;
1854   XmStringCharSet charSet;
1855   XmStringDirection dir;
1856   Boolean sep;
1857   GString *fileNameStr;
1858
1859   XmStringInitContext(&context, data->value);
1860   if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) {
1861     fileNameStr = new GString(fileName);
1862     if (viewer->openInNewWindow) {
1863       viewer->app->open(fileNameStr);
1864     } else {
1865       if (viewer->loadFile(fileNameStr)) {
1866         viewer->displayPage(1, viewer->core->getZoom(),
1867                             viewer->core->getRotate(), gTrue, gTrue);
1868       }
1869     }
1870     delete fileNameStr;
1871     XtFree(charSet);
1872     XtFree(fileName);
1873   }
1874   XmStringFreeContext(context);
1875 }
1876
1877 //------------------------------------------------------------------------
1878 // GUI code: "find" dialog
1879 //------------------------------------------------------------------------
1880
1881 void XPDFViewer::initFindDialog() {
1882   Widget row1, label, okBtn, closeBtn;
1883   Arg args[20];
1884   int n;
1885   XmString s;
1886
1887   //----- dialog
1888   n = 0;
1889   s = XmStringCreateLocalized(xpdfAppName ": Find");
1890   XtSetArg(args[n], XmNdialogTitle, s); ++n;
1891   XtSetArg(args[n], XmNnavigationType, XmNONE); ++n;
1892   XtSetArg(args[n], XmNautoUnmanage, False); ++n;
1893   findDialog = XmCreateFormDialog(win, "findDialog", args, n);
1894   XmStringFree(s);
1895
1896   //----- top row: search string entry
1897   n = 0;
1898   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1899   XtSetArg(args[n], XmNtopOffset, 4); ++n;
1900   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1901   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1902   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
1903   XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n;
1904   row1 = XmCreateRowColumn(findDialog, "row1", args, n);
1905   XtManageChild(row1);
1906   n = 0;
1907   s = XmStringCreateLocalized("Find text: ");
1908   XtSetArg(args[n], XmNlabelString, s); ++n;
1909   label = XmCreateLabel(row1, "label", args, n);
1910   XmStringFree(s);
1911   XtManageChild(label);
1912   n = 0;
1913   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
1914   findText = XmCreateTextField(row1, "text", args, n);
1915   XtManageChild(findText);
1916
1917   //----- "find" and "close" buttons
1918   n = 0;
1919   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
1920   XtSetArg(args[n], XmNtopWidget, row1); ++n;
1921   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1922   XtSetArg(args[n], XmNleftOffset, 4); ++n;
1923   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1924   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
1925   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
1926   okBtn = XmCreatePushButton(findDialog, "Find", args, n);
1927   XtManageChild(okBtn);
1928   XtAddCallback(okBtn, XmNactivateCallback,
1929                 &findFindCbk, (XtPointer)this);
1930   n = 0;
1931   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
1932   XtSetArg(args[n], XmNtopWidget, row1); ++n;
1933   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1934   XtSetArg(args[n], XmNrightOffset, 4); ++n;
1935   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1936   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
1937   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
1938   closeBtn = XmCreatePushButton(findDialog, "Close", args, n);
1939   XtManageChild(closeBtn);
1940   XtAddCallback(closeBtn, XmNactivateCallback,
1941                 &findCloseCbk, (XtPointer)this);
1942   n = 0;
1943   XtSetArg(args[n], XmNdefaultButton, okBtn); ++n;
1944   XtSetArg(args[n], XmNcancelButton, closeBtn); ++n;
1945 #if XmVersion > 1001
1946   XtSetArg(args[n], XmNinitialFocus, findText); ++n;
1947 #endif
1948   XtSetValues(findDialog, args, n);
1949 }
1950
1951 void XPDFViewer::findFindCbk(Widget widget, XtPointer ptr,
1952                              XtPointer callData) {
1953   XPDFViewer *viewer = (XPDFViewer *)ptr;
1954
1955   viewer->doFind(gFalse);
1956 }
1957
1958 void XPDFViewer::doFind(GBool next) {
1959   if (XtWindow(findDialog)) {
1960     XDefineCursor(display, XtWindow(findDialog), core->getBusyCursor());
1961   }
1962   core->find(XmTextFieldGetString(findText), next);
1963   if (XtWindow(findDialog)) {
1964     XUndefineCursor(display, XtWindow(findDialog));
1965   }
1966 }
1967
1968 void XPDFViewer::findCloseCbk(Widget widget, XtPointer ptr,
1969                               XtPointer callData) {
1970   XPDFViewer *viewer = (XPDFViewer *)ptr;
1971
1972   XtUnmanageChild(viewer->findDialog);
1973 }
1974
1975 //------------------------------------------------------------------------
1976 // GUI code: "save as" dialog
1977 //------------------------------------------------------------------------
1978
1979 void XPDFViewer::initSaveAsDialog() {
1980   Arg args[20];
1981   int n;
1982   XmString s1, s2, s3;
1983
1984   n = 0;
1985   s1 = XmStringCreateLocalized("Save");
1986   XtSetArg(args[n], XmNokLabelString, s1); ++n;
1987   s2 = XmStringCreateLocalized("*.[Pp][Dd][Ff]");
1988   XtSetArg(args[n], XmNpattern, s2); ++n;
1989   s3 = XmStringCreateLocalized(xpdfAppName ": Save as");
1990   XtSetArg(args[n], XmNdialogTitle, s3); ++n;
1991   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
1992   XtSetArg(args[n], XmNautoUnmanage, True); ++n;
1993   saveAsDialog = XmCreateFileSelectionDialog(win, "saveAsDialog", args, n);
1994   XmStringFree(s1);
1995   XmStringFree(s2);
1996   XmStringFree(s3);
1997   XtUnmanageChild(XmFileSelectionBoxGetChild(saveAsDialog,
1998                                              XmDIALOG_HELP_BUTTON));
1999   XtAddCallback(saveAsDialog, XmNokCallback,
2000                 &saveAsOkCbk, (XtPointer)this);
2001 }
2002
2003 void XPDFViewer::setSaveAsDialogDir(char *dir) {
2004   XmString s;
2005
2006   s = XmStringCreateLocalized(dir);
2007   XtVaSetValues(saveAsDialog, XmNdirectory, s, NULL);
2008   XmStringFree(s);
2009 }
2010
2011 void XPDFViewer::mapSaveAsDialog() {
2012   XmFileSelectionDoSearch(saveAsDialog, NULL);
2013   XtManageChild(saveAsDialog);
2014 }
2015
2016 void XPDFViewer::saveAsOkCbk(Widget widget, XtPointer ptr,
2017                              XtPointer callData) {
2018   XPDFViewer *viewer = (XPDFViewer *)ptr;
2019   XmFileSelectionBoxCallbackStruct *data =
2020     (XmFileSelectionBoxCallbackStruct *)callData;
2021   char *fileName;
2022   GString *fileNameStr;
2023   XmStringContext context;
2024   XmStringCharSet charSet;
2025   XmStringDirection dir;
2026   Boolean sep;
2027
2028   XmStringInitContext(&context, data->value);
2029   if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) {
2030     fileNameStr = new GString(fileName);
2031     viewer->core->getDoc()->saveAs(fileNameStr);
2032     delete fileNameStr;
2033     XtFree(charSet);
2034     XtFree(fileName);
2035   }
2036   XmStringFreeContext(context);
2037 }
2038
2039 //------------------------------------------------------------------------
2040 // GUI code: "print" dialog
2041 //------------------------------------------------------------------------
2042
2043 void XPDFViewer::initPrintDialog() {
2044   Widget sep1, sep2, row, label1, label2, okBtn, cancelBtn;
2045   Arg args[20];
2046   int n;
2047   XmString s;
2048   GString *psFileName;
2049
2050   //----- dialog
2051   n = 0;
2052   s = XmStringCreateLocalized(xpdfAppName ": Print");
2053   XtSetArg(args[n], XmNdialogTitle, s); ++n;
2054   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
2055   printDialog = XmCreateFormDialog(win, "printDialog", args, n);
2056   XmStringFree(s);
2057
2058   //----- "print with command"
2059   n = 0;
2060   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
2061   XtSetArg(args[n], XmNtopOffset, 4); ++n;
2062   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2063   XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY); ++n;
2064   XtSetArg(args[n], XmNset, XmSET); ++n;
2065   s = XmStringCreateLocalized("Print with command:");
2066   XtSetArg(args[n], XmNlabelString, s); ++n;
2067   printWithCmdBtn = XmCreateToggleButton(printDialog, "printWithCmd", args, n);
2068   XmStringFree(s);
2069   XtManageChild(printWithCmdBtn);
2070   XtAddCallback(printWithCmdBtn, XmNvalueChangedCallback,
2071                 &printWithCmdBtnCbk, (XtPointer)this);
2072   n = 0;
2073   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2074   XtSetArg(args[n], XmNtopWidget, printWithCmdBtn); ++n;
2075   XtSetArg(args[n], XmNtopOffset, 2); ++n;
2076   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2077   XtSetArg(args[n], XmNleftOffset, 16); ++n;
2078   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2079   XtSetArg(args[n], XmNrightOffset, 4); ++n;
2080   XtSetArg(args[n], XmNcolumns, 40); ++n;
2081   printCmdText = XmCreateTextField(printDialog, "printCmd", args, n);
2082   XtManageChild(printCmdText);
2083
2084   //----- "print with command"
2085   n = 0;
2086   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2087   XtSetArg(args[n], XmNtopWidget, printCmdText); ++n;
2088   XtSetArg(args[n], XmNtopOffset, 4); ++n;
2089   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2090   XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY); ++n;
2091   XtSetArg(args[n], XmNset, XmUNSET); ++n;
2092   s = XmStringCreateLocalized("Print to file:");
2093   XtSetArg(args[n], XmNlabelString, s); ++n;
2094   printToFileBtn = XmCreateToggleButton(printDialog, "printToFile", args, n);
2095   XmStringFree(s);
2096   XtManageChild(printToFileBtn);
2097   XtAddCallback(printToFileBtn, XmNvalueChangedCallback,
2098                 &printToFileBtnCbk, (XtPointer)this);
2099   n = 0;
2100   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2101   XtSetArg(args[n], XmNtopWidget, printToFileBtn); ++n;
2102   XtSetArg(args[n], XmNtopOffset, 2); ++n;
2103   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2104   XtSetArg(args[n], XmNleftOffset, 16); ++n;
2105   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2106   XtSetArg(args[n], XmNrightOffset, 4); ++n;
2107   XtSetArg(args[n], XmNcolumns, 40); ++n;
2108   XtSetArg(args[n], XmNsensitive, False); ++n;
2109   printFileText = XmCreateTextField(printDialog, "printFile", args, n);
2110   XtManageChild(printFileText);
2111
2112   //----- separator
2113   n = 0;
2114   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2115   XtSetArg(args[n], XmNtopWidget, printFileText); ++n;
2116   XtSetArg(args[n], XmNtopOffset, 8); ++n;
2117   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2118   XtSetArg(args[n], XmNleftOffset, 8); ++n;
2119   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2120   XtSetArg(args[n], XmNrightOffset, 8); ++n;
2121   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
2122   sep1 = XmCreateSeparator(printDialog, "sep1", args, n);
2123   XtManageChild(sep1);
2124
2125   //----- page range
2126   n = 0;
2127   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2128   XtSetArg(args[n], XmNtopWidget, sep1); ++n;
2129   XtSetArg(args[n], XmNtopOffset, 8); ++n;
2130   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2131   XtSetArg(args[n], XmNleftOffset, 4); ++n;
2132   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
2133   XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n;
2134   row = XmCreateRowColumn(printDialog, "row", args, n);
2135   XtManageChild(row);
2136   n = 0;
2137   s = XmStringCreateLocalized("Pages:");
2138   XtSetArg(args[n], XmNlabelString, s); ++n;
2139   label1 = XmCreateLabel(row, "label1", args, n);
2140   XmStringFree(s);
2141   XtManageChild(label1);
2142   n = 0;
2143   XtSetArg(args[n], XmNcolumns, 5); ++n;
2144   printFirstPage = XmCreateTextField(row, "printFirstPage", args, n);
2145   XtManageChild(printFirstPage);
2146   n = 0;
2147   s = XmStringCreateLocalized("to");
2148   XtSetArg(args[n], XmNlabelString, s); ++n;
2149   label2 = XmCreateLabel(row, "label2", args, n);
2150   XmStringFree(s);
2151   XtManageChild(label2);
2152   n = 0;
2153   XtSetArg(args[n], XmNcolumns, 5); ++n;
2154   printLastPage = XmCreateTextField(row, "printLastPage", args, n);
2155   XtManageChild(printLastPage);
2156
2157   //----- separator
2158   n = 0;
2159   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2160   XtSetArg(args[n], XmNtopWidget, row); ++n;
2161   XtSetArg(args[n], XmNtopOffset, 8); ++n;
2162   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2163   XtSetArg(args[n], XmNleftOffset, 8); ++n;
2164   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2165   XtSetArg(args[n], XmNrightOffset, 8); ++n;
2166   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
2167   sep2 = XmCreateSeparator(printDialog, "sep2", args, n);
2168   XtManageChild(sep2);
2169
2170   //----- "print" and "cancel" buttons
2171   n = 0;
2172   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2173   XtSetArg(args[n], XmNtopWidget, sep2); ++n;
2174   XtSetArg(args[n], XmNtopOffset, 8); ++n;
2175   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2176   XtSetArg(args[n], XmNleftOffset, 4); ++n;
2177   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
2178   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
2179   okBtn = XmCreatePushButton(printDialog, "Print", args, n);
2180   XtManageChild(okBtn);
2181   XtAddCallback(okBtn, XmNactivateCallback,
2182                 &printPrintCbk, (XtPointer)this);
2183   n = 0;
2184   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2185   XtSetArg(args[n], XmNtopWidget, sep2); ++n;
2186   XtSetArg(args[n], XmNtopOffset, 8); ++n;
2187   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2188   XtSetArg(args[n], XmNrightOffset, 4); ++n;
2189   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
2190   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
2191   cancelBtn = XmCreatePushButton(printDialog, "Cancel", args, n);
2192   XtManageChild(cancelBtn);
2193   n = 0;
2194   XtSetArg(args[n], XmNdefaultButton, okBtn); ++n;
2195   XtSetArg(args[n], XmNcancelButton, cancelBtn); ++n;
2196   XtSetValues(printDialog, args, n);
2197
2198   //----- initial values
2199   if ((psFileName = globalParams->getPSFile())) {
2200     if (psFileName->getChar(0) == '|') {
2201       XmTextFieldSetString(printCmdText,
2202                            psFileName->getCString() + 1);
2203     } else {
2204       XmTextFieldSetString(printFileText, psFileName->getCString());
2205     }
2206     delete psFileName;
2207   }
2208 }
2209
2210 void XPDFViewer::setupPrintDialog() {
2211   PDFDoc *doc;
2212   char buf[20];
2213   GString *pdfFileName, *psFileName, *psFileName2;
2214   char *p;
2215
2216   doc = core->getDoc();
2217   psFileName = globalParams->getPSFile();
2218   if (!psFileName || psFileName->getChar(0) == '|') {
2219     pdfFileName = doc->getFileName();
2220     p = pdfFileName->getCString() + pdfFileName->getLength() - 4;
2221     if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
2222       psFileName2 = new GString(pdfFileName->getCString(),
2223                                 pdfFileName->getLength() - 4);
2224     } else {
2225       psFileName2 = pdfFileName->copy();
2226     }
2227     psFileName2->append(".ps");
2228     XmTextFieldSetString(printFileText, psFileName2->getCString());
2229     delete psFileName2;
2230   }
2231   if (psFileName) {
2232     delete psFileName;
2233   }
2234
2235   sprintf(buf, "%d", doc->getNumPages());
2236   XmTextFieldSetString(printFirstPage, "1");
2237   XmTextFieldSetString(printLastPage, buf);
2238 }
2239
2240 void XPDFViewer::printWithCmdBtnCbk(Widget widget, XtPointer ptr,
2241                                     XtPointer callData) {
2242   XPDFViewer *viewer = (XPDFViewer *)ptr;
2243   XmToggleButtonCallbackStruct *data =
2244       (XmToggleButtonCallbackStruct *)callData;
2245
2246   if (data->set != XmSET) {
2247     XmToggleButtonSetState(viewer->printWithCmdBtn, True, False);
2248   }
2249   XmToggleButtonSetState(viewer->printToFileBtn, False, False);
2250   XtVaSetValues(viewer->printCmdText, XmNsensitive, True, NULL);
2251   XtVaSetValues(viewer->printFileText, XmNsensitive, False, NULL);
2252 }
2253
2254 void XPDFViewer::printToFileBtnCbk(Widget widget, XtPointer ptr,
2255                                    XtPointer callData) {
2256   XPDFViewer *viewer = (XPDFViewer *)ptr;
2257   XmToggleButtonCallbackStruct *data =
2258       (XmToggleButtonCallbackStruct *)callData;
2259
2260   if (data->set != XmSET) {
2261     XmToggleButtonSetState(viewer->printToFileBtn, True, False);
2262   }
2263   XmToggleButtonSetState(viewer->printWithCmdBtn, False, False);
2264   XtVaSetValues(viewer->printFileText, XmNsensitive, True, NULL);
2265   XtVaSetValues(viewer->printCmdText, XmNsensitive, False, NULL);
2266 }
2267
2268 void XPDFViewer::printPrintCbk(Widget widget, XtPointer ptr,
2269                                XtPointer callData) {
2270   XPDFViewer *viewer = (XPDFViewer *)ptr;
2271   unsigned char withCmd;
2272   GString *psFileName;
2273   int firstPage, lastPage;
2274   PDFDoc *doc;
2275   PSOutputDev *psOut;
2276
2277   doc = viewer->core->getDoc();
2278   if (!doc->okToPrint()) {
2279     error(-1, "Printing this document is not allowed.");
2280     return;
2281   }
2282
2283   viewer->core->setBusyCursor(gTrue);
2284
2285   XtVaGetValues(viewer->printWithCmdBtn, XmNset, &withCmd, NULL);
2286   if (withCmd) {
2287     psFileName = new GString(XmTextFieldGetString(viewer->printCmdText));
2288     psFileName->insert(0, '|');
2289   } else {
2290     psFileName = new GString(XmTextFieldGetString(viewer->printFileText));
2291   }
2292
2293   firstPage = atoi(XmTextFieldGetString(viewer->printFirstPage));
2294   lastPage = atoi(XmTextFieldGetString(viewer->printLastPage));
2295   if (firstPage < 1) {
2296     firstPage = 1;
2297   } else if (firstPage > doc->getNumPages()) {
2298     firstPage = doc->getNumPages();
2299   }
2300   if (lastPage < firstPage) {
2301     lastPage = firstPage;
2302   } else if (lastPage > doc->getNumPages()) {
2303     lastPage = doc->getNumPages();
2304   }
2305
2306   psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
2307                           doc->getCatalog(), firstPage, lastPage,
2308                           psModePS);
2309   if (psOut->isOk()) {
2310     doc->displayPages(psOut, firstPage, lastPage, 72, 72, 0, gFalse);
2311   }
2312   delete psOut;
2313   delete psFileName;
2314
2315   viewer->core->setBusyCursor(gFalse);
2316 }
2317
2318 //------------------------------------------------------------------------
2319 // GUI code: password dialog
2320 //------------------------------------------------------------------------
2321
2322 void XPDFViewer::initPasswordDialog() {
2323   Widget row, label, okBtn, cancelBtn;
2324   Arg args[20];
2325   int n;
2326   XmString s;
2327
2328   //----- dialog
2329   n = 0;
2330   s = XmStringCreateLocalized(xpdfAppName ": Password");
2331   XtSetArg(args[n], XmNdialogTitle, s); ++n;
2332   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
2333   passwordDialog = XmCreateFormDialog(win, "passwordDialog", args, n);
2334   XmStringFree(s);
2335
2336   //----- message
2337   n = 0;
2338   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
2339   XtSetArg(args[n], XmNtopOffset, 4); ++n;
2340   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2341   XtSetArg(args[n], XmNleftOffset, 4); ++n;
2342   s = XmStringCreateLocalized(" ");
2343   XtSetArg(args[n], XmNlabelString, s); ++n;
2344   passwordMsg = XmCreateLabel(passwordDialog, "msg", args, n);
2345   XmStringFree(s);
2346   XtManageChild(passwordMsg);
2347
2348   //----- label and password entry
2349   n = 0;
2350   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2351   XtSetArg(args[n], XmNtopWidget, passwordMsg); ++n;
2352   XtSetArg(args[n], XmNtopOffset, 4); ++n;
2353   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2354   XtSetArg(args[n], XmNleftOffset, 4); ++n;
2355   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2356   XtSetArg(args[n], XmNleftOffset, 4); ++n;
2357   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
2358   XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n;
2359   row = XmCreateRowColumn(passwordDialog, "row", args, n);
2360   XtManageChild(row);
2361   n = 0;
2362   s = XmStringCreateLocalized("Password: ");
2363   XtSetArg(args[n], XmNlabelString, s); ++n;
2364   label = XmCreateLabel(row, "label", args, n);
2365   XmStringFree(s);
2366   XtManageChild(label);
2367   n = 0;
2368   XtSetArg(args[n], XmNcolumns, 16); ++n;
2369   passwordText = XmCreateTextField(row, "text", args, n);
2370   XtManageChild(passwordText);
2371   XtAddCallback(passwordText, XmNmodifyVerifyCallback,
2372                 &passwordTextVerifyCbk, this);
2373
2374   //----- "Ok" and "Cancel" buttons
2375   n = 0;
2376   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2377   XtSetArg(args[n], XmNtopWidget, row); ++n;
2378   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2379   XtSetArg(args[n], XmNleftOffset, 4); ++n;
2380   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
2381   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
2382   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
2383   okBtn = XmCreatePushButton(passwordDialog, "Ok", args, n);
2384   XtManageChild(okBtn);
2385   XtAddCallback(okBtn, XmNactivateCallback,
2386                 &passwordOkCbk, (XtPointer)this);
2387   n = 0;
2388   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
2389   XtSetArg(args[n], XmNtopWidget, row); ++n;
2390   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2391   XtSetArg(args[n], XmNrightOffset, 4); ++n;
2392   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
2393   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
2394   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
2395   cancelBtn = XmCreatePushButton(passwordDialog, "Cancel", args, n);
2396   XtManageChild(cancelBtn);
2397   XtAddCallback(cancelBtn, XmNactivateCallback,
2398                 &passwordCancelCbk, (XtPointer)this);
2399   n = 0;
2400   XtSetArg(args[n], XmNdefaultButton, okBtn); ++n;
2401   XtSetArg(args[n], XmNcancelButton, cancelBtn); ++n;
2402 #if XmVersion > 1001
2403   XtSetArg(args[n], XmNinitialFocus, passwordText); ++n;
2404 #endif
2405   XtSetValues(passwordDialog, args, n);
2406 }
2407
2408 void XPDFViewer::passwordTextVerifyCbk(Widget widget, XtPointer ptr,
2409                                        XtPointer callData) {
2410   XPDFViewer *viewer = (XPDFViewer *)ptr;
2411   XmTextVerifyCallbackStruct *data =
2412       (XmTextVerifyCallbackStruct *)callData;
2413   int i, n;
2414
2415   i = (int)data->startPos;
2416   n = (int)data->endPos - i;
2417   if (i > viewer->password->getLength()) {
2418     i = viewer->password->getLength();
2419   }
2420   if (i + n > viewer->password->getLength()) {
2421     n = viewer->password->getLength() - i;
2422   }
2423   viewer->password->del(i, n);
2424   viewer->password->insert(i, data->text->ptr, data->text->length);
2425
2426   for (i = 0; i < data->text->length; ++i) {
2427     data->text->ptr[i] = '*';
2428   }
2429   data->doit = True;
2430 }
2431
2432 void XPDFViewer::passwordOkCbk(Widget widget, XtPointer ptr,
2433                                XtPointer callData) {
2434   XPDFViewer *viewer = (XPDFViewer *)ptr;
2435
2436   viewer->passwordDone = 1;
2437 }
2438
2439 void XPDFViewer::passwordCancelCbk(Widget widget, XtPointer ptr,
2440                                    XtPointer callData) {
2441   XPDFViewer *viewer = (XPDFViewer *)ptr;
2442
2443   viewer->passwordDone = -1;
2444 }
2445
2446 void XPDFViewer::getPassword(GBool again) {
2447   XmString s;
2448   XEvent event;
2449
2450   if (password) {
2451     delete password;
2452   }
2453   password = new GString();
2454
2455   XmTextFieldSetString(passwordText, "");
2456   s = XmStringCreateLocalized(
2457           again ? (char *)"Incorrect password.  Please try again."
2458                 : (char *)"This document requires a password.");
2459   XtVaSetValues(passwordMsg, XmNlabelString, s, NULL);
2460   XmStringFree(s);
2461   XtManageChild(passwordDialog);
2462   passwordDone = 0;
2463   do {
2464     XtAppNextEvent(app->getAppContext(), &event);
2465     XtDispatchEvent(&event);
2466   } while (!passwordDone);
2467
2468   if (passwordDone < 0) {
2469     delete password;
2470     password = NULL;
2471   }
2472 }
2473
2474 //------------------------------------------------------------------------
2475 // Motif support
2476 //------------------------------------------------------------------------
2477
2478 XmFontList XPDFViewer::createFontList(char *xlfd) {
2479   XmFontList fontList;
2480
2481 #if XmVersion <= 1001
2482
2483   XFontStruct *font;
2484   String params;
2485   Cardinal nParams;
2486
2487   font = XLoadQueryFont(display, xlfd);
2488   if (font) {
2489     fontList = XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
2490   } else {
2491     params = (String)xlfd;
2492     nParams = 1;
2493     XtAppWarningMsg(app->getAppContext(),
2494                     "noSuchFont", "CvtStringToXmFontList",
2495                     "XtToolkitError", "No such font: %s",
2496                     &params, &nParams);
2497     fontList = NULL;
2498   }
2499
2500 #else
2501
2502   XmFontListEntry entry;
2503
2504   entry = XmFontListEntryLoad(display, xlfd,
2505                               XmFONT_IS_FONT, XmFONTLIST_DEFAULT_TAG);
2506   fontList = XmFontListAppendEntry(NULL, entry);
2507   XmFontListEntryFree(&entry);
2508
2509 #endif
2510
2511   return fontList;
2512 }