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