1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
15 #include <X11/keysym.h>
16 #include <X11/cursorfont.h>
21 #include "GlobalParams.h"
23 #include "ErrorCodes.h"
25 #include "PSOutputDev.h"
26 #include "TextOutputDev.h"
27 #include "XPixmapOutputDev.h"
30 // these macro defns conflict with xpdf's Object class
31 #ifdef LESSTIF_VERSION
39 // hack around old X includes which are missing these symbols
41 #define XK_Page_Up 0xFF55
44 #define XK_Page_Down 0xFF56
47 #define XK_KP_Home 0xFF95
50 #define XK_KP_Left 0xFF96
53 #define XK_KP_Up 0xFF97
56 #define XK_KP_Right 0xFF98
59 #define XK_KP_Down 0xFF99
62 #define XK_KP_Prior 0xFF9A
65 #define XK_KP_Page_Up 0xFF9A
68 #define XK_KP_Next 0xFF9B
70 #ifndef XK_KP_Page_Down
71 #define XK_KP_Page_Down 0xFF9B
74 #define XK_KP_End 0xFF9C
77 #define XK_KP_Begin 0xFF9D
80 #define XK_KP_Insert 0xFF9E
83 #define XK_KP_Delete 0xFF9F
86 //------------------------------------------------------------------------
88 #define highlightNone 0
89 #define highlightNormal 1
90 #define highlightSelected 2
92 //------------------------------------------------------------------------
94 static int zoomDPI[maxZoom - minZoom + 1] = {
97 86, 104, 124, 149, 179
100 //------------------------------------------------------------------------
102 GString *XPDFCore::currentSelection = NULL;
103 XPDFCore *XPDFCore::currentSelectionOwner = NULL;
104 Atom XPDFCore::targetsAtom;
106 //------------------------------------------------------------------------
108 //------------------------------------------------------------------------
110 XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA,
111 Gulong paperColorA, GBool fullScreenA, GBool reverseVideo,
112 GBool installCmap, int rgbCubeSize) {
113 GString *initialZoom;
117 parentWidget = parentWidgetA;
118 display = XtDisplay(parentWidget);
119 screenNum = XScreenNumberOfScreen(XtScreen(parentWidget));
120 targetsAtom = XInternAtom(display, "TARGETS", False);
122 paperColor = paperColorA;
123 fullScreen = fullScreenA;
125 // for some reason, querying XmNvisual doesn't work (even if done
126 // after the window is mapped)
127 visual = DefaultVisual(display, screenNum);
128 XtVaGetValues(shell, XmNcolormap, &colormap, NULL);
133 drawAreaFrame = NULL;
141 // get the initial zoom value
142 initialZoom = globalParams->getInitialZoom();
143 if (!initialZoom->cmp("page")) {
145 } else if (!initialZoom->cmp("width")) {
148 zoom = atoi(initialZoom->getCString());
149 if (zoom < minZoom) {
151 } else if (zoom > maxZoom) {
160 selectXMin = selectXMax = 0;
161 selectYMin = selectYMax = 0;
163 lastDragLeft = lastDragTop = gTrue;
172 reqPasswordCbk = NULL;
175 historyCur = xpdfHistorySize - 1;
176 historyBLen = historyFLen = 0;
177 for (i = 0; i < xpdfHistorySize; ++i) {
178 history[i].fileName = NULL;
181 // optional features default to on
182 hyperlinksEnabled = gTrue;
183 selectEnabled = gTrue;
185 // do X-specific initialization and create the widgets
188 // create the OutputDev
189 out = new XPixmapOutputDev(display, screenNum, visual, colormap,
190 reverseVideo, paperColor,
191 installCmap, rgbCubeSize, gTrue,
192 &outputDevRedrawCbk, this);
196 XPDFCore::~XPDFCore() {
205 if (currentSelectionOwner == this && currentSelection) {
206 delete currentSelection;
207 currentSelection = NULL;
208 currentSelectionOwner = NULL;
210 for (i = 0; i < xpdfHistorySize; ++i) {
211 if (history[i].fileName) {
212 delete history[i].fileName;
216 XFreeGC(display, selectGC);
217 XFreeGC(display, highlightGC);
220 XFreeGC(display, drawAreaGC);
223 XtDestroyWidget(scrolledWin);
226 XFreeCursor(display, busyCursor);
229 XFreeCursor(display, linkCursor);
232 XFreeCursor(display, selectCursor);
236 //------------------------------------------------------------------------
237 // loadFile / displayPage / displayDest
238 //------------------------------------------------------------------------
240 int XPDFCore::loadFile(GString *fileName, GString *ownerPassword,
241 GString *userPassword) {
248 setCursor(busyCursor);
251 newDoc = new PDFDoc(fileName->copy(), ownerPassword, userPassword);
252 if (!newDoc->isOk()) {
253 err = newDoc->getErrorCode();
255 if (err != errEncrypted || !reqPasswordCbk) {
260 // try requesting a password
261 again = ownerPassword != NULL || userPassword != NULL;
263 if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) {
267 newDoc = new PDFDoc(fileName->copy(), password, password);
268 if (newDoc->isOk()) {
271 err = newDoc->getErrorCode();
273 if (err != errEncrypted) {
281 // replace old document
287 out->startDoc(doc->getXRef());
290 // nothing displayed yet
293 // save the modification time
294 modTime = getModTime(doc->getFileName()->getCString());
296 // update the parent window
298 (*updateCbk)(updateCbkData, doc->getFileName(), -1,
299 doc->getNumPages(), NULL);
302 // back to regular cursor
308 int XPDFCore::loadFile(BaseStream *stream, GString *ownerPassword,
309 GString *userPassword) {
316 setCursor(busyCursor);
319 newDoc = new PDFDoc(stream, ownerPassword, userPassword);
320 if (!newDoc->isOk()) {
321 err = newDoc->getErrorCode();
323 if (err != errEncrypted || !reqPasswordCbk) {
328 // try requesting a password
329 again = ownerPassword != NULL || userPassword != NULL;
331 if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) {
335 newDoc = new PDFDoc(stream, password, password);
336 if (newDoc->isOk()) {
339 err = newDoc->getErrorCode();
341 if (err != errEncrypted) {
349 // replace old document
355 out->startDoc(doc->getXRef());
358 // nothing displayed yet
361 // save the modification time
362 modTime = getModTime(doc->getFileName()->getCString());
364 // update the parent window
366 (*updateCbk)(updateCbkData, doc->getFileName(), -1,
367 doc->getNumPages(), NULL);
370 // back to regular cursor
376 void XPDFCore::resizeToPage(int pg) {
377 Dimension width, height;
378 double width1, height1;
379 Dimension topW, topH, topBorder, daW, daH;
380 Dimension displayW, displayH;
382 displayW = DisplayWidth(display, screenNum);
383 displayH = DisplayHeight(display, screenNum);
388 if (pg < 0 || pg > doc->getNumPages()) {
391 } else if (doc->getPageRotate(pg) == 90 ||
392 doc->getPageRotate(pg) == 270) {
393 width1 = doc->getPageHeight(pg);
394 height1 = doc->getPageWidth(pg);
396 width1 = doc->getPageWidth(pg);
397 height1 = doc->getPageHeight(pg);
399 if (zoom == zoomPage || zoom == zoomWidth) {
400 width = (Dimension)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
401 height = (Dimension)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
403 width = (Dimension)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
404 height = (Dimension)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
406 if (width > displayW - 100) {
407 width = displayW - 100;
409 if (height > displayH - 150) {
410 height = displayH - 150;
414 if (XtIsRealized(shell)) {
415 XtVaGetValues(shell, XmNwidth, &topW, XmNheight, &topH,
416 XmNborderWidth, &topBorder, NULL);
417 XtVaGetValues(drawArea, XmNwidth, &daW, XmNheight, &daH, NULL);
418 XtVaSetValues(shell, XmNwidth, width + (topW - daW),
419 XmNheight, height + (topH - daH), NULL);
421 XtVaSetValues(drawArea, XmNwidth, width, XmNheight, height, NULL);
425 void XPDFCore::clear() {
439 scrollX = scrollY = 0;
441 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
444 void XPDFCore::displayPage(int pageA, int zoomA, int rotateA,
445 GBool scrollToTop, GBool addToHist) {
452 int oldScrollX, oldScrollY;
454 // update the zoom and rotate values
455 newZoom = zoomA != zoom;
459 // check for document and valid page number
460 if (!doc || pageA <= 0 || pageA > doc->getNumPages()) {
465 setCursor(busyCursor);
468 // check for changes to the file
469 newModTime = getModTime(doc->getFileName()->getCString());
470 if (newModTime != modTime) {
471 if (loadFile(doc->getFileName()) == errNone) {
472 if (pageA > doc->getNumPages()) {
473 pageA = doc->getNumPages();
476 modTime = newModTime;
481 XFreeGC(display, selectGC);
482 XFreeGC(display, highlightGC);
493 // if zoom level changed, scroll to the top-left corner
495 scrollX = scrollY = 0;
498 // initialize mouse-related stuff
500 selectXMin = selectXMax = 0;
501 selectYMin = selectYMax = 0;
503 lastDragLeft = lastDragTop = gTrue;
506 rot = rotate + doc->getPageRotate(page);
509 } else if (rotate < 0) {
512 if (zoom == zoomPage) {
513 if (rot == 90 || rot == 270) {
514 hDPI = (drawAreaWidth / doc->getPageHeight(page)) * 72;
515 vDPI = (drawAreaHeight / doc->getPageWidth(page)) * 72;
517 hDPI = (drawAreaWidth / doc->getPageWidth(page)) * 72;
518 vDPI = (drawAreaHeight / doc->getPageHeight(page)) * 72;
520 dpi = (hDPI < vDPI) ? hDPI : vDPI;
521 } else if (zoom == zoomWidth) {
522 if (rot == 90 || rot == 270) {
523 dpi = (drawAreaWidth / doc->getPageHeight(page)) * 72;
525 dpi = (drawAreaWidth / doc->getPageWidth(page)) * 72;
528 dpi = zoomDPI[zoom - minZoom];
530 out->setWindow(XtWindow(drawArea));
531 doc->displayPage(out, page, dpi, rotate, gTrue);
532 oldScrollX = scrollX;
533 oldScrollY = scrollY;
535 if (scrollX != oldScrollX || scrollY != oldScrollY) {
536 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
540 gcValues.foreground = BlackPixel(display, screenNum) ^
541 WhitePixel(display, screenNum);
542 gcValues.function = GXxor;
543 selectGC = XCreateGC(display, out->getPixmap(),
544 GCForeground | GCFunction, &gcValues);
545 highlightGC = XCreateGC(display, out->getPixmap(),
546 GCForeground | GCFunction, &gcValues);
551 if (++historyCur == xpdfHistorySize) {
554 h = &history[historyCur];
558 if (doc->getFileName()) {
559 h->fileName = doc->getFileName()->copy();
564 if (historyBLen < xpdfHistorySize) {
570 // update the parent window
572 (*updateCbk)(updateCbkData, NULL, page, -1, "");
575 // back to regular cursor
579 void XPDFCore::displayDest(LinkDest *dest, int zoomA, int rotateA,
585 if (dest->isPageRef()) {
586 pageRef = dest->getPageRef();
587 pg = doc->findPage(pageRef.num, pageRef.gen);
589 pg = dest->getPageNum();
591 if (pg <= 0 || pg > doc->getNumPages()) {
595 displayPage(pg, zoomA, rotateA, gTrue, addToHist);
601 switch (dest->getKind()) {
603 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
604 if (dest->getChangeLeft() || dest->getChangeTop()) {
605 scrollTo(dest->getChangeLeft() ? dx : scrollX,
606 dest->getChangeTop() ? dy : scrollY);
608 //~ what is the zoom parameter?
618 out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
624 out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
629 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
635 //------------------------------------------------------------------------
636 // page/position changes
637 //------------------------------------------------------------------------
639 void XPDFCore::gotoNextPage(int inc, GBool top) {
642 if (!doc || doc->getNumPages() == 0) {
645 if (page < doc->getNumPages()) {
646 if ((pg = page + inc) > doc->getNumPages()) {
647 pg = doc->getNumPages();
649 displayPage(pg, zoom, rotate, top, gTrue);
655 void XPDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) {
658 if (!doc || doc->getNumPages() == 0) {
662 if (!fullScreen && bottom) {
663 scrollY = out->getPixmapHeight() - drawAreaHeight;
667 // displayPage will call updateScrollBars()
669 if ((pg = page - dec) < 1) {
672 displayPage(pg, zoom, rotate, top, gTrue);
678 void XPDFCore::goForward() {
679 if (historyFLen == 0) {
683 if (++historyCur == xpdfHistorySize) {
688 if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
689 if (loadFile(history[historyCur].fileName) != errNone) {
694 displayPage(history[historyCur].page, zoom, rotate, gFalse, gFalse);
697 void XPDFCore::goBackward() {
698 if (historyBLen <= 1) {
702 if (--historyCur < 0) {
703 historyCur = xpdfHistorySize - 1;
707 if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
708 if (loadFile(history[historyCur].fileName) != errNone) {
713 displayPage(history[historyCur].page, zoom, rotate, gFalse, gFalse);
716 void XPDFCore::scrollLeft(int nCols) {
717 scrollTo(scrollX - nCols * 16, scrollY);
720 void XPDFCore::scrollRight(int nCols) {
721 scrollTo(scrollX + nCols * 16, scrollY);
724 void XPDFCore::scrollUp(int nLines) {
725 scrollTo(scrollX, scrollY - nLines * 16);
728 void XPDFCore::scrollDown(int nLines) {
729 scrollTo(scrollX, scrollY + nLines * 16);
732 void XPDFCore::scrollPageUp() {
734 gotoPrevPage(1, gFalse, gTrue);
736 scrollTo(scrollX, scrollY - drawAreaHeight);
740 void XPDFCore::scrollPageDown() {
741 if (scrollY >= out->getPixmapHeight() - drawAreaHeight) {
742 gotoNextPage(1, gTrue);
744 scrollTo(scrollX, scrollY + drawAreaHeight);
748 void XPDFCore::scrollTo(int x, int y) {
754 maxPos = out ? out->getPixmapWidth() : 1;
755 if (maxPos < drawAreaWidth) {
756 maxPos = drawAreaWidth;
760 } else if (x > maxPos - drawAreaWidth) {
761 pos = maxPos - drawAreaWidth;
765 if (scrollX != pos) {
767 XmScrollBarSetValues(hScrollBar, scrollX, drawAreaWidth, 16,
768 drawAreaWidth, False);
772 maxPos = out ? out->getPixmapHeight() : 1;
773 if (maxPos < drawAreaHeight) {
774 maxPos = drawAreaHeight;
778 } else if (y > maxPos - drawAreaHeight) {
779 pos = maxPos - drawAreaHeight;
783 if (scrollY != pos) {
785 XmScrollBarSetValues(vScrollBar, scrollY, drawAreaHeight, 16,
786 drawAreaHeight, False);
791 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
795 //------------------------------------------------------------------------
797 //------------------------------------------------------------------------
799 void XPDFCore::setSelection(int newXMin, int newYMin,
800 int newXMax, int newYMax) {
803 GBool needRedraw, needScroll;
804 GBool moveLeft, moveRight, moveTop, moveBottom;
806 pixmap = out->getPixmap();
809 // erase old selection on off-screen bitmap
811 if (selectXMin < selectXMax && selectYMin < selectYMax) {
812 XFillRectangle(display, pixmap,
813 selectGC, selectXMin, selectYMin,
814 selectXMax - selectXMin, selectYMax - selectYMin);
818 // draw new selection on off-screen bitmap
819 if (newXMin < newXMax && newYMin < newYMax) {
820 XFillRectangle(display, pixmap,
821 selectGC, newXMin, newYMin,
822 newXMax - newXMin, newYMax - newYMin);
826 // check which edges moved
827 moveLeft = newXMin != selectXMin;
828 moveTop = newYMin != selectYMin;
829 moveRight = newXMax != selectXMax;
830 moveBottom = newYMax != selectYMax;
832 // redraw currently visible part of bitmap
835 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
836 (newYMin < selectYMin) ? newYMin : selectYMin,
837 (newXMin > selectXMin) ? newXMin : selectXMin,
838 (newYMax > selectYMax) ? newYMax : selectYMax);
841 redrawRectangle((newXMax < selectXMax) ? newXMax : selectXMax,
842 (newYMin < selectYMin) ? newYMin : selectYMin,
843 (newXMax > selectXMax) ? newXMax : selectXMax,
844 (newYMax > selectYMax) ? newYMax : selectYMax);
847 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
848 (newYMin < selectYMin) ? newYMin : selectYMin,
849 (newXMax > selectXMax) ? newXMax : selectXMax,
850 (newYMin > selectYMin) ? newYMin : selectYMin);
853 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
854 (newYMax < selectYMax) ? newYMax : selectYMax,
855 (newXMax > selectXMax) ? newXMax : selectXMax,
856 (newYMax > selectYMax) ? newYMax : selectYMax);
860 // switch to new selection coords
861 selectXMin = newXMin;
862 selectXMax = newXMax;
863 selectYMin = newYMin;
864 selectYMax = newYMax;
866 // scroll if necessary
873 if (moveLeft && selectXMin < x) {
876 } else if (moveRight && selectXMax >= x + drawAreaWidth) {
877 x = selectXMax - drawAreaWidth;
879 } else if (moveLeft && selectXMin >= x + drawAreaWidth) {
880 x = selectXMin - drawAreaWidth;
882 } else if (moveRight && selectXMax < x) {
886 if (moveTop && selectYMin < y) {
889 } else if (moveBottom && selectYMax >= y + drawAreaHeight) {
890 y = selectYMax - drawAreaHeight;
892 } else if (moveTop && selectYMin >= y + drawAreaHeight) {
893 y = selectYMin - drawAreaHeight;
895 } else if (moveBottom && selectYMax < y) {
904 void XPDFCore::moveSelection(int mx, int my) {
905 int xMin, yMin, xMax, yMax;
910 } else if (mx >= out->getPixmapWidth()) {
911 mx = out->getPixmapWidth() - 1;
915 } else if (my >= out->getPixmapHeight()) {
916 my = out->getPixmapHeight() - 1;
919 // move appropriate edges of selection
921 if (mx < selectXMax) {
927 lastDragLeft = gFalse;
930 if (mx > selectXMin) {
936 lastDragLeft = gTrue;
940 if (my < selectYMax) {
946 lastDragTop = gFalse;
949 if (my > selectYMin) {
959 // redraw the selection
960 setSelection(xMin, yMin, xMax, yMax);
963 // X's copy-and-paste mechanism is brain damaged. Xt doesn't help
964 // any, but doesn't make it too much worse, either. Motif, on the
965 // other hand, adds significant complexity to the mess. So here we
966 // blow off the Motif junk and stick to plain old Xt. The next two
967 // functions (copySelection and convertSelectionCbk) implement the
968 // magic needed to deal with Xt's mechanism. Note that this requires
969 // global variables (currentSelection and currentSelectionOwner).
971 void XPDFCore::copySelection() {
972 if (!doc->okToCopy()) {
975 if (currentSelection) {
976 delete currentSelection;
978 //~ for multithreading: need a mutex here
979 currentSelection = out->getText(selectXMin, selectYMin,
980 selectXMax, selectYMax);
981 currentSelectionOwner = this;
982 XtOwnSelection(drawArea, XA_PRIMARY, XtLastTimestampProcessed(display),
983 &convertSelectionCbk, NULL, NULL);
986 Boolean XPDFCore::convertSelectionCbk(Widget widget, Atom *selection,
987 Atom *target, Atom *type,
988 XtPointer *value, unsigned long *length,
992 // send back a list of supported conversion targets
993 if (*target == targetsAtom) {
994 if (!(array = (Atom *)XtMalloc(sizeof(Atom)))) {
997 array[0] = XA_STRING;
998 *value = (XtPointer)array;
1004 // send the selected text
1005 } else if (*target == XA_STRING) {
1006 //~ for multithreading: need a mutex here
1007 *value = XtNewString(currentSelection->getCString());
1008 *length = currentSelection->getLength();
1010 *format = 8; // 8-bit elements
1017 GBool XPDFCore::getSelection(int *xMin, int *yMin, int *xMax, int *yMax) {
1018 if (selectXMin >= selectXMax || selectYMin >= selectYMax) {
1028 GString *XPDFCore::extractText(int xMin, int yMin, int xMax, int yMax) {
1029 if (!doc->okToCopy()) {
1032 return out->getText(xMin, yMin, xMax, yMax);
1035 GString *XPDFCore::extractText(int pageNum,
1036 int xMin, int yMin, int xMax, int yMax) {
1037 TextOutputDev *textOut;
1040 if (!doc->okToCopy()) {
1043 textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
1044 if (!textOut->isOk()) {
1048 doc->displayPage(textOut, pageNum, dpi, rotate, gFalse);
1049 s = textOut->getText(xMin, yMin, xMax, yMax);
1054 //------------------------------------------------------------------------
1056 //------------------------------------------------------------------------
1058 void XPDFCore::doLink(int mx, int my) {
1063 out->cvtDevToUser(mx, my, &x, &y);
1064 if ((action = doc->findLink(x, y))) {
1069 void XPDFCore::doAction(LinkAction *action) {
1070 LinkActionKind kind;
1074 GString *fileName, *fileName2;
1076 GString *actionName;
1077 Object movieAnnot, obj1, obj2;
1081 switch (kind = action->getKind()) {
1083 // GoTo / GoToR action
1086 if (kind == actionGoTo) {
1089 if ((dest = ((LinkGoTo *)action)->getDest())) {
1090 dest = dest->copy();
1091 } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
1092 namedDest = namedDest->copy();
1097 if ((dest = ((LinkGoToR *)action)->getDest())) {
1098 dest = dest->copy();
1099 } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) {
1100 namedDest = namedDest->copy();
1102 s = ((LinkGoToR *)action)->getFileName()->getCString();
1103 //~ translate path name for VMS (deal with '/')
1104 if (isAbsolutePath(s)) {
1105 fileName = new GString(s);
1107 fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
1109 if (loadFile(fileName) != errNone) {
1122 dest = doc->findDest(namedDest);
1126 displayDest(dest, zoom, rotate, gTrue);
1129 if (kind == actionGoToR) {
1130 displayPage(1, zoom, 0, gFalse, gTrue);
1137 fileName = ((LinkLaunch *)action)->getFileName();
1138 s = fileName->getCString();
1139 if (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
1140 !strcmp(s + fileName->getLength() - 4, ".PDF")) {
1141 //~ translate path name for VMS (deal with '/')
1142 if (isAbsolutePath(s)) {
1143 fileName = fileName->copy();
1145 fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
1147 if (loadFile(fileName) != errNone) {
1152 displayPage(1, zoom, rotate, gFalse, gTrue);
1154 fileName = fileName->copy();
1155 if (((LinkLaunch *)action)->getParams()) {
1156 fileName->append(' ');
1157 fileName->append(((LinkLaunch *)action)->getParams());
1160 fileName->insert(0, "spawn/nowait ");
1161 #elif defined(__EMX__)
1162 fileName->insert(0, "start /min /n ");
1164 fileName->append(" &");
1166 msg = new GString("About to execute the command:\n");
1167 msg->append(fileName);
1168 if (doQuestionDialog("Launching external application", msg)) {
1169 system(fileName->getCString());
1178 if (!(cmd = globalParams->getURLCommand())) {
1179 error(-1, "No urlCommand defined in config file");
1182 runCommand(cmd, ((LinkURI *)action)->getURI());
1187 actionName = ((LinkNamed *)action)->getName();
1188 if (!actionName->cmp("NextPage")) {
1189 gotoNextPage(1, gTrue);
1190 } else if (!actionName->cmp("PrevPage")) {
1191 gotoPrevPage(1, gTrue, gFalse);
1192 } else if (!actionName->cmp("FirstPage")) {
1194 displayPage(1, zoom, rotate, gTrue, gTrue);
1196 } else if (!actionName->cmp("LastPage")) {
1197 if (page != doc->getNumPages()) {
1198 displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
1200 } else if (!actionName->cmp("GoBack")) {
1202 } else if (!actionName->cmp("GoForward")) {
1204 } else if (!actionName->cmp("Quit")) {
1206 (*actionCbk)(actionCbkData, "Quit");
1209 error(-1, "Unknown named action: '%s'", actionName->getCString());
1215 if (!(cmd = globalParams->getMovieCommand())) {
1216 error(-1, "No movieCommand defined in config file");
1219 if (((LinkMovie *)action)->hasAnnotRef()) {
1220 doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num,
1221 ((LinkMovie *)action)->getAnnotRef()->gen,
1224 doc->getCatalog()->getPage(page)->getAnnots(&obj1);
1225 if (obj1.isArray()) {
1226 for (i = 0; i < obj1.arrayGetLength(); ++i) {
1227 if (obj1.arrayGet(i, &movieAnnot)->isDict()) {
1228 if (movieAnnot.dictLookup("Subtype", &obj2)->isName("Movie")) {
1239 if (movieAnnot.isDict()) {
1240 if (movieAnnot.dictLookup("Movie", &obj1)->isDict()) {
1241 if (obj1.dictLookup("F", &obj2)) {
1242 if ((fileName = LinkAction::getFileSpecName(&obj2))) {
1243 if (!isAbsolutePath(fileName->getCString())) {
1244 fileName2 = appendToPath(
1245 grabPath(doc->getFileName()->getCString()),
1246 fileName->getCString());
1248 fileName = fileName2;
1250 runCommand(cmd, fileName);
1261 // unknown action type
1263 error(-1, "Unknown link action type: '%s'",
1264 ((LinkUnknown *)action)->getAction()->getCString());
1269 // Run a command, given a <cmdFmt> string with one '%s' in it, and an
1270 // <arg> string to insert in place of the '%s'.
1271 void XPDFCore::runCommand(GString *cmdFmt, GString *arg) {
1276 if ((s = strstr(cmdFmt->getCString(), "%s"))) {
1278 // filter out any quote marks (' or ") to avoid a potential
1281 while (i < cmd->getLength()) {
1282 if (cmd->getChar(i) == '"') {
1284 cmd->insert(i, "%22");
1286 } else if (cmd->getChar(i) == '\'') {
1288 cmd->insert(i, "%27");
1294 cmd->insert(0, cmdFmt->getCString(),
1295 s - cmdFmt->getCString());
1298 cmd = cmdFmt->copy();
1301 cmd->insert(0, "spawn/nowait ");
1302 #elif defined(__EMX__)
1303 cmd->insert(0, "start /min /n ");
1307 system(cmd->getCString());
1312 //------------------------------------------------------------------------
1314 //------------------------------------------------------------------------
1316 void XPDFCore::find(char *s) {
1318 TextOutputDev *textOut;
1319 int xMin, yMin, xMax, yMax;
1320 double xMin1, yMin1, xMax1, yMax1;
1325 // check for zero-length string
1331 // set cursor to watch
1332 setCursor(busyCursor);
1334 // convert to Unicode
1335 #if 1 //~ should do something more intelligent here
1337 u = (Unicode *)gmalloc(len * sizeof(Unicode));
1338 for (i = 0; i < len; ++i) {
1339 u[i] = (Unicode)(s[i] & 0xff);
1343 // search current page starting at current selection or top of page
1344 xMin = yMin = xMax = yMax = 0;
1345 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1347 yMin = (selectYMin + selectYMax) / 2;
1352 if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) {
1356 // search following pages
1357 textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
1358 if (!textOut->isOk()) {
1362 for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
1363 doc->displayPage(textOut, pg, 72, 0, gFalse);
1364 if (textOut->findText(u, len, gTrue, gTrue,
1365 &xMin1, &yMin1, &xMax1, &yMax1)) {
1370 // search previous pages
1371 for (pg = 1; pg < page; ++pg) {
1372 doc->displayPage(textOut, pg, 72, 0, gFalse);
1373 if (textOut->findText(u, len, gTrue, gTrue,
1374 &xMin1, &yMin1, &xMax1, &yMax1)) {
1380 // search current page ending at current selection
1381 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1383 yMax = (selectYMin + selectYMax) / 2;
1384 if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) {
1393 // found on a different page
1396 displayPage(pg, zoom, rotate, gTrue, gTrue);
1397 if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) {
1398 // this can happen if coalescing is bad
1402 // found: change the selection
1404 setSelection(xMin, yMin, xMax, yMax);
1405 #ifndef NO_TEXT_SELECT
1412 // reset cursors to normal
1416 //------------------------------------------------------------------------
1418 //------------------------------------------------------------------------
1420 void XPDFCore::setBusyCursor(GBool busy) {
1421 setCursor(busy ? busyCursor : None);
1424 void XPDFCore::takeFocus() {
1425 XmProcessTraversal(drawArea, XmTRAVERSE_CURRENT);
1428 //------------------------------------------------------------------------
1430 //------------------------------------------------------------------------
1432 void XPDFCore::initWindow() {
1436 // create the cursors
1437 busyCursor = XCreateFontCursor(display, XC_watch);
1438 linkCursor = XCreateFontCursor(display, XC_hand2);
1439 selectCursor = XCreateFontCursor(display, XC_cross);
1442 // create the scrolled window and scrollbars
1444 XtSetArg(args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED); ++n;
1445 XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n;
1446 scrolledWin = XmCreateScrolledWindow(parentWidget, "scroll", args, n);
1447 XtManageChild(scrolledWin);
1449 XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
1450 XtSetArg(args[n], XmNminimum, 0); ++n;
1451 XtSetArg(args[n], XmNmaximum, 1); ++n;
1452 XtSetArg(args[n], XmNsliderSize, 1); ++n;
1453 XtSetArg(args[n], XmNvalue, 0); ++n;
1454 XtSetArg(args[n], XmNincrement, 1); ++n;
1455 XtSetArg(args[n], XmNpageIncrement, 1); ++n;
1456 hScrollBar = XmCreateScrollBar(scrolledWin, "hScrollBar", args, n);
1457 XtManageChild(hScrollBar);
1458 XtAddCallback(hScrollBar, XmNvalueChangedCallback,
1459 &hScrollChangeCbk, (XtPointer)this);
1460 #ifndef DISABLE_SMOOTH_SCROLL
1461 XtAddCallback(hScrollBar, XmNdragCallback,
1462 &hScrollDragCbk, (XtPointer)this);
1465 XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n;
1466 XtSetArg(args[n], XmNminimum, 0); ++n;
1467 XtSetArg(args[n], XmNmaximum, 1); ++n;
1468 XtSetArg(args[n], XmNsliderSize, 1); ++n;
1469 XtSetArg(args[n], XmNvalue, 0); ++n;
1470 XtSetArg(args[n], XmNincrement, 1); ++n;
1471 XtSetArg(args[n], XmNpageIncrement, 1); ++n;
1472 vScrollBar = XmCreateScrollBar(scrolledWin, "vScrollBar", args, n);
1473 XtManageChild(vScrollBar);
1474 XtAddCallback(vScrollBar, XmNvalueChangedCallback,
1475 &vScrollChangeCbk, (XtPointer)this);
1476 #ifndef DISABLE_SMOOTH_SCROLL
1477 XtAddCallback(vScrollBar, XmNdragCallback,
1478 &vScrollDragCbk, (XtPointer)this);
1481 // create the drawing area
1483 XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); ++n;
1484 XtSetArg(args[n], XmNmarginWidth, 0); ++n;
1485 XtSetArg(args[n], XmNmarginHeight, 0); ++n;
1487 XtSetArg(args[n], XmNshadowThickness, 0); ++n;
1489 drawAreaFrame = XmCreateFrame(scrolledWin, "drawAreaFrame", args, n);
1490 XtManageChild(drawAreaFrame);
1492 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n;
1493 XtSetArg(args[n], XmNbackground, paperColor); ++n;
1494 XtSetArg(args[n], XmNwidth, 700); ++n;
1495 XtSetArg(args[n], XmNheight, 500); ++n;
1496 drawArea = XmCreateDrawingArea(drawAreaFrame, "drawArea", args, n);
1497 XtManageChild(drawArea);
1498 XtAddCallback(drawArea, XmNresizeCallback, &resizeCbk, (XtPointer)this);
1499 XtAddCallback(drawArea, XmNexposeCallback, &redrawCbk, (XtPointer)this);
1500 XtAddCallback(drawArea, XmNinputCallback, &inputCbk, (XtPointer)this);
1501 resizeCbk(drawArea, this, NULL);
1503 // set up mouse motion translations
1504 XtOverrideTranslations(drawArea, XtParseTranslationTable(
1505 "<Btn1Down>:DrawingAreaInput()\n"
1506 "<Btn1Up>:DrawingAreaInput()\n"
1507 "<Btn1Motion>:DrawingAreaInput()\n"
1508 "<Motion>:DrawingAreaInput()"));
1510 // can't create a GC until the window gets mapped
1516 void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr,
1517 XtPointer callData) {
1518 XPDFCore *core = (XPDFCore *)ptr;
1519 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1521 core->scrollTo(data->value, core->scrollY);
1524 void XPDFCore::hScrollDragCbk(Widget widget, XtPointer ptr,
1525 XtPointer callData) {
1526 XPDFCore *core = (XPDFCore *)ptr;
1527 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1529 core->scrollTo(data->value, core->scrollY);
1532 void XPDFCore::vScrollChangeCbk(Widget widget, XtPointer ptr,
1533 XtPointer callData) {
1534 XPDFCore *core = (XPDFCore *)ptr;
1535 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1537 core->scrollTo(core->scrollX, data->value);
1540 void XPDFCore::vScrollDragCbk(Widget widget, XtPointer ptr,
1541 XtPointer callData) {
1542 XPDFCore *core = (XPDFCore *)ptr;
1543 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1545 core->scrollTo(core->scrollX, data->value);
1548 void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1549 XPDFCore *core = (XPDFCore *)ptr;
1553 int oldScrollX, oldScrollY;
1556 XtSetArg(args[n], XmNwidth, &w); ++n;
1557 XtSetArg(args[n], XmNheight, &h); ++n;
1558 XtGetValues(core->drawArea, args, n);
1559 core->drawAreaWidth = (int)w;
1560 core->drawAreaHeight = (int)h;
1561 if (core->page >= 0 &&
1562 (core->zoom == zoomPage || core->zoom == zoomWidth)) {
1563 core->displayPage(core->page, core->zoom, core->rotate,
1566 oldScrollX = core->scrollX;
1567 oldScrollY = core->scrollY;
1568 core->updateScrollBars();
1569 if (core->scrollX != oldScrollX || core->scrollY != oldScrollY) {
1570 core->redrawRectangle(core->scrollX, core->scrollY,
1571 core->drawAreaWidth, core->drawAreaHeight);
1576 void XPDFCore::redrawCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1577 XPDFCore *core = (XPDFCore *)ptr;
1578 XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData;
1581 if (data->reason == XmCR_EXPOSE) {
1582 x = core->scrollX + data->event->xexpose.x;
1583 y = core->scrollY + data->event->xexpose.y;
1584 w = data->event->xexpose.width;
1585 h = data->event->xexpose.height;
1589 w = core->drawAreaWidth;
1590 h = core->drawAreaHeight;
1592 core->redrawRectangle(x, y, w, h);
1595 void XPDFCore::outputDevRedrawCbk(void *data) {
1596 XPDFCore *core = (XPDFCore *)data;
1598 core->redrawRectangle(core->scrollX, core->scrollY,
1599 core->drawAreaWidth, core->drawAreaHeight);
1602 void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1603 XPDFCore *core = (XPDFCore *)ptr;
1604 XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData;
1613 switch (data->event->type) {
1615 if (data->event->xbutton.button == 1) {
1617 if (core->doc && core->doc->getNumPages() > 0) {
1618 if (core->selectEnabled) {
1619 mx = core->scrollX + data->event->xbutton.x;
1620 my = core->scrollY + data->event->xbutton.y;
1621 core->setSelection(mx, my, mx, my);
1622 core->setCursor(core->selectCursor);
1623 core->dragging = gTrue;
1626 } else if (data->event->xbutton.button == 2) {
1627 if (!core->fullScreen) {
1628 core->panning = gTrue;
1629 core->panMX = data->event->xbutton.x;
1630 core->panMY = data->event->xbutton.y;
1632 } else if (data->event->xbutton.button == 4) { // mouse wheel up
1633 if (core->fullScreen) {
1634 core->gotoPrevPage(1, gTrue, gFalse);
1635 } else if (core->scrollY == 0) {
1636 core->gotoPrevPage(1, gFalse, gTrue);
1640 } else if (data->event->xbutton.button == 5) { // mouse wheel down
1641 if (core->fullScreen ||
1643 core->out->getPixmapHeight() - core->drawAreaHeight) {
1644 core->gotoNextPage(1, gTrue);
1646 core->scrollDown(1);
1648 } else if (data->event->xbutton.button == 6) { // second mouse wheel right
1649 if (!core->fullScreen) {
1650 core->scrollRight(1);
1652 } else if (data->event->xbutton.button == 7) { // second mouse wheel left
1653 if (!core->fullScreen) {
1654 core->scrollLeft(1);
1657 if (*core->mouseCbk) {
1658 (*core->mouseCbk)(core->mouseCbkData, data->event);
1663 if (data->event->xbutton.button == 1) {
1664 if (core->doc && core->doc->getNumPages() > 0) {
1665 mx = core->scrollX + data->event->xbutton.x;
1666 my = core->scrollY + data->event->xbutton.y;
1667 if (core->dragging) {
1668 core->dragging = gFalse;
1669 core->setCursor(None);
1670 core->moveSelection(mx, my);
1671 #ifndef NO_TEXT_SELECT
1672 if (core->selectXMin != core->selectXMax &&
1673 core->selectYMin != core->selectYMax) {
1674 if (core->doc->okToCopy()) {
1675 core->copySelection();
1677 error(-1, "Copying of text from this document is not allowed.");
1682 if (core->hyperlinksEnabled) {
1683 if (core->selectXMin == core->selectXMax ||
1684 core->selectYMin == core->selectYMax) {
1685 core->doLink(mx, my);
1689 } else if (data->event->xbutton.button == 2) {
1690 core->panning = gFalse;
1692 if (*core->mouseCbk) {
1693 (*core->mouseCbk)(core->mouseCbkData, data->event);
1698 if (core->doc && core->doc->getNumPages() > 0) {
1699 mx = core->scrollX + data->event->xbutton.x;
1700 my = core->scrollY + data->event->xbutton.y;
1701 if (core->dragging) {
1702 core->moveSelection(mx, my);
1703 } else if (core->hyperlinksEnabled) {
1704 core->out->cvtDevToUser(mx, my, &x, &y);
1705 if ((action = core->doc->findLink(x, y))) {
1706 core->setCursor(core->linkCursor);
1707 if (action != core->linkAction) {
1708 core->linkAction = action;
1709 if (core->updateCbk) {
1711 switch (action->getKind()) {
1713 s = "[internal link]";
1716 s = ((LinkGoToR *)action)->getFileName()->getCString();
1719 s = ((LinkLaunch *)action)->getFileName()->getCString();
1722 s = ((LinkURI *)action)->getURI()->getCString();
1725 s = ((LinkNamed *)action)->getName()->getCString();
1731 s = "[unknown link]";
1734 (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, s);
1738 core->setCursor(None);
1739 if (core->linkAction) {
1740 core->linkAction = NULL;
1741 if (core->updateCbk) {
1742 (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, "");
1748 if (core->panning) {
1749 core->scrollTo(core->scrollX - (data->event->xbutton.x - core->panMX),
1750 core->scrollY - (data->event->xbutton.y - core->panMY));
1751 core->panMX = data->event->xbutton.x;
1752 core->panMY = data->event->xbutton.y;
1756 n = XLookupString(&data->event->xkey, buf, sizeof(buf) - 1,
1758 core->keyPress(buf, key, data->event->xkey.state);
1763 void XPDFCore::keyPress(char *s, KeySym key, Guint modifiers) {
1767 if (modifiers & ControlMask) {
1768 displayPage(1, zoom, rotate, gTrue, gTrue);
1769 } else if (!fullScreen) {
1775 if (modifiers & ControlMask) {
1776 displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
1777 } else if (!fullScreen) {
1778 scrollTo(out->getPixmapWidth() - drawAreaWidth,
1779 out->getPixmapHeight() - drawAreaHeight);
1785 gotoPrevPage(1, gTrue, gFalse);
1791 case XK_KP_Page_Down:
1793 gotoNextPage(1, gTrue);
1825 (*keyPressCbk)(keyPressCbkData, s, key, modifiers);
1829 void XPDFCore::redrawRectangle(int x, int y, int w, int h) {
1838 if (x + w > scrollX + drawAreaWidth) {
1839 w = scrollX + drawAreaWidth - x;
1845 if (y + h > scrollY + drawAreaHeight) {
1846 h = scrollY + drawAreaHeight - y;
1849 // create a GC for the drawing area
1850 drawAreaWin = XtWindow(drawArea);
1852 gcValues.foreground = paperColor;
1853 drawAreaGC = XCreateGC(display, drawAreaWin, GCForeground, &gcValues);
1856 // draw white background past the edges of the document
1857 if (x + w > out->getPixmapWidth()) {
1858 XFillRectangle(display, drawAreaWin, drawAreaGC,
1859 out->getPixmapWidth() - scrollX, y - scrollY,
1860 x + w - out->getPixmapWidth(), h);
1861 w = out->getPixmapWidth() - x;
1863 if (y + h > out->getPixmapHeight()) {
1864 XFillRectangle(display, drawAreaWin, drawAreaGC,
1865 x - scrollX, out->getPixmapHeight() - scrollY,
1866 w, y + h - out->getPixmapHeight());
1867 h = out->getPixmapHeight() - y;
1870 // redraw (checking to see if pixmap has been allocated yet)
1871 if (out->getPixmapWidth() > 0) {
1872 XCopyArea(display, out->getPixmap(), drawAreaWin, drawAreaGC,
1873 x, y, w, h, x - scrollX, y - scrollY);
1877 void XPDFCore::updateScrollBars() {
1882 maxPos = out ? out->getPixmapWidth() : 1;
1883 if (maxPos < drawAreaWidth) {
1884 maxPos = drawAreaWidth;
1886 if (scrollX > maxPos - drawAreaWidth) {
1887 scrollX = maxPos - drawAreaWidth;
1890 XtSetArg(args[n], XmNvalue, scrollX); ++n;
1891 XtSetArg(args[n], XmNmaximum, maxPos); ++n;
1892 XtSetArg(args[n], XmNsliderSize, drawAreaWidth); ++n;
1893 XtSetArg(args[n], XmNincrement, 16); ++n;
1894 XtSetArg(args[n], XmNpageIncrement, drawAreaWidth); ++n;
1895 XtSetValues(hScrollBar, args, n);
1897 maxPos = out ? out->getPixmapHeight() : 1;
1898 if (maxPos < drawAreaHeight) {
1899 maxPos = drawAreaHeight;
1901 if (scrollY > maxPos - drawAreaHeight) {
1902 scrollY = maxPos - drawAreaHeight;
1905 XtSetArg(args[n], XmNvalue, scrollY); ++n;
1906 XtSetArg(args[n], XmNmaximum, maxPos); ++n;
1907 XtSetArg(args[n], XmNsliderSize, drawAreaHeight); ++n;
1908 XtSetArg(args[n], XmNincrement, 16); ++n;
1909 XtSetArg(args[n], XmNpageIncrement, drawAreaHeight); ++n;
1910 XtSetValues(vScrollBar, args, n);
1913 void XPDFCore::setCursor(Cursor cursor) {
1916 if (cursor == currentCursor) {
1919 if (!(topWin = XtWindow(shell))) {
1922 if (cursor == None) {
1923 XUndefineCursor(display, topWin);
1925 XDefineCursor(display, topWin, cursor);
1928 currentCursor = cursor;
1931 GBool XPDFCore::doQuestionDialog(char *title, GString *msg) {
1932 return doDialog(XmDIALOG_QUESTION, gTrue, title, msg);
1935 void XPDFCore::doInfoDialog(char *title, GString *msg) {
1936 doDialog(XmDIALOG_INFORMATION, gFalse, title, msg);
1939 void XPDFCore::doErrorDialog(char *title, GString *msg) {
1940 doDialog(XmDIALOG_ERROR, gFalse, title, msg);
1943 GBool XPDFCore::doDialog(int type, GBool hasCancel,
1944 char *title, GString *msg) {
1946 XtAppContext appContext;
1953 XtSetArg(args[n], XmNdialogType, type); ++n;
1954 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
1955 s1 = XmStringCreateLocalized(title);
1956 XtSetArg(args[n], XmNdialogTitle, s1); ++n;
1957 s2 = XmStringCreateLocalized(msg->getCString());
1958 XtSetArg(args[n], XmNmessageString, s2); ++n;
1959 dialog = XmCreateMessageDialog(drawArea, "questionDialog", args, n);
1962 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
1963 XtAddCallback(dialog, XmNokCallback,
1964 &dialogOkCbk, (XtPointer)this);
1966 XtAddCallback(dialog, XmNcancelCallback,
1967 &dialogCancelCbk, (XtPointer)this);
1969 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
1972 XtManageChild(dialog);
1974 appContext = XtWidgetToApplicationContext(dialog);
1977 XtAppNextEvent(appContext, &event);
1978 XtDispatchEvent(&event);
1979 } while (!dialogDone);
1981 XtUnmanageChild(dialog);
1982 XtDestroyWidget(dialog);
1984 return dialogDone > 0;
1987 void XPDFCore::dialogOkCbk(Widget widget, XtPointer ptr,
1988 XtPointer callData) {
1989 XPDFCore *core = (XPDFCore *)ptr;
1991 core->dialogDone = 1;
1994 void XPDFCore::dialogCancelCbk(Widget widget, XtPointer ptr,
1995 XtPointer callData) {
1996 XPDFCore *core = (XPDFCore *)ptr;
1998 core->dialogDone = -1;