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>
22 #include "GlobalParams.h"
24 #include "ErrorCodes.h"
26 #include "PSOutputDev.h"
27 #include "TextOutputDev.h"
28 #include "XPixmapOutputDev.h"
31 // these macro defns conflict with xpdf's Object class
32 #ifdef LESSTIF_VERSION
40 // hack around old X includes which are missing these symbols
42 #define XK_Page_Up 0xFF55
45 #define XK_Page_Down 0xFF56
48 #define XK_KP_Home 0xFF95
51 #define XK_KP_Left 0xFF96
54 #define XK_KP_Up 0xFF97
57 #define XK_KP_Right 0xFF98
60 #define XK_KP_Down 0xFF99
63 #define XK_KP_Prior 0xFF9A
66 #define XK_KP_Page_Up 0xFF9A
69 #define XK_KP_Next 0xFF9B
71 #ifndef XK_KP_Page_Down
72 #define XK_KP_Page_Down 0xFF9B
75 #define XK_KP_End 0xFF9C
78 #define XK_KP_Begin 0xFF9D
81 #define XK_KP_Insert 0xFF9E
84 #define XK_KP_Delete 0xFF9F
87 //------------------------------------------------------------------------
89 #define highlightNone 0
90 #define highlightNormal 1
91 #define highlightSelected 2
93 //------------------------------------------------------------------------
95 GString *XPDFCore::currentSelection = NULL;
96 XPDFCore *XPDFCore::currentSelectionOwner = NULL;
97 Atom XPDFCore::targetsAtom;
99 //------------------------------------------------------------------------
101 //------------------------------------------------------------------------
103 XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA,
104 Gulong paperColorA, GBool fullScreenA, GBool reverseVideo,
105 GBool installCmap, int rgbCubeSize) {
106 GString *initialZoom;
110 parentWidget = parentWidgetA;
111 display = XtDisplay(parentWidget);
112 screenNum = XScreenNumberOfScreen(XtScreen(parentWidget));
113 targetsAtom = XInternAtom(display, "TARGETS", False);
115 paperColor = paperColorA;
116 fullScreen = fullScreenA;
118 // for some reason, querying XmNvisual doesn't work (even if done
119 // after the window is mapped)
120 visual = DefaultVisual(display, screenNum);
121 XtVaGetValues(shell, XmNcolormap, &colormap, NULL);
126 drawAreaFrame = NULL;
134 // get the initial zoom value
135 initialZoom = globalParams->getInitialZoom();
136 if (!initialZoom->cmp("page")) {
138 } else if (!initialZoom->cmp("width")) {
141 zoom = atoi(initialZoom->getCString());
151 selectXMin = selectXMax = 0;
152 selectYMin = selectYMax = 0;
154 lastDragLeft = lastDragTop = gTrue;
163 reqPasswordCbk = NULL;
166 historyCur = xpdfHistorySize - 1;
167 historyBLen = historyFLen = 0;
168 for (i = 0; i < xpdfHistorySize; ++i) {
169 history[i].fileName = NULL;
172 // optional features default to on
173 hyperlinksEnabled = gTrue;
174 selectEnabled = gTrue;
176 // do X-specific initialization and create the widgets
179 // create the OutputDev
180 out = new XPixmapOutputDev(display, screenNum, visual, colormap,
181 reverseVideo, paperColor,
182 installCmap, rgbCubeSize, gTrue,
183 &outputDevRedrawCbk, this);
187 XPDFCore::~XPDFCore() {
196 if (currentSelectionOwner == this && currentSelection) {
197 delete currentSelection;
198 currentSelection = NULL;
199 currentSelectionOwner = NULL;
201 for (i = 0; i < xpdfHistorySize; ++i) {
202 if (history[i].fileName) {
203 delete history[i].fileName;
207 XFreeGC(display, selectGC);
208 XFreeGC(display, highlightGC);
211 XFreeGC(display, drawAreaGC);
214 XtDestroyWidget(scrolledWin);
217 XFreeCursor(display, busyCursor);
220 XFreeCursor(display, linkCursor);
223 XFreeCursor(display, selectCursor);
227 //------------------------------------------------------------------------
228 // loadFile / displayPage / displayDest
229 //------------------------------------------------------------------------
231 int XPDFCore::loadFile(GString *fileName, GString *ownerPassword,
232 GString *userPassword) {
239 setCursor(busyCursor);
242 newDoc = new PDFDoc(fileName->copy(), ownerPassword, userPassword);
243 if (!newDoc->isOk()) {
244 err = newDoc->getErrorCode();
246 if (err != errEncrypted || !reqPasswordCbk) {
251 // try requesting a password
252 again = ownerPassword != NULL || userPassword != NULL;
254 if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) {
258 newDoc = new PDFDoc(fileName->copy(), password, password);
259 if (newDoc->isOk()) {
262 err = newDoc->getErrorCode();
264 if (err != errEncrypted) {
272 // replace old document
278 out->startDoc(doc->getXRef());
281 // nothing displayed yet
284 // save the modification time
285 modTime = getModTime(doc->getFileName()->getCString());
287 // update the parent window
289 (*updateCbk)(updateCbkData, doc->getFileName(), -1,
290 doc->getNumPages(), NULL);
293 // back to regular cursor
299 int XPDFCore::loadFile(BaseStream *stream, GString *ownerPassword,
300 GString *userPassword) {
307 setCursor(busyCursor);
310 newDoc = new PDFDoc(stream, ownerPassword, userPassword);
311 if (!newDoc->isOk()) {
312 err = newDoc->getErrorCode();
314 if (err != errEncrypted || !reqPasswordCbk) {
319 // try requesting a password
320 again = ownerPassword != NULL || userPassword != NULL;
322 if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) {
326 newDoc = new PDFDoc(stream, password, password);
327 if (newDoc->isOk()) {
330 err = newDoc->getErrorCode();
332 if (err != errEncrypted) {
340 // replace old document
346 out->startDoc(doc->getXRef());
349 // nothing displayed yet
352 // save the modification time
353 modTime = getModTime(doc->getFileName()->getCString());
355 // update the parent window
357 (*updateCbk)(updateCbkData, doc->getFileName(), -1,
358 doc->getNumPages(), NULL);
361 // back to regular cursor
367 void XPDFCore::resizeToPage(int pg) {
368 Dimension width, height;
369 double width1, height1;
370 Dimension topW, topH, topBorder, daW, daH;
371 Dimension displayW, displayH;
373 displayW = DisplayWidth(display, screenNum);
374 displayH = DisplayHeight(display, screenNum);
379 if (pg < 0 || pg > doc->getNumPages()) {
382 } else if (doc->getPageRotate(pg) == 90 ||
383 doc->getPageRotate(pg) == 270) {
384 width1 = doc->getPageHeight(pg);
385 height1 = doc->getPageWidth(pg);
387 width1 = doc->getPageWidth(pg);
388 height1 = doc->getPageHeight(pg);
390 if (zoom == zoomPage || zoom == zoomWidth) {
391 width = (Dimension)(width1 * 0.01 * defZoom + 0.5);
392 height = (Dimension)(height1 * 0.01 * defZoom + 0.5);
394 width = (Dimension)(width1 * 0.01 * zoom + 0.5);
395 height = (Dimension)(height1 * 0.01 * zoom + 0.5);
397 if (width > displayW - 100) {
398 width = displayW - 100;
400 if (height > displayH - 150) {
401 height = displayH - 150;
405 if (XtIsRealized(shell)) {
406 XtVaGetValues(shell, XmNwidth, &topW, XmNheight, &topH,
407 XmNborderWidth, &topBorder, NULL);
408 XtVaGetValues(drawArea, XmNwidth, &daW, XmNheight, &daH, NULL);
409 XtVaSetValues(shell, XmNwidth, width + (topW - daW),
410 XmNheight, height + (topH - daH), NULL);
412 XtVaSetValues(drawArea, XmNwidth, width, XmNheight, height, NULL);
416 void XPDFCore::clear() {
430 scrollX = scrollY = 0;
432 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
435 void XPDFCore::displayPage(int pageA, double zoomA, int rotateA,
436 GBool scrollToTop, GBool addToHist) {
443 int oldScrollX, oldScrollY;
445 // update the zoom and rotate values
446 newZoom = zoomA != zoom;
450 // check for document and valid page number
451 if (!doc || pageA <= 0 || pageA > doc->getNumPages()) {
456 setCursor(busyCursor);
459 // check for changes to the file
460 newModTime = getModTime(doc->getFileName()->getCString());
461 if (newModTime != modTime) {
462 if (loadFile(doc->getFileName()) == errNone) {
463 if (pageA > doc->getNumPages()) {
464 pageA = doc->getNumPages();
467 modTime = newModTime;
472 XFreeGC(display, selectGC);
473 XFreeGC(display, highlightGC);
484 // if zoom level changed, scroll to the top-left corner
486 scrollX = scrollY = 0;
489 // initialize mouse-related stuff
491 selectXMin = selectXMax = 0;
492 selectYMin = selectYMax = 0;
494 lastDragLeft = lastDragTop = gTrue;
497 rot = rotate + doc->getPageRotate(page);
500 } else if (rotate < 0) {
503 if (zoom == zoomPage) {
504 if (rot == 90 || rot == 270) {
505 hDPI = (drawAreaWidth / doc->getPageHeight(page)) * 72;
506 vDPI = (drawAreaHeight / doc->getPageWidth(page)) * 72;
508 hDPI = (drawAreaWidth / doc->getPageWidth(page)) * 72;
509 vDPI = (drawAreaHeight / doc->getPageHeight(page)) * 72;
511 dpi = (hDPI < vDPI) ? hDPI : vDPI;
512 } else if (zoom == zoomWidth) {
513 if (rot == 90 || rot == 270) {
514 dpi = (drawAreaWidth / doc->getPageHeight(page)) * 72;
516 dpi = (drawAreaWidth / doc->getPageWidth(page)) * 72;
519 dpi = 0.01 * zoom * 72;
521 out->setWindow(XtWindow(drawArea));
522 doc->displayPage(out, page, dpi, dpi, rotate, gTrue);
523 oldScrollX = scrollX;
524 oldScrollY = scrollY;
526 if (scrollX != oldScrollX || scrollY != oldScrollY) {
527 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
531 gcValues.foreground = BlackPixel(display, screenNum) ^
532 WhitePixel(display, screenNum);
533 gcValues.function = GXxor;
534 selectGC = XCreateGC(display, out->getPixmap(),
535 GCForeground | GCFunction, &gcValues);
536 highlightGC = XCreateGC(display, out->getPixmap(),
537 GCForeground | GCFunction, &gcValues);
542 if (++historyCur == xpdfHistorySize) {
545 h = &history[historyCur];
549 if (doc->getFileName()) {
550 h->fileName = doc->getFileName()->copy();
555 if (historyBLen < xpdfHistorySize) {
561 // update the parent window
563 (*updateCbk)(updateCbkData, NULL, page, -1, "");
566 // back to regular cursor
570 void XPDFCore::displayDest(LinkDest *dest, double zoomA, int rotateA,
576 if (dest->isPageRef()) {
577 pageRef = dest->getPageRef();
578 pg = doc->findPage(pageRef.num, pageRef.gen);
580 pg = dest->getPageNum();
582 if (pg <= 0 || pg > doc->getNumPages()) {
586 displayPage(pg, zoomA, rotateA, gTrue, addToHist);
592 switch (dest->getKind()) {
594 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
595 if (dest->getChangeLeft() || dest->getChangeTop()) {
596 scrollTo(dest->getChangeLeft() ? dx : scrollX,
597 dest->getChangeTop() ? dy : scrollY);
599 //~ what is the zoom parameter?
609 out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
615 out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
620 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
626 //------------------------------------------------------------------------
627 // page/position changes
628 //------------------------------------------------------------------------
630 void XPDFCore::gotoNextPage(int inc, GBool top) {
633 if (!doc || doc->getNumPages() == 0) {
636 if (page < doc->getNumPages()) {
637 if ((pg = page + inc) > doc->getNumPages()) {
638 pg = doc->getNumPages();
640 displayPage(pg, zoom, rotate, top, gTrue);
646 void XPDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) {
649 if (!doc || doc->getNumPages() == 0) {
653 if (!fullScreen && bottom) {
654 scrollY = out->getPixmapHeight() - drawAreaHeight;
658 // displayPage will call updateScrollBars()
660 if ((pg = page - dec) < 1) {
663 displayPage(pg, zoom, rotate, top, gTrue);
669 void XPDFCore::goForward() {
670 if (historyFLen == 0) {
674 if (++historyCur == xpdfHistorySize) {
679 if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
680 if (loadFile(history[historyCur].fileName) != errNone) {
685 displayPage(history[historyCur].page, zoom, rotate, gFalse, gFalse);
688 void XPDFCore::goBackward() {
689 if (historyBLen <= 1) {
693 if (--historyCur < 0) {
694 historyCur = xpdfHistorySize - 1;
698 if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
699 if (loadFile(history[historyCur].fileName) != errNone) {
704 displayPage(history[historyCur].page, zoom, rotate, gFalse, gFalse);
707 void XPDFCore::scrollLeft(int nCols) {
708 scrollTo(scrollX - nCols * 16, scrollY);
711 void XPDFCore::scrollRight(int nCols) {
712 scrollTo(scrollX + nCols * 16, scrollY);
715 void XPDFCore::scrollUp(int nLines) {
716 scrollTo(scrollX, scrollY - nLines * 16);
719 void XPDFCore::scrollDown(int nLines) {
720 scrollTo(scrollX, scrollY + nLines * 16);
723 void XPDFCore::scrollPageUp() {
725 gotoPrevPage(1, gFalse, gTrue);
727 scrollTo(scrollX, scrollY - drawAreaHeight);
731 void XPDFCore::scrollPageDown() {
732 if (scrollY >= out->getPixmapHeight() - drawAreaHeight) {
733 gotoNextPage(1, gTrue);
735 scrollTo(scrollX, scrollY + drawAreaHeight);
739 void XPDFCore::scrollTo(int x, int y) {
745 maxPos = out ? out->getPixmapWidth() : 1;
746 if (maxPos < drawAreaWidth) {
747 maxPos = drawAreaWidth;
751 } else if (x > maxPos - drawAreaWidth) {
752 pos = maxPos - drawAreaWidth;
756 if (scrollX != pos) {
758 XmScrollBarSetValues(hScrollBar, scrollX, drawAreaWidth, 16,
759 drawAreaWidth, False);
763 maxPos = out ? out->getPixmapHeight() : 1;
764 if (maxPos < drawAreaHeight) {
765 maxPos = drawAreaHeight;
769 } else if (y > maxPos - drawAreaHeight) {
770 pos = maxPos - drawAreaHeight;
774 if (scrollY != pos) {
776 XmScrollBarSetValues(vScrollBar, scrollY, drawAreaHeight, 16,
777 drawAreaHeight, False);
782 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
786 //------------------------------------------------------------------------
788 //------------------------------------------------------------------------
790 void XPDFCore::setSelection(int newXMin, int newYMin,
791 int newXMax, int newYMax) {
794 GBool needRedraw, needScroll;
795 GBool moveLeft, moveRight, moveTop, moveBottom;
797 pixmap = out->getPixmap();
800 // erase old selection on off-screen bitmap
802 if (selectXMin < selectXMax && selectYMin < selectYMax) {
803 XFillRectangle(display, pixmap,
804 selectGC, selectXMin, selectYMin,
805 selectXMax - selectXMin, selectYMax - selectYMin);
809 // draw new selection on off-screen bitmap
810 if (newXMin < newXMax && newYMin < newYMax) {
811 XFillRectangle(display, pixmap,
812 selectGC, newXMin, newYMin,
813 newXMax - newXMin, newYMax - newYMin);
817 // check which edges moved
818 moveLeft = newXMin != selectXMin;
819 moveTop = newYMin != selectYMin;
820 moveRight = newXMax != selectXMax;
821 moveBottom = newYMax != selectYMax;
823 // redraw currently visible part of bitmap
826 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
827 (newYMin < selectYMin) ? newYMin : selectYMin,
828 (newXMin > selectXMin) ? newXMin : selectXMin,
829 (newYMax > selectYMax) ? newYMax : selectYMax);
832 redrawRectangle((newXMax < selectXMax) ? newXMax : selectXMax,
833 (newYMin < selectYMin) ? newYMin : selectYMin,
834 (newXMax > selectXMax) ? newXMax : selectXMax,
835 (newYMax > selectYMax) ? newYMax : selectYMax);
838 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
839 (newYMin < selectYMin) ? newYMin : selectYMin,
840 (newXMax > selectXMax) ? newXMax : selectXMax,
841 (newYMin > selectYMin) ? newYMin : selectYMin);
844 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
845 (newYMax < selectYMax) ? newYMax : selectYMax,
846 (newXMax > selectXMax) ? newXMax : selectXMax,
847 (newYMax > selectYMax) ? newYMax : selectYMax);
851 // switch to new selection coords
852 selectXMin = newXMin;
853 selectXMax = newXMax;
854 selectYMin = newYMin;
855 selectYMax = newYMax;
857 // scroll if necessary
864 if (moveLeft && selectXMin < x) {
867 } else if (moveRight && selectXMax >= x + drawAreaWidth) {
868 x = selectXMax - drawAreaWidth;
870 } else if (moveLeft && selectXMin >= x + drawAreaWidth) {
871 x = selectXMin - drawAreaWidth;
873 } else if (moveRight && selectXMax < x) {
877 if (moveTop && selectYMin < y) {
880 } else if (moveBottom && selectYMax >= y + drawAreaHeight) {
881 y = selectYMax - drawAreaHeight;
883 } else if (moveTop && selectYMin >= y + drawAreaHeight) {
884 y = selectYMin - drawAreaHeight;
886 } else if (moveBottom && selectYMax < y) {
895 void XPDFCore::moveSelection(int mx, int my) {
896 int xMin, yMin, xMax, yMax;
901 } else if (mx >= out->getPixmapWidth()) {
902 mx = out->getPixmapWidth() - 1;
906 } else if (my >= out->getPixmapHeight()) {
907 my = out->getPixmapHeight() - 1;
910 // move appropriate edges of selection
912 if (mx < selectXMax) {
918 lastDragLeft = gFalse;
921 if (mx > selectXMin) {
927 lastDragLeft = gTrue;
931 if (my < selectYMax) {
937 lastDragTop = gFalse;
940 if (my > selectYMin) {
950 // redraw the selection
951 setSelection(xMin, yMin, xMax, yMax);
954 // X's copy-and-paste mechanism is brain damaged. Xt doesn't help
955 // any, but doesn't make it too much worse, either. Motif, on the
956 // other hand, adds significant complexity to the mess. So here we
957 // blow off the Motif junk and stick to plain old Xt. The next two
958 // functions (copySelection and convertSelectionCbk) implement the
959 // magic needed to deal with Xt's mechanism. Note that this requires
960 // global variables (currentSelection and currentSelectionOwner).
962 void XPDFCore::copySelection() {
963 if (!doc->okToCopy()) {
966 if (currentSelection) {
967 delete currentSelection;
969 //~ for multithreading: need a mutex here
970 currentSelection = out->getText(selectXMin, selectYMin,
971 selectXMax, selectYMax);
972 currentSelectionOwner = this;
973 XtOwnSelection(drawArea, XA_PRIMARY, XtLastTimestampProcessed(display),
974 &convertSelectionCbk, NULL, NULL);
977 Boolean XPDFCore::convertSelectionCbk(Widget widget, Atom *selection,
978 Atom *target, Atom *type,
979 XtPointer *value, unsigned long *length,
983 // send back a list of supported conversion targets
984 if (*target == targetsAtom) {
985 if (!(array = (Atom *)XtMalloc(sizeof(Atom)))) {
988 array[0] = XA_STRING;
989 *value = (XtPointer)array;
995 // send the selected text
996 } else if (*target == XA_STRING) {
997 //~ for multithreading: need a mutex here
998 *value = XtNewString(currentSelection->getCString());
999 *length = currentSelection->getLength();
1001 *format = 8; // 8-bit elements
1008 GBool XPDFCore::getSelection(int *xMin, int *yMin, int *xMax, int *yMax) {
1009 if (selectXMin >= selectXMax || selectYMin >= selectYMax) {
1019 GString *XPDFCore::extractText(int xMin, int yMin, int xMax, int yMax) {
1020 if (!doc->okToCopy()) {
1023 return out->getText(xMin, yMin, xMax, yMax);
1026 GString *XPDFCore::extractText(int pageNum,
1027 int xMin, int yMin, int xMax, int yMax) {
1028 TextOutputDev *textOut;
1031 if (!doc->okToCopy()) {
1034 textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
1035 if (!textOut->isOk()) {
1039 doc->displayPage(textOut, pageNum, dpi, dpi, rotate, gFalse);
1040 s = textOut->getText(xMin, yMin, xMax, yMax);
1045 //------------------------------------------------------------------------
1047 //------------------------------------------------------------------------
1049 GBool XPDFCore::doLink(int mx, int my) {
1054 out->cvtDevToUser(mx, my, &x, &y);
1055 if ((action = doc->findLink(x, y))) {
1062 void XPDFCore::doAction(LinkAction *action) {
1063 LinkActionKind kind;
1067 GString *fileName, *fileName2;
1069 GString *actionName;
1070 Object movieAnnot, obj1, obj2;
1074 switch (kind = action->getKind()) {
1076 // GoTo / GoToR action
1079 if (kind == actionGoTo) {
1082 if ((dest = ((LinkGoTo *)action)->getDest())) {
1083 dest = dest->copy();
1084 } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
1085 namedDest = namedDest->copy();
1090 if ((dest = ((LinkGoToR *)action)->getDest())) {
1091 dest = dest->copy();
1092 } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) {
1093 namedDest = namedDest->copy();
1095 s = ((LinkGoToR *)action)->getFileName()->getCString();
1096 //~ translate path name for VMS (deal with '/')
1097 if (isAbsolutePath(s)) {
1098 fileName = new GString(s);
1100 fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
1102 if (loadFile(fileName) != errNone) {
1115 dest = doc->findDest(namedDest);
1119 displayDest(dest, zoom, rotate, gTrue);
1122 if (kind == actionGoToR) {
1123 displayPage(1, zoom, 0, gFalse, gTrue);
1130 fileName = ((LinkLaunch *)action)->getFileName();
1131 s = fileName->getCString();
1132 if (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
1133 !strcmp(s + fileName->getLength() - 4, ".PDF")) {
1134 //~ translate path name for VMS (deal with '/')
1135 if (isAbsolutePath(s)) {
1136 fileName = fileName->copy();
1138 fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
1140 if (loadFile(fileName) != errNone) {
1145 displayPage(1, zoom, rotate, gFalse, gTrue);
1147 fileName = fileName->copy();
1148 if (((LinkLaunch *)action)->getParams()) {
1149 fileName->append(' ');
1150 fileName->append(((LinkLaunch *)action)->getParams());
1153 fileName->insert(0, "spawn/nowait ");
1154 #elif defined(__EMX__)
1155 fileName->insert(0, "start /min /n ");
1157 fileName->append(" &");
1159 msg = new GString("About to execute the command:\n");
1160 msg->append(fileName);
1161 if (doQuestionDialog("Launching external application", msg)) {
1162 system(fileName->getCString());
1171 if (!(cmd = globalParams->getURLCommand())) {
1172 error(-1, "No urlCommand defined in config file");
1175 runCommand(cmd, ((LinkURI *)action)->getURI());
1180 actionName = ((LinkNamed *)action)->getName();
1181 if (!actionName->cmp("NextPage")) {
1182 gotoNextPage(1, gTrue);
1183 } else if (!actionName->cmp("PrevPage")) {
1184 gotoPrevPage(1, gTrue, gFalse);
1185 } else if (!actionName->cmp("FirstPage")) {
1187 displayPage(1, zoom, rotate, gTrue, gTrue);
1189 } else if (!actionName->cmp("LastPage")) {
1190 if (page != doc->getNumPages()) {
1191 displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
1193 } else if (!actionName->cmp("GoBack")) {
1195 } else if (!actionName->cmp("GoForward")) {
1197 } else if (!actionName->cmp("Quit")) {
1199 (*actionCbk)(actionCbkData, "Quit");
1202 error(-1, "Unknown named action: '%s'", actionName->getCString());
1208 if (!(cmd = globalParams->getMovieCommand())) {
1209 error(-1, "No movieCommand defined in config file");
1212 if (((LinkMovie *)action)->hasAnnotRef()) {
1213 doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num,
1214 ((LinkMovie *)action)->getAnnotRef()->gen,
1217 doc->getCatalog()->getPage(page)->getAnnots(&obj1);
1218 if (obj1.isArray()) {
1219 for (i = 0; i < obj1.arrayGetLength(); ++i) {
1220 if (obj1.arrayGet(i, &movieAnnot)->isDict()) {
1221 if (movieAnnot.dictLookup("Subtype", &obj2)->isName("Movie")) {
1232 if (movieAnnot.isDict()) {
1233 if (movieAnnot.dictLookup("Movie", &obj1)->isDict()) {
1234 if (obj1.dictLookup("F", &obj2)) {
1235 if ((fileName = LinkAction::getFileSpecName(&obj2))) {
1236 if (!isAbsolutePath(fileName->getCString())) {
1237 fileName2 = appendToPath(
1238 grabPath(doc->getFileName()->getCString()),
1239 fileName->getCString());
1241 fileName = fileName2;
1243 runCommand(cmd, fileName);
1254 // unknown action type
1256 error(-1, "Unknown link action type: '%s'",
1257 ((LinkUnknown *)action)->getAction()->getCString());
1262 // Run a command, given a <cmdFmt> string with one '%s' in it, and an
1263 // <arg> string to insert in place of the '%s'.
1264 void XPDFCore::runCommand(GString *cmdFmt, GString *arg) {
1268 if ((s = strstr(cmdFmt->getCString(), "%s"))) {
1269 cmd = mungeURL(arg);
1270 cmd->insert(0, cmdFmt->getCString(),
1271 s - cmdFmt->getCString());
1274 cmd = cmdFmt->copy();
1277 cmd->insert(0, "spawn/nowait ");
1278 #elif defined(__EMX__)
1279 cmd->insert(0, "start /min /n ");
1283 system(cmd->getCString());
1287 // Escape any characters in a URL which might cause problems when
1288 // calling system().
1289 GString *XPDFCore::mungeURL(GString *url) {
1290 static char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1291 "abcdefghijklmnopqrstuvwxyz"
1299 newURL = new GString();
1300 for (i = 0; i < url->getLength(); ++i) {
1301 c = url->getChar(i);
1302 if (strchr(allowed, c)) {
1305 sprintf(buf, "%%%02x", c & 0xff);
1306 newURL->append(buf);
1313 //------------------------------------------------------------------------
1315 //------------------------------------------------------------------------
1317 void XPDFCore::find(char *s, GBool next) {
1319 TextOutputDev *textOut;
1320 int xMin, yMin, xMax, yMax;
1321 double xMin1, yMin1, xMax1, yMax1;
1326 // check for zero-length string
1332 // set cursor to watch
1333 setCursor(busyCursor);
1335 // convert to Unicode
1336 #if 1 //~ should do something more intelligent here
1338 u = (Unicode *)gmalloc(len * sizeof(Unicode));
1339 for (i = 0; i < len; ++i) {
1340 u[i] = (Unicode)(s[i] & 0xff);
1344 // search current page starting at current selection or top of page
1345 startAtTop = !next && !(selectXMin < selectXMax && selectYMin < selectYMax);
1346 xMin = selectXMin + 1;
1347 yMin = selectYMin + 1;
1349 if (out->findText(u, len, startAtTop, gTrue, next, gFalse,
1350 &xMin, &yMin, &xMax, &yMax)) {
1354 // search following pages
1355 textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse);
1356 if (!textOut->isOk()) {
1360 for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
1361 doc->displayPage(textOut, pg, 72, 72, 0, gFalse);
1362 if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
1363 &xMin1, &yMin1, &xMax1, &yMax1)) {
1368 // search previous pages
1369 for (pg = 1; pg < page; ++pg) {
1370 doc->displayPage(textOut, pg, 72, 72, 0, gFalse);
1371 if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
1372 &xMin1, &yMin1, &xMax1, &yMax1)) {
1378 // search current page ending at current selection
1383 if (out->findText(u, len, gTrue, gFalse, gFalse, next,
1384 &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, gFalse, gFalse,
1398 &xMin, &yMin, &xMax, &yMax)) {
1399 // this can happen if coalescing is bad
1403 // found: change the selection
1405 setSelection(xMin, yMin, xMax, yMax);
1406 #ifndef NO_TEXT_SELECT
1413 // reset cursors to normal
1417 //------------------------------------------------------------------------
1419 //------------------------------------------------------------------------
1421 void XPDFCore::setBusyCursor(GBool busy) {
1422 setCursor(busy ? busyCursor : None);
1425 void XPDFCore::takeFocus() {
1426 XmProcessTraversal(drawArea, XmTRAVERSE_CURRENT);
1429 //------------------------------------------------------------------------
1431 //------------------------------------------------------------------------
1433 void XPDFCore::initWindow() {
1437 // create the cursors
1438 busyCursor = XCreateFontCursor(display, XC_watch);
1439 linkCursor = XCreateFontCursor(display, XC_hand2);
1440 selectCursor = XCreateFontCursor(display, XC_cross);
1443 // create the scrolled window and scrollbars
1445 XtSetArg(args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED); ++n;
1446 XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n;
1447 scrolledWin = XmCreateScrolledWindow(parentWidget, "scroll", args, n);
1448 XtManageChild(scrolledWin);
1450 XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
1451 XtSetArg(args[n], XmNminimum, 0); ++n;
1452 XtSetArg(args[n], XmNmaximum, 1); ++n;
1453 XtSetArg(args[n], XmNsliderSize, 1); ++n;
1454 XtSetArg(args[n], XmNvalue, 0); ++n;
1455 XtSetArg(args[n], XmNincrement, 1); ++n;
1456 XtSetArg(args[n], XmNpageIncrement, 1); ++n;
1457 hScrollBar = XmCreateScrollBar(scrolledWin, "hScrollBar", args, n);
1458 XtManageChild(hScrollBar);
1459 XtAddCallback(hScrollBar, XmNvalueChangedCallback,
1460 &hScrollChangeCbk, (XtPointer)this);
1461 #ifndef DISABLE_SMOOTH_SCROLL
1462 XtAddCallback(hScrollBar, XmNdragCallback,
1463 &hScrollDragCbk, (XtPointer)this);
1466 XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n;
1467 XtSetArg(args[n], XmNminimum, 0); ++n;
1468 XtSetArg(args[n], XmNmaximum, 1); ++n;
1469 XtSetArg(args[n], XmNsliderSize, 1); ++n;
1470 XtSetArg(args[n], XmNvalue, 0); ++n;
1471 XtSetArg(args[n], XmNincrement, 1); ++n;
1472 XtSetArg(args[n], XmNpageIncrement, 1); ++n;
1473 vScrollBar = XmCreateScrollBar(scrolledWin, "vScrollBar", args, n);
1474 XtManageChild(vScrollBar);
1475 XtAddCallback(vScrollBar, XmNvalueChangedCallback,
1476 &vScrollChangeCbk, (XtPointer)this);
1477 #ifndef DISABLE_SMOOTH_SCROLL
1478 XtAddCallback(vScrollBar, XmNdragCallback,
1479 &vScrollDragCbk, (XtPointer)this);
1482 // create the drawing area
1484 XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); ++n;
1485 XtSetArg(args[n], XmNmarginWidth, 0); ++n;
1486 XtSetArg(args[n], XmNmarginHeight, 0); ++n;
1488 XtSetArg(args[n], XmNshadowThickness, 0); ++n;
1490 drawAreaFrame = XmCreateFrame(scrolledWin, "drawAreaFrame", args, n);
1491 XtManageChild(drawAreaFrame);
1493 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n;
1494 XtSetArg(args[n], XmNbackground, paperColor); ++n;
1495 XtSetArg(args[n], XmNwidth, 700); ++n;
1496 XtSetArg(args[n], XmNheight, 500); ++n;
1497 drawArea = XmCreateDrawingArea(drawAreaFrame, "drawArea", args, n);
1498 XtManageChild(drawArea);
1499 XtAddCallback(drawArea, XmNresizeCallback, &resizeCbk, (XtPointer)this);
1500 XtAddCallback(drawArea, XmNexposeCallback, &redrawCbk, (XtPointer)this);
1501 XtAddCallback(drawArea, XmNinputCallback, &inputCbk, (XtPointer)this);
1502 resizeCbk(drawArea, this, NULL);
1504 // set up mouse motion translations
1505 XtOverrideTranslations(drawArea, XtParseTranslationTable(
1506 "<Btn1Down>:DrawingAreaInput()\n"
1507 "<Btn1Up>:DrawingAreaInput()\n"
1508 "<Btn1Motion>:DrawingAreaInput()\n"
1509 "<Motion>:DrawingAreaInput()"));
1511 // can't create a GC until the window gets mapped
1517 void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr,
1518 XtPointer callData) {
1519 XPDFCore *core = (XPDFCore *)ptr;
1520 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1522 core->scrollTo(data->value, core->scrollY);
1525 void XPDFCore::hScrollDragCbk(Widget widget, XtPointer ptr,
1526 XtPointer callData) {
1527 XPDFCore *core = (XPDFCore *)ptr;
1528 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1530 core->scrollTo(data->value, core->scrollY);
1533 void XPDFCore::vScrollChangeCbk(Widget widget, XtPointer ptr,
1534 XtPointer callData) {
1535 XPDFCore *core = (XPDFCore *)ptr;
1536 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1538 core->scrollTo(core->scrollX, data->value);
1541 void XPDFCore::vScrollDragCbk(Widget widget, XtPointer ptr,
1542 XtPointer callData) {
1543 XPDFCore *core = (XPDFCore *)ptr;
1544 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1546 core->scrollTo(core->scrollX, data->value);
1549 void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1550 XPDFCore *core = (XPDFCore *)ptr;
1554 int oldScrollX, oldScrollY;
1557 XtSetArg(args[n], XmNwidth, &w); ++n;
1558 XtSetArg(args[n], XmNheight, &h); ++n;
1559 XtGetValues(core->drawArea, args, n);
1560 core->drawAreaWidth = (int)w;
1561 core->drawAreaHeight = (int)h;
1562 if (core->page >= 0 &&
1563 (core->zoom == zoomPage || core->zoom == zoomWidth)) {
1564 core->displayPage(core->page, core->zoom, core->rotate,
1567 oldScrollX = core->scrollX;
1568 oldScrollY = core->scrollY;
1569 core->updateScrollBars();
1570 if (core->scrollX != oldScrollX || core->scrollY != oldScrollY) {
1571 core->redrawRectangle(core->scrollX, core->scrollY,
1572 core->drawAreaWidth, core->drawAreaHeight);
1577 void XPDFCore::redrawCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1578 XPDFCore *core = (XPDFCore *)ptr;
1579 XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData;
1582 if (data->reason == XmCR_EXPOSE) {
1583 x = core->scrollX + data->event->xexpose.x;
1584 y = core->scrollY + data->event->xexpose.y;
1585 w = data->event->xexpose.width;
1586 h = data->event->xexpose.height;
1590 w = core->drawAreaWidth;
1591 h = core->drawAreaHeight;
1593 core->redrawRectangle(x, y, w, h);
1596 void XPDFCore::outputDevRedrawCbk(void *data) {
1597 XPDFCore *core = (XPDFCore *)data;
1599 core->redrawRectangle(core->scrollX, core->scrollY,
1600 core->drawAreaWidth, core->drawAreaHeight);
1603 void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1604 XPDFCore *core = (XPDFCore *)ptr;
1605 XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData;
1614 switch (data->event->type) {
1616 if (data->event->xbutton.button == 1) {
1618 if (core->doc && core->doc->getNumPages() > 0) {
1619 if (core->selectEnabled) {
1620 mx = core->scrollX + data->event->xbutton.x;
1621 my = core->scrollY + data->event->xbutton.y;
1622 core->setSelection(mx, my, mx, my);
1623 core->setCursor(core->selectCursor);
1624 core->dragging = gTrue;
1627 } else if (data->event->xbutton.button == 2) {
1628 if (!core->fullScreen) {
1629 core->panning = gTrue;
1630 core->panMX = data->event->xbutton.x;
1631 core->panMY = data->event->xbutton.y;
1633 } else if (data->event->xbutton.button == 4) { // mouse wheel up
1634 if (core->fullScreen) {
1635 core->gotoPrevPage(1, gTrue, gFalse);
1636 } else if (core->scrollY == 0) {
1637 core->gotoPrevPage(1, gFalse, gTrue);
1641 } else if (data->event->xbutton.button == 5) { // mouse wheel down
1642 if (core->fullScreen ||
1644 core->out->getPixmapHeight() - core->drawAreaHeight) {
1645 core->gotoNextPage(1, gTrue);
1647 core->scrollDown(1);
1649 } else if (data->event->xbutton.button == 6) { // second mouse wheel right
1650 if (!core->fullScreen) {
1651 core->scrollRight(1);
1653 } else if (data->event->xbutton.button == 7) { // second mouse wheel left
1654 if (!core->fullScreen) {
1655 core->scrollLeft(1);
1658 if (*core->mouseCbk) {
1659 (*core->mouseCbk)(core->mouseCbkData, data->event);
1664 if (data->event->xbutton.button == 1) {
1665 if (core->doc && core->doc->getNumPages() > 0) {
1666 mx = core->scrollX + data->event->xbutton.x;
1667 my = core->scrollY + data->event->xbutton.y;
1668 if (core->dragging) {
1669 core->dragging = gFalse;
1670 core->setCursor(None);
1671 core->moveSelection(mx, my);
1672 #ifndef NO_TEXT_SELECT
1673 if (core->selectXMin != core->selectXMax &&
1674 core->selectYMin != core->selectYMax) {
1675 if (core->doc->okToCopy()) {
1676 core->copySelection();
1678 error(-1, "Copying of text from this document is not allowed.");
1683 if (core->hyperlinksEnabled) {
1684 if (core->selectXMin == core->selectXMax ||
1685 core->selectYMin == core->selectYMax) {
1686 core->doLink(mx, my);
1690 } else if (data->event->xbutton.button == 2) {
1691 core->panning = gFalse;
1693 if (*core->mouseCbk) {
1694 (*core->mouseCbk)(core->mouseCbkData, data->event);
1699 if (core->doc && core->doc->getNumPages() > 0) {
1700 mx = core->scrollX + data->event->xbutton.x;
1701 my = core->scrollY + data->event->xbutton.y;
1702 if (core->dragging) {
1703 core->moveSelection(mx, my);
1704 } else if (core->hyperlinksEnabled) {
1705 core->out->cvtDevToUser(mx, my, &x, &y);
1706 if ((action = core->doc->findLink(x, y))) {
1707 core->setCursor(core->linkCursor);
1708 if (action != core->linkAction) {
1709 core->linkAction = action;
1710 if (core->updateCbk) {
1712 switch (action->getKind()) {
1714 s = "[internal link]";
1717 s = ((LinkGoToR *)action)->getFileName()->getCString();
1720 s = ((LinkLaunch *)action)->getFileName()->getCString();
1723 s = ((LinkURI *)action)->getURI()->getCString();
1726 s = ((LinkNamed *)action)->getName()->getCString();
1732 s = "[unknown link]";
1735 (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, s);
1739 core->setCursor(None);
1740 if (core->linkAction) {
1741 core->linkAction = NULL;
1742 if (core->updateCbk) {
1743 (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, "");
1749 if (core->panning) {
1750 core->scrollTo(core->scrollX - (data->event->xbutton.x - core->panMX),
1751 core->scrollY - (data->event->xbutton.y - core->panMY));
1752 core->panMX = data->event->xbutton.x;
1753 core->panMY = data->event->xbutton.y;
1757 n = XLookupString(&data->event->xkey, buf, sizeof(buf) - 1,
1759 core->keyPress(buf, key, data->event->xkey.state);
1764 void XPDFCore::keyPress(char *s, KeySym key, Guint modifiers) {
1768 if (modifiers & ControlMask) {
1769 displayPage(1, zoom, rotate, gTrue, gTrue);
1770 } else if (!fullScreen) {
1776 if (modifiers & ControlMask) {
1777 displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
1778 } else if (!fullScreen) {
1779 scrollTo(out->getPixmapWidth() - drawAreaWidth,
1780 out->getPixmapHeight() - drawAreaHeight);
1786 gotoPrevPage(1, gTrue, gFalse);
1792 case XK_KP_Page_Down:
1794 gotoNextPage(1, gTrue);
1826 (*keyPressCbk)(keyPressCbkData, s, key, modifiers);
1830 void XPDFCore::redrawRectangle(int x, int y, int w, int h) {
1839 if (x + w > scrollX + drawAreaWidth) {
1840 w = scrollX + drawAreaWidth - x;
1846 if (y + h > scrollY + drawAreaHeight) {
1847 h = scrollY + drawAreaHeight - y;
1850 // create a GC for the drawing area
1851 drawAreaWin = XtWindow(drawArea);
1853 gcValues.foreground = paperColor;
1854 drawAreaGC = XCreateGC(display, drawAreaWin, GCForeground, &gcValues);
1857 // draw white background past the edges of the document
1858 if (x + w > out->getPixmapWidth()) {
1859 XFillRectangle(display, drawAreaWin, drawAreaGC,
1860 out->getPixmapWidth() - scrollX, y - scrollY,
1861 x + w - out->getPixmapWidth(), h);
1862 w = out->getPixmapWidth() - x;
1864 if (y + h > out->getPixmapHeight()) {
1865 XFillRectangle(display, drawAreaWin, drawAreaGC,
1866 x - scrollX, out->getPixmapHeight() - scrollY,
1867 w, y + h - out->getPixmapHeight());
1868 h = out->getPixmapHeight() - y;
1871 // redraw (checking to see if pixmap has been allocated yet)
1872 if (out->getPixmapWidth() > 0) {
1873 XCopyArea(display, out->getPixmap(), drawAreaWin, drawAreaGC,
1874 x, y, w, h, x - scrollX, y - scrollY);
1878 void XPDFCore::updateScrollBars() {
1883 maxPos = out ? out->getPixmapWidth() : 1;
1884 if (maxPos < drawAreaWidth) {
1885 maxPos = drawAreaWidth;
1887 if (scrollX > maxPos - drawAreaWidth) {
1888 scrollX = maxPos - drawAreaWidth;
1891 XtSetArg(args[n], XmNvalue, scrollX); ++n;
1892 XtSetArg(args[n], XmNmaximum, maxPos); ++n;
1893 XtSetArg(args[n], XmNsliderSize, drawAreaWidth); ++n;
1894 XtSetArg(args[n], XmNincrement, 16); ++n;
1895 XtSetArg(args[n], XmNpageIncrement, drawAreaWidth); ++n;
1896 XtSetValues(hScrollBar, args, n);
1898 maxPos = out ? out->getPixmapHeight() : 1;
1899 if (maxPos < drawAreaHeight) {
1900 maxPos = drawAreaHeight;
1902 if (scrollY > maxPos - drawAreaHeight) {
1903 scrollY = maxPos - drawAreaHeight;
1906 XtSetArg(args[n], XmNvalue, scrollY); ++n;
1907 XtSetArg(args[n], XmNmaximum, maxPos); ++n;
1908 XtSetArg(args[n], XmNsliderSize, drawAreaHeight); ++n;
1909 XtSetArg(args[n], XmNincrement, 16); ++n;
1910 XtSetArg(args[n], XmNpageIncrement, drawAreaHeight); ++n;
1911 XtSetValues(vScrollBar, args, n);
1914 void XPDFCore::setCursor(Cursor cursor) {
1917 if (cursor == currentCursor) {
1920 if (!(topWin = XtWindow(shell))) {
1923 if (cursor == None) {
1924 XUndefineCursor(display, topWin);
1926 XDefineCursor(display, topWin, cursor);
1929 currentCursor = cursor;
1932 GBool XPDFCore::doQuestionDialog(char *title, GString *msg) {
1933 return doDialog(XmDIALOG_QUESTION, gTrue, title, msg);
1936 void XPDFCore::doInfoDialog(char *title, GString *msg) {
1937 doDialog(XmDIALOG_INFORMATION, gFalse, title, msg);
1940 void XPDFCore::doErrorDialog(char *title, GString *msg) {
1941 doDialog(XmDIALOG_ERROR, gFalse, title, msg);
1944 GBool XPDFCore::doDialog(int type, GBool hasCancel,
1945 char *title, GString *msg) {
1946 Widget dialog, scroll, text;
1947 XtAppContext appContext;
1954 XtSetArg(args[n], XmNdialogType, type); ++n;
1955 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
1956 s1 = XmStringCreateLocalized(title);
1957 XtSetArg(args[n], XmNdialogTitle, s1); ++n;
1958 s2 = NULL; // make gcc happy
1959 if (msg->getLength() <= 80) {
1960 s2 = XmStringCreateLocalized(msg->getCString());
1961 XtSetArg(args[n], XmNmessageString, s2); ++n;
1963 dialog = XmCreateMessageDialog(drawArea, "questionDialog", args, n);
1965 if (msg->getLength() <= 80) {
1969 XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n;
1970 if (drawAreaWidth > 300) {
1971 XtSetArg(args[n], XmNwidth, drawAreaWidth - 100); ++n;
1973 scroll = XmCreateScrolledWindow(dialog, "scroll", args, n);
1974 XtManageChild(scroll);
1976 XtSetArg(args[n], XmNeditable, False); ++n;
1977 XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); ++n;
1978 XtSetArg(args[n], XmNvalue, msg->getCString()); ++n;
1979 XtSetArg(args[n], XmNshadowThickness, 0); ++n;
1980 text = XmCreateText(scroll, "text", args, n);
1981 XtManageChild(text);
1983 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
1984 XtAddCallback(dialog, XmNokCallback,
1985 &dialogOkCbk, (XtPointer)this);
1987 XtAddCallback(dialog, XmNcancelCallback,
1988 &dialogCancelCbk, (XtPointer)this);
1990 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
1993 XtManageChild(dialog);
1995 appContext = XtWidgetToApplicationContext(dialog);
1998 XtAppNextEvent(appContext, &event);
1999 XtDispatchEvent(&event);
2000 } while (!dialogDone);
2002 XtUnmanageChild(dialog);
2003 XtDestroyWidget(dialog);
2005 return dialogDone > 0;
2008 void XPDFCore::dialogOkCbk(Widget widget, XtPointer ptr,
2009 XtPointer callData) {
2010 XPDFCore *core = (XPDFCore *)ptr;
2012 core->dialogDone = 1;
2015 void XPDFCore::dialogCancelCbk(Widget widget, XtPointer ptr,
2016 XtPointer callData) {
2017 XPDFCore *core = (XPDFCore *)ptr;
2019 core->dialogDone = -1;