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/keysym.h>
19 #include <X11/cursorfont.h>
20 #ifdef HAVE_X11_XPM_H
21 #include <X11/xpm.h>
22 #endif
23 #if defined(__sgi) && (XmVERSION <= 1)
24 #define Object XtObject
25 #include <Sgm/HPanedW.h>
26 #undef Object
27 #endif
28 #include "gmem.h"
29 #include "gfile.h"
30 #include "GString.h"
31 #include "GList.h"
32 #include "Error.h"
33 #include "GlobalParams.h"
34 #include "PDFDoc.h"
35 #include "Link.h"
36 #include "ErrorCodes.h"
37 #include "Outline.h"
38 #include "UnicodeMap.h"
39 #ifndef DISABLE_OUTLINE
40 #define Object XtObject
41 #include "XPDFTree.h"
42 #undef Object
43 #endif
44 #include "XPDFApp.h"
45 #include "XPDFViewer.h"
46 #include "PSOutputDev.h"
47 #include "config.h"
48 
49 // these macro defns conflict with xpdf's Object class
50 #ifdef LESSTIF_VERSION
51 #undef XtDisplay
52 #undef XtScreen
53 #undef XtWindow
54 #undef XtParent
55 #undef XtIsRealized
56 #endif
57 
58 #if XmVERSION <= 1
59 #define XmSET   True
60 #define XmUNSET False
61 #endif
62 
63 // hack around old X includes which are missing these symbols
64 #ifndef XK_Page_Up
65 #define XK_Page_Up              0xFF55
66 #endif
67 #ifndef XK_Page_Down
68 #define XK_Page_Down            0xFF56
69 #endif
70 #ifndef XK_KP_Home
71 #define XK_KP_Home              0xFF95
72 #endif
73 #ifndef XK_KP_Left
74 #define XK_KP_Left              0xFF96
75 #endif
76 #ifndef XK_KP_Up
77 #define XK_KP_Up                0xFF97
78 #endif
79 #ifndef XK_KP_Right
80 #define XK_KP_Right             0xFF98
81 #endif
82 #ifndef XK_KP_Down
83 #define XK_KP_Down              0xFF99
84 #endif
85 #ifndef XK_KP_Prior
86 #define XK_KP_Prior             0xFF9A
87 #endif
88 #ifndef XK_KP_Page_Up
89 #define XK_KP_Page_Up           0xFF9A
90 #endif
91 #ifndef XK_KP_Next
92 #define XK_KP_Next              0xFF9B
93 #endif
94 #ifndef XK_KP_Page_Down
95 #define XK_KP_Page_Down         0xFF9B
96 #endif
97 #ifndef XK_KP_End
98 #define XK_KP_End               0xFF9C
99 #endif
100 #ifndef XK_KP_Begin
101 #define XK_KP_Begin             0xFF9D
102 #endif
103 #ifndef XK_KP_Insert
104 #define XK_KP_Insert            0xFF9E
105 #endif
106 #ifndef XK_KP_Delete
107 #define XK_KP_Delete            0xFF9F
108 #endif
109 
110 //------------------------------------------------------------------------
111 // GUI includes
112 //------------------------------------------------------------------------
113 
114 #include "xpdfIcon.xpm"
115 #include "leftArrow.xbm"
116 #include "leftArrowDis.xbm"
117 #include "dblLeftArrow.xbm"
118 #include "dblLeftArrowDis.xbm"
119 #include "rightArrow.xbm"
120 #include "rightArrowDis.xbm"
121 #include "dblRightArrow.xbm"
122 #include "dblRightArrowDis.xbm"
123 #include "backArrow.xbm"
124 #include "backArrowDis.xbm"
125 #include "forwardArrow.xbm"
126 #include "forwardArrowDis.xbm"
127 #include "find.xbm"
128 #include "findDis.xbm"
129 #include "print.xbm"
130 #include "printDis.xbm"
131 #include "about.xbm"
132 #include "about-text.h"
133 
134 //------------------------------------------------------------------------
135 
136 struct ZoomMenuInfo {
137   const char *label;
138   double zoom;
139 };
140 
141 static ZoomMenuInfo zoomMenuInfo[nZoomMenuItems] = {
142   { "400%",      400 },
143   { "200%",      200 },
144   { "150%",      150 },
145   { "125%",      125 },
146   { "100%",      100 },
147   { "50%",        50 },
148   { "25%",        25 },
149   { "12.5%",      12.5 },
150   { "fit page",  zoomPage },
151   { "fit width", zoomWidth }
152 };
153 
154 #define maxZoomIdx   0
155 #define defZoomIdx   3
156 #define minZoomIdx   7
157 #define zoomPageIdx  8
158 #define zoomWidthIdx 9
159 
160 //------------------------------------------------------------------------
161 
162 #define cmdMaxArgs 8
163 
164 XPDFViewerCmd XPDFViewer::cmdTab[] = {
165   { "about",                   0, gFalse, gFalse, &XPDFViewer::cmdAbout },
166   { "closeOutline",            0, gFalse, gFalse, &XPDFViewer::cmdCloseOutline },
167   { "closeWindow",             0, gFalse, gFalse, &XPDFViewer::cmdCloseWindow },
168   { "closeWindowOrQuit",       0, gFalse, gFalse, &XPDFViewer::cmdCloseWindowOrQuit },
169   { "continuousMode",          0, gFalse, gFalse, &XPDFViewer::cmdContinuousMode },
170   { "endPan",                  0, gTrue,  gTrue,  &XPDFViewer::cmdEndPan },
171   { "endSelection",            0, gTrue,  gTrue,  &XPDFViewer::cmdEndSelection },
172   { "find",                    0, gTrue,  gFalse, &XPDFViewer::cmdFind },
173   { "findNext",                0, gTrue,  gFalse, &XPDFViewer::cmdFindNext },
174   { "focusToDocWin",           0, gFalse, gFalse, &XPDFViewer::cmdFocusToDocWin },
175   { "focusToPageNum",          0, gFalse, gFalse, &XPDFViewer::cmdFocusToPageNum },
176   { "followLink",              0, gTrue,  gTrue,  &XPDFViewer::cmdFollowLink },
177   { "followLinkInNewWin",      0, gTrue,  gTrue,  &XPDFViewer::cmdFollowLinkInNewWin },
178   { "followLinkInNewWinNoSel", 0, gTrue,  gTrue,  &XPDFViewer::cmdFollowLinkInNewWinNoSel },
179   { "followLinkNoSel",         0, gTrue,  gTrue,  &XPDFViewer::cmdFollowLinkNoSel },
180   { "fullScreenMode",          0, gFalse, gFalse, &XPDFViewer::cmdFullScreenMode },
181   { "goBackward",              0, gFalse, gFalse, &XPDFViewer::cmdGoBackward },
182   { "goForward",               0, gFalse, gFalse, &XPDFViewer::cmdGoForward },
183   { "gotoDest",                1, gTrue,  gFalse, &XPDFViewer::cmdGotoDest },
184   { "gotoLastPage",            0, gTrue,  gFalse, &XPDFViewer::cmdGotoLastPage },
185   { "gotoLastPageNoScroll",    0, gTrue,  gFalse, &XPDFViewer::cmdGotoLastPageNoScroll },
186   { "gotoPage",                1, gTrue,  gFalse, &XPDFViewer::cmdGotoPage },
187   { "gotoPageNoScroll",        1, gTrue,  gFalse, &XPDFViewer::cmdGotoPageNoScroll },
188   { "nextPage",                0, gTrue,  gFalse, &XPDFViewer::cmdNextPage },
189   { "nextPageNoScroll",        0, gTrue,  gFalse, &XPDFViewer::cmdNextPageNoScroll },
190   { "open",                    0, gFalse, gFalse, &XPDFViewer::cmdOpen },
191   { "openFile",                1, gFalse, gFalse, &XPDFViewer::cmdOpenFile },
192   { "openFileAtDest",          2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtDest },
193   { "openFileAtDestInNewWin",  2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtDestInNewWin },
194   { "openFileAtPage",          2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtPage },
195   { "openFileAtPageInNewWin",  2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtPageInNewWin },
196   { "openFileInNewWin",        1, gFalse, gFalse, &XPDFViewer::cmdOpenFileInNewWin },
197   { "openInNewWin",            0, gFalse, gFalse, &XPDFViewer::cmdOpenInNewWin },
198   { "openOutline",             0, gFalse, gFalse, &XPDFViewer::cmdOpenOutline },
199   { "pageDown",                0, gTrue,  gFalse, &XPDFViewer::cmdPageDown },
200   { "pageUp",                  0, gTrue,  gFalse, &XPDFViewer::cmdPageUp },
201   { "postPopupMenu",           0, gFalse, gTrue,  &XPDFViewer::cmdPostPopupMenu },
202   { "prevPage",                0, gTrue,  gFalse, &XPDFViewer::cmdPrevPage },
203   { "prevPageNoScroll",        0, gTrue,  gFalse, &XPDFViewer::cmdPrevPageNoScroll },
204   { "print",                   0, gTrue,  gFalse, &XPDFViewer::cmdPrint },
205   { "quit",                    0, gFalse, gFalse, &XPDFViewer::cmdQuit },
206   { "raise",                   0, gFalse, gFalse, &XPDFViewer::cmdRaise },
207   { "redraw",                  0, gTrue,  gFalse, &XPDFViewer::cmdRedraw },
208   { "reload",                  0, gTrue,  gFalse, &XPDFViewer::cmdReload },
209   { "rotateCCW",               0, gTrue,  gFalse, &XPDFViewer::cmdRotateCCW },
210   { "rotateCW",                0, gTrue,  gFalse, &XPDFViewer::cmdRotateCW },
211   { "run",                     1, gFalse, gFalse, &XPDFViewer::cmdRun },
212   { "scrollDown",              1, gTrue,  gFalse, &XPDFViewer::cmdScrollDown },
213   { "scrollDownNextPage",      1, gTrue,  gFalse, &XPDFViewer::cmdScrollDownNextPage },
214   { "scrollLeft",              1, gTrue,  gFalse, &XPDFViewer::cmdScrollLeft },
215   { "scrollOutlineDown",       1, gTrue,  gFalse, &XPDFViewer::cmdScrollOutlineDown },
216   { "scrollOutlineUp",         1, gTrue,  gFalse, &XPDFViewer::cmdScrollOutlineUp },
217   { "scrollRight",             1, gTrue,  gFalse, &XPDFViewer::cmdScrollRight },
218   { "scrollToBottomEdge",      0, gTrue,  gFalse, &XPDFViewer::cmdScrollToBottomEdge },
219   { "scrollToBottomRight",     0, gTrue,  gFalse, &XPDFViewer::cmdScrollToBottomRight },
220   { "scrollToLeftEdge",        0, gTrue,  gFalse, &XPDFViewer::cmdScrollToLeftEdge },
221   { "scrollToRightEdge",       0, gTrue,  gFalse, &XPDFViewer::cmdScrollToRightEdge },
222   { "scrollToTopEdge",         0, gTrue,  gFalse, &XPDFViewer::cmdScrollToTopEdge },
223   { "scrollToTopLeft",         0, gTrue,  gFalse, &XPDFViewer::cmdScrollToTopLeft },
224   { "scrollUp",                1, gTrue,  gFalse, &XPDFViewer::cmdScrollUp },
225   { "scrollUpPrevPage",        1, gTrue,  gFalse, &XPDFViewer::cmdScrollUpPrevPage },
226   { "setSelection",            5, gTrue,  gFalse, &XPDFViewer::cmdSetSelection },
227   { "singlePageMode",          0, gFalse, gFalse, &XPDFViewer::cmdSinglePageMode },
228   { "startPan",                0, gTrue,  gTrue,  &XPDFViewer::cmdStartPan },
229   { "startSelection",          0, gTrue,  gTrue,  &XPDFViewer::cmdStartSelection },
230   { "toggleContinuousMode",    0, gFalse, gFalse, &XPDFViewer::cmdToggleContinuousMode },
231   { "toggleFullScreenMode",    0, gFalse, gFalse, &XPDFViewer::cmdToggleFullScreenMode },
232   { "toggleOutline",           0, gFalse, gFalse, &XPDFViewer::cmdToggleOutline },
233   { "windowMode",              0, gFalse, gFalse, &XPDFViewer::cmdWindowMode },
234   { "zoomFitPage",             0, gFalse, gFalse, &XPDFViewer::cmdZoomFitPage },
235   { "zoomFitWidth",            0, gFalse, gFalse, &XPDFViewer::cmdZoomFitWidth },
236   { "zoomIn",                  0, gFalse, gFalse, &XPDFViewer::cmdZoomIn },
237   { "zoomOut",                 0, gFalse, gFalse, &XPDFViewer::cmdZoomOut },
238   { "zoomPercent",             1, gFalse, gFalse, &XPDFViewer::cmdZoomPercent },
239   { "zoomToSelection",         0, gTrue,  gFalse, &XPDFViewer::cmdZoomToSelection }
240 };
241 
242 #define nCmds (sizeof(cmdTab) / sizeof(XPDFViewerCmd))
243 
244 //------------------------------------------------------------------------
245 
XPDFViewer(XPDFApp * appA,GString * fileName,int pageA,GString * destName,GBool fullScreen,GString * ownerPassword,GString * userPassword)246 XPDFViewer::XPDFViewer(XPDFApp *appA, GString *fileName,
247 		       int pageA, GString *destName, GBool fullScreen,
248 		       GString *ownerPassword, GString *userPassword) {
249   LinkDest *dest;
250   int pg;
251   double z;
252 
253   app = appA;
254   win = NULL;
255   core = NULL;
256   ok = gFalse;
257 #ifndef DISABLE_OUTLINE
258   outlineLabels = NULL;
259   outlineLabelsLength = outlineLabelsSize = 0;
260   outlinePaneWidth = 175;
261 #endif
262 
263   // do Motif-specific initialization and create the window;
264   // this also creates the core object
265   initWindow(fullScreen);
266   initAboutDialog();
267   initFindDialog();
268   initPrintDialog();
269   openDialog = NULL;
270   saveAsDialog = NULL;
271 
272   dest = NULL; // make gcc happy
273   pg = pageA; // make gcc happy
274 
275   if (fileName) {
276     if (loadFile(fileName, ownerPassword, userPassword)) {
277       getPageAndDest(pageA, destName, &pg, &dest);
278 #ifndef DISABLE_OUTLINE
279       if (outlineScroll != None &&
280 	  core->getDoc()->getOutline()->getItems() &&
281 	  core->getDoc()->getOutline()->getItems()->getLength() > 0) {
282 	XtVaSetValues(outlineScroll, XmNwidth, outlinePaneWidth, NULL);
283       }
284 #endif
285     } else {
286       return;
287     }
288   }
289   core->resizeToPage(pg);
290 
291   // map the window -- we do this after calling resizeToPage to avoid
292   // an annoying on-screen resize
293   mapWindow();
294 
295   // display the first page
296   z = core->getZoom();
297   if (dest) {
298     displayDest(dest, z, core->getRotate(), gTrue);
299     delete dest;
300   } else {
301     displayPage(pg, z, core->getRotate(), gTrue, gTrue);
302   }
303 
304   ok = gTrue;
305 }
306 
XPDFViewer(XPDFApp * appA,PDFDoc * doc,int pageA,GString * destName,GBool fullScreen)307 XPDFViewer::XPDFViewer(XPDFApp *appA, PDFDoc *doc, int pageA,
308 		       GString *destName, GBool fullScreen) {
309   LinkDest *dest;
310   int pg;
311   double z;
312 
313   app = appA;
314   win = NULL;
315   core = NULL;
316   ok = gFalse;
317 #ifndef DISABLE_OUTLINE
318   outlineLabels = NULL;
319   outlineLabelsLength = outlineLabelsSize = 0;
320   outlinePaneWidth = 175;
321 #endif
322 
323   // do Motif-specific initialization and create the window;
324   // this also creates the core object
325   initWindow(fullScreen);
326   initAboutDialog();
327   initFindDialog();
328   initPrintDialog();
329   openDialog = NULL;
330   saveAsDialog = NULL;
331 
332   dest = NULL; // make gcc happy
333   pg = pageA; // make gcc happy
334 
335   if (doc) {
336     core->loadDoc(doc);
337     getPageAndDest(pageA, destName, &pg, &dest);
338 #ifndef DISABLE_OUTLINE
339     if (outlineScroll != None &&
340 	core->getDoc()->getOutline()->getItems() &&
341 	core->getDoc()->getOutline()->getItems()->getLength() > 0) {
342       XtVaSetValues(outlineScroll, XmNwidth, outlinePaneWidth, NULL);
343     }
344 #endif
345   }
346   core->resizeToPage(pg);
347 
348   // map the window -- we do this after calling resizeToPage to avoid
349   // an annoying on-screen resize
350   mapWindow();
351 
352   // display the first page
353   z = core->getZoom();
354   if (dest) {
355     displayDest(dest, z, core->getRotate(), gTrue);
356     delete dest;
357   } else {
358     displayPage(pg, z, core->getRotate(), gTrue, gTrue);
359   }
360 
361   ok = gTrue;
362 }
363 
~XPDFViewer()364 XPDFViewer::~XPDFViewer() {
365   delete core;
366   if (aboutBigFont) {
367     XmFontListFree(aboutBigFont);
368   }
369   if (aboutVersionFont) {
370     XmFontListFree(aboutVersionFont);
371   }
372   if (aboutFixedFont) {
373     XmFontListFree(aboutFixedFont);
374   }
375   closeWindow();
376 #ifndef DISABLE_OUTLINE
377   if (outlineLabels) {
378     gfree(outlineLabels);
379   }
380 #endif
381 }
382 
open(GString * fileName,int pageA,GString * destName)383 void XPDFViewer::open(GString *fileName, int pageA, GString *destName) {
384   LinkDest *dest;
385   int pg;
386   double z;
387 
388   if (!core->getDoc() ||
389       !core->getDoc()->getFileName() ||
390       fileName->cmp(core->getDoc()->getFileName())) {
391     if (!loadFile(fileName, NULL, NULL)) {
392       return;
393     }
394   }
395   getPageAndDest(pageA, destName, &pg, &dest);
396   z = core->getZoom();
397   if (dest) {
398     displayDest(dest, z, core->getRotate(), gTrue);
399     delete dest;
400   } else {
401     displayPage(pg, z, core->getRotate(), gTrue, gTrue);
402   }
403 }
404 
clear()405 void XPDFViewer::clear() {
406   char *title;
407   XmString s;
408 
409   core->clear();
410 
411   // set up title
412   title = app->getTitle() ? app->getTitle()->getCString()
413                           : (char *)xpdfAppName;
414   XtVaSetValues(win, XmNtitle, title, XmNiconName, title, NULL);
415 
416   if (toolBar != None) {
417 
418     // set up number-of-pages display
419     s = XmStringCreateLocalized("");
420     XtVaSetValues(pageNumText, XmNlabelString, s, NULL);
421     XmStringFree(s);
422     s = XmStringCreateLocalized(" of 0");
423     XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL);
424     XmStringFree(s);
425 
426     // disable buttons
427     XtVaSetValues(prevTenPageBtn, XmNsensitive, False, NULL);
428     XtVaSetValues(prevPageBtn, XmNsensitive, False, NULL);
429     XtVaSetValues(nextTenPageBtn, XmNsensitive, False, NULL);
430     XtVaSetValues(nextPageBtn, XmNsensitive, False, NULL);
431   }
432 
433   // remove the old outline
434 #ifndef DISABLE_OUTLINE
435   setupOutline();
436 #endif
437 }
438 
439 //------------------------------------------------------------------------
440 // load / display
441 //------------------------------------------------------------------------
442 
loadFile(GString * fileName,GString * ownerPassword,GString * userPassword)443 GBool XPDFViewer::loadFile(GString *fileName, GString *ownerPassword,
444 			   GString *userPassword) {
445   return core->loadFile(fileName, ownerPassword, userPassword) == errNone;
446 }
447 
reloadFile()448 void XPDFViewer::reloadFile() {
449   int pg;
450 
451   if (!core->getDoc() || !core->getDoc()->getFileName()) {
452     return;
453   }
454   pg = core->getPageNum();
455   loadFile(core->getDoc()->getFileName());
456   if (pg > core->getDoc()->getNumPages()) {
457     pg = core->getDoc()->getNumPages();
458   }
459   displayPage(pg, core->getZoom(), core->getRotate(), gFalse, gFalse);
460 }
461 
displayPage(int pageA,double zoomA,int rotateA,GBool scrollToTop,GBool addToHist)462 void XPDFViewer::displayPage(int pageA, double zoomA, int rotateA,
463 			     GBool scrollToTop, GBool addToHist) {
464   core->displayPage(pageA, zoomA, rotateA, scrollToTop, addToHist);
465 }
466 
displayDest(LinkDest * dest,double zoomA,int rotateA,GBool addToHist)467 void XPDFViewer::displayDest(LinkDest *dest, double zoomA, int rotateA,
468 			     GBool addToHist) {
469   core->displayDest(dest, zoomA, rotateA, addToHist);
470 }
471 
getPageAndDest(int pageA,GString * destName,int * pageOut,LinkDest ** destOut)472 void XPDFViewer::getPageAndDest(int pageA, GString *destName,
473 				int *pageOut, LinkDest **destOut) {
474   Ref pageRef;
475 
476   // find the page number for a named destination
477   *pageOut = pageA;
478   *destOut = NULL;
479   if (destName && (*destOut = core->getDoc()->findDest(destName))) {
480     if ((*destOut)->isPageRef()) {
481       pageRef = (*destOut)->getPageRef();
482       *pageOut = core->getDoc()->findPage(pageRef.num, pageRef.gen);
483     } else {
484       *pageOut = (*destOut)->getPageNum();
485     }
486   }
487 
488   if (*pageOut <= 0) {
489     *pageOut = 1;
490   }
491   if (*pageOut > core->getDoc()->getNumPages()) {
492     *pageOut = core->getDoc()->getNumPages();
493   }
494 }
495 
496 //------------------------------------------------------------------------
497 // hyperlinks / actions
498 //------------------------------------------------------------------------
499 
doLink(int wx,int wy,GBool onlyIfNoSelection,GBool newWin)500 void XPDFViewer::doLink(int wx, int wy, GBool onlyIfNoSelection,
501 			GBool newWin) {
502   XPDFViewer *newViewer;
503   LinkAction *action;
504   int pg, selPg;
505   double xu, yu, selULX, selULY, selLRX, selLRY;
506 
507   if (core->getHyperlinksEnabled() &&
508       core->cvtWindowToUser(wx, wy, &pg, &xu, &yu) &&
509       !(onlyIfNoSelection &&
510 	core->getSelection(&selPg, &selULX, &selULY, &selLRX, &selLRY))) {
511     if ((action = core->findLink(pg, xu, yu))) {
512       if (newWin &&
513 	  core->getDoc()->getFileName() &&
514 	  (action->getKind() == actionGoTo ||
515 	   action->getKind() == actionGoToR ||
516 	   (action->getKind() == actionNamed &&
517 	    ((LinkNamed *)action)->getName()->cmp("Quit")))) {
518 	newViewer = app->open(core->getDoc()->getFileName());
519 	newViewer->core->doAction(action);
520       } else {
521 	core->doAction(action);
522       }
523     }
524   }
525 }
526 
actionCbk(void * data,char * action)527 void XPDFViewer::actionCbk(void *data, char *action) {
528   XPDFViewer *viewer = (XPDFViewer *)data;
529 
530   if (!strcmp(action, "Quit")) {
531     viewer->app->quit();
532   }
533 }
534 
535 //------------------------------------------------------------------------
536 // keyboard/mouse input
537 //------------------------------------------------------------------------
538 
keyPressCbk(void * data,KeySym key,Guint modifiers,XEvent * event)539 void XPDFViewer::keyPressCbk(void *data, KeySym key, Guint modifiers,
540 			     XEvent *event) {
541   XPDFViewer *viewer = (XPDFViewer *)data;
542   int keyCode;
543   GList *cmds;
544   int i;
545 
546   if (key >= 0x20 && key <= 0xfe) {
547     keyCode = (int)key;
548   } else if (key == XK_Tab ||
549 	     key == XK_KP_Tab) {
550     keyCode = xpdfKeyCodeTab;
551   } else if (key == XK_Return) {
552     keyCode = xpdfKeyCodeReturn;
553   } else if (key == XK_KP_Enter) {
554     keyCode = xpdfKeyCodeEnter;
555   } else if (key == XK_BackSpace) {
556     keyCode = xpdfKeyCodeBackspace;
557   } else if (key == XK_Insert ||
558 	     key == XK_KP_Insert) {
559     keyCode = xpdfKeyCodeInsert;
560   } else if (key == XK_Delete ||
561 	     key == XK_KP_Delete) {
562     keyCode = xpdfKeyCodeDelete;
563   } else if (key == XK_Home ||
564 	     key == XK_KP_Home) {
565     keyCode = xpdfKeyCodeHome;
566   } else if (key == XK_End ||
567 	     key == XK_KP_End) {
568     keyCode = xpdfKeyCodeEnd;
569   } else if (key == XK_Page_Up ||
570 	     key == XK_KP_Page_Up) {
571     keyCode = xpdfKeyCodePgUp;
572   } else if (key == XK_Page_Down ||
573 	     key == XK_KP_Page_Down) {
574     keyCode = xpdfKeyCodePgDn;
575   } else if (key == XK_Left ||
576 	     key == XK_KP_Left) {
577     keyCode = xpdfKeyCodeLeft;
578   } else if (key == XK_Right ||
579 	     key == XK_KP_Right) {
580     keyCode = xpdfKeyCodeRight;
581   } else if (key == XK_Up ||
582 	     key == XK_KP_Up) {
583     keyCode = xpdfKeyCodeUp;
584   } else if (key == XK_Down ||
585 	     key == XK_KP_Down) {
586     keyCode = xpdfKeyCodeDown;
587   } else if (key >= XK_F1 && key <= XK_F35) {
588     keyCode = xpdfKeyCodeF1 + (key - XK_F1);
589   } else {
590     return;
591   }
592 
593   if ((cmds = globalParams->getKeyBinding(keyCode,
594 					  viewer->getModifiers(modifiers),
595 					  viewer->getContext(modifiers)))) {
596     for (i = 0; i < cmds->getLength(); ++i) {
597       viewer->execCmd((GString *)cmds->get(i), event);
598     }
599     deleteGList(cmds, GString);
600   }
601 }
602 
mouseCbk(void * data,XEvent * event)603 void XPDFViewer::mouseCbk(void *data, XEvent *event) {
604   XPDFViewer *viewer = (XPDFViewer *)data;
605   int keyCode;
606   GList *cmds;
607   int i;
608 
609   if (event->type == ButtonPress) {
610     if (event->xbutton.button >= 1 && event->xbutton.button <= 32) {
611       keyCode = xpdfKeyCodeMousePress1 + event->xbutton.button - 1;
612     } else {
613       return;
614     }
615   } else if (event->type == ButtonRelease) {
616     if (event->xbutton.button >= 1 && event->xbutton.button <= 32) {
617       keyCode = xpdfKeyCodeMouseRelease1 + event->xbutton.button - 1;
618     } else {
619       return;
620     }
621   } else {
622     return;
623   }
624 
625   if ((cmds = globalParams->getKeyBinding(keyCode,
626 					  viewer->getModifiers(
627 						      event->xkey.state),
628 					  viewer->getContext(
629 						      event->xkey.state)))) {
630     for (i = 0; i < cmds->getLength(); ++i) {
631       viewer->execCmd((GString *)cmds->get(i), event);
632     }
633     deleteGList(cmds, GString);
634   }
635 }
636 
getModifiers(Guint modifiers)637 int XPDFViewer::getModifiers(Guint modifiers) {
638   int mods;
639 
640   mods = 0;
641   if (modifiers & ShiftMask) {
642     mods |= xpdfKeyModShift;
643   }
644   if (modifiers & ControlMask) {
645     mods |= xpdfKeyModCtrl;
646   }
647   if (modifiers & Mod1Mask) {
648     mods |= xpdfKeyModAlt;
649   }
650   return mods;
651 }
652 
getContext(Guint modifiers)653 int XPDFViewer::getContext(Guint modifiers) {
654   int context;
655 
656   context = (core->getFullScreen() ? xpdfKeyContextFullScreen
657                                    : xpdfKeyContextWindow) |
658             (core->getContinuousMode() ? xpdfKeyContextContinuous
659                                        : xpdfKeyContextSinglePage) |
660             (core->getLinkAction() ? xpdfKeyContextOverLink
661                                    : xpdfKeyContextOffLink) |
662             ((modifiers & Mod5Mask) ? xpdfKeyContextScrLockOn
663 	                            : xpdfKeyContextScrLockOff);
664   return context;
665 }
666 
execCmd(GString * cmd,XEvent * event)667 void XPDFViewer::execCmd(GString *cmd, XEvent *event) {
668   GString *name;
669   GString *args[cmdMaxArgs];
670   char *p0, *p1;
671   int nArgs, i;
672   int a, b, m, cmp;
673 
674   //----- parse the command
675   name = NULL;
676   nArgs = 0;
677   for (i = 0; i < cmdMaxArgs; ++i) {
678     args[i] = NULL;
679   }
680   p0 = cmd->getCString();
681   for (p1 = p0; *p1 && isalnum(*p1); ++p1) ;
682   if (p1 == p0) {
683     goto err1;
684   }
685   name = new GString(p0, p1 - p0);
686   if (*p1 == '(') {
687     while (nArgs < cmdMaxArgs) {
688       p0 = p1 + 1;
689       for (p1 = p0; *p1 && *p1 != ',' && *p1 != ')'; ++p1) ;
690       args[nArgs++] = new GString(p0, p1 - p0);
691       if (*p1 != ',') {
692 	break;
693       }
694     }
695     if (*p1 != ')') {
696       goto err1;
697     }
698     ++p1;
699   }
700   if (*p1) {
701     goto err1;
702   }
703 
704   //----- find the command
705   a = -1;
706   b = nCmds;
707   // invariant: cmdTab[a].name < name < cmdTab[b].name
708   while (b - a > 1) {
709     m = (a + b) / 2;
710     cmp = strcmp(cmdTab[m].name, name->getCString());
711     if (cmp < 0) {
712       a = m;
713     } else if (cmp > 0) {
714       b = m;
715     } else {
716       a = b = m;
717     }
718   }
719   if (cmp != 0) {
720     goto err1;
721   }
722 
723   //----- execute the command
724   if (nArgs != cmdTab[a].nArgs ||
725       (cmdTab[a].requiresEvent && !event)) {
726     goto err1;
727   }
728   if (cmdTab[a].requiresDoc && !core->getDoc()) {
729     // don't issue an error message for this -- it happens, e.g., when
730     // clicking in a window with no open PDF file
731     goto err2;
732   }
733   (this->*cmdTab[a].func)(args, nArgs, event);
734 
735   //----- clean up
736   delete name;
737   for (i = 0; i < nArgs; ++i) {
738     if (args[i]) {
739       delete args[i];
740     }
741   }
742   return;
743 
744  err1:
745   error(errConfig, -1, "Invalid command syntax: '{0:t}'", cmd);
746  err2:
747   if (name) {
748     delete name;
749   }
750   for (i = 0; i < nArgs; ++i) {
751     if (args[i]) {
752       delete args[i];
753     }
754   }
755 }
756 
757 //------------------------------------------------------------------------
758 // command functions
759 //------------------------------------------------------------------------
760 
mouseX(XEvent * event)761 static int mouseX(XEvent *event) {
762   switch (event->type) {
763   case ButtonPress:
764   case ButtonRelease:
765     return event->xbutton.x;
766   case KeyPress:
767     return event->xkey.x;
768   }
769   return 0;
770 }
771 
mouseY(XEvent * event)772 static int mouseY(XEvent *event) {
773   switch (event->type) {
774   case ButtonPress:
775   case ButtonRelease:
776     return event->xbutton.y;
777   case KeyPress:
778     return event->xkey.y;
779   }
780   return 0;
781 }
782 
cmdAbout(GString * args[],int nArgs,XEvent * event)783 void XPDFViewer::cmdAbout(GString *args[], int nArgs,
784 			  XEvent *event) {
785   XtManageChild(aboutDialog);
786 }
787 
cmdCloseOutline(GString * args[],int nArgs,XEvent * event)788 void XPDFViewer::cmdCloseOutline(GString *args[], int nArgs,
789 				 XEvent *event) {
790 #ifndef DISABLE_OUTLINE
791   Dimension w;
792 
793   if (outlineScroll == None) {
794     return;
795   }
796   XtVaGetValues(outlineScroll, XmNwidth, &w, NULL);
797   if (w > 1) {
798     outlinePaneWidth = w;
799     // this ugly kludge is apparently the only way to resize the panes
800     // within an XmPanedWindow
801     XtVaSetValues(outlineScroll, XmNpaneMinimum, 1,
802 		  XmNpaneMaximum, 1, NULL);
803     XtVaSetValues(outlineScroll, XmNpaneMinimum, 1,
804 		  XmNpaneMaximum, 10000, NULL);
805   }
806 #endif
807 }
808 
cmdCloseWindow(GString * args[],int nArgs,XEvent * event)809 void XPDFViewer::cmdCloseWindow(GString *args[], int nArgs,
810 				XEvent *event) {
811   app->close(this, gFalse);
812 }
813 
cmdCloseWindowOrQuit(GString * args[],int nArgs,XEvent * event)814 void XPDFViewer::cmdCloseWindowOrQuit(GString *args[], int nArgs,
815 				      XEvent *event) {
816   app->close(this, gTrue);
817 }
818 
cmdContinuousMode(GString * args[],int nArgs,XEvent * event)819 void XPDFViewer::cmdContinuousMode(GString *args[], int nArgs,
820 				   XEvent *event) {
821   Widget btn;
822 
823   if (core->getContinuousMode()) {
824     return;
825   }
826   core->setContinuousMode(gTrue);
827 
828   btn = XtNameToWidget(popupMenu, "continuousMode");
829   XtVaSetValues(btn, XmNset, XmSET, NULL);
830 }
831 
cmdEndPan(GString * args[],int nArgs,XEvent * event)832 void XPDFViewer::cmdEndPan(GString *args[], int nArgs,
833 			   XEvent *event) {
834   core->endPan(mouseX(event), mouseY(event));
835 }
836 
cmdEndSelection(GString * args[],int nArgs,XEvent * event)837 void XPDFViewer::cmdEndSelection(GString *args[], int nArgs,
838 				 XEvent *event) {
839   core->endSelection(mouseX(event), mouseY(event));
840 }
841 
cmdFind(GString * args[],int nArgs,XEvent * event)842 void XPDFViewer::cmdFind(GString *args[], int nArgs,
843 			 XEvent *event) {
844   mapFindDialog();
845 }
846 
cmdFindNext(GString * args[],int nArgs,XEvent * event)847 void XPDFViewer::cmdFindNext(GString *args[], int nArgs,
848 			     XEvent *event) {
849   doFind(gTrue);
850 }
851 
cmdFocusToDocWin(GString * args[],int nArgs,XEvent * event)852 void XPDFViewer::cmdFocusToDocWin(GString *args[], int nArgs,
853 				  XEvent *event) {
854   core->takeFocus();
855 }
856 
cmdFocusToPageNum(GString * args[],int nArgs,XEvent * event)857 void XPDFViewer::cmdFocusToPageNum(GString *args[], int nArgs,
858 				   XEvent *event) {
859   if (toolBar != None) {
860     XmTextFieldSetSelection(pageNumText, 0,
861 			    strlen(XmTextFieldGetString(pageNumText)),
862 			    XtLastTimestampProcessed(display));
863     XmProcessTraversal(pageNumText, XmTRAVERSE_CURRENT);
864   }
865 }
866 
cmdFollowLink(GString * args[],int nArgs,XEvent * event)867 void XPDFViewer::cmdFollowLink(GString *args[], int nArgs,
868 			       XEvent *event) {
869   doLink(mouseX(event), mouseY(event), gFalse, gFalse);
870 }
871 
cmdFollowLinkInNewWin(GString * args[],int nArgs,XEvent * event)872 void XPDFViewer::cmdFollowLinkInNewWin(GString *args[], int nArgs,
873 				       XEvent *event) {
874   doLink(mouseX(event), mouseY(event), gFalse, gTrue);
875 }
876 
cmdFollowLinkInNewWinNoSel(GString * args[],int nArgs,XEvent * event)877 void XPDFViewer::cmdFollowLinkInNewWinNoSel(GString *args[], int nArgs,
878 					    XEvent *event) {
879   doLink(mouseX(event), mouseY(event), gTrue, gTrue);
880 }
881 
cmdFollowLinkNoSel(GString * args[],int nArgs,XEvent * event)882 void XPDFViewer::cmdFollowLinkNoSel(GString *args[], int nArgs,
883 				    XEvent *event) {
884   doLink(mouseX(event), mouseY(event), gTrue, gFalse);
885 }
886 
cmdFullScreenMode(GString * args[],int nArgs,XEvent * event)887 void XPDFViewer::cmdFullScreenMode(GString *args[], int nArgs,
888 				   XEvent *event) {
889   PDFDoc *doc;
890   XPDFViewer *viewer;
891   int pg;
892   Widget btn;
893 
894   if (core->getFullScreen()) {
895     return;
896   }
897   pg = core->getPageNum();
898   XtPopdown(win);
899   doc = core->takeDoc(gFalse);
900   viewer = app->reopen(this, doc, pg, gTrue);
901 
902   btn = XtNameToWidget(viewer->popupMenu, "fullScreen");
903   XtVaSetValues(btn, XmNset, XmSET, NULL);
904 }
905 
cmdGoBackward(GString * args[],int nArgs,XEvent * event)906 void XPDFViewer::cmdGoBackward(GString *args[], int nArgs,
907 			       XEvent *event) {
908   core->goBackward();
909 }
910 
cmdGoForward(GString * args[],int nArgs,XEvent * event)911 void XPDFViewer::cmdGoForward(GString *args[], int nArgs,
912 			      XEvent *event) {
913   core->goForward();
914 }
915 
cmdGotoDest(GString * args[],int nArgs,XEvent * event)916 void XPDFViewer::cmdGotoDest(GString *args[], int nArgs,
917 			     XEvent *event) {
918   int pg;
919   LinkDest *dest;
920 
921   getPageAndDest(1, args[0], &pg, &dest);
922   if (dest) {
923     displayDest(dest, core->getZoom(), core->getRotate(), gTrue);
924     delete dest;
925   }
926 }
927 
cmdGotoLastPage(GString * args[],int nArgs,XEvent * event)928 void XPDFViewer::cmdGotoLastPage(GString *args[], int nArgs,
929 				 XEvent *event) {
930   displayPage(core->getDoc()->getNumPages(),
931 	      core->getZoom(), core->getRotate(),
932 	      gTrue, gTrue);
933 }
934 
cmdGotoLastPageNoScroll(GString * args[],int nArgs,XEvent * event)935 void XPDFViewer::cmdGotoLastPageNoScroll(GString *args[], int nArgs,
936 					 XEvent *event) {
937   displayPage(core->getDoc()->getNumPages(),
938 	      core->getZoom(), core->getRotate(),
939 	      gFalse, gTrue);
940 }
941 
cmdGotoPage(GString * args[],int nArgs,XEvent * event)942 void XPDFViewer::cmdGotoPage(GString *args[], int nArgs,
943 			     XEvent *event) {
944   int pg;
945 
946   pg = atoi(args[0]->getCString());
947   if (pg < 1 || pg > core->getDoc()->getNumPages()) {
948     return;
949   }
950   displayPage(pg, core->getZoom(), core->getRotate(), gTrue, gTrue);
951 }
952 
cmdGotoPageNoScroll(GString * args[],int nArgs,XEvent * event)953 void XPDFViewer::cmdGotoPageNoScroll(GString *args[], int nArgs,
954 				     XEvent *event) {
955   int pg;
956 
957   pg = atoi(args[0]->getCString());
958   if (pg < 1 || pg > core->getDoc()->getNumPages()) {
959     return;
960   }
961   displayPage(pg, core->getZoom(), core->getRotate(), gFalse, gTrue);
962 }
963 
cmdNextPage(GString * args[],int nArgs,XEvent * event)964 void XPDFViewer::cmdNextPage(GString *args[], int nArgs,
965 			     XEvent *event) {
966   core->gotoNextPage(1, gTrue);
967 }
968 
cmdNextPageNoScroll(GString * args[],int nArgs,XEvent * event)969 void XPDFViewer::cmdNextPageNoScroll(GString *args[], int nArgs,
970 				     XEvent *event) {
971   core->gotoNextPage(1, gFalse);
972 }
973 
cmdOpen(GString * args[],int nArgs,XEvent * event)974 void XPDFViewer::cmdOpen(GString *args[], int nArgs,
975 			 XEvent *event) {
976   mapOpenDialog(gFalse);
977 }
978 
cmdOpenFile(GString * args[],int nArgs,XEvent * event)979 void XPDFViewer::cmdOpenFile(GString *args[], int nArgs,
980 			     XEvent *event) {
981   open(args[0], 1, NULL);
982 }
983 
cmdOpenFileAtDest(GString * args[],int nArgs,XEvent * event)984 void XPDFViewer::cmdOpenFileAtDest(GString *args[], int nArgs,
985 				   XEvent *event) {
986   open(args[0], 1, args[1]);
987 }
988 
cmdOpenFileAtDestInNewWin(GString * args[],int nArgs,XEvent * event)989 void XPDFViewer::cmdOpenFileAtDestInNewWin(GString *args[], int nArgs,
990 					   XEvent *event) {
991   app->openAtDest(args[0], args[1]);
992 }
993 
cmdOpenFileAtPage(GString * args[],int nArgs,XEvent * event)994 void XPDFViewer::cmdOpenFileAtPage(GString *args[], int nArgs,
995 				   XEvent *event) {
996   open(args[0], atoi(args[1]->getCString()), NULL);
997 }
998 
cmdOpenFileAtPageInNewWin(GString * args[],int nArgs,XEvent * event)999 void XPDFViewer::cmdOpenFileAtPageInNewWin(GString *args[], int nArgs,
1000 					   XEvent *event) {
1001   app->open(args[0], atoi(args[1]->getCString()));
1002 }
1003 
cmdOpenFileInNewWin(GString * args[],int nArgs,XEvent * event)1004 void XPDFViewer::cmdOpenFileInNewWin(GString *args[], int nArgs,
1005 				     XEvent *event) {
1006   app->open(args[0]);
1007 }
1008 
cmdOpenInNewWin(GString * args[],int nArgs,XEvent * event)1009 void XPDFViewer::cmdOpenInNewWin(GString *args[], int nArgs,
1010 				 XEvent *event) {
1011   mapOpenDialog(gTrue);
1012 }
1013 
cmdOpenOutline(GString * args[],int nArgs,XEvent * event)1014 void XPDFViewer::cmdOpenOutline(GString *args[], int nArgs,
1015 				XEvent *event) {
1016 #ifndef DISABLE_OUTLINE
1017   Dimension w;
1018 
1019   if (outlineScroll == None) {
1020     return;
1021   }
1022   XtVaGetValues(outlineScroll, XmNwidth, &w, NULL);
1023   if (w == 1) {
1024     // this ugly kludge is apparently the only way to resize the panes
1025     // within an XmPanedWindow
1026     XtVaSetValues(outlineScroll, XmNpaneMinimum, outlinePaneWidth,
1027 		  XmNpaneMaximum, outlinePaneWidth, NULL);
1028     XtVaSetValues(outlineScroll, XmNpaneMinimum, 1,
1029 		  XmNpaneMaximum, 10000, NULL);
1030   }
1031 #endif
1032 }
1033 
cmdPageDown(GString * args[],int nArgs,XEvent * event)1034 void XPDFViewer::cmdPageDown(GString *args[], int nArgs,
1035 			     XEvent *event) {
1036   core->scrollPageDown();
1037 }
1038 
cmdPageUp(GString * args[],int nArgs,XEvent * event)1039 void XPDFViewer::cmdPageUp(GString *args[], int nArgs,
1040 			   XEvent *event) {
1041   core->scrollPageUp();
1042 }
1043 
cmdPostPopupMenu(GString * args[],int nArgs,XEvent * event)1044 void XPDFViewer::cmdPostPopupMenu(GString *args[], int nArgs,
1045 				  XEvent *event) {
1046   XmMenuPosition(popupMenu, event->type == ButtonPress ? &event->xbutton
1047 		                                       : (XButtonEvent *)NULL);
1048   XtManageChild(popupMenu);
1049 
1050   // this is magic (taken from DDD) - weird things happen if this
1051   // call isn't made (this is done in two different places, in hopes
1052   // of squashing this stupid bug)
1053   XtUngrabButton(core->getDrawAreaWidget(), AnyButton, AnyModifier);
1054 }
1055 
cmdPrevPage(GString * args[],int nArgs,XEvent * event)1056 void XPDFViewer::cmdPrevPage(GString *args[], int nArgs,
1057 			     XEvent *event) {
1058   core->gotoPrevPage(1, gTrue, gFalse);
1059 }
1060 
cmdPrevPageNoScroll(GString * args[],int nArgs,XEvent * event)1061 void XPDFViewer::cmdPrevPageNoScroll(GString *args[], int nArgs,
1062 				     XEvent *event) {
1063   core->gotoPrevPage(1, gFalse, gFalse);
1064 }
1065 
cmdPrint(GString * args[],int nArgs,XEvent * event)1066 void XPDFViewer::cmdPrint(GString *args[], int nArgs,
1067 			  XEvent *event) {
1068   XtManageChild(printDialog);
1069 }
1070 
cmdQuit(GString * args[],int nArgs,XEvent * event)1071 void XPDFViewer::cmdQuit(GString *args[], int nArgs,
1072 			 XEvent *event) {
1073   app->quit();
1074 }
1075 
cmdRaise(GString * args[],int nArgs,XEvent * event)1076 void XPDFViewer::cmdRaise(GString *args[], int nArgs,
1077 			  XEvent *event) {
1078   XMapRaised(display, XtWindow(win));
1079   XFlush(display);
1080 }
1081 
cmdRedraw(GString * args[],int nArgs,XEvent * event)1082 void XPDFViewer::cmdRedraw(GString *args[], int nArgs,
1083 			   XEvent *event) {
1084   displayPage(core->getPageNum(), core->getZoom(), core->getRotate(),
1085 	      gFalse, gFalse);
1086 }
1087 
cmdReload(GString * args[],int nArgs,XEvent * event)1088 void XPDFViewer::cmdReload(GString *args[], int nArgs,
1089 			   XEvent *event) {
1090   reloadFile();
1091 }
1092 
cmdRotateCCW(GString * args[],int nArgs,XEvent * event)1093 void XPDFViewer::cmdRotateCCW(GString *args[], int nArgs,
1094 			     XEvent *event) {
1095   int r;
1096 
1097   r = core->getRotate();
1098   r = (r == 0) ? 270 : r - 90;
1099   displayPage(core->getPageNum(), core->getZoom(), r, gTrue, gFalse);
1100 }
1101 
cmdRotateCW(GString * args[],int nArgs,XEvent * event)1102 void XPDFViewer::cmdRotateCW(GString *args[], int nArgs,
1103 			     XEvent *event) {
1104   int r;
1105 
1106   r = core->getRotate();
1107   r = (r == 270) ? 0 : r + 90;
1108   displayPage(core->getPageNum(), core->getZoom(), r, gTrue, gFalse);
1109 }
1110 
cmdRun(GString * args[],int nArgs,XEvent * event)1111 void XPDFViewer::cmdRun(GString *args[], int nArgs,
1112 			XEvent *event) {
1113   GString *fmt, *cmd, *s;
1114   LinkAction *action;
1115   double selLRX, selLRY, selURX, selURY, mouseX, mouseY;
1116   int selPage, mousePage;
1117   GBool gotSel, gotMouse;
1118   char buf[64];
1119   char *p;
1120   char c0, c1;
1121   int i;
1122 
1123   cmd = new GString();
1124   fmt = args[0];
1125   i = 0;
1126   gotSel = gotMouse = gFalse;
1127   while (i < fmt->getLength()) {
1128     c0 = fmt->getChar(i);
1129     if (c0 == '%' && i+1 < fmt->getLength()) {
1130       c1 = fmt->getChar(i+1);
1131       switch (c1) {
1132       case 'f':
1133 	if (core->getDoc() && (s = core->getDoc()->getFileName())) {
1134 	  cmd->append(s);
1135 	}
1136 	break;
1137       case 'b':
1138 	if (core->getDoc() && (s = core->getDoc()->getFileName())) {
1139 	  if ((p = strrchr(s->getCString(), '.'))) {
1140 	    cmd->append(s->getCString(), p - s->getCString());
1141 	  } else {
1142 	    cmd->append(s);
1143 	  }
1144 	}
1145 	break;
1146       case 'u':
1147 	if ((action = core->getLinkAction()) &&
1148 	    action->getKind() == actionURI) {
1149 	  s = core->mungeURL(((LinkURI *)action)->getURI());
1150 	  cmd->append(s);
1151 	  delete s;
1152 	}
1153 	break;
1154       case 'p':
1155 	if (core->getDoc()) {
1156 	  sprintf(buf, "%d", core->getPageNum());
1157 	  cmd->append(buf);
1158 	}
1159 	break;
1160       case 'x':
1161       case 'y':
1162       case 'X':
1163       case 'Y':
1164 	if (!gotSel) {
1165 	  if (!core->getSelection(&selPage, &selURX, &selURY,
1166 				  &selLRX, &selLRY)) {
1167 	    selPage = 0;
1168 	    selURX = selURY = selLRX = selLRY = 0;
1169 	  }
1170 	  gotSel = gTrue;
1171 	}
1172 	sprintf(buf, "%g",
1173 		(c1 == 'x') ? selURX :
1174 		(c1 == 'y') ? selURY :
1175 		(c1 == 'X') ? selLRX : selLRY);
1176 	cmd->append(buf);
1177 	break;
1178       case 'i':
1179       case 'j':
1180       case 'k':
1181 	if (!gotMouse) {
1182 	  if (event->type == ButtonPress || event->type == ButtonRelease) {
1183 	    core->cvtWindowToUser(event->xbutton.x, event->xbutton.y,
1184 				  &mousePage, &mouseX, &mouseY);
1185 	  } else if (event->type == KeyPress) {
1186 	    core->cvtWindowToUser(event->xkey.x, event->xkey.y,
1187 				  &mousePage, &mouseX, &mouseY);
1188 	  } else {
1189 	    mousePage = 0;
1190 	    mouseX = mouseY = 0;
1191 	  }
1192 	  gotMouse = gTrue;
1193 	}
1194 	if (c1 == 'i') {
1195 	  sprintf(buf, "%d", mousePage);
1196 	} else {
1197 	  sprintf(buf, "%g", (c1 == 'j') ? mouseX : mouseY);
1198 	}
1199 	cmd->append(buf);
1200 	break;
1201       default:
1202 	cmd->append(c1);
1203 	break;
1204       }
1205       i += 2;
1206     } else {
1207       cmd->append(c0);
1208       ++i;
1209     }
1210   }
1211 #ifdef VMS
1212   cmd->insert(0, "spawn/nowait ");
1213 #elif defined(__EMX__)
1214   cmd->insert(0, "start /min /n ");
1215 #else
1216   cmd->append(" &");
1217 #endif
1218   system(cmd->getCString());
1219   delete cmd;
1220 }
1221 
cmdScrollDown(GString * args[],int nArgs,XEvent * event)1222 void XPDFViewer::cmdScrollDown(GString *args[], int nArgs,
1223 			       XEvent *event) {
1224   core->scrollDown(atoi(args[0]->getCString()));
1225 }
1226 
cmdScrollDownNextPage(GString * args[],int nArgs,XEvent * event)1227 void XPDFViewer::cmdScrollDownNextPage(GString *args[], int nArgs,
1228 				       XEvent *event) {
1229   core->scrollDownNextPage(atoi(args[0]->getCString()));
1230 }
1231 
cmdScrollLeft(GString * args[],int nArgs,XEvent * event)1232 void XPDFViewer::cmdScrollLeft(GString *args[], int nArgs,
1233 			       XEvent *event) {
1234   core->scrollLeft(atoi(args[0]->getCString()));
1235 }
1236 
cmdScrollOutlineDown(GString * args[],int nArgs,XEvent * event)1237 void XPDFViewer::cmdScrollOutlineDown(GString *args[], int nArgs,
1238 				      XEvent *event) {
1239 #ifndef DISABLE_OUTLINE
1240   Widget sb;
1241   int val, inc, pageInc, m, slider;
1242 
1243   if (outlineScroll == None) {
1244     return;
1245   }
1246   if ((sb = XtNameToWidget(outlineScroll, "VertScrollBar"))) {
1247     XtVaGetValues(sb, XmNvalue, &val, XmNincrement, &inc,
1248 		  XmNpageIncrement, &pageInc, XmNmaximum, &m,
1249 		  XmNsliderSize, &slider, NULL);
1250     if ((val += inc * atoi(args[0]->getCString())) > m - slider) {
1251       val = m - slider;
1252     }
1253     XmScrollBarSetValues(sb, val, slider, inc, pageInc, True);
1254   }
1255 #endif
1256 }
1257 
cmdScrollOutlineUp(GString * args[],int nArgs,XEvent * event)1258 void XPDFViewer::cmdScrollOutlineUp(GString *args[], int nArgs,
1259 				    XEvent *event) {
1260 #ifndef DISABLE_OUTLINE
1261   Widget sb;
1262   int val, inc, pageInc, m, slider;
1263 
1264   if (outlineScroll == None) {
1265     return;
1266   }
1267   if ((sb = XtNameToWidget(outlineScroll, "VertScrollBar"))) {
1268     XtVaGetValues(sb, XmNvalue, &val, XmNincrement, &inc,
1269 		  XmNpageIncrement, &pageInc, XmNminimum, &m,
1270 		  XmNsliderSize, &slider, NULL);
1271     if ((val -= inc * atoi(args[0]->getCString())) < m) {
1272       val = m;
1273     }
1274     XmScrollBarSetValues(sb, val, slider, inc, pageInc, True);
1275   }
1276 #endif
1277 }
1278 
cmdScrollRight(GString * args[],int nArgs,XEvent * event)1279 void XPDFViewer::cmdScrollRight(GString *args[], int nArgs,
1280 				XEvent *event) {
1281   core->scrollRight(atoi(args[0]->getCString()));
1282 }
1283 
cmdScrollToBottomEdge(GString * args[],int nArgs,XEvent * event)1284 void XPDFViewer::cmdScrollToBottomEdge(GString *args[], int nArgs,
1285 				       XEvent *event) {
1286   core->scrollToBottomEdge();
1287 }
1288 
cmdScrollToBottomRight(GString * args[],int nArgs,XEvent * event)1289 void XPDFViewer::cmdScrollToBottomRight(GString *args[], int nArgs,
1290 					XEvent *event) {
1291   core->scrollToBottomRight();
1292 }
1293 
cmdScrollToLeftEdge(GString * args[],int nArgs,XEvent * event)1294 void XPDFViewer::cmdScrollToLeftEdge(GString *args[], int nArgs,
1295 				     XEvent *event) {
1296   core->scrollToLeftEdge();
1297 }
1298 
cmdScrollToRightEdge(GString * args[],int nArgs,XEvent * event)1299 void XPDFViewer::cmdScrollToRightEdge(GString *args[], int nArgs,
1300 				      XEvent *event) {
1301   core->scrollToRightEdge();
1302 }
1303 
cmdScrollToTopEdge(GString * args[],int nArgs,XEvent * event)1304 void XPDFViewer::cmdScrollToTopEdge(GString *args[], int nArgs,
1305 				    XEvent *event) {
1306   core->scrollToTopEdge();
1307 }
1308 
cmdScrollToTopLeft(GString * args[],int nArgs,XEvent * event)1309 void XPDFViewer::cmdScrollToTopLeft(GString *args[], int nArgs,
1310 				    XEvent *event) {
1311   core->scrollToTopLeft();
1312 }
1313 
cmdScrollUp(GString * args[],int nArgs,XEvent * event)1314 void XPDFViewer::cmdScrollUp(GString *args[], int nArgs,
1315 			     XEvent *event) {
1316   core->scrollUp(atoi(args[0]->getCString()));
1317 }
1318 
cmdScrollUpPrevPage(GString * args[],int nArgs,XEvent * event)1319 void XPDFViewer::cmdScrollUpPrevPage(GString *args[], int nArgs,
1320 				     XEvent *event) {
1321   core->scrollUpPrevPage(atoi(args[0]->getCString()));
1322 }
1323 
cmdSetSelection(GString * args[],int nArgs,XEvent * event)1324 void XPDFViewer::cmdSetSelection(GString *args[], int nArgs, XEvent *event) {
1325   int pg, ulx, uly, lrx, lry;
1326 
1327   pg = atoi(args[0]->getCString());
1328   core->cvtUserToDev(core->getPageNum(),
1329 		     atof(args[1]->getCString()), atof(args[2]->getCString()),
1330 		     &ulx, &uly);
1331   core->cvtUserToDev(core->getPageNum(),
1332 		     atof(args[3]->getCString()), atof(args[4]->getCString()),
1333 		     &lrx, &lry);
1334   core->setSelection(pg, ulx, uly, lrx, lry);
1335 }
1336 
cmdSinglePageMode(GString * args[],int nArgs,XEvent * event)1337 void XPDFViewer::cmdSinglePageMode(GString *args[], int nArgs,
1338 				   XEvent *event) {
1339   Widget btn;
1340 
1341   if (!core->getContinuousMode()) {
1342     return;
1343   }
1344   core->setContinuousMode(gFalse);
1345 
1346   btn = XtNameToWidget(popupMenu, "continuousMode");
1347   XtVaSetValues(btn, XmNset, XmUNSET, NULL);
1348 }
1349 
cmdStartPan(GString * args[],int nArgs,XEvent * event)1350 void XPDFViewer::cmdStartPan(GString *args[], int nArgs,
1351 			     XEvent *event) {
1352   core->startPan(mouseX(event), mouseY(event));
1353 }
1354 
cmdStartSelection(GString * args[],int nArgs,XEvent * event)1355 void XPDFViewer::cmdStartSelection(GString *args[], int nArgs,
1356 				   XEvent *event) {
1357   core->startSelection(mouseX(event), mouseY(event));
1358 }
1359 
cmdToggleContinuousMode(GString * args[],int nArgs,XEvent * event)1360 void XPDFViewer::cmdToggleContinuousMode(GString *args[], int nArgs,
1361 					 XEvent *event) {
1362   if (core->getContinuousMode()) {
1363     cmdSinglePageMode(NULL, 0, event);
1364   } else {
1365     cmdContinuousMode(NULL, 0, event);
1366   }
1367 }
1368 
cmdToggleFullScreenMode(GString * args[],int nArgs,XEvent * event)1369 void XPDFViewer::cmdToggleFullScreenMode(GString *args[], int nArgs,
1370 					 XEvent *event) {
1371   if (core->getFullScreen()) {
1372     cmdWindowMode(NULL, 0, event);
1373   } else {
1374     cmdFullScreenMode(NULL, 0, event);
1375   }
1376 }
1377 
cmdToggleOutline(GString * args[],int nArgs,XEvent * event)1378 void XPDFViewer::cmdToggleOutline(GString *args[], int nArgs,
1379 				  XEvent *event) {
1380 #ifndef DISABLE_OUTLINE
1381   Dimension w;
1382 
1383   if (outlineScroll == None) {
1384     return;
1385   }
1386   XtVaGetValues(outlineScroll, XmNwidth, &w, NULL);
1387   if (w > 1) {
1388     cmdCloseOutline(NULL, 0, event);
1389   } else {
1390     cmdOpenOutline(NULL, 0, event);
1391   }
1392 #endif
1393 }
1394 
cmdWindowMode(GString * args[],int nArgs,XEvent * event)1395 void XPDFViewer::cmdWindowMode(GString *args[], int nArgs,
1396 			       XEvent *event) {
1397   PDFDoc *doc;
1398   XPDFViewer *viewer;
1399   int pg;
1400   Widget btn;
1401 
1402   if (!core->getFullScreen()) {
1403     return;
1404   }
1405   pg = core->getPageNum();
1406   XtPopdown(win);
1407   doc = core->takeDoc(gFalse);
1408   viewer = app->reopen(this, doc, pg, gFalse);
1409 
1410   btn = XtNameToWidget(viewer->popupMenu, "fullScreen");
1411   XtVaSetValues(btn, XmNset, XmUNSET, NULL);
1412 }
1413 
cmdZoomFitPage(GString * args[],int nArgs,XEvent * event)1414 void XPDFViewer::cmdZoomFitPage(GString *args[], int nArgs,
1415 				XEvent *event) {
1416   if (core->getZoom() != zoomPage) {
1417     setZoomIdx(zoomPageIdx);
1418     displayPage(core->getPageNum(), zoomPage,
1419 		core->getRotate(), gTrue, gFalse);
1420   }
1421 }
1422 
cmdZoomFitWidth(GString * args[],int nArgs,XEvent * event)1423 void XPDFViewer::cmdZoomFitWidth(GString *args[], int nArgs,
1424 				 XEvent *event) {
1425   if (core->getZoom() != zoomWidth) {
1426     setZoomIdx(zoomWidthIdx);
1427     displayPage(core->getPageNum(), zoomWidth,
1428 		core->getRotate(), gTrue, gFalse);
1429   }
1430 }
1431 
cmdZoomIn(GString * args[],int nArgs,XEvent * event)1432 void XPDFViewer::cmdZoomIn(GString *args[], int nArgs,
1433 			   XEvent *event) {
1434   int z;
1435 
1436   z = getZoomIdx();
1437   if (z <= minZoomIdx && z > maxZoomIdx) {
1438     --z;
1439     setZoomIdx(z);
1440     displayPage(core->getPageNum(), zoomMenuInfo[z].zoom,
1441 		core->getRotate(), gTrue, gFalse);
1442   }
1443 }
1444 
cmdZoomOut(GString * args[],int nArgs,XEvent * event)1445 void XPDFViewer::cmdZoomOut(GString *args[], int nArgs,
1446 			    XEvent *event) {
1447   int z;
1448 
1449   z = getZoomIdx();
1450   if (z < minZoomIdx && z >= maxZoomIdx) {
1451     ++z;
1452     setZoomIdx(z);
1453     displayPage(core->getPageNum(), zoomMenuInfo[z].zoom,
1454 		core->getRotate(), gTrue, gFalse);
1455   }
1456 }
1457 
cmdZoomPercent(GString * args[],int nArgs,XEvent * event)1458 void XPDFViewer::cmdZoomPercent(GString *args[], int nArgs,
1459 				XEvent *event) {
1460   double z;
1461 
1462   z = atof(args[0]->getCString());
1463   setZoomVal(z);
1464   displayPage(core->getPageNum(), z, core->getRotate(), gTrue, gFalse);
1465 }
1466 
cmdZoomToSelection(GString * args[],int nArgs,XEvent * event)1467 void XPDFViewer::cmdZoomToSelection(GString *args[], int nArgs,
1468 				    XEvent *event) {
1469   int pg;
1470   double ulx, uly, lrx, lry;
1471 
1472   if (core->getSelection(&pg, &ulx, &uly, &lrx, &lry)) {
1473     core->zoomToRect(pg, ulx, uly, lrx, lry);
1474   }
1475 }
1476 
1477 //------------------------------------------------------------------------
1478 // GUI code: main window
1479 //------------------------------------------------------------------------
1480 
initWindow(GBool fullScreen)1481 void XPDFViewer::initWindow(GBool fullScreen) {
1482   Colormap colormap;
1483   XColor xcol;
1484   Atom state, val;
1485   Arg args[20];
1486   int n;
1487   char *title;
1488 
1489   display = XtDisplay(app->getAppShell());
1490   screenNum = XScreenNumberOfScreen(XtScreen(app->getAppShell()));
1491 
1492   toolBar = None;
1493 #ifndef DISABLE_OUTLINE
1494   outlineScroll = None;
1495 #endif
1496 
1497   // private colormap
1498   if (app->getInstallCmap()) {
1499     XtVaGetValues(app->getAppShell(), XmNcolormap, &colormap, NULL);
1500     // ensure that BlackPixel and WhitePixel are reserved in the
1501     // new colormap
1502     xcol.red = xcol.green = xcol.blue = 0;
1503     XAllocColor(display, colormap, &xcol);
1504     xcol.red = xcol.green = xcol.blue = 65535;
1505     XAllocColor(display, colormap, &xcol);
1506     colormap = XCopyColormapAndFree(display, colormap);
1507   }
1508 
1509   // top-level window
1510   n = 0;
1511   title = app->getTitle() ? app->getTitle()->getCString()
1512                           : (char *)xpdfAppName;
1513   XtSetArg(args[n], XmNtitle, title); ++n;
1514   XtSetArg(args[n], XmNiconName, title); ++n;
1515   XtSetArg(args[n], XmNminWidth, 100); ++n;
1516   XtSetArg(args[n], XmNminHeight, 100); ++n;
1517   XtSetArg(args[n], XmNbaseWidth, 0); ++n;
1518   XtSetArg(args[n], XmNbaseHeight, 0); ++n;
1519   XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); ++n;
1520   win = XtCreatePopupShell("win", topLevelShellWidgetClass,
1521 			   app->getAppShell(), args, n);
1522   if (app->getInstallCmap()) {
1523     XtVaSetValues(win, XmNcolormap, colormap, NULL);
1524   }
1525   XmAddWMProtocolCallback(win, XInternAtom(display, "WM_DELETE_WINDOW", False),
1526 			  &closeMsgCbk, this);
1527 
1528   // create the full-screen window
1529   if (fullScreen) {
1530     initCore(win, gTrue);
1531 
1532   // create the normal (non-full-screen) window
1533   } else {
1534     if (app->getGeometry()) {
1535       n = 0;
1536       XtSetArg(args[n], XmNgeometry, app->getGeometry()->getCString()); ++n;
1537       XtSetValues(win, args, n);
1538     }
1539 
1540     n = 0;
1541     form = XmCreateForm(win, "form", args, n);
1542     XtManageChild(form);
1543 
1544 #ifdef DISABLE_OUTLINE
1545     initToolbar(form);
1546     n = 0;
1547     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1548     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1549     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1550     XtSetValues(toolBar, args, n);
1551 
1552     initCore(form, gFalse);
1553     n = 0;
1554     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1555     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
1556     XtSetArg(args[n], XmNbottomWidget, toolBar); ++n;
1557     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1558     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1559     XtSetValues(core->getWidget(), args, n);
1560 #else
1561     initToolbar(form);
1562     n = 0;
1563     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1564     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1565     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1566     XtSetValues(toolBar, args, n);
1567 
1568     initPanedWin(form);
1569     n = 0;
1570     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1571     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
1572     XtSetArg(args[n], XmNbottomWidget, toolBar); ++n;
1573     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1574     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1575     XtSetValues(panedWin, args, n);
1576 
1577     initCore(panedWin, fullScreen);
1578     n = 0;
1579     XtSetArg(args[n], XmNpositionIndex, 1); ++n;
1580     XtSetArg(args[n], XmNallowResize, True); ++n;
1581     XtSetArg(args[n], XmNpaneMinimum, 1); ++n;
1582     XtSetArg(args[n], XmNpaneMaximum, 10000); ++n;
1583     XtSetValues(core->getWidget(), args, n);
1584 #endif
1585   }
1586 
1587   // set the zoom menu to match the initial zoom setting
1588   setZoomVal(core->getZoom());
1589 
1590   // set traversal order
1591   XtVaSetValues(core->getDrawAreaWidget(),
1592 		XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
1593   if (toolBar != None) {
1594     XtVaSetValues(backBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1595 		  NULL);
1596     XtVaSetValues(prevTenPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1597 		  NULL);
1598     XtVaSetValues(prevPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1599 		  NULL);
1600     XtVaSetValues(nextPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1601 		  NULL);
1602     XtVaSetValues(nextTenPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1603 		  NULL);
1604     XtVaSetValues(forwardBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1605 		  NULL);
1606     XtVaSetValues(pageNumText, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1607 		  NULL);
1608     XtVaSetValues(zoomWidget, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1609 		  NULL);
1610     XtVaSetValues(findBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1611 		  NULL);
1612     XtVaSetValues(printBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1613 		  NULL);
1614     XtVaSetValues(aboutBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1615 		  NULL);
1616     XtVaSetValues(quitBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP,
1617 		  NULL);
1618   }
1619 
1620   initPopupMenu();
1621 
1622   if (fullScreen) {
1623     // Set both the old-style Motif decorations hint and the new-style
1624     // _NET_WM_STATE property.  This is redundant, but might be useful
1625     // for older window managers.  We also set the geometry to +0+0 to
1626     // avoid interactive placement.  (Note: we need to realize the
1627     // shell, so it has a Window on which to set the _NET_WM_STATE
1628     // property, but we don't want to map it until later, so we set
1629     // mappedWhenManaged to false.)
1630     n = 0;
1631     XtSetArg(args[n], XmNmappedWhenManaged, False); ++n;
1632     XtSetArg(args[n], XmNmwmDecorations, 0); ++n;
1633     XtSetArg(args[n], XmNgeometry, "+0+0"); ++n;
1634     XtSetValues(win, args, n);
1635     XtRealizeWidget(win);
1636     state = XInternAtom(display, "_NET_WM_STATE", False);
1637     val = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", False);
1638     XChangeProperty(display, XtWindow(win), state, XA_ATOM, 32,
1639 		    PropModeReplace, (Guchar *)&val, 1);
1640   }
1641 }
1642 
initToolbar(Widget parent)1643 void XPDFViewer::initToolbar(Widget parent) {
1644   Widget label, lastBtn;
1645 #ifndef USE_COMBO_BOX
1646   Widget btn;
1647 #endif
1648   Arg args[20];
1649   int n;
1650   XmString s, emptyString;
1651   int i;
1652 
1653   // toolbar
1654   n = 0;
1655   toolBar = XmCreateForm(parent, "toolBar", args, n);
1656   XtManageChild(toolBar);
1657 
1658   // create an empty string -- this is used for buttons that will get
1659   // pixmaps later
1660   emptyString = XmStringCreateLocalized("");
1661 
1662   // page movement buttons
1663   n = 0;
1664   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
1665   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1666   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1667   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1668   XtSetArg(args[n], XmNsensitive, False); ++n;
1669   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1670   backBtn = XmCreatePushButton(toolBar, "back", args, n);
1671   addToolTip(backBtn, "Back");
1672   XtManageChild(backBtn);
1673   XtAddCallback(backBtn, XmNactivateCallback,
1674 		&backCbk, (XtPointer)this);
1675   n = 0;
1676   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1677   XtSetArg(args[n], XmNleftWidget, backBtn); ++n;
1678   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1679   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1680   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1681   XtSetArg(args[n], XmNsensitive, False); ++n;
1682   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1683   prevTenPageBtn = XmCreatePushButton(toolBar, "prevTenPage", args, n);
1684   addToolTip(prevTenPageBtn, "-10 pages");
1685   XtManageChild(prevTenPageBtn);
1686   XtAddCallback(prevTenPageBtn, XmNactivateCallback,
1687 		&prevTenPageCbk, (XtPointer)this);
1688   n = 0;
1689   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1690   XtSetArg(args[n], XmNleftWidget, prevTenPageBtn); ++n;
1691   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1692   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1693   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1694   XtSetArg(args[n], XmNsensitive, False); ++n;
1695   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1696   prevPageBtn = XmCreatePushButton(toolBar, "prevPage", args, n);
1697   addToolTip(prevPageBtn, "Previous page");
1698   XtManageChild(prevPageBtn);
1699   XtAddCallback(prevPageBtn, XmNactivateCallback,
1700 		&prevPageCbk, (XtPointer)this);
1701   n = 0;
1702   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1703   XtSetArg(args[n], XmNleftWidget, prevPageBtn); ++n;
1704   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1705   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1706   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1707   XtSetArg(args[n], XmNsensitive, False); ++n;
1708   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1709   nextPageBtn = XmCreatePushButton(toolBar, "nextPage", args, n);
1710   addToolTip(nextPageBtn, "Next page");
1711   XtManageChild(nextPageBtn);
1712   XtAddCallback(nextPageBtn, XmNactivateCallback,
1713 		&nextPageCbk, (XtPointer)this);
1714   n = 0;
1715   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1716   XtSetArg(args[n], XmNleftWidget, nextPageBtn); ++n;
1717   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1718   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1719   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1720   XtSetArg(args[n], XmNsensitive, False); ++n;
1721   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1722   nextTenPageBtn = XmCreatePushButton(toolBar, "nextTenPage", args, n);
1723   addToolTip(nextTenPageBtn, "+10 pages");
1724   XtManageChild(nextTenPageBtn);
1725   XtAddCallback(nextTenPageBtn, XmNactivateCallback,
1726 		&nextTenPageCbk, (XtPointer)this);
1727   n = 0;
1728   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1729   XtSetArg(args[n], XmNleftWidget, nextTenPageBtn); ++n;
1730   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1731   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1732   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1733   XtSetArg(args[n], XmNsensitive, False); ++n;
1734   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1735   forwardBtn = XmCreatePushButton(toolBar, "forward", args, n);
1736   addToolTip(forwardBtn, "Forward");
1737   XtManageChild(forwardBtn);
1738   XtAddCallback(forwardBtn, XmNactivateCallback,
1739 		&forwardCbk, (XtPointer)this);
1740 
1741   // page number display
1742   n = 0;
1743   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1744   XtSetArg(args[n], XmNleftWidget, forwardBtn); ++n;
1745   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1746   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1747   s = XmStringCreateLocalized("Page ");
1748   XtSetArg(args[n], XmNlabelString, s); ++n;
1749   label = XmCreateLabel(toolBar, "pageLabel", args, n);
1750   XmStringFree(s);
1751   XtManageChild(label);
1752   n = 0;
1753   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1754   XtSetArg(args[n], XmNleftWidget, label); ++n;
1755   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1756   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1757   XtSetArg(args[n], XmNmarginWidth, 3); ++n;
1758   XtSetArg(args[n], XmNmarginHeight, 3); ++n;
1759   XtSetArg(args[n], XmNcolumns, 5); ++n;
1760   pageNumText = XmCreateTextField(toolBar, "pageNum", args, n);
1761   XtManageChild(pageNumText);
1762   XtAddCallback(pageNumText, XmNactivateCallback,
1763 		&pageNumCbk, (XtPointer)this);
1764   n = 0;
1765   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1766   XtSetArg(args[n], XmNleftWidget, pageNumText); ++n;
1767   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1768   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1769   s = XmStringCreateLocalized(" of 00000");
1770   XtSetArg(args[n], XmNlabelString, s); ++n;
1771   XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); ++n;
1772   XtSetArg(args[n], XmNrecomputeSize, False); ++n;
1773   pageCountLabel = XmCreateLabel(toolBar, "pageCountLabel", args, n);
1774   XmStringFree(s);
1775   XtManageChild(pageCountLabel);
1776   s = XmStringCreateLocalized(" of 0");
1777   XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL);
1778   XmStringFree(s);
1779 
1780   // zoom menu
1781 #if USE_COMBO_BOX
1782   XmString st[nZoomMenuItems];
1783   n = 0;
1784   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1785   XtSetArg(args[n], XmNleftWidget, pageCountLabel); ++n;
1786   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1787   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1788   XtSetArg(args[n], XmNmarginWidth, 0); ++n;
1789   XtSetArg(args[n], XmNmarginHeight, 0); ++n;
1790   XtSetArg(args[n], XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); ++n;
1791   XtSetArg(args[n], XmNpositionMode, XmONE_BASED); ++n;
1792   XtSetArg(args[n], XmNcolumns, 7); ++n;
1793   for (i = 0; i < nZoomMenuItems; ++i) {
1794     st[i] = XmStringCreateLocalized((char *)zoomMenuInfo[i].label);
1795   }
1796   XtSetArg(args[n], XmNitems, st); ++n;
1797   XtSetArg(args[n], XmNitemCount, nZoomMenuItems); ++n;
1798   zoomComboBox = XmCreateComboBox(toolBar, "zoomComboBox", args, n);
1799   for (i = 0; i < nZoomMenuItems; ++i) {
1800     XmStringFree(st[i]);
1801   }
1802   addToolTip(zoomComboBox, "Zoom");
1803   XtAddCallback(zoomComboBox, XmNselectionCallback,
1804 		&zoomComboBoxCbk, (XtPointer)this);
1805   XtManageChild(zoomComboBox);
1806   zoomWidget = zoomComboBox;
1807 #else
1808   Widget menuPane;
1809   char buf[16];
1810   n = 0;
1811   menuPane = XmCreatePulldownMenu(toolBar, "zoomMenuPane", args, n);
1812   for (i = 0; i < nZoomMenuItems; ++i) {
1813     n = 0;
1814     s = XmStringCreateLocalized((char *)zoomMenuInfo[i].label);
1815     XtSetArg(args[n], XmNlabelString, s); ++n;
1816     XtSetArg(args[n], XmNuserData, (XtPointer)i); ++n;
1817     sprintf(buf, "zoom%d", i);
1818     btn = XmCreatePushButton(menuPane, buf, args, n);
1819     XmStringFree(s);
1820     XtManageChild(btn);
1821     XtAddCallback(btn, XmNactivateCallback,
1822 		  &zoomMenuCbk, (XtPointer)this);
1823     zoomMenuBtns[i] = btn;
1824   }
1825   n = 0;
1826   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1827   XtSetArg(args[n], XmNleftWidget, pageCountLabel); ++n;
1828   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1829   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1830   XtSetArg(args[n], XmNmarginWidth, 0); ++n;
1831   XtSetArg(args[n], XmNmarginHeight, 0); ++n;
1832   XtSetArg(args[n], XmNsubMenuId, menuPane); ++n;
1833   zoomMenu = XmCreateOptionMenu(toolBar, "zoomMenu", args, n);
1834   addToolTip(zoomMenu, "Zoom");
1835   XtManageChild(zoomMenu);
1836   zoomWidget = zoomMenu;
1837 #endif
1838 
1839   // find/print/about buttons
1840   n = 0;
1841   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1842   XtSetArg(args[n], XmNleftWidget, zoomWidget); ++n;
1843   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1844   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1845   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1846   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1847   findBtn = XmCreatePushButton(toolBar, "find", args, n);
1848   addToolTip(findBtn, "Find");
1849   XtManageChild(findBtn);
1850   XtAddCallback(findBtn, XmNactivateCallback,
1851 		&findCbk, (XtPointer)this);
1852   n = 0;
1853   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1854   XtSetArg(args[n], XmNleftWidget, findBtn); ++n;
1855   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1856   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1857   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1858   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1859   printBtn = XmCreatePushButton(toolBar, "print", args, n);
1860   addToolTip(printBtn, "Print");
1861   XtManageChild(printBtn);
1862   XtAddCallback(printBtn, XmNactivateCallback,
1863 		&printCbk, (XtPointer)this);
1864   n = 0;
1865   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1866   XtSetArg(args[n], XmNleftWidget, printBtn); ++n;
1867   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1868   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1869   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1870   XtSetArg(args[n], XmNlabelString, emptyString); ++n;
1871   aboutBtn = XmCreatePushButton(toolBar, "about", args, n);
1872   addToolTip(aboutBtn, "About / help");
1873   XtManageChild(aboutBtn);
1874   XtAddCallback(aboutBtn, XmNactivateCallback,
1875 		&aboutCbk, (XtPointer)this);
1876   lastBtn = aboutBtn;
1877 
1878   // quit button
1879   n = 0;
1880   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
1881   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1882   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1883   XtSetArg(args[n], XmNmarginWidth, 6); ++n;
1884   s = XmStringCreateLocalized("Quit");
1885   XtSetArg(args[n], XmNlabelString, s); ++n;
1886   quitBtn = XmCreatePushButton(toolBar, "quit", args, n);
1887   XmStringFree(s);
1888   XtManageChild(quitBtn);
1889   XtAddCallback(quitBtn, XmNactivateCallback,
1890 		&quitCbk, (XtPointer)this);
1891 
1892   // link label
1893   n = 0;
1894   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
1895   XtSetArg(args[n], XmNleftWidget, lastBtn); ++n;
1896   XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); ++n;
1897   XtSetArg(args[n], XmNrightWidget, quitBtn); ++n;
1898   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
1899   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
1900   s = XmStringCreateLocalized("");
1901   XtSetArg(args[n], XmNlabelString, s); ++n;
1902   XtSetArg(args[n], XmNrecomputeSize, True); ++n;
1903   XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); ++n;
1904   linkLabel = XmCreateLabel(toolBar, "linkLabel", args, n);
1905   XmStringFree(s);
1906   XtManageChild(linkLabel);
1907 
1908   XmStringFree(emptyString);
1909 }
1910 
1911 #ifndef DISABLE_OUTLINE
initPanedWin(Widget parent)1912 void XPDFViewer::initPanedWin(Widget parent) {
1913   Widget clipWin;
1914   Arg args[20];
1915   int n;
1916 
1917   // paned window
1918   n = 0;
1919   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
1920 #if defined(__sgi) && (XmVERSION <= 1)
1921   panedWin = SgCreateHorzPanedWindow(parent, "panedWin", args, n);
1922 #else
1923   panedWin = XmCreatePanedWindow(parent, "panedWin", args, n);
1924 #endif
1925   XtManageChild(panedWin);
1926 
1927   // scrolled window for outline container
1928   n = 0;
1929   XtSetArg(args[n], XmNpositionIndex, 0); ++n;
1930   XtSetArg(args[n], XmNallowResize, True); ++n;
1931   XtSetArg(args[n], XmNpaneMinimum, 1); ++n;
1932   XtSetArg(args[n], XmNpaneMaximum, 10000); ++n;
1933 #if !(defined(__sgi) && (XmVERSION <= 1))
1934   XtSetArg(args[n], XmNwidth, 1); ++n;
1935 #endif
1936   XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n;
1937   outlineScroll = XmCreateScrolledWindow(panedWin, "outlineScroll", args, n);
1938   XtManageChild(outlineScroll);
1939   XtVaGetValues(outlineScroll, XmNclipWindow, &clipWin, NULL);
1940   XtVaSetValues(clipWin, XmNbackground, app->getPaperPixel(), NULL);
1941 
1942   // outline tree
1943   n = 0;
1944   XtSetArg(args[n], XmNbackground, app->getPaperPixel()); ++n;
1945   outlineTree = XPDFCreateTree(outlineScroll, "outlineTree", args, n);
1946   XtManageChild(outlineTree);
1947   XtAddCallback(outlineTree, XPDFNselectionCallback, &outlineSelectCbk,
1948 		(XtPointer)this);
1949 }
1950 #endif
1951 
initCore(Widget parent,GBool fullScreen)1952 void XPDFViewer::initCore(Widget parent, GBool fullScreen) {
1953   core = new XPDFCore(win, parent,
1954 		      app->getPaperRGB(), app->getPaperPixel(),
1955 		      app->getMattePixel(fullScreen),
1956 		      fullScreen, app->getReverseVideo(),
1957 		      app->getInstallCmap(), app->getRGBCubeSize());
1958   core->setUpdateCbk(&updateCbk, this);
1959   core->setActionCbk(&actionCbk, this);
1960   core->setKeyPressCbk(&keyPressCbk, this);
1961   core->setMouseCbk(&mouseCbk, this);
1962 }
1963 
initPopupMenu()1964 void XPDFViewer::initPopupMenu() {
1965   Widget btn;
1966   Arg args[20];
1967   int n;
1968   XmString s, s2;
1969 
1970   n = 0;
1971 #if XmVersion < 1002
1972   // older versions of Motif need this, newer ones choke on it,
1973   // sometimes not displaying the menu at all, maybe depending on the
1974   // state of the NumLock key (taken from DDD)
1975   XtSetArg(args[n], XmNmenuPost, "<Btn3Down>"); ++n;
1976 #endif
1977   popupMenu = XmCreatePopupMenu(core->getDrawAreaWidget(), "popupMenu",
1978 				args, n);
1979   n = 0;
1980   s = XmStringCreateLocalized("Open...");
1981   XtSetArg(args[n], XmNlabelString, s); ++n;
1982   s2 = XmStringCreateLocalized("O");
1983   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
1984   btn = XmCreatePushButton(popupMenu, "open", args, n);
1985   XmStringFree(s);
1986   XmStringFree(s2);
1987   XtManageChild(btn);
1988   XtAddCallback(btn, XmNactivateCallback,
1989 		&openCbk, (XtPointer)this);
1990   n = 0;
1991   s = XmStringCreateLocalized("Open in new window...");
1992   XtSetArg(args[n], XmNlabelString, s); ++n;
1993   btn = XmCreatePushButton(popupMenu, "openInNewWindow", args, n);
1994   XmStringFree(s);
1995   XtManageChild(btn);
1996   XtAddCallback(btn, XmNactivateCallback,
1997 		&openInNewWindowCbk, (XtPointer)this);
1998   n = 0;
1999   s = XmStringCreateLocalized("Reload");
2000   XtSetArg(args[n], XmNlabelString, s); ++n;
2001   s2 = XmStringCreateLocalized("R");
2002   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
2003   btn = XmCreatePushButton(popupMenu, "reload", args, n);
2004   XmStringFree(s);
2005   XmStringFree(s2);
2006   XtManageChild(btn);
2007   XtAddCallback(btn, XmNactivateCallback,
2008 		&reloadCbk, (XtPointer)this);
2009   n = 0;
2010   s = XmStringCreateLocalized("Save as...");
2011   XtSetArg(args[n], XmNlabelString, s); ++n;
2012   btn = XmCreatePushButton(popupMenu, "saveAs", args, n);
2013   XmStringFree(s);
2014   XtManageChild(btn);
2015   XtAddCallback(btn, XmNactivateCallback,
2016 		&saveAsCbk, (XtPointer)this);
2017   n = 0;
2018   btn = XmCreateSeparator(popupMenu, "sep1", args, n);
2019   XtManageChild(btn);
2020   n = 0;
2021   s = XmStringCreateLocalized("Continuous view");
2022   XtSetArg(args[n], XmNlabelString, s); ++n;
2023   XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
2024   XtSetArg(args[n], XmNvisibleWhenOff, True); ++n;
2025   XtSetArg(args[n], XmNset, core->getContinuousMode() ? XmSET : XmUNSET); ++n;
2026   btn = XmCreateToggleButton(popupMenu, "continuousMode", args, n);
2027   XmStringFree(s);
2028   XtManageChild(btn);
2029   XtAddCallback(btn, XmNvalueChangedCallback,
2030 		&continuousModeToggleCbk, (XtPointer)this);
2031   n = 0;
2032   s = XmStringCreateLocalized("Full screen");
2033   XtSetArg(args[n], XmNlabelString, s); ++n;
2034   XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
2035   XtSetArg(args[n], XmNvisibleWhenOff, True); ++n;
2036   XtSetArg(args[n], XmNset, core->getFullScreen() ? XmSET : XmUNSET); ++n;
2037   btn = XmCreateToggleButton(popupMenu, "fullScreen", args, n);
2038   XmStringFree(s);
2039   XtManageChild(btn);
2040   XtAddCallback(btn, XmNvalueChangedCallback,
2041 		&fullScreenToggleCbk, (XtPointer)this);
2042   n = 0;
2043   s = XmStringCreateLocalized("Rotate counterclockwise");
2044   XtSetArg(args[n], XmNlabelString, s); ++n;
2045   btn = XmCreatePushButton(popupMenu, "rotateCCW", args, n);
2046   XmStringFree(s);
2047   XtManageChild(btn);
2048   XtAddCallback(btn, XmNactivateCallback,
2049 		&rotateCCWCbk, (XtPointer)this);
2050   n = 0;
2051   s = XmStringCreateLocalized("Rotate clockwise");
2052   XtSetArg(args[n], XmNlabelString, s); ++n;
2053   btn = XmCreatePushButton(popupMenu, "rotateCW", args, n);
2054   XmStringFree(s);
2055   XtManageChild(btn);
2056   XtAddCallback(btn, XmNactivateCallback,
2057 		&rotateCWCbk, (XtPointer)this);
2058   n = 0;
2059   s = XmStringCreateLocalized("Zoom to selection");
2060   XtSetArg(args[n], XmNlabelString, s); ++n;
2061   btn = XmCreatePushButton(popupMenu, "zoomToSelection", args, n);
2062   XmStringFree(s);
2063   XtManageChild(btn);
2064   XtAddCallback(btn, XmNactivateCallback,
2065 		&zoomToSelectionCbk, (XtPointer)this);
2066   n = 0;
2067   btn = XmCreateSeparator(popupMenu, "sep2", args, n);
2068   XtManageChild(btn);
2069   n = 0;
2070   s = XmStringCreateLocalized("Close");
2071   XtSetArg(args[n], XmNlabelString, s); ++n;
2072   s2 = XmStringCreateLocalized("Ctrl+W");
2073   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
2074   btn = XmCreatePushButton(popupMenu, "close", args, n);
2075   XmStringFree(s);
2076   XmStringFree(s2);
2077   XtManageChild(btn);
2078   XtAddCallback(btn, XmNactivateCallback,
2079 		&closeCbk, (XtPointer)this);
2080   n = 0;
2081   s = XmStringCreateLocalized("Quit");
2082   XtSetArg(args[n], XmNlabelString, s); ++n;
2083   s2 = XmStringCreateLocalized("Q");
2084   XtSetArg(args[n], XmNacceleratorText, s2); ++n;
2085   btn = XmCreatePushButton(popupMenu, "quit", args, n);
2086   XmStringFree(s);
2087   XmStringFree(s2);
2088   XtManageChild(btn);
2089   XtAddCallback(btn, XmNactivateCallback,
2090 		&quitCbk, (XtPointer)this);
2091 
2092   // this is magic (taken from DDD) - weird things happen if this
2093   // call isn't made
2094   XtUngrabButton(core->getDrawAreaWidget(), AnyButton, AnyModifier);
2095 }
2096 
addToolTip(Widget widget,char * text)2097 void XPDFViewer::addToolTip(Widget widget, char *text) {
2098 #ifdef XmNtoolTipString
2099   XmString s;
2100   Cardinal n, i;
2101   WidgetList children;
2102 
2103   if (XtIsComposite(widget)) {
2104     XtVaGetValues(widget, XmNnumChildren, &n, XmNchildren, &children, NULL);
2105     for (i = 0; i < n; ++i) {
2106       addToolTip(children[i], text);
2107     }
2108   } else {
2109     s = XmStringCreateLocalized(text);
2110     XtVaSetValues(widget, XmNtoolTipString, s, NULL);
2111     XmStringFree(s);
2112   }
2113 #endif
2114 }
2115 
mapWindow()2116 void XPDFViewer::mapWindow() {
2117 #ifdef HAVE_X11_XPM_H
2118   Pixmap iconPixmap;
2119 #endif
2120   int depth;
2121   Pixel fg, bg, arm;
2122 
2123   // show the window
2124   XtPopup(win, XtGrabNone);
2125   core->takeFocus();
2126 
2127   // create the icon
2128 #ifdef HAVE_X11_XPM_H
2129   if (XpmCreatePixmapFromData(display, XtWindow(win), xpdfIcon,
2130 			      &iconPixmap, NULL, NULL) == XpmSuccess) {
2131     XtVaSetValues(win, XmNiconPixmap, iconPixmap, NULL);
2132   }
2133 #endif
2134 
2135   // set button bitmaps (must be done after the window is mapped)
2136   if (toolBar != None) {
2137     XtVaGetValues(backBtn, XmNdepth, &depth,
2138 		  XmNforeground, &fg, XmNbackground, &bg,
2139 		  XmNarmColor, &arm, NULL);
2140     XtVaSetValues(backBtn, XmNlabelType, XmPIXMAP,
2141 		  XmNlabelPixmap,
2142 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2143 					      (char *)backArrow_bits,
2144 					      backArrow_width,
2145 					      backArrow_height,
2146 					      fg, bg, depth),
2147 		  XmNarmPixmap,
2148 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2149 					      (char *)backArrow_bits,
2150 					      backArrow_width,
2151 					      backArrow_height,
2152 					      fg, arm, depth),
2153 		  XmNlabelInsensitivePixmap,
2154 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2155 					      (char *)backArrowDis_bits,
2156 					      backArrowDis_width,
2157 					      backArrowDis_height,
2158 					      fg, bg, depth),
2159 		  NULL);
2160     XtVaSetValues(prevTenPageBtn, XmNlabelType, XmPIXMAP,
2161 		  XmNlabelPixmap,
2162 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2163 					      (char *)dblLeftArrow_bits,
2164 					      dblLeftArrow_width,
2165 					      dblLeftArrow_height,
2166 					      fg, bg, depth),
2167 		  XmNarmPixmap,
2168 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2169 					      (char *)dblLeftArrow_bits,
2170 					      dblLeftArrow_width,
2171 					      dblLeftArrow_height,
2172 					      fg, arm, depth),
2173 		  XmNlabelInsensitivePixmap,
2174 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2175 					      (char *)dblLeftArrowDis_bits,
2176 					      dblLeftArrowDis_width,
2177 					      dblLeftArrowDis_height,
2178 					      fg, bg, depth),
2179 		  NULL);
2180     XtVaSetValues(prevPageBtn, XmNlabelType, XmPIXMAP,
2181 		  XmNlabelPixmap,
2182 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2183 					      (char *)leftArrow_bits,
2184 					      leftArrow_width,
2185 					      leftArrow_height,
2186 					      fg, bg, depth),
2187 		  XmNarmPixmap,
2188 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2189 					      (char *)leftArrow_bits,
2190 					      leftArrow_width,
2191 					      leftArrow_height,
2192 					      fg, arm, depth),
2193 		  XmNlabelInsensitivePixmap,
2194 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2195 					      (char *)leftArrowDis_bits,
2196 					      leftArrowDis_width,
2197 					      leftArrowDis_height,
2198 					      fg, bg, depth),
2199 		  NULL);
2200     XtVaSetValues(nextPageBtn, XmNlabelType, XmPIXMAP,
2201 		  XmNlabelPixmap,
2202 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2203 					      (char *)rightArrow_bits,
2204 					      rightArrow_width,
2205 					      rightArrow_height,
2206 					      fg, bg, depth),
2207 		  XmNarmPixmap,
2208 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2209 					      (char *)rightArrow_bits,
2210 					      rightArrow_width,
2211 					      rightArrow_height,
2212 					      fg, arm, depth),
2213 		  XmNlabelInsensitivePixmap,
2214 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2215 					      (char *)rightArrowDis_bits,
2216 					      rightArrowDis_width,
2217 					      rightArrowDis_height,
2218 					      fg, bg, depth),
2219 		  NULL);
2220     XtVaSetValues(nextTenPageBtn, XmNlabelType, XmPIXMAP,
2221 		  XmNlabelPixmap,
2222 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2223 					      (char *)dblRightArrow_bits,
2224 					      dblRightArrow_width,
2225 					      dblRightArrow_height,
2226 					      fg, bg, depth),
2227 		  XmNarmPixmap,
2228 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2229 					      (char *)dblRightArrow_bits,
2230 					      dblRightArrow_width,
2231 					      dblRightArrow_height,
2232 					      fg, arm, depth),
2233 		  XmNlabelInsensitivePixmap,
2234 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2235 					      (char *)dblRightArrowDis_bits,
2236 					      dblRightArrowDis_width,
2237 					      dblRightArrowDis_height,
2238 					      fg, bg, depth),
2239 		  NULL);
2240     XtVaSetValues(forwardBtn, XmNlabelType, XmPIXMAP,
2241 		  XmNlabelPixmap,
2242 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2243 					      (char *)forwardArrow_bits,
2244 					      forwardArrow_width,
2245 					      forwardArrow_height,
2246 					      fg, bg, depth),
2247 		  XmNarmPixmap,
2248 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2249 					      (char *)forwardArrow_bits,
2250 					      forwardArrow_width,
2251 					      forwardArrow_height,
2252 					      fg, arm, depth),
2253 		  XmNlabelInsensitivePixmap,
2254 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2255 					      (char *)forwardArrowDis_bits,
2256 					      forwardArrowDis_width,
2257 					      forwardArrowDis_height,
2258 					      fg, bg, depth),
2259 		  NULL);
2260     XtVaSetValues(findBtn, XmNlabelType, XmPIXMAP,
2261 		  XmNlabelPixmap,
2262 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2263 					      (char *)find_bits,
2264 					      find_width,
2265 					      find_height,
2266 					      fg, bg, depth),
2267 		  XmNarmPixmap,
2268 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2269 					      (char *)find_bits,
2270 					      find_width,
2271 					      find_height,
2272 					      fg, arm, depth),
2273 		  XmNlabelInsensitivePixmap,
2274 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2275 					      (char *)findDis_bits,
2276 					      findDis_width,
2277 					      findDis_height,
2278 					      fg, bg, depth),
2279 		  NULL);
2280     XtVaSetValues(printBtn, XmNlabelType, XmPIXMAP,
2281 		  XmNlabelPixmap,
2282 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2283 					      (char *)print_bits,
2284 					      print_width,
2285 					      print_height,
2286 					      fg, bg, depth),
2287 		  XmNarmPixmap,
2288 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2289 					      (char *)print_bits,
2290 					      print_width,
2291 					      print_height,
2292 					      fg, arm, depth),
2293 		  XmNlabelInsensitivePixmap,
2294 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2295 					      (char *)printDis_bits,
2296 					      printDis_width,
2297 					      printDis_height,
2298 					      fg, bg, depth),
2299 		  NULL);
2300     XtVaSetValues(aboutBtn, XmNlabelType, XmPIXMAP,
2301 		  XmNlabelPixmap,
2302 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2303 					      (char *)about_bits,
2304 					      about_width,
2305 					      about_height,
2306 					      fg, bg, depth),
2307 		  XmNarmPixmap,
2308 		  XCreatePixmapFromBitmapData(display, XtWindow(toolBar),
2309 					      (char *)about_bits,
2310 					      about_width,
2311 					      about_height,
2312 					      fg, arm, depth),
2313 		  NULL);
2314   }
2315 }
2316 
closeWindow()2317 void XPDFViewer::closeWindow() {
2318   XtPopdown(win);
2319   XtDestroyWidget(win);
2320 }
2321 
getZoomIdx()2322 int XPDFViewer::getZoomIdx() {
2323   int i;
2324 
2325   for (i = 0; i < nZoomMenuItems; ++i) {
2326     if (core->getZoom() == zoomMenuInfo[i].zoom) {
2327       return i;
2328     }
2329   }
2330   return -1;
2331 }
2332 
setZoomIdx(int idx)2333 void XPDFViewer::setZoomIdx(int idx) {
2334   if (toolBar == None) {
2335     return;
2336   }
2337 #if USE_COMBO_BOX
2338   XtVaSetValues(zoomComboBox, XmNselectedPosition, idx + 1, NULL);
2339 #else
2340   XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[idx], NULL);
2341 #endif
2342 }
2343 
setZoomVal(double z)2344 void XPDFViewer::setZoomVal(double z) {
2345   if (toolBar == None) {
2346     return;
2347   }
2348 
2349 #if USE_COMBO_BOX
2350   char buf[32];
2351   XmString s;
2352   int i;
2353 
2354   for (i = 0; i < nZoomMenuItems; ++i) {
2355     if (z == zoomMenuInfo[i].zoom) {
2356       XtVaSetValues(zoomComboBox, XmNselectedPosition, i + 1, NULL);
2357       return;
2358     }
2359   }
2360   sprintf(buf, "%d%%", (int)z);
2361   s = XmStringCreateLocalized(buf);
2362   XtVaSetValues(zoomComboBox, XmNselectedItem, s, NULL);
2363   XmStringFree(s);
2364 #else
2365   int i;
2366 
2367   for (i = 0; i < nZoomMenuItems; ++i) {
2368     if (z == zoomMenuInfo[i].zoom) {
2369       XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[i], NULL);
2370       return;
2371     }
2372   }
2373   for (i = maxZoomIdx; i < minZoomIdx; ++i) {
2374     if (z > zoomMenuInfo[i].zoom) {
2375       break;
2376     }
2377   }
2378   XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[i], NULL);
2379 #endif
2380 }
2381 
prevPageCbk(Widget widget,XtPointer ptr,XtPointer callData)2382 void XPDFViewer::prevPageCbk(Widget widget, XtPointer ptr,
2383 			     XtPointer callData) {
2384   XPDFViewer *viewer = (XPDFViewer *)ptr;
2385 
2386   viewer->core->gotoPrevPage(1, gTrue, gFalse);
2387   viewer->core->takeFocus();
2388 }
2389 
prevTenPageCbk(Widget widget,XtPointer ptr,XtPointer callData)2390 void XPDFViewer::prevTenPageCbk(Widget widget, XtPointer ptr,
2391 				XtPointer callData) {
2392   XPDFViewer *viewer = (XPDFViewer *)ptr;
2393 
2394   viewer->core->gotoPrevPage(10, gTrue, gFalse);
2395   viewer->core->takeFocus();
2396 }
2397 
nextPageCbk(Widget widget,XtPointer ptr,XtPointer callData)2398 void XPDFViewer::nextPageCbk(Widget widget, XtPointer ptr,
2399 			     XtPointer callData) {
2400   XPDFViewer *viewer = (XPDFViewer *)ptr;
2401 
2402   viewer->core->gotoNextPage(1, gTrue);
2403   viewer->core->takeFocus();
2404 }
2405 
nextTenPageCbk(Widget widget,XtPointer ptr,XtPointer callData)2406 void XPDFViewer::nextTenPageCbk(Widget widget, XtPointer ptr,
2407 				XtPointer callData) {
2408   XPDFViewer *viewer = (XPDFViewer *)ptr;
2409 
2410   viewer->core->gotoNextPage(10, gTrue);
2411   viewer->core->takeFocus();
2412 }
2413 
backCbk(Widget widget,XtPointer ptr,XtPointer callData)2414 void XPDFViewer::backCbk(Widget widget, XtPointer ptr,
2415 			 XtPointer callData) {
2416   XPDFViewer *viewer = (XPDFViewer *)ptr;
2417 
2418   viewer->core->goBackward();
2419   viewer->core->takeFocus();
2420 }
2421 
forwardCbk(Widget widget,XtPointer ptr,XtPointer callData)2422 void XPDFViewer::forwardCbk(Widget widget, XtPointer ptr,
2423 			    XtPointer callData) {
2424   XPDFViewer *viewer = (XPDFViewer *)ptr;
2425 
2426   viewer->core->goForward();
2427   viewer->core->takeFocus();
2428 }
2429 
2430 #if USE_COMBO_BOX
2431 
zoomComboBoxCbk(Widget widget,XtPointer ptr,XtPointer callData)2432 void XPDFViewer::zoomComboBoxCbk(Widget widget, XtPointer ptr,
2433 				 XtPointer callData) {
2434   XPDFViewer *viewer = (XPDFViewer *)ptr;
2435   XmComboBoxCallbackStruct *data = (XmComboBoxCallbackStruct *)callData;
2436   double z;
2437   char *s;
2438   XmStringContext context;
2439   XmStringCharSet charSet;
2440   XmStringDirection dir;
2441   Boolean sep;
2442 
2443   z = viewer->core->getZoom();
2444   if (data->item_position == 0) {
2445     XmStringInitContext(&context, data->item_or_text);
2446     if (XmStringGetNextSegment(context, &s, &charSet, &dir, &sep)) {
2447       z = atof(s);
2448       if (z <= 1) {
2449 	z = defZoom;
2450       }
2451       XtFree(charSet);
2452       XtFree(s);
2453     }
2454     XmStringFreeContext(context);
2455   } else {
2456     z = zoomMenuInfo[data->item_position - 1].zoom;
2457   }
2458   // only redraw if this was triggered by an event; otherwise
2459   // the caller is responsible for doing the redraw
2460   if (z != viewer->core->getZoom() && data->event) {
2461     viewer->displayPage(viewer->core->getPageNum(), z,
2462 			viewer->core->getRotate(), gTrue, gFalse);
2463   }
2464   viewer->core->takeFocus();
2465 }
2466 
2467 #else // USE_COMBO_BOX
2468 
zoomMenuCbk(Widget widget,XtPointer ptr,XtPointer callData)2469 void XPDFViewer::zoomMenuCbk(Widget widget, XtPointer ptr,
2470 			     XtPointer callData) {
2471   XPDFViewer *viewer = (XPDFViewer *)ptr;
2472   XmPushButtonCallbackStruct *data = (XmPushButtonCallbackStruct *)callData;
2473   XtPointer userData;
2474   double z;
2475 
2476   XtVaGetValues(widget, XmNuserData, &userData, NULL);
2477   z = zoomMenuInfo[(long)userData].zoom;
2478   // only redraw if this was triggered by an event; otherwise
2479   // the caller is responsible for doing the redraw
2480   if (z != viewer->core->getZoom() && data->event) {
2481     viewer->displayPage(viewer->core->getPageNum(), z,
2482 			viewer->core->getRotate(), gTrue, gFalse);
2483   }
2484   viewer->core->takeFocus();
2485 }
2486 
2487 #endif // USE_COMBO_BOX
2488 
findCbk(Widget widget,XtPointer ptr,XtPointer callData)2489 void XPDFViewer::findCbk(Widget widget, XtPointer ptr,
2490 			 XtPointer callData) {
2491   XPDFViewer *viewer = (XPDFViewer *)ptr;
2492 
2493   if (!viewer->core->getDoc()) {
2494     return;
2495   }
2496   viewer->mapFindDialog();
2497 }
2498 
printCbk(Widget widget,XtPointer ptr,XtPointer callData)2499 void XPDFViewer::printCbk(Widget widget, XtPointer ptr,
2500 			  XtPointer callData) {
2501   XPDFViewer *viewer = (XPDFViewer *)ptr;
2502 
2503   if (!viewer->core->getDoc()) {
2504     return;
2505   }
2506   XtManageChild(viewer->printDialog);
2507 }
2508 
aboutCbk(Widget widget,XtPointer ptr,XtPointer callData)2509 void XPDFViewer::aboutCbk(Widget widget, XtPointer ptr,
2510 			  XtPointer callData) {
2511   XPDFViewer *viewer = (XPDFViewer *)ptr;
2512 
2513   XtManageChild(viewer->aboutDialog);
2514 }
2515 
quitCbk(Widget widget,XtPointer ptr,XtPointer callData)2516 void XPDFViewer::quitCbk(Widget widget, XtPointer ptr,
2517 			 XtPointer callData) {
2518   XPDFViewer *viewer = (XPDFViewer *)ptr;
2519 
2520   viewer->app->quit();
2521 }
2522 
openCbk(Widget widget,XtPointer ptr,XtPointer callData)2523 void XPDFViewer::openCbk(Widget widget, XtPointer ptr,
2524 			 XtPointer callData) {
2525   XPDFViewer *viewer = (XPDFViewer *)ptr;
2526 
2527   viewer->mapOpenDialog(gFalse);
2528 }
2529 
openInNewWindowCbk(Widget widget,XtPointer ptr,XtPointer callData)2530 void XPDFViewer::openInNewWindowCbk(Widget widget, XtPointer ptr,
2531 				    XtPointer callData) {
2532   XPDFViewer *viewer = (XPDFViewer *)ptr;
2533 
2534   viewer->mapOpenDialog(gTrue);
2535 }
2536 
reloadCbk(Widget widget,XtPointer ptr,XtPointer callData)2537 void XPDFViewer::reloadCbk(Widget widget, XtPointer ptr,
2538 			 XtPointer callData) {
2539   XPDFViewer *viewer = (XPDFViewer *)ptr;
2540 
2541   viewer->reloadFile();
2542 }
2543 
saveAsCbk(Widget widget,XtPointer ptr,XtPointer callData)2544 void XPDFViewer::saveAsCbk(Widget widget, XtPointer ptr,
2545 			   XtPointer callData) {
2546   XPDFViewer *viewer = (XPDFViewer *)ptr;
2547 
2548   if (!viewer->core->getDoc()) {
2549     return;
2550   }
2551   viewer->mapSaveAsDialog();
2552 }
2553 
continuousModeToggleCbk(Widget widget,XtPointer ptr,XtPointer callData)2554 void XPDFViewer::continuousModeToggleCbk(Widget widget, XtPointer ptr,
2555 					 XtPointer callData) {
2556   XPDFViewer *viewer = (XPDFViewer *)ptr;
2557   XmToggleButtonCallbackStruct *data =
2558       (XmToggleButtonCallbackStruct *)callData;
2559 
2560   viewer->core->setContinuousMode(data->set == XmSET);
2561 }
2562 
fullScreenToggleCbk(Widget widget,XtPointer ptr,XtPointer callData)2563 void XPDFViewer::fullScreenToggleCbk(Widget widget, XtPointer ptr,
2564 				     XtPointer callData) {
2565   XPDFViewer *viewer = (XPDFViewer *)ptr;
2566   XmToggleButtonCallbackStruct *data =
2567       (XmToggleButtonCallbackStruct *)callData;
2568 
2569   if (data->set == XmSET) {
2570     viewer->cmdFullScreenMode(NULL, 0, NULL);
2571   } else {
2572     viewer->cmdWindowMode(NULL, 0, NULL);
2573   }
2574 }
2575 
rotateCCWCbk(Widget widget,XtPointer ptr,XtPointer callData)2576 void XPDFViewer::rotateCCWCbk(Widget widget, XtPointer ptr,
2577 			      XtPointer callData) {
2578   XPDFViewer *viewer = (XPDFViewer *)ptr;
2579 
2580   viewer->cmdRotateCCW(NULL, 0, NULL);
2581 }
2582 
rotateCWCbk(Widget widget,XtPointer ptr,XtPointer callData)2583 void XPDFViewer::rotateCWCbk(Widget widget, XtPointer ptr,
2584 			     XtPointer callData) {
2585   XPDFViewer *viewer = (XPDFViewer *)ptr;
2586 
2587   viewer->cmdRotateCW(NULL, 0, NULL);
2588 }
2589 
zoomToSelectionCbk(Widget widget,XtPointer ptr,XtPointer callData)2590 void XPDFViewer::zoomToSelectionCbk(Widget widget, XtPointer ptr,
2591 				    XtPointer callData) {
2592   XPDFViewer *viewer = (XPDFViewer *)ptr;
2593   int pg;
2594   double ulx, uly, lrx, lry;
2595 
2596   if (viewer->core->getSelection(&pg, &ulx, &uly, &lrx, &lry)) {
2597     viewer->core->zoomToRect(pg, ulx, uly, lrx, lry);
2598   }
2599 }
2600 
closeCbk(Widget widget,XtPointer ptr,XtPointer callData)2601 void XPDFViewer::closeCbk(Widget widget, XtPointer ptr,
2602 			  XtPointer callData) {
2603   XPDFViewer *viewer = (XPDFViewer *)ptr;
2604 
2605   viewer->app->close(viewer, gFalse);
2606 }
2607 
closeMsgCbk(Widget widget,XtPointer ptr,XtPointer callData)2608 void XPDFViewer::closeMsgCbk(Widget widget, XtPointer ptr,
2609 			     XtPointer callData) {
2610   XPDFViewer *viewer = (XPDFViewer *)ptr;
2611 
2612   viewer->app->close(viewer, gTrue);
2613 }
2614 
pageNumCbk(Widget widget,XtPointer ptr,XtPointer callData)2615 void XPDFViewer::pageNumCbk(Widget widget, XtPointer ptr,
2616 			    XtPointer callData) {
2617   XPDFViewer *viewer = (XPDFViewer *)ptr;
2618   char *s, *p;
2619   int pg;
2620   char buf[20];
2621 
2622   if (!viewer->core->getDoc()) {
2623     goto err;
2624   }
2625   s = XmTextFieldGetString(viewer->pageNumText);
2626   for (p = s; *p; ++p) {
2627     if (!isdigit(*p)) {
2628       goto err;
2629     }
2630   }
2631   pg = atoi(s);
2632   if (pg < 1 || pg > viewer->core->getDoc()->getNumPages()) {
2633     goto err;
2634   }
2635   viewer->displayPage(pg, viewer->core->getZoom(),
2636 		      viewer->core->getRotate(), gFalse, gTrue);
2637   viewer->core->takeFocus();
2638   return;
2639 
2640  err:
2641   XBell(viewer->display, 0);
2642   sprintf(buf, "%d", viewer->core->getPageNum());
2643   XmTextFieldSetString(viewer->pageNumText, buf);
2644 }
2645 
updateCbk(void * data,GString * fileName,int pageNum,int numPages,const char * linkString)2646 void XPDFViewer::updateCbk(void *data, GString *fileName,
2647 			   int pageNum, int numPages, const char *linkString) {
2648   XPDFViewer *viewer = (XPDFViewer *)data;
2649   GString *title;
2650   char buf[20];
2651   XmString s;
2652 
2653   if (fileName) {
2654     if (!(title = viewer->app->getTitle())) {
2655       title = (new GString(xpdfAppName))->append(": ")->append(fileName);
2656     }
2657     XtVaSetValues(viewer->win, XmNtitle, title->getCString(),
2658 		  XmNiconName, title->getCString(), NULL);
2659     if (!viewer->app->getTitle()) {
2660       delete title;
2661     }
2662 #ifndef DISABLE_OUTLINE
2663     viewer->setupOutline();
2664 #endif
2665     viewer->setupPrintDialog();
2666   }
2667 
2668   if (viewer->toolBar != None) {
2669     if (pageNum >= 0) {
2670       s = XmStringCreateLocalized("");
2671       XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL);
2672       XmStringFree(s);
2673       sprintf(buf, "%d", pageNum);
2674       XmTextFieldSetString(viewer->pageNumText, buf);
2675       XtVaSetValues(viewer->prevTenPageBtn, XmNsensitive,
2676 		    pageNum > 1, NULL);
2677       XtVaSetValues(viewer->prevPageBtn, XmNsensitive,
2678 		    pageNum > 1, NULL);
2679       XtVaSetValues(viewer->nextTenPageBtn, XmNsensitive,
2680 		    pageNum < viewer->core->getDoc()->getNumPages(), NULL);
2681       XtVaSetValues(viewer->nextPageBtn, XmNsensitive,
2682 		    pageNum < viewer->core->getDoc()->getNumPages(), NULL);
2683       XtVaSetValues(viewer->backBtn, XmNsensitive,
2684 		    viewer->core->canGoBack(), NULL);
2685       XtVaSetValues(viewer->forwardBtn, XmNsensitive,
2686 		    viewer->core->canGoForward(), NULL);
2687     }
2688 
2689     if (numPages >= 0) {
2690       sprintf(buf, " of %d", numPages);
2691       s = XmStringCreateLocalized(buf);
2692       XtVaSetValues(viewer->pageCountLabel, XmNlabelString, s, NULL);
2693       XmStringFree(s);
2694     }
2695 
2696     if (linkString) {
2697       s = XmStringCreateLocalized((char *)linkString);
2698       XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL);
2699       XmStringFree(s);
2700     }
2701   }
2702 }
2703 
2704 //------------------------------------------------------------------------
2705 // GUI code: outline
2706 //------------------------------------------------------------------------
2707 
2708 #ifndef DISABLE_OUTLINE
2709 
setupOutline()2710 void XPDFViewer::setupOutline() {
2711   GList *items;
2712   UnicodeMap *uMap;
2713   GString *enc;
2714   int i;
2715 
2716   if (outlineScroll == None) {
2717     return;
2718   }
2719 
2720   // unmanage and destroy the old labels
2721   if (outlineLabels) {
2722     XtUnmanageChildren(outlineLabels, outlineLabelsLength);
2723     for (i = 0; i < outlineLabelsLength; ++i) {
2724       XtDestroyWidget(outlineLabels[i]);
2725     }
2726     gfree(outlineLabels);
2727     outlineLabels = NULL;
2728     outlineLabelsLength = outlineLabelsSize = 0;
2729   }
2730 
2731   if (core->getDoc()) {
2732 
2733     // create the new labels
2734     items = core->getDoc()->getOutline()->getItems();
2735     if (items && items->getLength() > 0) {
2736       enc = new GString("Latin1");
2737       uMap = globalParams->getUnicodeMap(enc);
2738       delete enc;
2739       setupOutlineItems(items, NULL, uMap);
2740       uMap->decRefCnt();
2741     }
2742 
2743     // manage the new labels
2744     XtManageChildren(outlineLabels, outlineLabelsLength);
2745   }
2746 }
2747 
setupOutlineItems(GList * items,Widget parent,UnicodeMap * uMap)2748 void XPDFViewer::setupOutlineItems(GList *items, Widget parent,
2749 				   UnicodeMap *uMap) {
2750   OutlineItem *item;
2751   GList *kids;
2752   Widget label;
2753   Arg args[20];
2754   GString *title;
2755   char buf[8];
2756   XmString s;
2757   int i, j, n;
2758 
2759   for (i = 0; i < items->getLength(); ++i) {
2760     item = (OutlineItem *)items->get(i);
2761     title = new GString();
2762     for (j = 0; j < item->getTitleLength(); ++j) {
2763       n = uMap->mapUnicode(item->getTitle()[j], buf, sizeof(buf));
2764       title->append(buf, n);
2765     }
2766     n = 0;
2767     XtSetArg(args[n], XPDFNentryPosition, i); ++n;
2768     if (parent) {
2769       XtSetArg(args[n], XPDFNentryParent, parent); ++n;
2770     }
2771     XtSetArg(args[n], XPDFNentryExpanded, item->isOpen()); ++n;
2772     s = XmStringCreateLocalized(title->getCString());
2773     delete title;
2774     XtSetArg(args[n], XmNlabelString, s); ++n;
2775     XtSetArg(args[n], XmNuserData, item); ++n;
2776     XtSetArg(args[n], XmNmarginWidth, 0); ++n;
2777     XtSetArg(args[n], XmNmarginHeight, 2); ++n;
2778     XtSetArg(args[n], XmNshadowThickness, 0); ++n;
2779     XtSetArg(args[n], XmNforeground,
2780 	     app->getReverseVideo() ? WhitePixel(display, screenNum)
2781 	                            : BlackPixel(display, screenNum)); ++n;
2782     XtSetArg(args[n], XmNbackground, app->getPaperPixel()); ++n;
2783     label = XmCreateLabelGadget(outlineTree, "label", args, n);
2784     XmStringFree(s);
2785     if (outlineLabelsLength == outlineLabelsSize) {
2786       outlineLabelsSize += 64;
2787       outlineLabels = (Widget *)greallocn(outlineLabels,
2788 					  outlineLabelsSize, sizeof(Widget *));
2789     }
2790     outlineLabels[outlineLabelsLength++] = label;
2791     item->open();
2792     if ((kids = item->getKids())) {
2793       setupOutlineItems(kids, label, uMap);
2794     }
2795   }
2796 }
2797 
outlineSelectCbk(Widget widget,XtPointer ptr,XtPointer callData)2798 void XPDFViewer::outlineSelectCbk(Widget widget, XtPointer ptr,
2799 				  XtPointer callData) {
2800   XPDFViewer *viewer = (XPDFViewer *)ptr;
2801   XPDFTreeSelectCallbackStruct *data =
2802       (XPDFTreeSelectCallbackStruct *)callData;
2803   OutlineItem *item;
2804 
2805   XtVaGetValues(data->selectedItem, XmNuserData, &item, NULL);
2806   if (item) {
2807     if (item->getAction()) {
2808       viewer->core->doAction(item->getAction());
2809     }
2810   }
2811   viewer->core->takeFocus();
2812 }
2813 
2814 #endif // !DISABLE_OUTLINE
2815 
2816 //------------------------------------------------------------------------
2817 // GUI code: "about" dialog
2818 //------------------------------------------------------------------------
2819 
initAboutDialog()2820 void XPDFViewer::initAboutDialog() {
2821   Widget scrolledWin, col, label, sep, closeBtn;
2822   Arg args[20];
2823   int n, i;
2824   XmString s;
2825   char buf[20];
2826 
2827   //----- dialog
2828   n = 0;
2829   s = XmStringCreateLocalized(xpdfAppName ": About");
2830   XtSetArg(args[n], XmNdialogTitle, s); ++n;
2831   XtSetArg(args[n], XmNwidth, 450); ++n;
2832   XtSetArg(args[n], XmNheight, 300); ++n;
2833   aboutDialog = XmCreateFormDialog(win, "aboutDialog", args, n);
2834   XmStringFree(s);
2835 
2836   //----- "close" button
2837   n = 0;
2838   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2839   XtSetArg(args[n], XmNrightOffset, 4); ++n;
2840   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
2841   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
2842   closeBtn = XmCreatePushButton(aboutDialog, "Close", args, n);
2843   XtManageChild(closeBtn);
2844   n = 0;
2845   XtSetArg(args[n], XmNdefaultButton, closeBtn); ++n;
2846   XtSetArg(args[n], XmNcancelButton, closeBtn); ++n;
2847   XtSetValues(aboutDialog, args, n);
2848 
2849   //----- scrolled window and RowColumn
2850   n = 0;
2851   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
2852   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
2853   XtSetArg(args[n], XmNbottomWidget, closeBtn); ++n;
2854   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
2855   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
2856   XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n;
2857   scrolledWin = XmCreateScrolledWindow(aboutDialog, "scrolledWin", args, n);
2858   XtManageChild(scrolledWin);
2859   n = 0;
2860   XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n;
2861   XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n;
2862   col = XmCreateRowColumn(scrolledWin, "col", args, n);
2863   XtManageChild(col);
2864 
2865   //----- fonts
2866   aboutBigFont =
2867     createFontList("-*-times-bold-i-normal--20-*-*-*-*-*-iso8859-1");
2868   aboutVersionFont =
2869     createFontList("-*-times-medium-r-normal--16-*-*-*-*-*-iso8859-1");
2870   aboutFixedFont =
2871     createFontList("-*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1");
2872 
2873   //----- heading
2874   n = 0;
2875   s = XmStringCreateLocalized("Xpdf");
2876   XtSetArg(args[n], XmNlabelString, s); ++n;
2877   XtSetArg(args[n], XmNfontList, aboutBigFont); ++n;
2878   label = XmCreateLabel(col, "h0", args, n);
2879   XmStringFree(s);
2880   XtManageChild(label);
2881   n = 0;
2882   s = XmStringCreateLocalized("Version " xpdfVersion);
2883   XtSetArg(args[n], XmNlabelString, s); ++n;
2884   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
2885   label = XmCreateLabel(col, "h1", args, n);
2886   XmStringFree(s);
2887   XtManageChild(label);
2888   n = 0;
2889   s = XmStringCreateLocalized(xpdfCopyright);
2890   XtSetArg(args[n], XmNlabelString, s); ++n;
2891   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
2892   label = XmCreateLabel(col, "h2", args, n);
2893   XmStringFree(s);
2894   XtManageChild(label);
2895   n = 0;
2896   s = XmStringCreateLocalized(" ");
2897   XtSetArg(args[n], XmNlabelString, s); ++n;
2898   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
2899   label = XmCreateLabel(col, "h3", args, n);
2900   XmStringFree(s);
2901   XtManageChild(label);
2902   n = 0;
2903   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
2904   sep = XmCreateSeparator(col, "sep", args, n);
2905   XtManageChild(sep);
2906   n = 0;
2907   s = XmStringCreateLocalized(" ");
2908   XtSetArg(args[n], XmNlabelString, s); ++n;
2909   XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n;
2910   label = XmCreateLabel(col, "h4", args, n);
2911   XmStringFree(s);
2912   XtManageChild(label);
2913   n = 0;
2914 
2915   //----- text
2916   for (i = 0; aboutWinText[i]; ++i) {
2917     n = 0;
2918     s = XmStringCreateLocalized((char *)aboutWinText[i]);
2919     XtSetArg(args[n], XmNlabelString, s); ++n;
2920     XtSetArg(args[n], XmNfontList, aboutFixedFont); ++n;
2921     sprintf(buf, "t%d", i);
2922     label = XmCreateLabel(col, buf, args, n);
2923     XtManageChild(label);
2924     XmStringFree(s);
2925   }
2926 }
2927 
2928 //------------------------------------------------------------------------
2929 // GUI code: "open" dialog
2930 //------------------------------------------------------------------------
2931 
initOpenDialog()2932 void XPDFViewer::initOpenDialog() {
2933   Arg args[20];
2934   int n;
2935   XmString s1, s2, s3;
2936   GString *dir;
2937 
2938   n = 0;
2939   s1 = XmStringCreateLocalized("Open");
2940   XtSetArg(args[n], XmNokLabelString, s1); ++n;
2941   s2 = XmStringCreateLocalized("*.[Pp][Dd][Ff]");
2942   XtSetArg(args[n], XmNpattern, s2); ++n;
2943   s3 = XmStringCreateLocalized(xpdfAppName ": Open");
2944   XtSetArg(args[n], XmNdialogTitle, s3); ++n;
2945   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
2946   XtSetArg(args[n], XmNautoUnmanage, True); ++n;
2947   openDialog = XmCreateFileSelectionDialog(win, "openDialog", args, n);
2948   XmStringFree(s1);
2949   XmStringFree(s2);
2950   XmStringFree(s3);
2951   XtUnmanageChild(XmFileSelectionBoxGetChild(openDialog,
2952 					     XmDIALOG_HELP_BUTTON));
2953   XtAddCallback(openDialog, XmNokCallback,
2954 		&openOkCbk, (XtPointer)this);
2955 
2956   if (core->getDoc() && core->getDoc()->getFileName()) {
2957     dir = makePathAbsolute(grabPath(
2958 	      core->getDoc()->getFileName()->getCString()));
2959     s1 = XmStringCreateLocalized(dir->getCString());
2960     XtVaSetValues(openDialog, XmNdirectory, s1, NULL);
2961     XmStringFree(s1);
2962     delete dir;
2963   }
2964 }
2965 
mapOpenDialog(GBool openInNewWindowA)2966 void XPDFViewer::mapOpenDialog(GBool openInNewWindowA) {
2967   if (!openDialog) {
2968     initOpenDialog();
2969   }
2970   openInNewWindow = openInNewWindowA;
2971   XmFileSelectionDoSearch(openDialog, NULL);
2972   XtManageChild(openDialog);
2973 }
2974 
openOkCbk(Widget widget,XtPointer ptr,XtPointer callData)2975 void XPDFViewer::openOkCbk(Widget widget, XtPointer ptr,
2976 			   XtPointer callData) {
2977   XPDFViewer *viewer = (XPDFViewer *)ptr;
2978   XmFileSelectionBoxCallbackStruct *data =
2979     (XmFileSelectionBoxCallbackStruct *)callData;
2980   char *fileName;
2981   XmStringContext context;
2982   XmStringCharSet charSet;
2983   XmStringDirection dir;
2984   Boolean sep;
2985   GString *fileNameStr;
2986 
2987   XmStringInitContext(&context, data->value);
2988   if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) {
2989     fileNameStr = new GString(fileName);
2990     if (viewer->openInNewWindow) {
2991       viewer->app->open(fileNameStr);
2992     } else {
2993       if (viewer->loadFile(fileNameStr)) {
2994 	viewer->displayPage(1, viewer->core->getZoom(),
2995 			    viewer->core->getRotate(), gTrue, gTrue);
2996       }
2997     }
2998     delete fileNameStr;
2999     XtFree(charSet);
3000     XtFree(fileName);
3001   }
3002   XmStringFreeContext(context);
3003 }
3004 
3005 //------------------------------------------------------------------------
3006 // GUI code: "find" dialog
3007 //------------------------------------------------------------------------
3008 
initFindDialog()3009 void XPDFViewer::initFindDialog() {
3010   Widget form1, label, okBtn, closeBtn;
3011   Arg args[20];
3012   int n;
3013   XmString s;
3014 
3015   //----- dialog
3016   n = 0;
3017   s = XmStringCreateLocalized(xpdfAppName ": Find");
3018   XtSetArg(args[n], XmNdialogTitle, s); ++n;
3019   XtSetArg(args[n], XmNnavigationType, XmNONE); ++n;
3020   XtSetArg(args[n], XmNautoUnmanage, False); ++n;
3021   findDialog = XmCreateFormDialog(win, "findDialog", args, n);
3022   XmStringFree(s);
3023 
3024   //----- "find" and "close" buttons
3025   n = 0;
3026   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3027   XtSetArg(args[n], XmNleftOffset, 4); ++n;
3028   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
3029   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
3030   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
3031   okBtn = XmCreatePushButton(findDialog, "Find", args, n);
3032   XtManageChild(okBtn);
3033   XtAddCallback(okBtn, XmNactivateCallback,
3034 		&findFindCbk, (XtPointer)this);
3035   n = 0;
3036   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3037   XtSetArg(args[n], XmNrightOffset, 4); ++n;
3038   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
3039   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
3040   XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n;
3041   closeBtn = XmCreatePushButton(findDialog, "Close", args, n);
3042   XtManageChild(closeBtn);
3043   XtAddCallback(closeBtn, XmNactivateCallback,
3044 		&findCloseCbk, (XtPointer)this);
3045 
3046   //----- checkboxes
3047   n = 0;
3048   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3049   XtSetArg(args[n], XmNleftOffset, 4); ++n;
3050   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
3051   XtSetArg(args[n], XmNbottomWidget, okBtn); ++n;
3052   XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
3053 #if XmVERSION <= 1
3054   XtSetArg(args[n], XmNindicatorOn, True); ++n;
3055 #else
3056   XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_FILL); ++n;
3057 #endif
3058   XtSetArg(args[n], XmNset, XmUNSET); ++n;
3059   s = XmStringCreateLocalized("Search backward");
3060   XtSetArg(args[n], XmNlabelString, s); ++n;
3061   findBackwardToggle = XmCreateToggleButton(findDialog, "backward", args, n);
3062   XmStringFree(s);
3063   XtManageChild(findBackwardToggle);
3064   n = 0;
3065   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
3066   XtSetArg(args[n], XmNleftWidget, findBackwardToggle); ++n;
3067   XtSetArg(args[n], XmNleftOffset, 16); ++n;
3068   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
3069   XtSetArg(args[n], XmNbottomWidget, okBtn); ++n;
3070   XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
3071 #if XmVERSION <= 1
3072   XtSetArg(args[n], XmNindicatorOn, True); ++n;
3073 #else
3074   XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_FILL); ++n;
3075 #endif
3076   XtSetArg(args[n], XmNset, XmUNSET); ++n;
3077   s = XmStringCreateLocalized("Match case");
3078   XtSetArg(args[n], XmNlabelString, s); ++n;
3079   findCaseSensitiveToggle =
3080       XmCreateToggleButton(findDialog, "matchCase", args, n);
3081   XmStringFree(s);
3082   XtManageChild(findCaseSensitiveToggle);
3083   n = 0;
3084   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
3085   XtSetArg(args[n], XmNleftWidget, findCaseSensitiveToggle); ++n;
3086   XtSetArg(args[n], XmNleftOffset, 16); ++n;
3087   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3088   XtSetArg(args[n], XmNrightOffset, 4); ++n;
3089   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
3090   XtSetArg(args[n], XmNbottomWidget, okBtn); ++n;
3091   XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n;
3092 #if XmVERSION <= 1
3093   XtSetArg(args[n], XmNindicatorOn, True); ++n;
3094 #else
3095   XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_FILL); ++n;
3096 #endif
3097   XtSetArg(args[n], XmNset, XmUNSET); ++n;
3098   s = XmStringCreateLocalized("Whole words only");
3099   XtSetArg(args[n], XmNlabelString, s); ++n;
3100   findWholeWordToggle = XmCreateToggleButton(findDialog, "wholeWord", args, n);
3101   XmStringFree(s);
3102   XtManageChild(findWholeWordToggle);
3103 
3104   //----- search string entry
3105   n = 0;
3106   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
3107   XtSetArg(args[n], XmNtopOffset, 4); ++n;
3108   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
3109   XtSetArg(args[n], XmNbottomWidget, findBackwardToggle); ++n;
3110   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3111   XtSetArg(args[n], XmNleftOffset, 2); ++n;
3112   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3113   XtSetArg(args[n], XmNrightOffset, 2); ++n;
3114   form1 = XmCreateForm(findDialog, "form", args, n);
3115   XtManageChild(form1);
3116   n = 0;
3117   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
3118   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
3119   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3120   s = XmStringCreateLocalized("Find text: ");
3121   XtSetArg(args[n], XmNlabelString, s); ++n;
3122   label = XmCreateLabel(form1, "label", args, n);
3123   XmStringFree(s);
3124   XtManageChild(label);
3125   n = 0;
3126   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
3127   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
3128   XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n;
3129   XtSetArg(args[n], XmNleftWidget, label); ++n;
3130   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3131   findText = XmCreateTextField(form1, "text", args, n);
3132   XtManageChild(findText);
3133 #ifdef LESSTIF_VERSION
3134   XtAddCallback(findText, XmNactivateCallback,
3135 		&findFindCbk, (XtPointer)this);
3136 #endif
3137 
3138   //----- dialog parameters
3139   n = 0;
3140   XtSetArg(args[n], XmNdefaultButton, okBtn); ++n;
3141   XtSetArg(args[n], XmNcancelButton, closeBtn); ++n;
3142 #if XmVersion > 1001
3143   XtSetArg(args[n], XmNinitialFocus, findText); ++n;
3144 #endif
3145   XtSetValues(findDialog, args, n);
3146 }
3147 
findFindCbk(Widget widget,XtPointer ptr,XtPointer callData)3148 void XPDFViewer::findFindCbk(Widget widget, XtPointer ptr,
3149 			     XtPointer callData) {
3150   XPDFViewer *viewer = (XPDFViewer *)ptr;
3151 
3152   viewer->doFind(gFalse);
3153 }
3154 
mapFindDialog()3155 void XPDFViewer::mapFindDialog() {
3156   XmTextFieldSetSelection(findText, 0, XmTextFieldGetLastPosition(findText),
3157 			  XtLastTimestampProcessed(display));
3158   XmTextFieldSetInsertionPosition(findText, 0);
3159   XtManageChild(findDialog);
3160 }
3161 
doFind(GBool next)3162 void XPDFViewer::doFind(GBool next) {
3163   if (XtWindow(findDialog)) {
3164     XDefineCursor(display, XtWindow(findDialog), core->getBusyCursor());
3165   }
3166   core->find(XmTextFieldGetString(findText),
3167 	     XmToggleButtonGetState(findCaseSensitiveToggle),
3168 	     next,
3169 	     XmToggleButtonGetState(findBackwardToggle),
3170 	     XmToggleButtonGetState(findWholeWordToggle),
3171 	     gFalse);
3172   if (XtWindow(findDialog)) {
3173     XUndefineCursor(display, XtWindow(findDialog));
3174   }
3175 }
3176 
findCloseCbk(Widget widget,XtPointer ptr,XtPointer callData)3177 void XPDFViewer::findCloseCbk(Widget widget, XtPointer ptr,
3178 			      XtPointer callData) {
3179   XPDFViewer *viewer = (XPDFViewer *)ptr;
3180 
3181   XtUnmanageChild(viewer->findDialog);
3182 }
3183 
3184 //------------------------------------------------------------------------
3185 // GUI code: "save as" dialog
3186 //------------------------------------------------------------------------
3187 
initSaveAsDialog()3188 void XPDFViewer::initSaveAsDialog() {
3189   Arg args[20];
3190   int n;
3191   XmString s1, s2, s3;
3192   GString *dir;
3193 
3194   n = 0;
3195   s1 = XmStringCreateLocalized("Save");
3196   XtSetArg(args[n], XmNokLabelString, s1); ++n;
3197   s2 = XmStringCreateLocalized("*.[Pp][Dd][Ff]");
3198   XtSetArg(args[n], XmNpattern, s2); ++n;
3199   s3 = XmStringCreateLocalized(xpdfAppName ": Save as");
3200   XtSetArg(args[n], XmNdialogTitle, s3); ++n;
3201   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
3202   XtSetArg(args[n], XmNautoUnmanage, True); ++n;
3203   saveAsDialog = XmCreateFileSelectionDialog(win, "saveAsDialog", args, n);
3204   XmStringFree(s1);
3205   XmStringFree(s2);
3206   XmStringFree(s3);
3207   XtUnmanageChild(XmFileSelectionBoxGetChild(saveAsDialog,
3208 					     XmDIALOG_HELP_BUTTON));
3209   XtAddCallback(saveAsDialog, XmNokCallback,
3210 		&saveAsOkCbk, (XtPointer)this);
3211 
3212   if (core->getDoc() && core->getDoc()->getFileName()) {
3213     dir = makePathAbsolute(grabPath(
3214 	      core->getDoc()->getFileName()->getCString()));
3215     s1 = XmStringCreateLocalized(dir->getCString());
3216     XtVaSetValues(saveAsDialog, XmNdirectory, s1, NULL);
3217     XmStringFree(s1);
3218     delete dir;
3219   }
3220 }
3221 
mapSaveAsDialog()3222 void XPDFViewer::mapSaveAsDialog() {
3223   if (!saveAsDialog) {
3224     initSaveAsDialog();
3225   }
3226   XmFileSelectionDoSearch(saveAsDialog, NULL);
3227   XtManageChild(saveAsDialog);
3228 }
3229 
saveAsOkCbk(Widget widget,XtPointer ptr,XtPointer callData)3230 void XPDFViewer::saveAsOkCbk(Widget widget, XtPointer ptr,
3231 			     XtPointer callData) {
3232   XPDFViewer *viewer = (XPDFViewer *)ptr;
3233   XmFileSelectionBoxCallbackStruct *data =
3234     (XmFileSelectionBoxCallbackStruct *)callData;
3235   char *fileName;
3236   GString *fileNameStr;
3237   XmStringContext context;
3238   XmStringCharSet charSet;
3239   XmStringDirection dir;
3240   Boolean sep;
3241 
3242   XmStringInitContext(&context, data->value);
3243   if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) {
3244     fileNameStr = new GString(fileName);
3245     viewer->core->getDoc()->saveAs(fileNameStr);
3246     delete fileNameStr;
3247     XtFree(charSet);
3248     XtFree(fileName);
3249   }
3250   XmStringFreeContext(context);
3251 }
3252 
3253 //------------------------------------------------------------------------
3254 // GUI code: "print" dialog
3255 //------------------------------------------------------------------------
3256 
initPrintDialog()3257 void XPDFViewer::initPrintDialog() {
3258   Widget sep1, sep2, row, label1, label2, okBtn, cancelBtn;
3259   Arg args[20];
3260   int n;
3261   XmString s;
3262   GString *psFileName;
3263 
3264   //----- dialog
3265   n = 0;
3266   s = XmStringCreateLocalized(xpdfAppName ": Print");
3267   XtSetArg(args[n], XmNdialogTitle, s); ++n;
3268   XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
3269   printDialog = XmCreateFormDialog(win, "printDialog", args, n);
3270   XmStringFree(s);
3271 
3272   //----- "print with command"
3273   n = 0;
3274   XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n;
3275   XtSetArg(args[n], XmNtopOffset, 4); ++n;
3276   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3277   XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY); ++n;
3278   XtSetArg(args[n], XmNset, XmSET); ++n;
3279   s = XmStringCreateLocalized("Print with command:");
3280   XtSetArg(args[n], XmNlabelString, s); ++n;
3281   printWithCmdBtn = XmCreateToggleButton(printDialog, "printWithCmd", args, n);
3282   XmStringFree(s);
3283   XtManageChild(printWithCmdBtn);
3284   XtAddCallback(printWithCmdBtn, XmNvalueChangedCallback,
3285 		&printWithCmdBtnCbk, (XtPointer)this);
3286   n = 0;
3287   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3288   XtSetArg(args[n], XmNtopWidget, printWithCmdBtn); ++n;
3289   XtSetArg(args[n], XmNtopOffset, 2); ++n;
3290   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3291   XtSetArg(args[n], XmNleftOffset, 16); ++n;
3292   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3293   XtSetArg(args[n], XmNrightOffset, 4); ++n;
3294   XtSetArg(args[n], XmNcolumns, 40); ++n;
3295   printCmdText = XmCreateTextField(printDialog, "printCmd", args, n);
3296   XtManageChild(printCmdText);
3297 
3298   //----- "print to file"
3299   n = 0;
3300   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3301   XtSetArg(args[n], XmNtopWidget, printCmdText); ++n;
3302   XtSetArg(args[n], XmNtopOffset, 4); ++n;
3303   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3304   XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY); ++n;
3305   XtSetArg(args[n], XmNset, XmUNSET); ++n;
3306   s = XmStringCreateLocalized("Print to file:");
3307   XtSetArg(args[n], XmNlabelString, s); ++n;
3308   printToFileBtn = XmCreateToggleButton(printDialog, "printToFile", args, n);
3309   XmStringFree(s);
3310   XtManageChild(printToFileBtn);
3311   XtAddCallback(printToFileBtn, XmNvalueChangedCallback,
3312 		&printToFileBtnCbk, (XtPointer)this);
3313   n = 0;
3314   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3315   XtSetArg(args[n], XmNtopWidget, printToFileBtn); ++n;
3316   XtSetArg(args[n], XmNtopOffset, 2); ++n;
3317   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3318   XtSetArg(args[n], XmNleftOffset, 16); ++n;
3319   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3320   XtSetArg(args[n], XmNrightOffset, 4); ++n;
3321   XtSetArg(args[n], XmNcolumns, 40); ++n;
3322   XtSetArg(args[n], XmNsensitive, False); ++n;
3323   printFileText = XmCreateTextField(printDialog, "printFile", args, n);
3324   XtManageChild(printFileText);
3325 
3326   //----- separator
3327   n = 0;
3328   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3329   XtSetArg(args[n], XmNtopWidget, printFileText); ++n;
3330   XtSetArg(args[n], XmNtopOffset, 8); ++n;
3331   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3332   XtSetArg(args[n], XmNleftOffset, 8); ++n;
3333   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3334   XtSetArg(args[n], XmNrightOffset, 8); ++n;
3335   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
3336   sep1 = XmCreateSeparator(printDialog, "sep1", args, n);
3337   XtManageChild(sep1);
3338 
3339   //----- page range
3340   n = 0;
3341   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3342   XtSetArg(args[n], XmNtopWidget, sep1); ++n;
3343   XtSetArg(args[n], XmNtopOffset, 8); ++n;
3344   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3345   XtSetArg(args[n], XmNleftOffset, 4); ++n;
3346   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
3347   XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n;
3348   row = XmCreateRowColumn(printDialog, "row", args, n);
3349   XtManageChild(row);
3350   n = 0;
3351   s = XmStringCreateLocalized("Pages:");
3352   XtSetArg(args[n], XmNlabelString, s); ++n;
3353   label1 = XmCreateLabel(row, "label1", args, n);
3354   XmStringFree(s);
3355   XtManageChild(label1);
3356   n = 0;
3357   XtSetArg(args[n], XmNcolumns, 5); ++n;
3358   printFirstPage = XmCreateTextField(row, "printFirstPage", args, n);
3359   XtManageChild(printFirstPage);
3360   n = 0;
3361   s = XmStringCreateLocalized("to");
3362   XtSetArg(args[n], XmNlabelString, s); ++n;
3363   label2 = XmCreateLabel(row, "label2", args, n);
3364   XmStringFree(s);
3365   XtManageChild(label2);
3366   n = 0;
3367   XtSetArg(args[n], XmNcolumns, 5); ++n;
3368   printLastPage = XmCreateTextField(row, "printLastPage", args, n);
3369   XtManageChild(printLastPage);
3370 
3371   //----- separator
3372   n = 0;
3373   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3374   XtSetArg(args[n], XmNtopWidget, row); ++n;
3375   XtSetArg(args[n], XmNtopOffset, 8); ++n;
3376   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3377   XtSetArg(args[n], XmNleftOffset, 8); ++n;
3378   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3379   XtSetArg(args[n], XmNrightOffset, 8); ++n;
3380   XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
3381   sep2 = XmCreateSeparator(printDialog, "sep2", args, n);
3382   XtManageChild(sep2);
3383 
3384   //----- "print" and "cancel" buttons
3385   n = 0;
3386   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3387   XtSetArg(args[n], XmNtopWidget, sep2); ++n;
3388   XtSetArg(args[n], XmNtopOffset, 8); ++n;
3389   XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
3390   XtSetArg(args[n], XmNleftOffset, 4); ++n;
3391   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
3392   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
3393   okBtn = XmCreatePushButton(printDialog, "Print", args, n);
3394   XtManageChild(okBtn);
3395   XtAddCallback(okBtn, XmNactivateCallback,
3396 		&printPrintCbk, (XtPointer)this);
3397   n = 0;
3398   XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n;
3399   XtSetArg(args[n], XmNtopWidget, sep2); ++n;
3400   XtSetArg(args[n], XmNtopOffset, 8); ++n;
3401   XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n;
3402   XtSetArg(args[n], XmNrightOffset, 4); ++n;
3403   XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n;
3404   XtSetArg(args[n], XmNbottomOffset, 4); ++n;
3405   cancelBtn = XmCreatePushButton(printDialog, "Cancel", args, n);
3406   XtManageChild(cancelBtn);
3407   n = 0;
3408   XtSetArg(args[n], XmNdefaultButton, okBtn); ++n;
3409   XtSetArg(args[n], XmNcancelButton, cancelBtn); ++n;
3410   XtSetValues(printDialog, args, n);
3411 
3412   //----- initial values
3413   if ((psFileName = globalParams->getPSFile())) {
3414     if (psFileName->getChar(0) == '|') {
3415       XmTextFieldSetString(printCmdText,
3416 			   psFileName->getCString() + 1);
3417     } else {
3418       XmTextFieldSetString(printFileText, psFileName->getCString());
3419     }
3420     delete psFileName;
3421   }
3422 }
3423 
setupPrintDialog()3424 void XPDFViewer::setupPrintDialog() {
3425   PDFDoc *doc;
3426   char buf[20];
3427   GString *pdfFileName, *psFileName, *psFileName2;
3428   char *p;
3429 
3430   doc = core->getDoc();
3431   psFileName = globalParams->getPSFile();
3432   if (!psFileName || psFileName->getChar(0) == '|') {
3433     if ((pdfFileName = doc->getFileName())) {
3434       p = pdfFileName->getCString() + pdfFileName->getLength() - 4;
3435       if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
3436 	psFileName2 = new GString(pdfFileName->getCString(),
3437 				  pdfFileName->getLength() - 4);
3438       } else {
3439 	psFileName2 = pdfFileName->copy();
3440       }
3441       psFileName2->append(".ps");
3442       XmTextFieldSetString(printFileText, psFileName2->getCString());
3443       delete psFileName2;
3444     }
3445   }
3446   if (psFileName && psFileName->getChar(0) == '|') {
3447     XmToggleButtonSetState(printWithCmdBtn, True, False);
3448     XmToggleButtonSetState(printToFileBtn, False, False);
3449     XtVaSetValues(printCmdText, XmNsensitive, True, NULL);
3450     XtVaSetValues(printFileText, XmNsensitive, False, NULL);
3451   } else {
3452     XmToggleButtonSetState(printWithCmdBtn, False, False);
3453     XmToggleButtonSetState(printToFileBtn, True, False);
3454     XtVaSetValues(printCmdText, XmNsensitive, False, NULL);
3455     XtVaSetValues(printFileText, XmNsensitive, True, NULL);
3456   }
3457   if (psFileName) {
3458     delete psFileName;
3459   }
3460 
3461   sprintf(buf, "%d", doc->getNumPages());
3462   XmTextFieldSetString(printFirstPage, "1");
3463   XmTextFieldSetString(printLastPage, buf);
3464 }
3465 
printWithCmdBtnCbk(Widget widget,XtPointer ptr,XtPointer callData)3466 void XPDFViewer::printWithCmdBtnCbk(Widget widget, XtPointer ptr,
3467 				    XtPointer callData) {
3468   XPDFViewer *viewer = (XPDFViewer *)ptr;
3469   XmToggleButtonCallbackStruct *data =
3470       (XmToggleButtonCallbackStruct *)callData;
3471 
3472   if (data->set != XmSET) {
3473     XmToggleButtonSetState(viewer->printWithCmdBtn, True, False);
3474   }
3475   XmToggleButtonSetState(viewer->printToFileBtn, False, False);
3476   XtVaSetValues(viewer->printCmdText, XmNsensitive, True, NULL);
3477   XtVaSetValues(viewer->printFileText, XmNsensitive, False, NULL);
3478 }
3479 
printToFileBtnCbk(Widget widget,XtPointer ptr,XtPointer callData)3480 void XPDFViewer::printToFileBtnCbk(Widget widget, XtPointer ptr,
3481 				   XtPointer callData) {
3482   XPDFViewer *viewer = (XPDFViewer *)ptr;
3483   XmToggleButtonCallbackStruct *data =
3484       (XmToggleButtonCallbackStruct *)callData;
3485 
3486   if (data->set != XmSET) {
3487     XmToggleButtonSetState(viewer->printToFileBtn, True, False);
3488   }
3489   XmToggleButtonSetState(viewer->printWithCmdBtn, False, False);
3490   XtVaSetValues(viewer->printFileText, XmNsensitive, True, NULL);
3491   XtVaSetValues(viewer->printCmdText, XmNsensitive, False, NULL);
3492 }
3493 
printPrintCbk(Widget widget,XtPointer ptr,XtPointer callData)3494 void XPDFViewer::printPrintCbk(Widget widget, XtPointer ptr,
3495 			       XtPointer callData) {
3496   XPDFViewer *viewer = (XPDFViewer *)ptr;
3497   unsigned char withCmd;
3498   GString *psFileName;
3499   int firstPage, lastPage;
3500   PDFDoc *doc;
3501   PSOutputDev *psOut;
3502 
3503   doc = viewer->core->getDoc();
3504   if (!doc->okToPrint()) {
3505     error(errNotAllowed, -1, "Printing this document is not allowed.");
3506     return;
3507   }
3508 
3509   viewer->core->setBusyCursor(gTrue);
3510 
3511   XtVaGetValues(viewer->printWithCmdBtn, XmNset, &withCmd, NULL);
3512   if (withCmd) {
3513     psFileName = new GString(XmTextFieldGetString(viewer->printCmdText));
3514     psFileName->insert(0, '|');
3515   } else {
3516     psFileName = new GString(XmTextFieldGetString(viewer->printFileText));
3517   }
3518 
3519   firstPage = atoi(XmTextFieldGetString(viewer->printFirstPage));
3520   lastPage = atoi(XmTextFieldGetString(viewer->printLastPage));
3521   if (firstPage < 1) {
3522     firstPage = 1;
3523   } else if (firstPage > doc->getNumPages()) {
3524     firstPage = doc->getNumPages();
3525   }
3526   if (lastPage < firstPage) {
3527     lastPage = firstPage;
3528   } else if (lastPage > doc->getNumPages()) {
3529     lastPage = doc->getNumPages();
3530   }
3531 
3532   psOut = new PSOutputDev(psFileName->getCString(), doc,
3533 			  firstPage, lastPage, psModePS);
3534   if (psOut->isOk()) {
3535     doc->displayPages(psOut, firstPage, lastPage, 72, 72,
3536 		      0, gTrue, globalParams->getPSCrop(), gTrue);
3537   }
3538   delete psOut;
3539   delete psFileName;
3540 
3541   viewer->core->setBusyCursor(gFalse);
3542 }
3543 
3544 //------------------------------------------------------------------------
3545 // Motif support
3546 //------------------------------------------------------------------------
3547 
createFontList(char * xlfd)3548 XmFontList XPDFViewer::createFontList(char *xlfd) {
3549   XmFontList fontList;
3550 
3551 #if XmVersion <= 1001
3552 
3553   XFontStruct *font;
3554   String params;
3555   Cardinal nParams;
3556 
3557   font = XLoadQueryFont(display, xlfd);
3558   if (font) {
3559     fontList = XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
3560   } else {
3561     params = (String)xlfd;
3562     nParams = 1;
3563     XtAppWarningMsg(app->getAppContext(),
3564 		    "noSuchFont", "CvtStringToXmFontList",
3565 		    "XtToolkitError", "No such font: %s",
3566 		    &params, &nParams);
3567     fontList = NULL;
3568   }
3569 
3570 #else
3571 
3572   XmFontListEntry entry;
3573 
3574   entry = XmFontListEntryLoad(display, xlfd,
3575 			      XmFONT_IS_FONT, XmFONTLIST_DEFAULT_TAG);
3576   fontList = XmFontListAppendEntry(NULL, entry);
3577   XmFontListEntryFree(&entry);
3578 
3579 #endif
3580 
3581   return fontList;
3582 }
3583