1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
14 #include <X11/cursorfont.h>
15 #include <X11/keysym.h>
18 #include "parseargs.h"
31 #include "XOutputDev.h"
32 #include "LTKOutputDev.h"
33 #include "PSOutputDev.h"
34 #include "TextOutputDev.h"
39 #ifdef XlibSpecificationRelease
40 #if XlibSpecificationRelease < 5
41 typedef char *XPointer;
44 typedef char *XPointer;
47 // hack around old X includes which are missing these symbols
49 #define XK_Page_Up 0xFF55
52 #define XK_Page_Down 0xFF56
55 //------------------------------------------------------------------------
56 // misc constants / enums
57 //------------------------------------------------------------------------
59 #define remoteCmdLength 256
69 //------------------------------------------------------------------------
71 //------------------------------------------------------------------------
73 // loadFile / displayPage
74 static GBool loadFile(GString *fileName);
75 static void displayPage(int page1, int zoom1, int rotate1);
77 // key press and menu callbacks
78 static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers,
80 static void menuCbk(LTKMenuItem *item);
83 static void buttonPressCbk(LTKWidget *canvas1, int n,
84 int mx, int my, int button, GBool dblClick);
85 static void buttonReleaseCbk(LTKWidget *canvas1, int n,
86 int mx, int my, int button, GBool click);
87 static void doLink(int mx, int my);
88 static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my);
89 static void mouseDragCbk(LTKWidget *widget, int widgetNum,
90 int mx, int my, int button);
93 static void nextPageCbk(LTKWidget *button, int n, GBool on);
94 static void nextTenPageCbk(LTKWidget *button, int n, GBool on);
95 static void prevPageCbk(LTKWidget *button, int n, GBool on);
96 static void prevTenPageCbk(LTKWidget *button, int n, GBool on);
97 static void pageNumCbk(LTKWidget *textIn, int n, GString *text);
98 static void zoomInCbk(LTKWidget *button, int n, GBool on);
99 static void zoomOutCbk(LTKWidget *button, int n, GBool on);
100 static void postScriptCbk(LTKWidget *button, int n, GBool on);
101 static void aboutCbk(LTKWidget *button, int n, GBool on);
102 static void quitCbk(LTKWidget *button, int n, GBool on);
104 // scrollbar callbacks
105 static void scrollVertCbk(LTKWidget *scrollbar, int n, int val);
106 static void scrollHorizCbk(LTKWidget *scrollbar, int n, int val);
109 static void layoutCbk(LTKWindow *win1);
110 static void propChangeCbk(LTKWindow *win1, Atom atom);
113 static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax);
116 static void mapOpenDialog();
117 static void openButtonCbk(LTKWidget *button, int n, GBool on);
118 static void openSelectCbk(LTKWidget *widget, int n, GString *name);
121 static void mapSaveDialog();
122 static void saveButtonCbk(LTKWidget *button, int n, GBool on);
123 static void saveSelectCbk(LTKWidget *widget, int n, GString *name);
125 // "PostScript" dialog
126 static void mapPSDialog();
127 static void psButtonCbk(LTKWidget *button, int n, GBool on);
130 static void mapAboutWin();
131 static void closeAboutCbk(LTKWidget *button, int n, GBool on);
134 static void findCbk(LTKWidget *button, int n, GBool on);
135 static void mapFindWin();
136 static void findButtonCbk(LTKWidget *button, int n, GBool on);
137 static void doFind(char *s);
140 static void killCbk(LTKWindow *win1);
142 //------------------------------------------------------------------------
144 //------------------------------------------------------------------------
146 #include "xpdfIcon.xpm"
147 #include "leftArrow.xbm"
148 #include "dblLeftArrow.xbm"
149 #include "rightArrow.xbm"
150 #include "dblRightArrow.xbm"
151 #include "zoomIn.xbm"
152 #include "zoomOut.xbm"
154 #include "postscript.xbm"
156 #include "xpdf-ltk.h"
158 //------------------------------------------------------------------------
159 // command line options
160 //------------------------------------------------------------------------
162 static XrmOptionDescRec opts[] = {
163 {"-display", ".display", XrmoptionSepArg, NULL},
164 {"-foreground", ".foreground", XrmoptionSepArg, NULL},
165 {"-fg", ".foreground", XrmoptionSepArg, NULL},
166 {"-background", ".background", XrmoptionSepArg, NULL},
167 {"-bg", ".background", XrmoptionSepArg, NULL},
168 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
169 {"-g", ".geometry", XrmoptionSepArg, NULL},
170 {"-font", ".font", XrmoptionSepArg, NULL},
171 {"-fn", ".font", XrmoptionSepArg, NULL},
172 {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"},
173 {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL},
174 {"-papercolor", ".paperColor", XrmoptionSepArg, NULL},
175 {"-z", ".initialZoom", XrmoptionSepArg, NULL},
176 {"-ps", ".psFile", XrmoptionSepArg, NULL},
177 {"-paperw", ".psPaperWidth", XrmoptionSepArg, NULL},
178 {"-paperh", ".psPaperHeight", XrmoptionSepArg, NULL},
179 {"-level1", ".psLevel1", XrmoptionNoArg, (XPointer)"false"},
183 GBool printCommands = gFalse;
184 static GBool printHelp = gFalse;
185 static char remoteName[100] = "xpdf_";
186 static GBool doRemoteRaise = gFalse;
187 static GBool doRemoteQuit = gFalse;
189 static ArgDesc argDesc[] = {
190 {"-err", argFlag, &errorsToTTY, 0,
191 "send error messages to /dev/tty instead of stderr"},
192 {"-z", argIntDummy, NULL, 0,
193 "initial zoom level (-5..5)"},
194 {"-g", argStringDummy, NULL, 0,
195 "initial window geometry"},
196 {"-geometry", argStringDummy, NULL, 0,
197 "initial window geometry"},
198 {"-remote", argString, remoteName + 5, sizeof(remoteName) - 5,
199 "start/contact xpdf remote server with specified name"},
200 {"-raise", argFlag, &doRemoteRaise, 0,
201 "raise xpdf remote server window (with -remote only)"},
202 {"-quit", argFlag, &doRemoteQuit, 0,
203 "kill xpdf remote server (with -remote only)"},
204 {"-cmap", argFlagDummy, NULL, 0,
205 "install a private colormap"},
206 {"-rgb", argIntDummy, NULL, 0,
207 "biggest RGB cube to allocate (default is 5)"},
208 {"-papercolor", argStringDummy, NULL, 0,
209 "color of paper background"},
210 {"-ps", argStringDummy, NULL, 0,
211 "default PostScript file/command name"},
212 {"-paperw", argIntDummy, NULL, 0,
213 "paper width, in points"},
214 {"-paperh", argIntDummy, NULL, 0,
215 "paper height, in points"},
216 {"-level1", argFlagDummy, NULL, 0,
217 "generate Level 1 PostScript"},
218 {"-cmd", argFlag, &printCommands, 0,
219 "print commands as they're executed"},
220 {"-h", argFlag, &printHelp, 0,
221 "print usage information"},
222 {"-help", argFlag, &printHelp, 0,
223 "print usage information"},
227 //------------------------------------------------------------------------
229 //------------------------------------------------------------------------
231 // zoom factor is 1.2 (similar to DVI magsteps)
234 static int zoomDPI[maxZoom - minZoom + 1] = {
237 86, 104, 124, 149, 179
243 static LTKOutputDev *out;
250 static LinkAction *linkAction; // mouse pointer is over this link
251 static int // coordinates of current selection:
252 selectXMin, selectYMin, // (xMin==xMax || yMin==yMax) means there
253 selectXMax, selectYMax; // is no selection
254 static GBool lastDragLeft; // last dragged selection edge was left/right
255 static GBool lastDragTop; // last dragged selection edge was top/bottom
256 static int panMX, panMY; // last mouse position for pan
258 static GString *defPSFileName;
259 static GString *psFileName;
260 static int psFirstPage, psLastPage;
262 static GString *fileReqDir; // current directory for file requesters
264 static GString *urlCommand; // command to execute for URI links
267 static Display *display;
268 static LTKWindow *win;
269 static LTKScrollingCanvas *canvas;
270 static LTKScrollbar *hScrollbar, *vScrollbar;
271 static LTKTextIn *pageNumText;
272 static LTKLabel *numPagesLabel;
273 static LTKLabel *linkLabel;
274 static LTKWindow *aboutWin;
275 static LTKWindow *psDialog;
276 static LTKWindow *openDialog;
277 static LTKWindow *saveDialog;
278 static LTKWindow *findWin;
279 static Atom remoteAtom;
282 //------------------------------------------------------------------------
284 //------------------------------------------------------------------------
286 int main(int argc, char *argv[]) {
289 char cmd[remoteCmdLength];
293 unsigned long paperColor;
309 fileReqDir = getCurrentDir();
313 paperWidth = paperHeight = -1;
314 ok = parseArgs(argDesc, &argc, argv);
320 initParams(xpdfConfigFile);
322 // create LTKApp (and parse X-related args)
323 app = new LTKApp("xpdf", opts, &argc, argv);
324 app->setKillCbk(&killCbk);
325 display = app->getDisplay();
327 // check command line
329 ok = ok && remoteName[5] && !doRemoteQuit && argc >= 1 && argc <= 3;
330 else if (doRemoteQuit)
331 ok = ok && remoteName[5] && argc == 1;
333 ok = ok && argc >= 1 && argc <= 3;
334 if (!ok || printHelp) {
335 fprintf(stderr, "xpdf version %s\n", xpdfVersion);
336 fprintf(stderr, "%s\n", xpdfCopyright);
337 printUsage("xpdf", "[<PDF-file> [<page>]]", argDesc);
342 name = new GString(argv[1]);
350 // look for already-running remote server
352 remoteAtom = XInternAtom(display, remoteName, False);
353 xwin = XGetSelectionOwner(display, remoteAtom);
356 sprintf(cmd, "%c %d %.200s", doRemoteRaise ? 'D' : 'd',
357 pg, name->getCString());
358 XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
359 PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
361 } else if (doRemoteRaise) {
362 XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
363 PropModeReplace, (Guchar *)"r", 2);
364 } else if (doRemoteQuit) {
365 XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
366 PropModeReplace, (Guchar *)"q", 2);
375 fprintf(errFile, "xpdf version %s\n", xpdfVersion);
376 fprintf(errFile, "%s\n", xpdfCopyright);
379 defPSFileName = app->getStringResource("psFile", NULL);
381 if (!loadFile(name)) {
386 fileReqDir = makePathAbsolute(grabPath(name->getCString()));
389 // check for legal page number
390 if (doc && (pg < 1 || pg > doc->getNumPages()))
394 win = makeWindow(app);
397 canvas = (LTKScrollingCanvas *)win->findWidget("canvas");
398 hScrollbar = (LTKScrollbar *)win->findWidget("hScrollbar");
399 vScrollbar = (LTKScrollbar *)win->findWidget("vScrollbar");
400 pageNumText = (LTKTextIn *)win->findWidget("pageNum");
401 numPagesLabel = (LTKLabel *)win->findWidget("numPages");
402 linkLabel = (LTKLabel *)win->findWidget("link");
403 win->setKeyCbk(&keyPressCbk);
404 win->setLayoutCbk(&layoutCbk);
405 canvas->setButtonPressCbk(&buttonPressCbk);
406 canvas->setButtonReleaseCbk(&buttonReleaseCbk);
407 canvas->setMouseMoveCbk(&mouseMoveCbk);
408 canvas->setMouseDragCbk(&mouseDragCbk);
409 hScrollbar->setRepeatPeriod(0);
410 vScrollbar->setRepeatPeriod(0);
413 paperWidth = app->getIntResource("psPaperWidth", defPaperWidth);
414 paperHeight = app->getIntResource("psPaperHeight", defPaperHeight);
415 psOutLevel1 = app->getBoolResource("psLevel1", gFalse);
416 urlCommand = app->getStringResource("urlCommand", NULL);
417 installCmap = app->getBoolResource("installCmap", gFalse);
419 win->setInstallCmap(gTrue);
420 rgbCubeSize = app->getIntResource("rgbCubeSize", defaultRGBCube);
421 paperColor = app->getColorResource("paperColor", "white",
422 WhitePixel(display, app->getScreenNum()),
424 zoom = app->getIntResource("initialZoom", defZoom);
427 else if (zoom > maxZoom)
436 } else if (doc->getPageRotate(pg) == 90 || doc->getPageRotate(pg) == 270) {
437 width = (int)(doc->getPageHeight(pg) + 0.5);
438 height = (int)(doc->getPageWidth(pg) + 0.5);
440 width = (int)(doc->getPageWidth(pg) + 0.5);
441 height = (int)(doc->getPageHeight(pg) + 0.5);
443 width = (width * zoomDPI[zoom - minZoom]) / 72 + 28;
444 if (width > (Guint)app->getDisplayWidth() - 100)
445 width = app->getDisplayWidth() - 100;
446 height = (height * zoomDPI[zoom - minZoom]) / 72 + 56;
447 if (height > (Guint)app->getDisplayHeight() - 100)
448 height = app->getDisplayHeight() - 100;
449 app->getGeometryResource("geometry", &x, &y, &width, &height);
451 // finish setting up window
452 sprintf(s, "of %d", doc ? doc->getNumPages() : 0);
453 numPagesLabel->setText(s);
455 title = new GString("xpdf: ");
458 title = new GString("xpdf");
460 win->setTitle(title);
461 win->layout(x, y, width, height);
468 gcValues.foreground = BlackPixel(display, win->getScreenNum()) ^
469 WhitePixel(display, win->getScreenNum());
470 gcValues.function = GXxor;
471 selectGC = XCreateGC(display, win->getXWindow(),
472 GCForeground | GCFunction, &gcValues);
474 // set up remote server
475 if (remoteAtom != None) {
476 win->setPropChangeCbk(&propChangeCbk);
477 xwin = win->getXWindow();
478 XSetSelectionOwner(display, remoteAtom, xwin, CurrentTime);
481 // create output device
482 out = new LTKOutputDev(win, paperColor);
484 // display first page
485 displayPage(pg, zoom, 0);
494 // release remote control atom
495 if (remoteAtom != None)
496 XSetSelectionOwner(display, remoteAtom, None, CurrentTime);
515 delete defPSFileName;
522 // check for memory leaks
523 Object::memCheck(errFile);
529 //------------------------------------------------------------------------
530 // loadFile / displayPage
531 //------------------------------------------------------------------------
533 static GBool loadFile(GString *fileName) {
541 win->setBusyCursor(gTrue);
544 newDoc = new PDFDoc(fileName);
545 if (!newDoc->isOk()) {
548 win->setBusyCursor(gFalse);
552 // replace old document
557 // nothing displayed yet
560 // init PostScript output params
564 psFileName = defPSFileName->copy();
566 p = fileName->getCString() + fileName->getLength() - 4;
567 if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
568 psFileName = new GString(fileName->getCString(),
569 fileName->getLength() - 4);
571 psFileName = fileName->copy();
572 psFileName->append(".ps");
575 psLastPage = doc->getNumPages();
577 // set up title, number-of-pages display; back to normal cursor
579 title = new GString("xpdf: ");
580 title->append(fileName);
581 win->setTitle(title);
582 sprintf(s, "of %d", doc->getNumPages());
583 numPagesLabel->setText(s);
584 win->setBusyCursor(gFalse);
591 static void displayPage(int page1, int zoom1, int rotate1) {
594 // check for document
600 win->setBusyCursor(gTrue);
602 // new page/zoom/rotate values
607 // initialize mouse-related stuff
609 win->setDefaultCursor();
610 linkLabel->setText(NULL);
611 selectXMin = selectXMax = 0;
612 selectYMin = selectYMax = 0;
613 lastDragLeft = lastDragTop = gTrue;
616 doc->displayPage(out, page, zoomDPI[zoom - minZoom], rotate, gTrue);
619 // update page number display
620 sprintf(s, "%d", page);
621 pageNumText->setText(s);
623 // back to regular cursor
624 win->setBusyCursor(gFalse);
627 //------------------------------------------------------------------------
628 // key press and menu callbacks
629 //------------------------------------------------------------------------
631 static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers,
645 nextPageCbk(NULL, 0, gTrue);
649 prevPageCbk(NULL, 0, gTrue);
652 if (vScrollbar->getPos() >=
653 canvas->getRealHeight() - canvas->getHeight()) {
654 nextPageCbk(NULL, 0, gTrue);
656 vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
657 canvas->getHeight());
658 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
663 if (vScrollbar->getPos() == 0) {
664 prevPageCbk(NULL, 0, gTrue);
666 vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
667 canvas->getHeight());
668 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
673 displayPage(page, zoom, rotate);
677 quitCbk(NULL, 0, gTrue);
683 hScrollbar->setPos(0, canvas->getWidth());
684 vScrollbar->setPos(0, canvas->getHeight());
685 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
688 hScrollbar->setPos(canvas->getRealWidth() - canvas->getWidth(),
690 vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(),
691 canvas->getHeight());
692 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
695 if (vScrollbar->getPos() == 0) {
696 prevPageCbk(NULL, 0, gTrue);
698 vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
699 canvas->getHeight());
700 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
704 if (vScrollbar->getPos() >=
705 canvas->getRealHeight() - canvas->getHeight()) {
706 nextPageCbk(NULL, 0, gTrue);
708 vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
709 canvas->getHeight());
710 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
714 hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth());
715 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
718 hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth());
719 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
722 vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight());
723 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
726 vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight());
727 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
733 static void menuCbk(LTKMenuItem *item) {
736 switch (item->getItemNum()) {
746 r = (rotate == 0) ? 270 : rotate - 90;
747 displayPage(page, zoom, r);
750 case menuRotateRight:
752 r = (rotate == 270) ? 0 : rotate + 90;
753 displayPage(page, zoom, r);
762 //------------------------------------------------------------------------
764 //------------------------------------------------------------------------
766 static void buttonPressCbk(LTKWidget *canvas1, int n,
767 int mx, int my, int button, GBool dblClick) {
771 setSelection(mx, my, mx, my);
772 } else if (button == 2) {
773 panMX = mx - hScrollbar->getPos();
774 panMY = my - vScrollbar->getPos();
778 static void buttonReleaseCbk(LTKWidget *canvas1, int n,
779 int mx, int my, int button, GBool click) {
787 if (selectXMin < selectXMax && selectYMin < selectYMax) {
788 #ifndef NO_TEXT_SELECT
789 if (doc->okToCopy()) {
790 s = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
791 win->setSelection(NULL, s);
797 setSelection(mx, my, mx, my);
803 static void doLink(int mx, int my) {
805 LinkAction *action = NULL;
814 LTKButtonDialog *dialog;
817 out->cvtDevToUser(mx, my, &x, &y);
818 if ((action = doc->findLink(x, y))) {
819 switch (kind = action->getKind()) {
821 // GoTo / GoToR action
824 if (kind == actionGoTo) {
827 if ((dest = ((LinkGoTo *)action)->getDest()))
829 else if ((namedDest = ((LinkGoTo *)action)->getNamedDest()))
830 namedDest = namedDest->copy();
834 if ((dest = ((LinkGoToR *)action)->getDest()))
836 else if ((namedDest = ((LinkGoToR *)action)->getNamedDest()))
837 namedDest = namedDest->copy();
838 s = ((LinkGoToR *)action)->getFileName()->getCString();
839 //~ translate path name for VMS (deal with '/')
840 if (isAbsolutePath(s))
841 fileName = new GString(s);
843 fileName = appendToPath(
844 grabPath(doc->getFileName()->getCString()), s);
845 if (!loadFile(fileName)) {
854 dest = doc->findDest(namedDest);
858 if (kind == actionGoToR)
859 displayPage(1, zoom, 0);
861 if (dest->isPageRef()) {
862 pageRef = dest->getPageRef();
863 pg = doc->findPage(pageRef.num, pageRef.gen);
865 pg = dest->getPageNum();
867 if (pg > 0 && pg != page)
868 displayPage(pg, zoom, rotate);
870 displayPage(1, zoom, rotate);
871 switch (dest->getKind()) {
873 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
874 if (dest->getChangeLeft() || dest->getChangeTop()) {
875 if (dest->getChangeLeft())
876 hScrollbar->setPos(dx, canvas->getWidth());
877 if (dest->getChangeTop())
878 vScrollbar->setPos(dy, canvas->getHeight());
879 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
881 //~ what is the zoom parameter?
886 hScrollbar->setPos(0, canvas->getWidth());
887 vScrollbar->setPos(0, canvas->getHeight());
888 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
893 out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
894 hScrollbar->setPos(0, canvas->getWidth());
895 vScrollbar->setPos(dy, canvas->getHeight());
896 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
901 out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
902 hScrollbar->setPos(dx, canvas->getWidth());
903 vScrollbar->setPos(0, canvas->getHeight());
904 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
908 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
909 hScrollbar->setPos(dx, canvas->getWidth());
910 vScrollbar->setPos(dy, canvas->getHeight());
911 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
920 fileName = ((LinkLaunch *)action)->getFileName();
921 s = fileName->getCString();
922 if (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
923 !strcmp(s + fileName->getLength() - 4, ".PDF")) {
924 //~ translate path name for VMS (deal with '/')
925 if (isAbsolutePath(s))
926 fileName = fileName->copy();
928 fileName = appendToPath(
929 grabPath(doc->getFileName()->getCString()), s);
930 if (!loadFile(fileName))
932 displayPage(1, zoom, rotate);
934 fileName = fileName->copy();
935 if (((LinkLaunch *)action)->getParams()) {
936 fileName->append(' ');
937 fileName->append(((LinkLaunch *)action)->getParams());
940 fileName->insert(0, "spawn/nowait ");
941 #elif defined(__EMX__)
942 fileName->insert(0, "start /min /n ");
944 fileName->append(" &");
946 dialog = new LTKButtonDialog(win, "xpdf: Launch",
947 "Execute the command:",
948 fileName->getCString(),
949 NULL, "Ok", "Cancel");
951 system(fileName->getCString());
960 for (s = urlCommand->getCString(); *s; ++s) {
961 if (s[0] == '%' && s[1] == 's')
965 fileName = new GString(urlCommand->getCString(),
966 s - urlCommand->getCString());
967 fileName->append(((LinkURI *)action)->getURI());
968 fileName->append(s+2);
970 fileName = urlCommand->copy();
973 fileName->insert(0, "spawn/nowait ");
974 #elif defined(__EMX__)
975 fileName->insert(0, "start /min /n ");
977 fileName->append(" &");
979 system(fileName->getCString());
982 fprintf(errFile, "URI: %s\n",
983 ((LinkURI *)action)->getURI()->getCString());
987 // unknown action type
989 error(-1, "Unknown link action type: '%s'",
990 ((LinkUnknown *)action)->getAction()->getCString());
996 static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my) {
1003 out->cvtDevToUser(mx, my, &x, &y);
1004 if ((action = doc->findLink(x, y))) {
1005 if (action != linkAction) {
1007 win->setCursor(XC_hand2);
1008 linkAction = action;
1010 switch (linkAction->getKind()) {
1012 s = "[internal link]";
1015 s = ((LinkGoToR *)linkAction)->getFileName()->getCString();
1018 s = ((LinkLaunch *)linkAction)->getFileName()->getCString();
1021 s = ((LinkURI *)action)->getURI()->getCString();
1024 s = "[unknown link]";
1027 linkLabel->setText(s);
1032 win->setDefaultCursor();
1033 linkLabel->setText(NULL);
1038 static void mouseDragCbk(LTKWidget *widget, int widgetNum,
1039 int mx, int my, int button) {
1041 int xMin, yMin, xMax, yMax;
1046 // clip mouse coords
1050 else if (x >= canvas->getRealWidth())
1051 x = canvas->getRealWidth() - 1;
1055 else if (y >= canvas->getRealHeight())
1056 y = canvas->getRealHeight() - 1;
1058 // move appropriate edges of selection
1060 if (x < selectXMax) {
1066 lastDragLeft = gFalse;
1069 if (x > selectXMin) {
1075 lastDragLeft = gTrue;
1079 if (y < selectYMax) {
1085 lastDragTop = gFalse;
1088 if (y > selectYMin) {
1094 lastDragTop = gTrue;
1098 // redraw the selection
1099 setSelection(xMin, yMin, xMax, yMax);
1102 } else if (button == 2) {
1103 mx -= hScrollbar->getPos();
1104 my -= vScrollbar->getPos();
1105 hScrollbar->setPos(hScrollbar->getPos() - (mx - panMX),
1106 canvas->getWidth());
1107 vScrollbar->setPos(vScrollbar->getPos() - (my - panMY),
1108 canvas->getHeight());
1109 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1115 //------------------------------------------------------------------------
1117 //------------------------------------------------------------------------
1119 static void nextPageCbk(LTKWidget *button, int n, GBool on) {
1122 if (page < doc->getNumPages()) {
1123 vScrollbar->setPos(0, canvas->getHeight());
1124 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1125 displayPage(page + 1, zoom, rotate);
1131 static void nextTenPageCbk(LTKWidget *button, int n, GBool on) {
1136 if (page < doc->getNumPages()) {
1137 vScrollbar->setPos(0, canvas->getHeight());
1138 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1139 if ((pg = page + 10) > doc->getNumPages())
1140 pg = doc->getNumPages();
1141 displayPage(pg, zoom, rotate);
1147 static void prevPageCbk(LTKWidget *button, int n, GBool on) {
1151 vScrollbar->setPos(0, canvas->getHeight());
1152 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1153 displayPage(page - 1, zoom, rotate);
1159 static void prevTenPageCbk(LTKWidget *button, int n, GBool on) {
1165 vScrollbar->setPos(0, canvas->getHeight());
1166 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1167 if ((pg = page - 10) < 1)
1169 displayPage(pg, zoom, rotate);
1175 static void pageNumCbk(LTKWidget *textIn, int n, GString *text) {
1181 page1 = atoi(text->getCString());
1182 if (page1 >= 1 && page1 <= doc->getNumPages()) {
1184 displayPage(page1, zoom, rotate);
1187 sprintf(s, "%d", page);
1188 pageNumText->setText(s);
1192 static void zoomInCbk(LTKWidget *button, int n, GBool on) {
1196 displayPage(page, zoom + 1, rotate);
1201 static void zoomOutCbk(LTKWidget *button, int n, GBool on) {
1205 displayPage(page, zoom - 1, rotate);
1210 static void postScriptCbk(LTKWidget *button, int n, GBool on) {
1216 static void aboutCbk(LTKWidget *button, int n, GBool on) {
1220 static void quitCbk(LTKWidget *button, int n, GBool on) {
1224 //------------------------------------------------------------------------
1225 // scrollbar callbacks
1226 //------------------------------------------------------------------------
1228 static void scrollVertCbk(LTKWidget *scrollbar, int n, int val) {
1229 canvas->scroll(hScrollbar->getPos(), val);
1230 XSync(display, False);
1233 static void scrollHorizCbk(LTKWidget *scrollbar, int n, int val) {
1234 canvas->scroll(val, vScrollbar->getPos());
1235 XSync(display, False);
1238 //------------------------------------------------------------------------
1240 //------------------------------------------------------------------------
1242 static void layoutCbk(LTKWindow *win1) {
1243 hScrollbar->setLimits(0, canvas->getRealWidth() - 1);
1244 hScrollbar->setPos(hScrollbar->getPos(), canvas->getWidth());
1245 hScrollbar->setScrollDelta(16);
1246 vScrollbar->setLimits(0, canvas->getRealHeight() - 1);
1247 vScrollbar->setPos(vScrollbar->getPos(), canvas->getHeight());
1248 vScrollbar->setScrollDelta(16);
1249 canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
1252 static void propChangeCbk(LTKWindow *win1, Atom atom) {
1257 Gulong size, remain;
1259 GString *newFileName;
1263 xwin = win1->getXWindow();
1264 if (XGetWindowProperty(display, xwin, remoteAtom,
1265 0, remoteCmdLength/4, True, remoteAtom,
1266 &type, &format, &size, &remain,
1267 (Guchar **)&cmd) != Success)
1273 if (cmd[0] == 'D' || cmd[0] == 'r'){
1278 // display file / page
1279 if (cmd[0] == 'd' || cmd[0] == 'D') {
1282 if (!(p = strchr(p, ' ')))
1284 newFileName = new GString(p + 1);
1285 XFree((XPointer)cmd);
1286 if (!doc || newFileName->cmp(doc->getFileName())) {
1287 if (!loadFile(newFileName))
1292 if (newPage != page && newPage >= 1 && newPage <= doc->getNumPages())
1293 displayPage(newPage, zoom, rotate);
1296 } else if (cmd[0] == 'q') {
1301 //------------------------------------------------------------------------
1303 //------------------------------------------------------------------------
1305 static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax) {
1307 GBool needRedraw, needScroll;
1308 GBool moveLeft, moveRight, moveTop, moveBottom;
1310 // erase old selection on canvas pixmap
1311 needRedraw = gFalse;
1312 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1313 XFillRectangle(canvas->getDisplay(), canvas->getPixmap(),
1314 selectGC, selectXMin, selectYMin,
1315 selectXMax - selectXMin, selectYMax - selectYMin);
1319 // draw new selection on canvas pixmap
1320 if (newXMin < newXMax && newYMin < newYMax) {
1321 XFillRectangle(canvas->getDisplay(), canvas->getPixmap(),
1322 selectGC, newXMin, newYMin,
1323 newXMax - newXMin, newYMax - newYMin);
1327 // check which edges moved
1328 moveLeft = newXMin != selectXMin;
1329 moveTop = newYMin != selectYMin;
1330 moveRight = newXMax != selectXMax;
1331 moveBottom = newYMax != selectYMax;
1333 // redraw currently visible part of canvas
1336 canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
1337 (newYMin < selectYMin) ? newYMin : selectYMin,
1338 (newXMin > selectXMin) ? newXMin : selectXMin,
1339 (newYMax > selectYMax) ? newYMax : selectYMax);
1342 canvas->redrawRect((newXMax < selectXMax) ? newXMax : selectXMax,
1343 (newYMin < selectYMin) ? newYMin : selectYMin,
1344 (newXMax > selectXMax) ? newXMax : selectXMax,
1345 (newYMax > selectYMax) ? newYMax : selectYMax);
1348 canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
1349 (newYMin < selectYMin) ? newYMin : selectYMin,
1350 (newXMax > selectXMax) ? newXMax : selectXMax,
1351 (newYMin > selectYMin) ? newYMin : selectYMin);
1354 canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
1355 (newYMax < selectYMax) ? newYMax : selectYMax,
1356 (newXMax > selectXMax) ? newXMax : selectXMax,
1357 (newYMax > selectYMax) ? newYMax : selectYMax);
1361 // switch to new selection coords
1362 selectXMin = newXMin;
1363 selectXMax = newXMax;
1364 selectYMin = newYMin;
1365 selectYMax = newYMax;
1367 // scroll canvas if necessary
1368 needScroll = gFalse;
1369 w = canvas->getWidth();
1370 h = canvas->getHeight();
1371 x = hScrollbar->getPos();
1372 y = vScrollbar->getPos();
1373 if (moveLeft && selectXMin < x) {
1376 } else if (moveRight && selectXMax >= x + w) {
1379 } else if (moveLeft && selectXMin >= x + w) {
1382 } else if (moveRight && selectXMax < x) {
1386 if (moveTop && selectYMin < y) {
1389 } else if (moveBottom && selectYMax >= y + h) {
1392 } else if (moveTop && selectYMin >= y + h) {
1395 } else if (moveBottom && selectYMax < y) {
1400 hScrollbar->setPos(x, w);
1401 vScrollbar->setPos(y, h);
1402 canvas->scroll(x, y);
1406 //------------------------------------------------------------------------
1408 //------------------------------------------------------------------------
1410 static void mapOpenDialog() {
1411 openDialog = makeOpenDialog(app);
1412 ((LTKFileReq *)openDialog->findWidget("fileReq"))->setDir(fileReqDir);
1413 openDialog->layoutDialog(win, -1, -1);
1417 static void openButtonCbk(LTKWidget *button, int n, GBool on) {
1418 LTKFileReq *fileReq;
1423 fileReq = (LTKFileReq *)openDialog->findWidget("fileReq");
1424 if ((sel = fileReq->getSelection()))
1425 openSelectCbk(fileReq, 0, sel);
1432 fileReqDir = ((LTKFileReq *)openDialog->findWidget("fileReq"))->getDir();
1439 static void openSelectCbk(LTKWidget *widget, int n, GString *name) {
1442 name1 = name->copy();
1445 fileReqDir = ((LTKFileReq *)openDialog->findWidget("fileReq"))->getDir();
1449 if (loadFile(name1))
1450 displayPage(1, zoom, rotate);
1453 //------------------------------------------------------------------------
1454 // "Save PDF" dialog
1455 //------------------------------------------------------------------------
1457 static void mapSaveDialog() {
1458 saveDialog = makeSaveDialog(app);
1459 ((LTKFileReq *)saveDialog->findWidget("fileReq"))->setDir(fileReqDir);
1460 saveDialog->layoutDialog(win, -1, -1);
1464 static void saveButtonCbk(LTKWidget *button, int n, GBool on) {
1465 LTKFileReq *fileReq;
1472 fileReq = (LTKFileReq *)saveDialog->findWidget("fileReq");
1473 if ((sel = fileReq->getSelection()))
1474 saveSelectCbk(fileReq, 0, sel);
1481 fileReqDir = ((LTKFileReq *)saveDialog->findWidget("fileReq"))->getDir();
1488 static void saveSelectCbk(LTKWidget *widget, int n, GString *name) {
1491 name1 = name->copy();
1494 fileReqDir = ((LTKFileReq *)saveDialog->findWidget("fileReq"))->getDir();
1498 win->setBusyCursor(gTrue);
1501 win->setBusyCursor(gFalse);
1504 //------------------------------------------------------------------------
1505 // "PostScript" dialog
1506 //------------------------------------------------------------------------
1508 static void mapPSDialog() {
1512 psDialog = makePostScriptDialog(app);
1513 sprintf(s, "%d", psFirstPage);
1514 widget = (LTKTextIn *)psDialog->findWidget("firstPage");
1516 sprintf(s, "%d", psLastPage);
1517 widget = (LTKTextIn *)psDialog->findWidget("lastPage");
1519 widget = (LTKTextIn *)psDialog->findWidget("fileName");
1520 widget->setText(psFileName->getCString());
1521 psDialog->layoutDialog(win, -1, -1);
1525 static void psButtonCbk(LTKWidget *button, int n, GBool on) {
1534 // extract params and close the dialog
1535 widget = (LTKTextIn *)psDialog->findWidget("firstPage");
1536 psFirstPage = atoi(widget->getText()->getCString());
1537 if (psFirstPage < 1)
1539 widget = (LTKTextIn *)psDialog->findWidget("lastPage");
1540 psLastPage = atoi(widget->getText()->getCString());
1541 if (psLastPage < psFirstPage)
1542 psLastPage = psFirstPage;
1543 else if (psLastPage > doc->getNumPages())
1544 psLastPage = doc->getNumPages();
1545 widget = (LTKTextIn *)psDialog->findWidget("fileName");
1548 psFileName = widget->getText()->copy();
1549 if (!(psFileName->getChar(0) == '|' ||
1550 psFileName->cmp("-") == 0))
1551 makePathAbsolute(psFileName);
1553 // do the PostScript output
1554 psDialog->setBusyCursor(gTrue);
1555 win->setBusyCursor(gTrue);
1556 if (doc->okToPrint()) {
1557 psOut = new PSOutputDev(psFileName->getCString(), doc->getCatalog(),
1558 psFirstPage, psLastPage, gTrue, gFalse);
1559 if (psOut->isOk()) {
1560 doc->displayPages(psOut, psFirstPage, psLastPage,
1561 zoomDPI[zoom - minZoom], rotate);
1567 win->setBusyCursor(gFalse);
1575 //------------------------------------------------------------------------
1577 //------------------------------------------------------------------------
1579 static void mapAboutWin() {
1583 aboutWin = makeAboutWindow(app);
1584 aboutWin->layout(-1, -1, -1, -1);
1589 static void closeAboutCbk(LTKWidget *button, int n, GBool on) {
1594 //------------------------------------------------------------------------
1596 //------------------------------------------------------------------------
1598 static void findCbk(LTKWidget *button, int n, GBool on) {
1604 static void mapFindWin() {
1608 findWin = makeFindWindow(app);
1609 findWin->layout(-1, -1, -1, -1);
1614 static void findButtonCbk(LTKWidget *button, int n, GBool on) {
1620 textIn = (LTKTextIn *)findWin->findWidget("text");
1621 doFind(textIn->getText()->getCString());
1628 static void doFind(char *s) {
1629 TextOutputDev *textOut;
1630 int xMin, yMin, xMax, yMax;
1631 double xMin1, yMin1, xMax1, yMax1;
1636 // check for zero-length string
1642 // set cursors to watch
1643 win->setBusyCursor(gTrue);
1644 findWin->setBusyCursor(gTrue);
1646 // search current page starting at current selection or top of page
1647 xMin = yMin = xMax = yMax = 0;
1648 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1650 yMin = (selectYMin + selectYMax) / 2;
1655 if (out->findText(s, top, gTrue, &xMin, &yMin, &xMax, &yMax))
1658 // search following pages
1659 textOut = new TextOutputDev(NULL, gFalse);
1660 if (!textOut->isOk()) {
1664 for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
1665 doc->displayPage(textOut, pg, 72, 0, gFalse);
1666 if (textOut->findText(s, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1))
1670 // search previous pages
1671 for (pg = 1; pg < page; ++pg) {
1672 doc->displayPage(textOut, pg, 72, 0, gFalse);
1673 if (textOut->findText(s, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1))
1678 // search current page ending at current selection
1679 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1681 yMax = (selectYMin + selectYMax) / 2;
1682 if (out->findText(s, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax))
1690 // found on a different page
1693 displayPage(pg, zoom, rotate);
1694 if (!out->findText(s, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax))
1695 goto done; // this can happen if coalescing is bad
1697 // found: change the selection
1699 setSelection(xMin, yMin, xMax, yMax);
1700 #ifndef NO_TEXT_SELECT
1701 if (doc->okToCopy()) {
1702 s1 = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
1703 win->setSelection(NULL, s1);
1708 // reset cursors to normal
1709 win->setBusyCursor(gFalse);
1710 findWin->setBusyCursor(gFalse);
1713 //------------------------------------------------------------------------
1714 // app kill callback
1715 //------------------------------------------------------------------------
1717 static void killCbk(LTKWindow *win1) {
1720 } else if (win1 == aboutWin) {
1723 } else if (win1 == psDialog) {
1726 } else if (win1 == openDialog) {
1729 } else if (win1 == saveDialog) {
1732 } else if (win1 == findWin) {