1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
15 #include <X11/cursorfont.h>
16 #include <X11/keysym.h>
19 #include "parseargs.h"
32 #include "XOutputDev.h"
33 #include "LTKOutputDev.h"
34 #include "PSOutputDev.h"
35 #include "TextOutputDev.h"
40 #ifdef XlibSpecificationRelease
41 #if XlibSpecificationRelease < 5
42 typedef char *XPointer;
45 typedef char *XPointer;
48 // hack around old X includes which are missing these symbols
50 #define XK_Page_Up 0xFF55
53 #define XK_Page_Down 0xFF56
56 #define XK_KP_Home 0xFF95
59 #define XK_KP_Left 0xFF96
62 #define XK_KP_Up 0xFF97
65 #define XK_KP_Right 0xFF98
68 #define XK_KP_Down 0xFF99
71 #define XK_KP_Prior 0xFF9A
74 #define XK_KP_Page_Up 0xFF9A
77 #define XK_KP_Next 0xFF9B
79 #ifndef XK_KP_Page_Down
80 #define XK_KP_Page_Down 0xFF9B
83 #define XK_KP_End 0xFF9C
86 #define XK_KP_Begin 0xFF9D
89 #define XK_KP_Insert 0xFF9E
92 #define XK_KP_Delete 0xFF9F
95 //------------------------------------------------------------------------
96 // misc constants / enums
97 //------------------------------------------------------------------------
99 #define remoteCmdLength 256
110 //------------------------------------------------------------------------
112 //------------------------------------------------------------------------
114 // loadFile / displayPage
115 static GBool loadFile(GString *fileName);
116 static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist);
118 // key press and menu callbacks
119 static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers,
121 static void menuCbk(LTKMenuItem *item);
124 static void buttonPressCbk(LTKWidget *canvas1, int n,
125 int mx, int my, int button, GBool dblClick);
126 static void buttonReleaseCbk(LTKWidget *canvas1, int n,
127 int mx, int my, int button, GBool click);
128 static void doLink(int mx, int my);
129 static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my);
130 static void mouseDragCbk(LTKWidget *widget, int widgetNum,
131 int mx, int my, int button);
134 static void nextPageCbk(LTKWidget *button, int n, GBool on);
135 static void nextTenPageCbk(LTKWidget *button, int n, GBool on);
136 static void gotoNextPage(int inc, GBool top);
137 static void prevPageCbk(LTKWidget *button, int n, GBool on);
138 static void prevTenPageCbk(LTKWidget *button, int n, GBool on);
139 static void gotoPrevPage(int dec, GBool top, GBool bottom);
140 static void backCbk(LTKWidget *button, int n, GBool on);
141 static void forwardCbk(LTKWidget *button, int n, GBool on);
142 static void pageNumCbk(LTKWidget *textIn, int n, GString *text);
143 static void zoomMenuCbk(LTKMenuItem *item);
144 static void postScriptCbk(LTKWidget *button, int n, GBool on);
145 static void aboutCbk(LTKWidget *button, int n, GBool on);
146 static void quitCbk(LTKWidget *button, int n, GBool on);
148 // scrollbar callbacks
149 static void scrollVertCbk(LTKWidget *scrollbar, int n, int val);
150 static void scrollHorizCbk(LTKWidget *scrollbar, int n, int val);
153 static void layoutCbk(LTKWindow *win1);
154 static void updateScrollbars();
155 static void propChangeCbk(LTKWindow *win1, Atom atom);
158 static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax);
161 static void mapOpenDialog();
162 static void openButtonCbk(LTKWidget *button, int n, GBool on);
163 static void openSelectCbk(LTKWidget *widget, int n, GString *name);
166 static void reloadCbk();
169 static void mapSaveDialog();
170 static void saveButtonCbk(LTKWidget *button, int n, GBool on);
171 static void saveSelectCbk(LTKWidget *widget, int n, GString *name);
173 // "PostScript" dialog
174 static void mapPSDialog();
175 static void psButtonCbk(LTKWidget *button, int n, GBool on);
178 static void mapAboutWin();
179 static void closeAboutCbk(LTKWidget *button, int n, GBool on);
182 static void findCbk(LTKWidget *button, int n, GBool on);
183 static void mapFindWin();
184 static void findButtonCbk(LTKWidget *button, int n, GBool on);
185 static void doFind(char *s);
188 static void killCbk(LTKWindow *win1);
190 //------------------------------------------------------------------------
191 // command line options
192 //------------------------------------------------------------------------
194 static XrmOptionDescRec opts[] = {
195 {"-display", ".display", XrmoptionSepArg, NULL},
196 {"-foreground", ".foreground", XrmoptionSepArg, NULL},
197 {"-fg", ".foreground", XrmoptionSepArg, NULL},
198 {"-background", ".background", XrmoptionSepArg, NULL},
199 {"-bg", ".background", XrmoptionSepArg, NULL},
200 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
201 {"-g", ".geometry", XrmoptionSepArg, NULL},
202 {"-font", ".font", XrmoptionSepArg, NULL},
203 {"-fn", ".font", XrmoptionSepArg, NULL},
204 {"-title", ".title", XrmoptionSepArg, NULL},
205 {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"},
206 {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL},
207 {"-papercolor", ".paperColor", XrmoptionSepArg, NULL},
209 {"-eucjp", ".eucjp", XrmoptionNoArg, (XPointer)"off"},
212 {"-t1lib", ".t1libControl", XrmoptionSepArg, NULL},
214 #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
215 {"-freetype", ".freeTypeControl", XrmoptionSepArg, NULL},
217 {"-z", ".initialZoom", XrmoptionSepArg, NULL},
218 {"-ps", ".psFile", XrmoptionSepArg, NULL},
219 {"-paperw", ".psPaperWidth", XrmoptionSepArg, NULL},
220 {"-paperh", ".psPaperHeight", XrmoptionSepArg, NULL},
221 {"-level1", ".psLevel1", XrmoptionNoArg, (XPointer)"false"},
225 static GBool printVersion = gFalse;
226 static GBool printHelp = gFalse;
227 static char remoteName[100] = "xpdf_";
228 static GBool doRemoteRaise = gFalse;
229 static GBool doRemoteQuit = gFalse;
230 static GBool viKeys = gFalse;
231 static char userPassword[33] = "";
232 static GBool fullScreen = gFalse;
234 static ArgDesc argDesc[] = {
235 {"-z", argStringDummy, NULL, 0,
236 "initial zoom level (-5..5, page, width)"},
237 {"-g", argStringDummy, NULL, 0,
238 "initial window geometry"},
239 {"-geometry", argStringDummy, NULL, 0,
240 "initial window geometry"},
241 {"-title", argStringDummy, NULL, 0,
243 {"-remote", argString, remoteName + 5, sizeof(remoteName) - 5,
244 "start/contact xpdf remote server with specified name"},
245 {"-raise", argFlag, &doRemoteRaise, 0,
246 "raise xpdf remote server window (with -remote only)"},
247 {"-quit", argFlag, &doRemoteQuit, 0,
248 "kill xpdf remote server (with -remote only)"},
249 {"-cmap", argFlagDummy, NULL, 0,
250 "install a private colormap"},
251 {"-rgb", argIntDummy, NULL, 0,
252 "biggest RGB cube to allocate (default is 5)"},
253 {"-papercolor", argStringDummy, NULL, 0,
254 "color of paper background"},
256 {"-eucjp", argStringDummy, NULL, 0,
257 "convert Japanese text to EUC-JP"},
260 {"-t1lib", argStringDummy, NULL, 0,
261 "t1lib font control: none, plain, low, high"},
263 #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
264 {"-freetype", argStringDummy, NULL, 0,
265 "FreeType font control: none, plain, aa"},
267 {"-ps", argStringDummy, NULL, 0,
268 "default PostScript file/command name"},
269 {"-paperw", argIntDummy, NULL, 0,
270 "paper width, in points"},
271 {"-paperh", argIntDummy, NULL, 0,
272 "paper height, in points"},
273 {"-level1", argFlagDummy, NULL, 0,
274 "generate Level 1 PostScript"},
275 {"-upw", argString, userPassword, sizeof(userPassword),
276 "user password (for encrypted files)"},
277 {"-fullscreen", argFlag, &fullScreen, 0,
278 "run in full-screen (presentation) mode"},
279 {"-cmd", argFlag, &printCommands, 0,
280 "print commands as they're executed"},
281 {"-q", argFlag, &errQuiet, 0,
282 "don't print any messages or errors"},
283 {"-v", argFlag, &printVersion, 0,
284 "print copyright and version info"},
285 {"-h", argFlag, &printHelp, 0,
286 "print usage information"},
287 {"-help", argFlag, &printHelp, 0,
288 "print usage information"},
292 //------------------------------------------------------------------------
294 //------------------------------------------------------------------------
296 // zoom factor is 1.2 (similar to DVI magsteps)
300 #define zoomWidth 101
301 static int zoomDPI[maxZoom - minZoom + 1] = {
304 86, 104, 124, 149, 179
307 #define defZoomStr "1"
311 static LTKOutputDev *out;
318 static time_t modTime; // last modification time of PDF file
320 static LinkAction *linkAction; // mouse pointer is over this link
321 static int // coordinates of current selection:
322 selectXMin, selectYMin, // (xMin==xMax || yMin==yMax) means there
323 selectXMax, selectYMax; // is no selection
324 static GBool lastDragLeft; // last dragged selection edge was left/right
325 static GBool lastDragTop; // last dragged selection edge was top/bottom
326 static int panMX, panMY; // last mouse position for pan
332 #define historySize 50
333 static History // page history queue
334 history[historySize];
335 static int historyCur; // currently displayed page
336 static int historyBLen; // number of valid entries backward from
338 static int historyFLen; // number of valid entries forward from
341 static GString *defPSFileName;
342 static GString *psFileName;
343 static int psFirstPage, psLastPage;
345 static GString *fileReqDir; // current directory for file requesters
347 static GString *urlCommand; // command to execute for URI links
349 static GString *windowTitle; // window title string
352 static Display *display;
353 static LTKWindow *win;
354 static LTKMenu *zoomMenu;
355 static LTKScrollingCanvas *canvas;
356 static LTKScrollbar *hScrollbar, *vScrollbar;
357 static LTKTextIn *pageNumText;
358 static LTKLabel *numPagesLabel;
359 static LTKLabel *linkLabel;
360 static LTKMenuButton *zoomMenuBtn;
361 static LTKWindow *aboutWin;
362 static LTKWindow *psDialog;
363 static LTKWindow *openDialog;
364 static LTKWindow *saveDialog;
365 static LTKWindow *findWin;
366 static Atom remoteAtom;
369 //------------------------------------------------------------------------
371 //------------------------------------------------------------------------
373 #include "xpdfIcon.xpm"
374 #include "leftArrow.xbm"
375 #include "dblLeftArrow.xbm"
376 #include "rightArrow.xbm"
377 #include "dblRightArrow.xbm"
378 #include "backArrow.xbm"
379 #include "forwardArrow.xbm"
381 #include "postscript.xbm"
383 #include "xpdf-ltk.h"
385 //------------------------------------------------------------------------
387 //------------------------------------------------------------------------
389 int main(int argc, char *argv[]) {
392 char cmd[remoteCmdLength];
396 unsigned long paperColor;
400 double width1, height1;
415 fileReqDir = getCurrentDir();
419 paperWidth = paperHeight = -1;
420 ok = parseArgs(argDesc, &argc, argv);
426 initParams(xpdfConfigFile);
428 // create LTKApp (and parse X-related args)
429 app = new LTKApp("xpdf", opts, &argc, argv);
430 app->setKillCbk(&killCbk);
431 display = app->getDisplay();
433 // check command line
435 ok = ok && remoteName[5] && !doRemoteQuit && argc >= 1 && argc <= 3;
436 else if (doRemoteQuit)
437 ok = ok && remoteName[5] && argc == 1;
439 ok = ok && argc >= 1 && argc <= 3;
440 if (!ok || printVersion || printHelp) {
441 fprintf(stderr, "xpdf version %s\n", xpdfVersion);
442 fprintf(stderr, "%s\n", xpdfCopyright);
444 printUsage("xpdf", "[<PDF-file> [<page>]]", argDesc);
450 name = new GString(argv[1]);
458 // look for already-running remote server
460 remoteAtom = XInternAtom(display, remoteName, False);
461 xwin = XGetSelectionOwner(display, remoteAtom);
464 sprintf(cmd, "%c %d %.200s", doRemoteRaise ? 'D' : 'd',
465 pg, name->getCString());
466 XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
467 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
469 } else if (doRemoteRaise) {
470 XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
471 PropModeReplace, (Guchar *)"r", 2);
472 } else if (doRemoteQuit) {
473 XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
474 PropModeReplace, (Guchar *)"q", 2);
483 historyCur = historySize - 1;
484 historyBLen = historyFLen = 0;
485 for (i = 0; i < historySize; ++i)
486 history[i].fileName = NULL;
489 defPSFileName = app->getStringResource("psFile", NULL);
491 if (!loadFile(name)) {
496 fileReqDir = makePathAbsolute(grabPath(name->getCString()));
499 // check for legal page number
500 if (doc && (pg < 1 || pg > doc->getNumPages()))
507 win = makeFullScreenWindow(app);
508 win->setDecorated(gFalse);
510 zoomMenu = makeZoomMenu();
511 win = makeWindow(app);
514 canvas = (LTKScrollingCanvas *)win->findWidget("canvas");
515 hScrollbar = (LTKScrollbar *)win->findWidget("hScrollbar");
516 vScrollbar = (LTKScrollbar *)win->findWidget("vScrollbar");
517 pageNumText = (LTKTextIn *)win->findWidget("pageNum");
518 numPagesLabel = (LTKLabel *)win->findWidget("numPages");
519 linkLabel = (LTKLabel *)win->findWidget("link");
520 zoomMenuBtn = (LTKMenuButton *)win->findWidget("zoom");
521 win->setKeyCbk(&keyPressCbk);
522 win->setLayoutCbk(&layoutCbk);
523 canvas->setButtonPressCbk(&buttonPressCbk);
524 canvas->setButtonReleaseCbk(&buttonReleaseCbk);
525 canvas->setMouseMoveCbk(&mouseMoveCbk);
526 canvas->setMouseDragCbk(&mouseDragCbk);
528 hScrollbar->setRepeatPeriod(0);
529 vScrollbar->setRepeatPeriod(0);
533 paperWidth = app->getIntResource("psPaperWidth", defPaperWidth);
534 paperHeight = app->getIntResource("psPaperHeight", defPaperHeight);
535 psOutLevel1 = app->getBoolResource("psLevel1", gFalse);
536 urlCommand = app->getStringResource("urlCommand", NULL);
537 windowTitle = app->getStringResource("title", NULL);
538 installCmap = app->getBoolResource("installCmap", gFalse);
540 win->setInstallCmap(gTrue);
541 rgbCubeSize = app->getIntResource("rgbCubeSize", defaultRGBCube);
542 paperColor = app->getColorResource("paperColor", "white",
543 WhitePixel(display, app->getScreenNum()),
546 useEUCJP = app->getBoolResource("eucjp", gFalse);
551 t1libControl = app->getStringResource("t1libControl", "low");
553 #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
554 freeTypeControl = app->getStringResource("freeTypeControl", "aa");
556 t1Courier = app->getStringResource("t1Courier", NULL);
557 t1CourierBold = app->getStringResource("t1CourierBold", NULL);
558 t1CourierBoldOblique = app->getStringResource("t1CourierBoldOblique", NULL);
559 t1CourierOblique = app->getStringResource("t1CourierOblique", NULL);
560 t1Helvetica = app->getStringResource("t1Helvetica", NULL);
561 t1HelveticaBold = app->getStringResource("t1HelveticaBold", NULL);
562 t1HelveticaBoldOblique =
563 app->getStringResource("t1HelveticaBoldOblique", NULL);
564 t1HelveticaOblique = app->getStringResource("t1HelveticaOblique", NULL);
565 t1Symbol = app->getStringResource("t1Symbol", NULL);
566 t1TimesBold = app->getStringResource("t1TimesBold", NULL);
567 t1TimesBoldItalic = app->getStringResource("t1TimesBoldItalic", NULL);
568 t1TimesItalic = app->getStringResource("t1TimesItalic", NULL);
569 t1TimesRoman = app->getStringResource("t1TimesRoman", NULL);
570 t1ZapfDingbats = app->getStringResource("t1ZapfDingbats", NULL);
572 japan12Font = app->getStringResource("japaneseFont", NULL);
574 #if CHINESE_GB_SUPPORT
575 gb12Font = app->getStringResource("chineseGBFont", NULL);
577 #if CHINESE_CNS_SUPPORT
578 cns13Font = app->getStringResource("chineseCNSFont", NULL);
583 zoomStr = app->getStringResource("initialZoom", defZoomStr);
584 if (!zoomStr->cmp("page")) {
586 i = maxZoom - minZoom + 2;
587 } else if (!zoomStr->cmp("width")) {
589 i = maxZoom - minZoom + 3;
591 zoom = atoi(zoomStr->getCString());
594 else if (zoom > maxZoom)
599 zoomMenuBtn->setInitialMenuItem(zoomMenu->getItem(i));
601 viKeys = app->getBoolResource("viKeys", gFalse);
606 width = app->getDisplayWidth();
607 height = app->getDisplayHeight();
611 app->getGeometryResource("geometry", &x, &y, &width, &height);
612 if (width == 0 || height == 0) {
613 if (!doc || doc->getNumPages() == 0) {
616 } else if (doc->getPageRotate(pg) == 90 ||
617 doc->getPageRotate(pg) == 270) {
618 width1 = doc->getPageHeight(pg);
619 height1 = doc->getPageWidth(pg);
621 width1 = doc->getPageWidth(pg);
622 height1 = doc->getPageHeight(pg);
624 if (zoom == zoomPage || zoom == zoomWidth) {
625 width = (int)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
626 height = (int)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
628 width = (int)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
629 height = (int)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
633 if (width > (Guint)app->getDisplayWidth() - 100) {
634 width = app->getDisplayWidth() - 100;
636 if (height > (Guint)app->getDisplayHeight() - 100) {
637 height = app->getDisplayHeight() - 100;
642 // finish setting up window
644 sprintf(s, "of %d", doc ? doc->getNumPages() : 0);
645 numPagesLabel->setText(s);
648 title = windowTitle->copy();
650 title = new GString("xpdf: ");
653 title = new GString("xpdf");
655 win->setTitle(title);
656 win->layout(x, y, width, height);
663 gcValues.foreground = BlackPixel(display, win->getScreenNum()) ^
664 WhitePixel(display, win->getScreenNum());
665 gcValues.function = GXxor;
666 selectGC = XCreateGC(display, win->getXWindow(),
667 GCForeground | GCFunction, &gcValues);
669 // set up remote server
670 if (remoteAtom != None) {
671 win->setPropChangeCbk(&propChangeCbk);
672 xwin = win->getXWindow();
673 XSetSelectionOwner(display, remoteAtom, xwin, CurrentTime);
676 // create output device
677 out = new LTKOutputDev(win, paperColor);
680 // display first page
681 displayPage(pg, zoom, 0, gTrue);
690 // release remote control atom
691 if (remoteAtom != None)
692 XSetSelectionOwner(display, remoteAtom, None, CurrentTime);
718 delete defPSFileName;
734 #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
735 if (freeTypeControl) {
736 delete freeTypeControl;
743 delete t1CourierBold;
745 if (t1CourierBoldOblique) {
746 delete t1CourierBoldOblique;
748 if (t1CourierOblique) {
749 delete t1CourierOblique;
754 if (t1HelveticaBold) {
755 delete t1HelveticaBold;
757 if (t1HelveticaBoldOblique) {
758 delete t1HelveticaBoldOblique;
760 if (t1HelveticaOblique) {
761 delete t1HelveticaOblique;
769 if (t1TimesBoldItalic) {
770 delete t1TimesBoldItalic;
773 delete t1TimesItalic;
778 if (t1ZapfDingbats) {
779 delete t1ZapfDingbats;
786 #if CHINESE_GB_SUPPORT
791 #if CHINESE_CNS_SUPPORT
796 for (i = 0; i < historySize; ++i) {
797 if (history[i].fileName) {
798 delete history[i].fileName;
803 // check for memory leaks
804 Object::memCheck(errFile ? errFile : stderr);
805 gMemReport(errFile ? errFile : stderr);
810 //------------------------------------------------------------------------
811 // loadFile / displayPage
812 //------------------------------------------------------------------------
814 static GBool loadFile(GString *fileName) {
823 win->setBusyCursor(gTrue);
826 if (userPassword[0]) {
827 userPW = new GString(userPassword);
831 newDoc = new PDFDoc(fileName, userPW);
835 if (!newDoc->isOk()) {
838 win->setBusyCursor(gFalse);
842 // replace old document
849 // nothing displayed yet
852 // save the modification time
853 modTime = getModTime(fileName->getCString());
855 // init PostScript output params
859 psFileName = defPSFileName->copy();
861 p = fileName->getCString() + fileName->getLength() - 4;
862 if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
863 psFileName = new GString(fileName->getCString(),
864 fileName->getLength() - 4);
866 psFileName = fileName->copy();
867 psFileName->append(".ps");
870 psLastPage = doc->getNumPages();
872 // set up title, number-of-pages display; back to normal cursor
875 title = new GString("xpdf: ");
876 title->append(fileName);
877 win->setTitle(title);
880 sprintf(s, "of %d", doc->getNumPages());
881 numPagesLabel->setText(s);
883 win->setBusyCursor(gFalse);
890 static void displayPage(int page1, int zoom1, int rotate1, GBool addToHist) {
892 double hDPI, vDPI, dpi;
897 // check for document
898 if (!doc || doc->getNumPages() == 0)
901 // check for changes to the file
902 modTime1 = getModTime(doc->getFileName()->getCString());
903 if (modTime1 != modTime) {
904 if (loadFile(doc->getFileName()->copy())) {
905 if (page1 > doc->getNumPages()) {
906 page1 = doc->getNumPages();
914 win->setBusyCursor(gTrue);
916 // new page/zoom/rotate values
921 // initialize mouse-related stuff
923 win->setDefaultCursor();
925 linkLabel->setText(NULL);
927 selectXMin = selectXMax = 0;
928 selectYMin = selectYMax = 0;
929 lastDragLeft = lastDragTop = gTrue;
932 rot = rotate + doc->getPageRotate(page);
938 if (rot == 90 || rot == 270) {
939 hDPI = (win->getWidth() / doc->getPageHeight(page)) * 72;
940 vDPI = (win->getHeight() / doc->getPageWidth(page)) * 72;
942 hDPI = (win->getWidth() / doc->getPageWidth(page)) * 72;
943 vDPI = (win->getHeight() / doc->getPageHeight(page)) * 72;
945 dpi = (hDPI < vDPI) ? hDPI : vDPI;
946 } else if (zoom == zoomPage) {
947 if (rot == 90 || rot == 270) {
948 hDPI = ((win->getWidth() - 28) / doc->getPageHeight(page)) * 72;
949 vDPI = ((win->getHeight() - 56) / doc->getPageWidth(page)) * 72;
951 hDPI = ((win->getWidth() - 28) / doc->getPageWidth(page)) * 72;
952 vDPI = ((win->getHeight() - 56) / doc->getPageHeight(page)) * 72;
954 dpi = (hDPI < vDPI) ? hDPI : vDPI;
955 } else if (zoom == zoomWidth) {
956 if (rot == 90 || rot == 270) {
957 dpi = ((win->getWidth() - 28) / doc->getPageHeight(page)) * 72;
959 dpi = ((win->getWidth() - 28) / doc->getPageWidth(page)) * 72;
962 dpi = zoomDPI[zoom - minZoom];
964 doc->displayPage(out, page, dpi, rotate, gTrue);
967 // update page number display
969 sprintf(s, "%d", page);
970 pageNumText->setText(s);
975 if (++historyCur == historySize)
977 h = &history[historyCur];
980 h->fileName = doc->getFileName()->copy();
982 if (historyBLen < historySize)
987 // back to regular cursor
988 win->setBusyCursor(gFalse);
991 //------------------------------------------------------------------------
992 // key press and menu callbacks
993 //------------------------------------------------------------------------
995 static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers,
1013 gotoNextPage(1, !(modifiers & Mod5Mask));
1017 gotoPrevPage(1, !(modifiers & Mod5Mask), gFalse);
1021 vScrollbar->getPos() >=
1022 canvas->getRealHeight() - canvas->getHeight()) {
1023 gotoNextPage(1, gTrue);
1025 vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
1026 canvas->getHeight());
1027 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1033 gotoPrevPage(1, gTrue, gFalse);
1034 } else if (vScrollbar->getPos() == 0) {
1035 gotoPrevPage(1, gFalse, gTrue);
1037 vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
1038 canvas->getHeight());
1039 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1042 case 'h': // vi-style left
1047 hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth());
1048 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1051 case 'l': // vi-style right
1056 hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth());
1057 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1060 case 'k': // vi-style up
1065 vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight());
1066 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1069 case 'j': // vi-style down
1074 vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight());
1075 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1080 displayPage(page, zoom, rotate, gFalse);
1084 quitCbk(NULL, 0, gTrue);
1094 hScrollbar->setPos(0, canvas->getWidth());
1095 vScrollbar->setPos(0, canvas->getHeight());
1096 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1103 hScrollbar->setPos(canvas->getRealWidth() - canvas->getWidth(),
1104 canvas->getWidth());
1105 vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(),
1106 canvas->getHeight());
1107 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1112 gotoPrevPage(1, gTrue, gFalse);
1113 } else if (vScrollbar->getPos() == 0) {
1114 gotoPrevPage(1, gFalse, gTrue);
1116 vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
1117 canvas->getHeight());
1118 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1122 case XK_KP_Page_Down:
1124 vScrollbar->getPos() >=
1125 canvas->getRealHeight() - canvas->getHeight()) {
1126 gotoNextPage(1, gTrue);
1128 vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
1129 canvas->getHeight());
1130 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1138 hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth());
1139 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1146 hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth());
1147 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1154 vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight());
1155 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1162 vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight());
1163 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1169 static void menuCbk(LTKMenuItem *item) {
1172 switch (item->getItemNum()) {
1183 case menuRotateLeft:
1185 r = (rotate == 0) ? 270 : rotate - 90;
1186 displayPage(page, zoom, r, gFalse);
1189 case menuRotateRight:
1191 r = (rotate == 270) ? 0 : rotate + 90;
1192 displayPage(page, zoom, r, gFalse);
1201 //------------------------------------------------------------------------
1203 //------------------------------------------------------------------------
1205 static void buttonPressCbk(LTKWidget *canvas1, int n,
1206 int mx, int my, int button, GBool dblClick) {
1207 if (!doc || doc->getNumPages() == 0)
1210 setSelection(mx, my, mx, my);
1211 } else if (!fullScreen && button == 2) {
1212 panMX = mx - hScrollbar->getPos();
1213 panMY = my - vScrollbar->getPos();
1217 static void buttonReleaseCbk(LTKWidget *canvas1, int n,
1218 int mx, int my, int button, GBool click) {
1221 if (!doc || doc->getNumPages() == 0)
1226 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1227 #ifndef NO_TEXT_SELECT
1228 if (doc->okToCopy()) {
1229 s = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
1230 win->setSelection(NULL, s);
1232 error(-1, "Copying of text from this document is not allowed.");
1238 setSelection(mx, my, mx, my);
1244 static void doLink(int mx, int my) {
1245 LinkActionKind kind;
1246 LinkAction *action = NULL;
1251 GString *actionName;
1256 LTKButtonDialog *dialog;
1260 out->cvtDevToUser(mx, my, &x, &y);
1261 if ((action = doc->findLink(x, y))) {
1262 switch (kind = action->getKind()) {
1264 // GoTo / GoToR action
1267 if (kind == actionGoTo) {
1270 if ((dest = ((LinkGoTo *)action)->getDest()))
1271 dest = dest->copy();
1272 else if ((namedDest = ((LinkGoTo *)action)->getNamedDest()))
1273 namedDest = namedDest->copy();
1277 if ((dest = ((LinkGoToR *)action)->getDest()))
1278 dest = dest->copy();
1279 else if ((namedDest = ((LinkGoToR *)action)->getNamedDest()))
1280 namedDest = namedDest->copy();
1281 s = ((LinkGoToR *)action)->getFileName()->getCString();
1282 //~ translate path name for VMS (deal with '/')
1283 if (isAbsolutePath(s))
1284 fileName = new GString(s);
1286 fileName = appendToPath(
1287 grabPath(doc->getFileName()->getCString()), s);
1288 if (!loadFile(fileName)) {
1297 dest = doc->findDest(namedDest);
1301 if (kind == actionGoToR)
1302 displayPage(1, zoom, 0, gTrue);
1304 if (dest->isPageRef()) {
1305 pageRef = dest->getPageRef();
1306 pg = doc->findPage(pageRef.num, pageRef.gen);
1308 pg = dest->getPageNum();
1310 if (pg > 0 && pg != page)
1311 displayPage(pg, zoom, rotate, gTrue);
1313 displayPage(1, zoom, rotate, gTrue);
1318 switch (dest->getKind()) {
1320 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
1321 if (dest->getChangeLeft() || dest->getChangeTop()) {
1322 if (dest->getChangeLeft())
1323 hScrollbar->setPos(dx, canvas->getWidth());
1324 if (dest->getChangeTop())
1325 vScrollbar->setPos(dy, canvas->getHeight());
1326 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1328 //~ what is the zoom parameter?
1333 hScrollbar->setPos(0, canvas->getWidth());
1334 vScrollbar->setPos(0, canvas->getHeight());
1335 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1340 out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
1341 hScrollbar->setPos(0, canvas->getWidth());
1342 vScrollbar->setPos(dy, canvas->getHeight());
1343 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1348 out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
1349 hScrollbar->setPos(dx, canvas->getWidth());
1350 vScrollbar->setPos(0, canvas->getHeight());
1351 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1355 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
1356 hScrollbar->setPos(dx, canvas->getWidth());
1357 vScrollbar->setPos(dy, canvas->getHeight());
1358 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1367 fileName = ((LinkLaunch *)action)->getFileName();
1368 s = fileName->getCString();
1369 if (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
1370 !strcmp(s + fileName->getLength() - 4, ".PDF")) {
1371 //~ translate path name for VMS (deal with '/')
1372 if (isAbsolutePath(s))
1373 fileName = fileName->copy();
1375 fileName = appendToPath(
1376 grabPath(doc->getFileName()->getCString()), s);
1377 if (!loadFile(fileName))
1379 displayPage(1, zoom, rotate, gTrue);
1381 fileName = fileName->copy();
1382 if (((LinkLaunch *)action)->getParams()) {
1383 fileName->append(' ');
1384 fileName->append(((LinkLaunch *)action)->getParams());
1387 fileName->insert(0, "spawn/nowait ");
1388 #elif defined(__EMX__)
1389 fileName->insert(0, "start /min /n ");
1391 fileName->append(" &");
1393 dialog = new LTKButtonDialog(win, "xpdf: Launch",
1394 "Execute the command:",
1395 fileName->getCString(),
1396 NULL, "Ok", "Cancel");
1398 system(fileName->getCString());
1407 for (s = urlCommand->getCString(); *s; ++s) {
1408 if (s[0] == '%' && s[1] == 's') {
1413 fileName = ((LinkURI *)action)->getURI()->copy();
1414 // filter out any quote marks (' or ") to avoid a potential
1417 while (i < fileName->getLength()) {
1418 if (fileName->getChar(i) == '"') {
1420 fileName->insert(i, "%22");
1422 } else if (fileName->getChar(i) == '\'') {
1424 fileName->insert(i, "%27");
1430 fileName->insert(0, urlCommand->getCString(),
1431 s - urlCommand->getCString());
1432 fileName->append(s+2);
1434 fileName = urlCommand->copy();
1437 fileName->insert(0, "spawn/nowait ");
1438 #elif defined(__EMX__)
1439 fileName->insert(0, "start /min /n ");
1441 fileName->append(" &");
1443 system(fileName->getCString());
1446 fprintf(errFile, "URI: %s\n",
1447 ((LinkURI *)action)->getURI()->getCString());
1453 actionName = ((LinkNamed *)action)->getName();
1454 if (!actionName->cmp("NextPage")) {
1455 gotoNextPage(1, gTrue);
1456 } else if (!actionName->cmp("PrevPage")) {
1457 gotoPrevPage(1, gTrue, gFalse);
1458 } else if (!actionName->cmp("FirstPage")) {
1460 displayPage(1, zoom, rotate, gTrue);
1462 } else if (!actionName->cmp("LastPage")) {
1463 if (page != doc->getNumPages()) {
1464 displayPage(doc->getNumPages(), zoom, rotate, gTrue);
1466 } else if (!actionName->cmp("GoBack")) {
1467 backCbk(NULL, 0, gTrue);
1468 } else if (!actionName->cmp("GoForward")) {
1469 forwardCbk(NULL, 0, gTrue);
1470 } else if (!actionName->cmp("Quit")) {
1471 quitCbk(NULL, 0, gTrue);
1473 error(-1, "Unknown named action: '%s'", actionName->getCString());
1477 // unknown action type
1479 error(-1, "Unknown link action type: '%s'",
1480 ((LinkUnknown *)action)->getAction()->getCString());
1486 static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my) {
1491 if (!doc || doc->getNumPages() == 0)
1493 out->cvtDevToUser(mx, my, &x, &y);
1494 if ((action = doc->findLink(x, y))) {
1495 if (action != linkAction) {
1497 win->setCursor(XC_hand2);
1499 linkAction = action;
1502 switch (linkAction->getKind()) {
1504 s = "[internal link]";
1507 s = ((LinkGoToR *)linkAction)->getFileName()->getCString();
1510 s = ((LinkLaunch *)linkAction)->getFileName()->getCString();
1513 s = ((LinkURI *)action)->getURI()->getCString();
1516 s = ((LinkNamed *)linkAction)->getName()->getCString();
1519 s = "[unknown link]";
1522 linkLabel->setText(s);
1528 win->setDefaultCursor();
1530 linkLabel->setText(NULL);
1536 static void mouseDragCbk(LTKWidget *widget, int widgetNum,
1537 int mx, int my, int button) {
1539 int xMin, yMin, xMax, yMax;
1544 // clip mouse coords
1548 else if (x >= canvas->getRealWidth())
1549 x = canvas->getRealWidth() - 1;
1553 else if (y >= canvas->getRealHeight())
1554 y = canvas->getRealHeight() - 1;
1556 // move appropriate edges of selection
1558 if (x < selectXMax) {
1564 lastDragLeft = gFalse;
1567 if (x > selectXMin) {
1573 lastDragLeft = gTrue;
1577 if (y < selectYMax) {
1583 lastDragTop = gFalse;
1586 if (y > selectYMin) {
1592 lastDragTop = gTrue;
1596 // redraw the selection
1597 setSelection(xMin, yMin, xMax, yMax);
1600 } else if (!fullScreen && button == 2) {
1601 mx -= hScrollbar->getPos();
1602 my -= vScrollbar->getPos();
1603 hScrollbar->setPos(hScrollbar->getPos() - (mx - panMX),
1604 canvas->getWidth());
1605 vScrollbar->setPos(vScrollbar->getPos() - (my - panMY),
1606 canvas->getHeight());
1607 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1613 //------------------------------------------------------------------------
1615 //------------------------------------------------------------------------
1617 static void nextPageCbk(LTKWidget *button, int n, GBool on) {
1618 gotoNextPage(1, gTrue);
1621 static void nextTenPageCbk(LTKWidget *button, int n, GBool on) {
1622 gotoNextPage(10, gTrue);
1625 static void gotoNextPage(int inc, GBool top) {
1628 if (!doc || doc->getNumPages() == 0) {
1631 if (page < doc->getNumPages()) {
1632 if (top && !fullScreen) {
1633 vScrollbar->setPos(0, canvas->getHeight());
1634 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1636 if ((pg = page + inc) > doc->getNumPages()) {
1637 pg = doc->getNumPages();
1639 displayPage(pg, zoom, rotate, gTrue);
1645 static void prevPageCbk(LTKWidget *button, int n, GBool on) {
1646 gotoPrevPage(1, gTrue, gFalse);
1649 static void prevTenPageCbk(LTKWidget *button, int n, GBool on) {
1650 gotoPrevPage(10, gTrue, gFalse);
1653 static void gotoPrevPage(int dec, GBool top, GBool bottom) {
1656 if (!doc || doc->getNumPages() == 0) {
1660 if (top && !fullScreen) {
1661 vScrollbar->setPos(0, canvas->getHeight());
1662 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1663 } else if (bottom && !fullScreen) {
1664 vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(),
1665 canvas->getHeight());
1666 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1668 if ((pg = page - dec) < 1) {
1671 displayPage(pg, zoom, rotate, gTrue);
1677 static void backCbk(LTKWidget *button, int n, GBool on) {
1678 if (historyBLen <= 1) {
1682 if (--historyCur < 0)
1683 historyCur = historySize - 1;
1686 if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
1687 if (!loadFile(history[historyCur].fileName->copy())) {
1692 displayPage(history[historyCur].page, zoom, rotate, gFalse);
1695 static void forwardCbk(LTKWidget *button, int n, GBool on) {
1696 if (historyFLen == 0) {
1700 if (++historyCur == historySize)
1704 if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
1705 if (!loadFile(history[historyCur].fileName->copy())) {
1710 displayPage(history[historyCur].page, zoom, rotate, gFalse);
1713 static void pageNumCbk(LTKWidget *textIn, int n, GString *text) {
1717 if (!doc || doc->getNumPages() == 0)
1719 page1 = atoi(text->getCString());
1720 if (page1 >= 1 && page1 <= doc->getNumPages()) {
1722 displayPage(page1, zoom, rotate, gTrue);
1725 sprintf(s, "%d", page);
1726 pageNumText->setText(s);
1730 static void zoomMenuCbk(LTKMenuItem *item) {
1733 if (!doc || doc->getNumPages() == 0) {
1736 z = item->getItemNum();
1738 displayPage(page, z, rotate, gFalse);
1742 static void postScriptCbk(LTKWidget *button, int n, GBool on) {
1748 static void aboutCbk(LTKWidget *button, int n, GBool on) {
1752 static void quitCbk(LTKWidget *button, int n, GBool on) {
1756 //------------------------------------------------------------------------
1757 // scrollbar callbacks
1758 //------------------------------------------------------------------------
1760 static void scrollVertCbk(LTKWidget *scrollbar, int n, int val) {
1761 canvas->scroll(hScrollbar->getPos(), val);
1762 XSync(display, False);
1765 static void scrollHorizCbk(LTKWidget *scrollbar, int n, int val) {
1766 canvas->scroll(val, vScrollbar->getPos());
1767 XSync(display, False);
1770 //------------------------------------------------------------------------
1772 //------------------------------------------------------------------------
1774 static void layoutCbk(LTKWindow *win1) {
1775 if (page >= 0 && (zoom == zoomPage || zoom == zoomWidth)) {
1776 displayPage(page, zoom, rotate, gFalse);
1782 static void updateScrollbars() {
1786 hScrollbar->setLimits(0, canvas->getRealWidth() - 1);
1787 hScrollbar->setPos(hScrollbar->getPos(), canvas->getWidth());
1788 hScrollbar->setScrollDelta(16);
1789 vScrollbar->setLimits(0, canvas->getRealHeight() - 1);
1790 vScrollbar->setPos(vScrollbar->getPos(), canvas->getHeight());
1791 vScrollbar->setScrollDelta(16);
1792 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1795 static void propChangeCbk(LTKWindow *win1, Atom atom) {
1800 Gulong size, remain;
1802 GString *newFileName;
1806 xwin = win1->getXWindow();
1807 if (XGetWindowProperty(display, xwin, remoteAtom,
1808 0, remoteCmdLength/4, True, remoteAtom,
1809 &type, &format, &size, &remain,
1810 (Guchar **)&cmd) != Success)
1816 if (cmd[0] == 'D' || cmd[0] == 'r'){
1821 // display file / page
1822 if (cmd[0] == 'd' || cmd[0] == 'D') {
1825 if (!(p = strchr(p, ' ')))
1827 newFileName = new GString(p + 1);
1828 XFree((XPointer)cmd);
1829 if (!doc || newFileName->cmp(doc->getFileName())) {
1830 if (!loadFile(newFileName))
1835 if (newPage != page && newPage >= 1 && newPage <= doc->getNumPages())
1836 displayPage(newPage, zoom, rotate, gTrue);
1839 } else if (cmd[0] == 'q') {
1844 //------------------------------------------------------------------------
1846 //------------------------------------------------------------------------
1848 static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax) {
1850 GBool needRedraw, needScroll;
1851 GBool moveLeft, moveRight, moveTop, moveBottom;
1853 // erase old selection on canvas pixmap
1854 needRedraw = gFalse;
1855 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1856 XFillRectangle(canvas->getDisplay(), canvas->getPixmap(),
1857 selectGC, selectXMin, selectYMin,
1858 selectXMax - selectXMin, selectYMax - selectYMin);
1862 // draw new selection on canvas pixmap
1863 if (newXMin < newXMax && newYMin < newYMax) {
1864 XFillRectangle(canvas->getDisplay(), canvas->getPixmap(),
1865 selectGC, newXMin, newYMin,
1866 newXMax - newXMin, newYMax - newYMin);
1870 // check which edges moved
1871 moveLeft = newXMin != selectXMin;
1872 moveTop = newYMin != selectYMin;
1873 moveRight = newXMax != selectXMax;
1874 moveBottom = newYMax != selectYMax;
1876 // redraw currently visible part of canvas
1879 canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
1880 (newYMin < selectYMin) ? newYMin : selectYMin,
1881 (newXMin > selectXMin) ? newXMin : selectXMin,
1882 (newYMax > selectYMax) ? newYMax : selectYMax);
1885 canvas->redrawRect((newXMax < selectXMax) ? newXMax : selectXMax,
1886 (newYMin < selectYMin) ? newYMin : selectYMin,
1887 (newXMax > selectXMax) ? newXMax : selectXMax,
1888 (newYMax > selectYMax) ? newYMax : selectYMax);
1891 canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
1892 (newYMin < selectYMin) ? newYMin : selectYMin,
1893 (newXMax > selectXMax) ? newXMax : selectXMax,
1894 (newYMin > selectYMin) ? newYMin : selectYMin);
1897 canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
1898 (newYMax < selectYMax) ? newYMax : selectYMax,
1899 (newXMax > selectXMax) ? newXMax : selectXMax,
1900 (newYMax > selectYMax) ? newYMax : selectYMax);
1904 // switch to new selection coords
1905 selectXMin = newXMin;
1906 selectXMax = newXMax;
1907 selectYMin = newYMin;
1908 selectYMax = newYMax;
1910 // scroll canvas if necessary
1914 needScroll = gFalse;
1915 w = canvas->getWidth();
1916 h = canvas->getHeight();
1917 x = hScrollbar->getPos();
1918 y = vScrollbar->getPos();
1919 if (moveLeft && selectXMin < x) {
1922 } else if (moveRight && selectXMax >= x + w) {
1925 } else if (moveLeft && selectXMin >= x + w) {
1928 } else if (moveRight && selectXMax < x) {
1932 if (moveTop && selectYMin < y) {
1935 } else if (moveBottom && selectYMax >= y + h) {
1938 } else if (moveTop && selectYMin >= y + h) {
1941 } else if (moveBottom && selectYMax < y) {
1946 hScrollbar->setPos(x, w);
1947 vScrollbar->setPos(y, h);
1948 canvas->scroll(x, y);
1952 //------------------------------------------------------------------------
1954 //------------------------------------------------------------------------
1956 static void mapOpenDialog() {
1957 openDialog = makeOpenDialog(app);
1958 ((LTKFileReq *)openDialog->findWidget("fileReq"))->setDir(fileReqDir);
1959 openDialog->layoutDialog(win, -1, -1);
1963 static void openButtonCbk(LTKWidget *button, int n, GBool on) {
1964 LTKFileReq *fileReq;
1969 fileReq = (LTKFileReq *)openDialog->findWidget("fileReq");
1970 if (!(sel = fileReq->getSelection())) {
1973 openSelectCbk(fileReq, 0, sel);
1978 fileReqDir = ((LTKFileReq *)openDialog->findWidget("fileReq"))->getDir();
1985 static void openSelectCbk(LTKWidget *widget, int n, GString *name) {
1988 name1 = name->copy();
1991 fileReqDir = ((LTKFileReq *)openDialog->findWidget("fileReq"))->getDir();
1995 if (loadFile(name1)) {
1996 vScrollbar->setPos(0, canvas->getHeight());
1997 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1998 displayPage(1, zoom, rotate, gTrue);
2002 //------------------------------------------------------------------------
2004 //------------------------------------------------------------------------
2006 static void reloadCbk() {
2013 if (loadFile(doc->getFileName()->copy())) {
2014 if (pg > doc->getNumPages()) {
2015 pg = doc->getNumPages();
2017 displayPage(pg, zoom, rotate, gFalse);
2021 //------------------------------------------------------------------------
2022 // "Save PDF" dialog
2023 //------------------------------------------------------------------------
2025 static void mapSaveDialog() {
2026 saveDialog = makeSaveDialog(app);
2027 ((LTKFileReq *)saveDialog->findWidget("fileReq"))->setDir(fileReqDir);
2028 saveDialog->layoutDialog(win, -1, -1);
2032 static void saveButtonCbk(LTKWidget *button, int n, GBool on) {
2033 LTKFileReq *fileReq;
2040 fileReq = (LTKFileReq *)saveDialog->findWidget("fileReq");
2041 if (!(sel = fileReq->getSelection())) {
2044 saveSelectCbk(fileReq, 0, sel);
2049 fileReqDir = ((LTKFileReq *)saveDialog->findWidget("fileReq"))->getDir();
2056 static void saveSelectCbk(LTKWidget *widget, int n, GString *name) {
2059 name1 = name->copy();
2062 fileReqDir = ((LTKFileReq *)saveDialog->findWidget("fileReq"))->getDir();
2066 win->setBusyCursor(gTrue);
2069 win->setBusyCursor(gFalse);
2072 //------------------------------------------------------------------------
2073 // "PostScript" dialog
2074 //------------------------------------------------------------------------
2076 static void mapPSDialog() {
2080 psDialog = makePostScriptDialog(app);
2081 sprintf(s, "%d", psFirstPage);
2082 widget = (LTKTextIn *)psDialog->findWidget("firstPage");
2084 sprintf(s, "%d", psLastPage);
2085 widget = (LTKTextIn *)psDialog->findWidget("lastPage");
2087 widget = (LTKTextIn *)psDialog->findWidget("fileName");
2088 widget->setText(psFileName->getCString());
2089 psDialog->layoutDialog(win, -1, -1);
2093 static void psButtonCbk(LTKWidget *button, int n, GBool on) {
2102 // extract params and close the dialog
2103 widget = (LTKTextIn *)psDialog->findWidget("firstPage");
2104 psFirstPage = atoi(widget->getText()->getCString());
2105 if (psFirstPage < 1)
2107 widget = (LTKTextIn *)psDialog->findWidget("lastPage");
2108 psLastPage = atoi(widget->getText()->getCString());
2109 if (psLastPage < psFirstPage)
2110 psLastPage = psFirstPage;
2111 else if (psLastPage > doc->getNumPages())
2112 psLastPage = doc->getNumPages();
2113 widget = (LTKTextIn *)psDialog->findWidget("fileName");
2116 psFileName = widget->getText()->copy();
2117 if (!(psFileName->getChar(0) == '|' ||
2118 psFileName->cmp("-") == 0))
2119 makePathAbsolute(psFileName);
2121 // do the PostScript output
2122 psDialog->setBusyCursor(gTrue);
2123 win->setBusyCursor(gTrue);
2124 if (doc->okToPrint()) {
2125 psOut = new PSOutputDev(psFileName->getCString(), doc->getCatalog(),
2126 psFirstPage, psLastPage, gTrue, gFalse);
2127 if (psOut->isOk()) {
2128 doc->displayPages(psOut, psFirstPage, psLastPage, 72, 0, gFalse);
2132 error(-1, "Printing this document is not allowed.");
2136 win->setBusyCursor(gFalse);
2144 //------------------------------------------------------------------------
2146 //------------------------------------------------------------------------
2148 static void mapAboutWin() {
2152 aboutWin = makeAboutWindow(app);
2153 aboutWin->layout(-1, -1, -1, -1);
2158 static void closeAboutCbk(LTKWidget *button, int n, GBool on) {
2163 //------------------------------------------------------------------------
2165 //------------------------------------------------------------------------
2167 static void findCbk(LTKWidget *button, int n, GBool on) {
2168 if (!doc || doc->getNumPages() == 0)
2173 static void mapFindWin() {
2177 findWin = makeFindWindow(app);
2178 findWin->layout(-1, -1, -1, -1);
2183 static void findButtonCbk(LTKWidget *button, int n, GBool on) {
2186 if (!doc || doc->getNumPages() == 0)
2189 textIn = (LTKTextIn *)findWin->findWidget("text");
2190 doFind(textIn->getText()->getCString());
2197 static void doFind(char *s) {
2198 TextOutputDev *textOut;
2199 int xMin, yMin, xMax, yMax;
2200 double xMin1, yMin1, xMax1, yMax1;
2205 // check for zero-length string
2211 // set cursors to watch
2212 win->setBusyCursor(gTrue);
2213 findWin->setBusyCursor(gTrue);
2215 // search current page starting at current selection or top of page
2216 xMin = yMin = xMax = yMax = 0;
2217 if (selectXMin < selectXMax && selectYMin < selectYMax) {
2219 yMin = (selectYMin + selectYMax) / 2;
2224 if (out->findText(s, top, gTrue, &xMin, &yMin, &xMax, &yMax))
2227 // search following pages
2228 textOut = new TextOutputDev(NULL,
2229 useEUCJP ? textOutASCII7 : textOutLatin1,
2231 if (!textOut->isOk()) {
2235 for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
2236 doc->displayPage(textOut, pg, 72, 0, gFalse);
2237 if (textOut->findText(s, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1))
2241 // search previous pages
2242 for (pg = 1; pg < page; ++pg) {
2243 doc->displayPage(textOut, pg, 72, 0, gFalse);
2244 if (textOut->findText(s, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1))
2249 // search current page ending at current selection
2250 if (selectXMin < selectXMax && selectYMin < selectYMax) {
2252 yMax = (selectYMin + selectYMax) / 2;
2253 if (out->findText(s, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax))
2261 // found on a different page
2264 displayPage(pg, zoom, rotate, gTrue);
2265 if (!out->findText(s, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax))
2266 goto done; // this can happen if coalescing is bad
2268 // found: change the selection
2270 setSelection(xMin, yMin, xMax, yMax);
2271 #ifndef NO_TEXT_SELECT
2272 if (doc->okToCopy()) {
2273 s1 = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
2274 win->setSelection(NULL, s1);
2279 // reset cursors to normal
2280 win->setBusyCursor(gFalse);
2281 findWin->setBusyCursor(gFalse);
2284 //------------------------------------------------------------------------
2285 // app kill callback
2286 //------------------------------------------------------------------------
2288 static void killCbk(LTKWindow *win1) {
2291 } else if (win1 == aboutWin) {
2294 } else if (win1 == psDialog) {
2297 } else if (win1 == openDialog) {
2300 } else if (win1 == saveDialog) {
2303 } else if (win1 == findWin) {