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"
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
88#define highlightNone 0
89#define highlightNormal 1
90#define highlightSelected 2
94static int zoomDPI[maxZoom - minZoom + 1] = {
97 86, 104, 124, 149, 179
102GString *XPDFCore::currentSelection = NULL;
103XPDFCore *XPDFCore::currentSelectionOwner = NULL;
109XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA,
110 Gulong paperColorA, GBool fullScreenA, GBool reverseVideo,
111 GBool installCmap,
int rgbCubeSize) {
112 GString *initialZoom;
116 parentWidget = parentWidgetA;
117 display = XtDisplay(parentWidget);
118 screenNum = XScreenNumberOfScreen(XtScreen(parentWidget));
120 paperColor = paperColorA;
121 fullScreen = fullScreenA;
125 visual = DefaultVisual(display, screenNum);
126 XtVaGetValues(shell, XmNcolormap, &colormap, NULL);
131 drawAreaFrame = NULL;
140 initialZoom = globalParams->getInitialZoom();
141 if (!initialZoom->cmp(
"page")) {
143 }
else if (!initialZoom->cmp(
"width")) {
146 zoom = atoi(initialZoom->getCString());
147 if (zoom < minZoom) {
149 }
else if (zoom > maxZoom) {
157 selectXMin = selectXMax = 0;
158 selectYMin = selectYMax = 0;
160 lastDragLeft = lastDragTop = gTrue;
169 reqPasswordCbk = NULL;
172 historyCur = xpdfHistorySize - 1;
173 historyBLen = historyFLen = 0;
174 for (i = 0; i < xpdfHistorySize; ++i) {
175 history[i].fileName = NULL;
179 hyperlinksEnabled = gTrue;
180 selectEnabled = gTrue;
186 out =
new XPixmapOutputDev(display, screenNum, visual, colormap,
187 reverseVideo, paperColor,
188 installCmap, rgbCubeSize, gTrue,
189 &outputDevRedrawCbk,
this);
193XPDFCore::~XPDFCore() {
202 if (currentSelectionOwner ==
this && currentSelection) {
203 delete currentSelection;
204 currentSelection = NULL;
205 currentSelectionOwner = NULL;
207 for (i = 0; i < xpdfHistorySize; ++i) {
208 if (history[i].fileName) {
209 delete history[i].fileName;
213 XFreeGC(display, selectGC);
214 XFreeGC(display, highlightGC);
217 XFreeGC(display, drawAreaGC);
220 XtDestroyWidget(drawArea);
223 XtDestroyWidget(drawAreaFrame);
226 XtDestroyWidget(vScrollBar);
229 XtDestroyWidget(hScrollBar);
232 XtDestroyWidget(scrolledWin);
235 XFreeCursor(display, busyCursor);
238 XFreeCursor(display, linkCursor);
241 XFreeCursor(display, selectCursor);
249int XPDFCore::loadFile(GString *fileName, GString *ownerPassword,
250 GString *userPassword) {
257 setCursor(busyCursor);
260 newDoc =
new PDFDoc(fileName->copy(), ownerPassword, userPassword);
261 if (!newDoc->isOk()) {
262 err = newDoc->getErrorCode();
264 if (err != errEncrypted || !reqPasswordCbk) {
270 again = ownerPassword != NULL || userPassword != NULL;
272 if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) {
276 newDoc =
new PDFDoc(fileName->copy(), password, password);
277 if (newDoc->isOk()) {
280 err = newDoc->getErrorCode();
282 if (err != errEncrypted) {
296 out->startDoc(doc->getXRef());
303 modTime = getModTime(doc->getFileName()->getCString());
307 (*updateCbk)(updateCbkData, doc->getFileName(), -1,
308 doc->getNumPages(), NULL);
317void XPDFCore::resizeToPage(
int pg) {
318 Dimension width, height;
319 double width1, height1;
320 Dimension topW, topH, topBorder, daW, daH;
321 Dimension displayW, displayH;
323 displayW = DisplayWidth(display, screenNum);
324 displayH = DisplayHeight(display, screenNum);
329 if (pg < 0 || pg > doc->getNumPages()) {
332 }
else if (doc->getPageRotate(pg) == 90 ||
333 doc->getPageRotate(pg) == 270) {
334 width1 = doc->getPageHeight(pg);
335 height1 = doc->getPageWidth(pg);
337 width1 = doc->getPageWidth(pg);
338 height1 = doc->getPageHeight(pg);
340 if (zoom == zoomPage || zoom == zoomWidth) {
341 width = (Dimension)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
342 height = (Dimension)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
344 width = (Dimension)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
345 height = (Dimension)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
347 if (width > displayW - 100) {
348 width = displayW - 100;
350 if (height > displayH - 150) {
351 height = displayH - 150;
355 if (XtIsRealized(shell)) {
356 XtVaGetValues(shell, XmNwidth, &topW, XmNheight, &topH,
357 XmNborderWidth, &topBorder, NULL);
358 XtVaGetValues(drawArea, XmNwidth, &daW, XmNheight, &daH, NULL);
359 XtVaSetValues(shell, XmNwidth, width + (topW - daW),
360 XmNheight, height + (topH - daH), NULL);
362 XtVaSetValues(drawArea, XmNwidth, width, XmNheight, height, NULL);
366void XPDFCore::clear() {
380 scrollX = scrollY = 0;
382 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
385void XPDFCore::displayPage(
int pageA,
int zoomA,
int rotateA,
386 GBool scrollToTop, GBool addToHist) {
393 int oldScrollX, oldScrollY;
396 newZoom = zoomA != zoom;
401 if (!doc || pageA <= 0 || pageA > doc->getNumPages()) {
406 setCursor(busyCursor);
410 newModTime = getModTime(doc->getFileName()->getCString());
411 if (newModTime != modTime) {
412 if (loadFile(doc->getFileName()) == errNone) {
413 if (pageA > doc->getNumPages()) {
414 pageA = doc->getNumPages();
417 modTime = newModTime;
422 XFreeGC(display, selectGC);
423 XFreeGC(display, highlightGC);
436 scrollX = scrollY = 0;
441 selectXMin = selectXMax = 0;
442 selectYMin = selectYMax = 0;
444 lastDragLeft = lastDragTop = gTrue;
447 rot = rotate + doc->getPageRotate(page);
450 }
else if (rotate < 0) {
453 if (zoom == zoomPage) {
454 if (rot == 90 || rot == 270) {
455 hDPI = (drawAreaWidth / doc->getPageHeight(page)) * 72;
456 vDPI = (drawAreaHeight / doc->getPageWidth(page)) * 72;
458 hDPI = (drawAreaWidth / doc->getPageWidth(page)) * 72;
459 vDPI = (drawAreaHeight / doc->getPageHeight(page)) * 72;
461 dpi = (hDPI < vDPI) ? hDPI : vDPI;
462 }
else if (zoom == zoomWidth) {
463 if (rot == 90 || rot == 270) {
464 dpi = (drawAreaWidth / doc->getPageHeight(page)) * 72;
466 dpi = (drawAreaWidth / doc->getPageWidth(page)) * 72;
469 dpi = zoomDPI[zoom - minZoom];
471 out->setWindow(XtWindow(drawArea));
472 doc->displayPage(out, page, dpi, rotate, gTrue);
473 oldScrollX = scrollX;
474 oldScrollY = scrollY;
476 if (scrollX != oldScrollX || scrollY != oldScrollY) {
477 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
483 if (++historyCur == xpdfHistorySize) {
486 h = &history[historyCur];
490 h->fileName = doc->getFileName()->copy();
492 if (historyBLen < xpdfHistorySize) {
500 (*updateCbk)(updateCbkData, NULL, page, -1,
"");
504 gcValues.foreground = BlackPixel(display, screenNum) ^
505 WhitePixel(display, screenNum);
506 gcValues.function = GXxor;
507 selectGC = XCreateGC(display, out->getPixmap(),
508 GCForeground | GCFunction, &gcValues);
509 highlightGC = XCreateGC(display, out->getPixmap(),
510 GCForeground | GCFunction, &gcValues);
516void XPDFCore::displayDest(LinkDest *dest,
int zoomA,
int rotateA,
522 if (dest->isPageRef()) {
523 pageRef = dest->getPageRef();
524 pg = doc->findPage(pageRef.num, pageRef.gen);
526 pg = dest->getPageNum();
528 if (pg <= 0 || pg > doc->getNumPages()) {
532 displayPage(pg, zoomA, rotateA, gTrue, addToHist);
538 switch (dest->getKind()) {
540 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
541 if (dest->getChangeLeft() || dest->getChangeTop()) {
542 scrollTo(dest->getChangeLeft() ? dx : scrollX,
543 dest->getChangeTop() ? dy : scrollY);
555 out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
561 out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
566 out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
576void XPDFCore::gotoNextPage(
int inc, GBool top) {
579 if (!doc || doc->getNumPages() == 0) {
582 if (page < doc->getNumPages()) {
583 if ((pg = page + inc) > doc->getNumPages()) {
584 pg = doc->getNumPages();
586 displayPage(pg, zoom, rotate, top, gTrue);
592void XPDFCore::gotoPrevPage(
int dec, GBool top, GBool bottom) {
595 if (!doc || doc->getNumPages() == 0) {
599 if (!fullScreen && bottom) {
600 scrollY = out->getPixmapHeight() - drawAreaHeight;
606 if ((pg = page - dec) < 1) {
609 displayPage(pg, zoom, rotate, top, gTrue);
615void XPDFCore::goForward() {
616 if (historyFLen == 0) {
620 if (++historyCur == xpdfHistorySize) {
625 if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
626 if (loadFile(history[historyCur].fileName) != errNone) {
631 displayPage(history[historyCur].page, zoom, rotate, gFalse, gFalse);
634void XPDFCore::goBackward() {
635 if (historyBLen <= 1) {
639 if (--historyCur < 0) {
640 historyCur = xpdfHistorySize - 1;
644 if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
645 if (loadFile(history[historyCur].fileName) != errNone) {
650 displayPage(history[historyCur].page, zoom, rotate, gFalse, gFalse);
653void XPDFCore::scrollLeft(
int nCols) {
654 scrollTo(scrollX - nCols * 16, scrollY);
657void XPDFCore::scrollRight(
int nCols) {
658 scrollTo(scrollX + nCols * 16, scrollY);
661void XPDFCore::scrollUp(
int nLines) {
662 scrollTo(scrollX, scrollY - nLines * 16);
665void XPDFCore::scrollDown(
int nLines) {
666 scrollTo(scrollX, scrollY + nLines * 16);
669void XPDFCore::scrollPageUp() {
671 gotoPrevPage(1, gFalse, gTrue);
673 scrollTo(scrollX, scrollY - drawAreaHeight);
677void XPDFCore::scrollPageDown() {
678 if (scrollY >= out->getPixmapHeight() - drawAreaHeight) {
679 gotoNextPage(1, gTrue);
681 scrollTo(scrollX, scrollY + drawAreaHeight);
685void XPDFCore::scrollTo(
int x,
int y) {
691 maxPos = out ? out->getPixmapWidth() : 1;
692 if (maxPos < drawAreaWidth) {
693 maxPos = drawAreaWidth;
697 }
else if (x > maxPos - drawAreaWidth) {
698 pos = maxPos - drawAreaWidth;
702 if (scrollX != pos) {
704 XmScrollBarSetValues(hScrollBar, scrollX, drawAreaWidth, 16,
705 drawAreaWidth, False);
709 maxPos = out ? out->getPixmapHeight() : 1;
710 if (maxPos < drawAreaHeight) {
711 maxPos = drawAreaHeight;
715 }
else if (y > maxPos - drawAreaHeight) {
716 pos = maxPos - drawAreaHeight;
720 if (scrollY != pos) {
722 XmScrollBarSetValues(vScrollBar, scrollY, drawAreaHeight, 16,
723 drawAreaHeight, False);
728 redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight);
736void XPDFCore::setSelection(
int newXMin,
int newYMin,
737 int newXMax,
int newYMax) {
740 GBool needRedraw, needScroll;
741 GBool moveLeft, moveRight, moveTop, moveBottom;
743 pixmap = out->getPixmap();
748 if (selectXMin < selectXMax && selectYMin < selectYMax) {
749 XFillRectangle(display, pixmap,
750 selectGC, selectXMin, selectYMin,
751 selectXMax - selectXMin, selectYMax - selectYMin);
756 if (newXMin < newXMax && newYMin < newYMax) {
757 XFillRectangle(display, pixmap,
758 selectGC, newXMin, newYMin,
759 newXMax - newXMin, newYMax - newYMin);
764 moveLeft = newXMin != selectXMin;
765 moveTop = newYMin != selectYMin;
766 moveRight = newXMax != selectXMax;
767 moveBottom = newYMax != selectYMax;
772 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
773 (newYMin < selectYMin) ? newYMin : selectYMin,
774 (newXMin > selectXMin) ? newXMin : selectXMin,
775 (newYMax > selectYMax) ? newYMax : selectYMax);
778 redrawRectangle((newXMax < selectXMax) ? newXMax : selectXMax,
779 (newYMin < selectYMin) ? newYMin : selectYMin,
780 (newXMax > selectXMax) ? newXMax : selectXMax,
781 (newYMax > selectYMax) ? newYMax : selectYMax);
784 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
785 (newYMin < selectYMin) ? newYMin : selectYMin,
786 (newXMax > selectXMax) ? newXMax : selectXMax,
787 (newYMin > selectYMin) ? newYMin : selectYMin);
790 redrawRectangle((newXMin < selectXMin) ? newXMin : selectXMin,
791 (newYMax < selectYMax) ? newYMax : selectYMax,
792 (newXMax > selectXMax) ? newXMax : selectXMax,
793 (newYMax > selectYMax) ? newYMax : selectYMax);
798 selectXMin = newXMin;
799 selectXMax = newXMax;
800 selectYMin = newYMin;
801 selectYMax = newYMax;
810 if (moveLeft && selectXMin < x) {
813 }
else if (moveRight && selectXMax >= x + drawAreaWidth) {
814 x = selectXMax - drawAreaWidth;
816 }
else if (moveLeft && selectXMin >= x + drawAreaWidth) {
817 x = selectXMin - drawAreaWidth;
819 }
else if (moveRight && selectXMax < x) {
823 if (moveTop && selectYMin < y) {
826 }
else if (moveBottom && selectYMax >= y + drawAreaHeight) {
827 y = selectYMax - drawAreaHeight;
829 }
else if (moveTop && selectYMin >= y + drawAreaHeight) {
830 y = selectYMin - drawAreaHeight;
832 }
else if (moveBottom && selectYMax < y) {
841void XPDFCore::moveSelection(
int mx,
int my) {
842 int xMin, yMin, xMax, yMax;
847 }
else if (mx >= out->getPixmapWidth()) {
848 mx = out->getPixmapWidth() - 1;
852 }
else if (my >= out->getPixmapHeight()) {
853 my = out->getPixmapHeight() - 1;
858 if (mx < selectXMax) {
864 lastDragLeft = gFalse;
867 if (mx > selectXMin) {
873 lastDragLeft = gTrue;
877 if (my < selectYMax) {
883 lastDragTop = gFalse;
886 if (my > selectYMin) {
897 setSelection(xMin, yMin, xMax, yMax);
908void XPDFCore::copySelection() {
909 if (!doc->okToCopy()) {
912 if (currentSelection) {
913 delete currentSelection;
916 currentSelection = out->getText(selectXMin, selectYMin,
917 selectXMax, selectYMax);
918 currentSelectionOwner =
this;
919 XtOwnSelection(drawArea, XA_PRIMARY, XtLastTimestampProcessed(display),
920 &convertSelectionCbk, NULL, NULL);
923Boolean XPDFCore::convertSelectionCbk(Widget widget, Atom *selection,
924 Atom *target, Atom *type,
925 XtPointer *value,
unsigned long *length,
927 if (*target != XA_STRING) {
931 *value = XtNewString(currentSelection->getCString());
932 *length = currentSelection->getLength();
938GBool XPDFCore::getSelection(
int *xMin,
int *yMin,
int *xMax,
int *yMax) {
939 if (selectXMin >= selectXMax || selectYMin >= selectYMax) {
949GString *XPDFCore::extractText(
int xMin,
int yMin,
int xMax,
int yMax) {
950 if (!doc->okToCopy()) {
953 return out->getText(xMin, yMin, xMax, yMax);
956GString *XPDFCore::extractText(
int pageNum,
957 int xMin,
int yMin,
int xMax,
int yMax) {
958 TextOutputDev *textOut;
961 if (!doc->okToCopy()) {
964 textOut =
new TextOutputDev(NULL, gFalse, gFalse);
965 if (!textOut->isOk()) {
969 doc->displayPage(textOut, pageNum, dpi, rotate, gFalse);
970 s = textOut->getText(xMin, yMin, xMax, yMax);
979void XPDFCore::doLink(
int mx,
int my) {
984 out->cvtDevToUser(mx, my, &x, &y);
985 if ((action = doc->findLink(x, y))) {
990void XPDFCore::doAction(LinkAction *action) {
995 GString *fileName, *fileName2;
998 Object movieAnnot, obj1, obj2;
1002 switch (kind = action->getKind()) {
1007 if (kind == actionGoTo) {
1010 if ((dest = ((LinkGoTo *)action)->getDest())) {
1011 dest = dest->copy();
1012 }
else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) {
1013 namedDest = namedDest->copy();
1018 if ((dest = ((LinkGoToR *)action)->getDest())) {
1019 dest = dest->copy();
1020 }
else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) {
1021 namedDest = namedDest->copy();
1023 s = ((LinkGoToR *)action)->getFileName()->getCString();
1025 if (isAbsolutePath(s)) {
1026 fileName =
new GString(s);
1028 fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
1030 if (loadFile(fileName) != errNone) {
1043 dest = doc->findDest(namedDest);
1047 displayDest(dest, zoom, rotate, gTrue);
1050 if (kind == actionGoToR) {
1051 displayPage(1, zoom, 0, gFalse, gTrue);
1058 fileName = ((LinkLaunch *)action)->getFileName();
1059 s = fileName->getCString();
1060 if (!strcmp(s + fileName->getLength() - 4,
".pdf") ||
1061 !strcmp(s + fileName->getLength() - 4,
".PDF")) {
1063 if (isAbsolutePath(s)) {
1064 fileName = fileName->copy();
1066 fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s);
1068 if (loadFile(fileName) != errNone) {
1073 displayPage(1, zoom, rotate, gFalse, gTrue);
1075 fileName = fileName->copy();
1076 if (((LinkLaunch *)action)->getParams()) {
1077 fileName->append(
' ');
1078 fileName->append(((LinkLaunch *)action)->getParams());
1081 fileName->insert(0,
"spawn/nowait ");
1082#elif defined(__EMX__)
1083 fileName->insert(0,
"start /min /n ");
1085 fileName->append(
" &");
1087 msg =
new GString(
"About to execute the command:\n");
1088 msg->append(fileName);
1089 if (doQuestionDialog(
"Launching external application", msg)) {
1090 system(fileName->getCString());
1099 if (!(cmd = globalParams->getURLCommand())) {
1100 error(-1,
"No urlCommand defined in config file");
1103 runCommand(cmd, ((LinkURI *)action)->getURI());
1108 actionName = ((LinkNamed *)action)->getName();
1109 if (!actionName->cmp(
"NextPage")) {
1110 gotoNextPage(1, gTrue);
1111 }
else if (!actionName->cmp(
"PrevPage")) {
1112 gotoPrevPage(1, gTrue, gFalse);
1113 }
else if (!actionName->cmp(
"FirstPage")) {
1115 displayPage(1, zoom, rotate, gTrue, gTrue);
1117 }
else if (!actionName->cmp(
"LastPage")) {
1118 if (page != doc->getNumPages()) {
1119 displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
1121 }
else if (!actionName->cmp(
"GoBack")) {
1123 }
else if (!actionName->cmp(
"GoForward")) {
1125 }
else if (!actionName->cmp(
"Quit")) {
1127 (*actionCbk)(actionCbkData,
"Quit");
1130 error(-1,
"Unknown named action: '%s'", actionName->getCString());
1136 if (!(cmd = globalParams->getMovieCommand())) {
1137 error(-1,
"No movieCommand defined in config file");
1140 if (((LinkMovie *)action)->hasAnnotRef()) {
1141 doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num,
1142 ((LinkMovie *)action)->getAnnotRef()->gen,
1145 doc->getCatalog()->getPage(page)->getAnnots(&obj1);
1146 if (obj1.isArray()) {
1147 for (i = 0; i < obj1.arrayGetLength(); ++i) {
1148 if (obj1.arrayGet(i, &movieAnnot)->isDict()) {
1149 if (movieAnnot.dictLookup(
"Subtype", &obj2)->isName(
"Movie")) {
1160 if (movieAnnot.isDict()) {
1161 if (movieAnnot.dictLookup(
"Movie", &obj1)->isDict()) {
1162 if (obj1.dictLookup(
"F", &obj2)) {
1163 if ((fileName = LinkAction::getFileSpecName(&obj2))) {
1164 if (!isAbsolutePath(fileName->getCString())) {
1165 fileName2 = appendToPath(
1166 grabPath(doc->getFileName()->getCString()),
1167 fileName->getCString());
1169 fileName = fileName2;
1171 runCommand(cmd, fileName);
1184 error(-1,
"Unknown link action type: '%s'",
1185 ((LinkUnknown *)action)->getAction()->getCString());
1192void XPDFCore::runCommand(GString *cmdFmt, GString *arg) {
1197 if ((s = strstr(cmdFmt->getCString(),
"%s"))) {
1202 while (i < cmd->getLength()) {
1203 if (cmd->getChar(i) ==
'"') {
1205 cmd->insert(i,
"%22");
1207 }
else if (cmd->getChar(i) ==
'\'') {
1209 cmd->insert(i,
"%27");
1215 cmd->insert(0, cmdFmt->getCString(),
1216 s - cmdFmt->getCString());
1219 cmd = cmdFmt->copy();
1222 cmd->insert(0,
"spawn/nowait ");
1223#elif defined(__EMX__)
1224 cmd->insert(0,
"start /min /n ");
1228 system(cmd->getCString());
1237void XPDFCore::find(
char *s) {
1239 TextOutputDev *textOut;
1240 int xMin, yMin, xMax, yMax;
1241 double xMin1, yMin1, xMax1, yMax1;
1253 setCursor(busyCursor);
1258 u = (Unicode *)gmalloc(len *
sizeof(Unicode));
1259 for (i = 0; i < len; ++i) {
1260 u[i] = (Unicode)(s[i] & 0xff);
1265 xMin = yMin = xMax = yMax = 0;
1266 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1268 yMin = (selectYMin + selectYMax) / 2;
1273 if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) {
1278 textOut =
new TextOutputDev(NULL, gFalse, gFalse);
1279 if (!textOut->isOk()) {
1283 for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
1284 doc->displayPage(textOut, pg, 72, 0, gFalse);
1285 if (textOut->findText(u, len, gTrue, gTrue,
1286 &xMin1, &yMin1, &xMax1, &yMax1)) {
1292 for (pg = 1; pg < page; ++pg) {
1293 doc->displayPage(textOut, pg, 72, 0, gFalse);
1294 if (textOut->findText(u, len, gTrue, gTrue,
1295 &xMin1, &yMin1, &xMax1, &yMax1)) {
1302 if (selectXMin < selectXMax && selectYMin < selectYMax) {
1304 yMax = (selectYMin + selectYMax) / 2;
1305 if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) {
1317 displayPage(pg, zoom, rotate, gTrue, gTrue);
1318 if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) {
1325 setSelection(xMin, yMin, xMax, yMax);
1326#ifndef NO_TEXT_SELECT
1341void XPDFCore::setBusyCursor(GBool busy) {
1342 setCursor(busy ? busyCursor : None);
1345void XPDFCore::takeFocus() {
1346 XmProcessTraversal(drawArea, XmTRAVERSE_CURRENT);
1353void XPDFCore::initWindow() {
1358 busyCursor = XCreateFontCursor(display, XC_watch);
1359 linkCursor = XCreateFontCursor(display, XC_hand2);
1360 selectCursor = XCreateFontCursor(display, XC_cross);
1365 XtSetArg(args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED); ++n;
1366 XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n;
1367 scrolledWin = XmCreateScrolledWindow(parentWidget,
"scroll", args, n);
1368 XtManageChild(scrolledWin);
1370 XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n;
1371 XtSetArg(args[n], XmNminimum, 0); ++n;
1372 XtSetArg(args[n], XmNmaximum, 1); ++n;
1373 XtSetArg(args[n], XmNsliderSize, 1); ++n;
1374 XtSetArg(args[n], XmNvalue, 0); ++n;
1375 XtSetArg(args[n], XmNincrement, 1); ++n;
1376 XtSetArg(args[n], XmNpageIncrement, 1); ++n;
1377 hScrollBar = XmCreateScrollBar(scrolledWin,
"hScrollBar", args, n);
1378 XtManageChild(hScrollBar);
1379 XtAddCallback(hScrollBar, XmNvalueChangedCallback,
1380 &hScrollChangeCbk, (XtPointer)
this);
1381#ifndef DISABLE_SMOOTH_SCROLL
1382 XtAddCallback(hScrollBar, XmNdragCallback,
1383 &hScrollDragCbk, (XtPointer)
this);
1386 XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n;
1387 XtSetArg(args[n], XmNminimum, 0); ++n;
1388 XtSetArg(args[n], XmNmaximum, 1); ++n;
1389 XtSetArg(args[n], XmNsliderSize, 1); ++n;
1390 XtSetArg(args[n], XmNvalue, 0); ++n;
1391 XtSetArg(args[n], XmNincrement, 1); ++n;
1392 XtSetArg(args[n], XmNpageIncrement, 1); ++n;
1393 vScrollBar = XmCreateScrollBar(scrolledWin,
"vScrollBar", args, n);
1394 XtManageChild(vScrollBar);
1395 XtAddCallback(vScrollBar, XmNvalueChangedCallback,
1396 &vScrollChangeCbk, (XtPointer)
this);
1397#ifndef DISABLE_SMOOTH_SCROLL
1398 XtAddCallback(vScrollBar, XmNdragCallback,
1399 &vScrollDragCbk, (XtPointer)
this);
1404 XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); ++n;
1405 XtSetArg(args[n], XmNmarginWidth, 0); ++n;
1406 XtSetArg(args[n], XmNmarginHeight, 0); ++n;
1408 XtSetArg(args[n], XmNshadowThickness, 0); ++n;
1410 drawAreaFrame = XmCreateFrame(scrolledWin,
"drawAreaFrame", args, n);
1411 XtManageChild(drawAreaFrame);
1413 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n;
1414 XtSetArg(args[n], XmNbackground, paperColor); ++n;
1415 XtSetArg(args[n], XmNwidth, 700); ++n;
1416 XtSetArg(args[n], XmNheight, 500); ++n;
1417 drawArea = XmCreateDrawingArea(drawAreaFrame,
"drawArea", args, n);
1418 XtManageChild(drawArea);
1419 XtAddCallback(drawArea, XmNresizeCallback, &resizeCbk, (XtPointer)
this);
1420 XtAddCallback(drawArea, XmNexposeCallback, &redrawCbk, (XtPointer)
this);
1421 XtAddCallback(drawArea, XmNinputCallback, &inputCbk, (XtPointer)
this);
1422 resizeCbk(drawArea,
this, NULL);
1425 XtOverrideTranslations(drawArea, XtParseTranslationTable(
1426 "<Btn1Down>:DrawingAreaInput()\n"
1427 "<Btn1Up>:DrawingAreaInput()\n"
1428 "<Btn1Motion>:DrawingAreaInput()\n"
1429 "<Motion>:DrawingAreaInput()"));
1437void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr,
1438 XtPointer callData) {
1439 XPDFCore *core = (XPDFCore *)ptr;
1440 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1442 core->scrollTo(data->value, core->scrollY);
1445void XPDFCore::hScrollDragCbk(Widget widget, XtPointer ptr,
1446 XtPointer callData) {
1447 XPDFCore *core = (XPDFCore *)ptr;
1448 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1450 core->scrollTo(data->value, core->scrollY);
1453void XPDFCore::vScrollChangeCbk(Widget widget, XtPointer ptr,
1454 XtPointer callData) {
1455 XPDFCore *core = (XPDFCore *)ptr;
1456 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1458 core->scrollTo(core->scrollX, data->value);
1461void XPDFCore::vScrollDragCbk(Widget widget, XtPointer ptr,
1462 XtPointer callData) {
1463 XPDFCore *core = (XPDFCore *)ptr;
1464 XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData;
1466 core->scrollTo(core->scrollX, data->value);
1469void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1470 XPDFCore *core = (XPDFCore *)ptr;
1476 XtSetArg(args[n], XmNwidth, &w); ++n;
1477 XtSetArg(args[n], XmNheight, &h); ++n;
1478 XtGetValues(core->drawArea, args, n);
1479 core->drawAreaWidth = (int)w;
1480 core->drawAreaHeight = (int)h;
1481 if (core->page >= 0 &&
1482 (core->zoom == zoomPage || core->zoom == zoomWidth)) {
1483 core->displayPage(core->page, core->zoom, core->rotate,
1486 core->updateScrollBars();
1490void XPDFCore::redrawCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1491 XPDFCore *core = (XPDFCore *)ptr;
1492 XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData;
1495 if (data->reason == XmCR_EXPOSE) {
1496 x = core->scrollX + data->event->xexpose.x;
1497 y = core->scrollY + data->event->xexpose.y;
1498 w = data->event->xexpose.width;
1499 h = data->event->xexpose.height;
1503 w = core->drawAreaWidth;
1504 h = core->drawAreaHeight;
1506 core->redrawRectangle(x, y, w, h);
1509void XPDFCore::outputDevRedrawCbk(
void *data) {
1510 XPDFCore *core = (XPDFCore *)data;
1512 core->redrawRectangle(core->scrollX, core->scrollY,
1513 core->drawAreaWidth, core->drawAreaHeight);
1516void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) {
1517 XPDFCore *core = (XPDFCore *)ptr;
1518 XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData;
1527 switch (data->event->type) {
1529 if (data->event->xbutton.button == 1) {
1531 if (core->doc && core->doc->getNumPages() > 0) {
1532 if (core->selectEnabled) {
1533 mx = core->scrollX + data->event->xbutton.x;
1534 my = core->scrollY + data->event->xbutton.y;
1535 core->setSelection(mx, my, mx, my);
1536 core->setCursor(core->selectCursor);
1537 core->dragging = gTrue;
1540 }
else if (data->event->xbutton.button == 2) {
1541 if (!core->fullScreen) {
1542 core->panning = gTrue;
1543 core->panMX = data->event->xbutton.x;
1544 core->panMY = data->event->xbutton.y;
1546 }
else if (data->event->xbutton.button == 4) {
1547 if (core->fullScreen) {
1548 core->gotoPrevPage(1, gTrue, gFalse);
1549 }
else if (core->scrollY == 0) {
1550 core->gotoPrevPage(1, gFalse, gTrue);
1554 }
else if (data->event->xbutton.button == 5) {
1555 if (core->fullScreen ||
1557 core->out->getPixmapHeight() - core->drawAreaHeight) {
1558 core->gotoNextPage(1, gTrue);
1560 core->scrollDown(1);
1562 }
else if (data->event->xbutton.button == 6) {
1563 if (!core->fullScreen) {
1564 core->scrollRight(1);
1566 }
else if (data->event->xbutton.button == 7) {
1567 if (!core->fullScreen) {
1568 core->scrollLeft(1);
1571 if (*core->mouseCbk) {
1572 (*core->mouseCbk)(core->mouseCbkData, data->event);
1577 if (data->event->xbutton.button == 1) {
1578 if (core->doc && core->doc->getNumPages() > 0) {
1579 mx = core->scrollX + data->event->xbutton.x;
1580 my = core->scrollY + data->event->xbutton.y;
1581 if (core->dragging) {
1582 core->dragging = gFalse;
1583 core->setCursor(None);
1584 core->moveSelection(mx, my);
1585#ifndef NO_TEXT_SELECT
1586 if (core->selectXMin != core->selectXMax &&
1587 core->selectYMin != core->selectYMax) {
1588 if (core->doc->okToCopy()) {
1589 core->copySelection();
1591 error(-1,
"Copying of text from this document is not allowed.");
1596 if (core->hyperlinksEnabled) {
1597 if (core->selectXMin == core->selectXMax ||
1598 core->selectYMin == core->selectYMax) {
1599 core->doLink(mx, my);
1603 }
else if (data->event->xbutton.button == 2) {
1604 core->panning = gFalse;
1606 if (*core->mouseCbk) {
1607 (*core->mouseCbk)(core->mouseCbkData, data->event);
1612 if (core->doc && core->doc->getNumPages() > 0) {
1613 mx = core->scrollX + data->event->xbutton.x;
1614 my = core->scrollY + data->event->xbutton.y;
1615 if (core->dragging) {
1616 core->moveSelection(mx, my);
1617 }
else if (core->hyperlinksEnabled) {
1618 core->out->cvtDevToUser(mx, my, &x, &y);
1619 if ((action = core->doc->findLink(x, y))) {
1620 core->setCursor(core->linkCursor);
1621 if (action != core->linkAction) {
1622 core->linkAction = action;
1623 if (core->updateCbk) {
1625 switch (action->getKind()) {
1627 s =
"[internal link]";
1630 s = ((LinkGoToR *)action)->getFileName()->getCString();
1633 s = ((LinkLaunch *)action)->getFileName()->getCString();
1636 s = ((LinkURI *)action)->getURI()->getCString();
1639 s = ((LinkNamed *)action)->getName()->getCString();
1645 s =
"[unknown link]";
1648 (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, s);
1652 core->setCursor(None);
1653 if (core->linkAction) {
1654 core->linkAction = NULL;
1655 if (core->updateCbk) {
1656 (*core->updateCbk)(core->updateCbkData, NULL, -1, -1,
"");
1662 if (core->panning) {
1663 core->scrollTo(core->scrollX - (data->event->xbutton.x - core->panMX),
1664 core->scrollY - (data->event->xbutton.y - core->panMY));
1665 core->panMX = data->event->xbutton.x;
1666 core->panMY = data->event->xbutton.y;
1670 n = XLookupString(&data->event->xkey, buf,
sizeof(buf) - 1,
1672 core->keyPress(buf, key, data->event->xkey.state);
1677void XPDFCore::keyPress(
char *s, KeySym key, Guint modifiers) {
1681 if (modifiers & ControlMask) {
1682 displayPage(1, zoom, rotate, gTrue, gTrue);
1683 }
else if (!fullScreen) {
1689 if (modifiers & ControlMask) {
1690 displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue);
1691 }
else if (!fullScreen) {
1692 scrollTo(out->getPixmapWidth() - drawAreaWidth,
1693 out->getPixmapHeight() - drawAreaHeight);
1699 gotoPrevPage(1, gTrue, gFalse);
1705 case XK_KP_Page_Down:
1707 gotoNextPage(1, gTrue);
1739 (*keyPressCbk)(keyPressCbkData, s, key, modifiers);
1743void XPDFCore::redrawRectangle(
int x,
int y,
int w,
int h) {
1752 if (x + w > scrollX + drawAreaWidth) {
1753 w = scrollX + drawAreaWidth - x;
1759 if (y + h > scrollY + drawAreaHeight) {
1760 h = scrollY + drawAreaHeight - y;
1764 drawAreaWin = XtWindow(drawArea);
1766 gcValues.foreground = paperColor;
1767 drawAreaGC = XCreateGC(display, drawAreaWin, GCForeground, &gcValues);
1771 if (x + w > out->getPixmapWidth()) {
1772 XFillRectangle(display, drawAreaWin, drawAreaGC,
1773 out->getPixmapWidth() - scrollX, y - scrollY,
1774 x + w - out->getPixmapWidth(), h);
1775 w = out->getPixmapWidth() - x;
1777 if (y + h > out->getPixmapHeight()) {
1778 XFillRectangle(display, drawAreaWin, drawAreaGC,
1779 x - scrollX, out->getPixmapHeight() - scrollY,
1780 w, y + h - out->getPixmapHeight());
1781 h = out->getPixmapHeight() - y;
1785 if (out->getPixmapWidth() > 0) {
1786 XCopyArea(display, out->getPixmap(), drawAreaWin, drawAreaGC,
1787 x, y, w, h, x - scrollX, y - scrollY);
1791void XPDFCore::updateScrollBars() {
1796 maxPos = out ? out->getPixmapWidth() : 1;
1797 if (maxPos < drawAreaWidth) {
1798 maxPos = drawAreaWidth;
1800 if (scrollX > maxPos - drawAreaWidth) {
1801 scrollX = maxPos - drawAreaWidth;
1804 XtSetArg(args[n], XmNvalue, scrollX); ++n;
1805 XtSetArg(args[n], XmNmaximum, maxPos); ++n;
1806 XtSetArg(args[n], XmNsliderSize, drawAreaWidth); ++n;
1807 XtSetArg(args[n], XmNincrement, 16); ++n;
1808 XtSetArg(args[n], XmNpageIncrement, drawAreaWidth); ++n;
1809 XtSetValues(hScrollBar, args, n);
1811 maxPos = out ? out->getPixmapHeight() : 1;
1812 if (maxPos < drawAreaHeight) {
1813 maxPos = drawAreaHeight;
1815 if (scrollY > maxPos - drawAreaHeight) {
1816 scrollY = maxPos - drawAreaHeight;
1819 XtSetArg(args[n], XmNvalue, scrollY); ++n;
1820 XtSetArg(args[n], XmNmaximum, maxPos); ++n;
1821 XtSetArg(args[n], XmNsliderSize, drawAreaHeight); ++n;
1822 XtSetArg(args[n], XmNincrement, 16); ++n;
1823 XtSetArg(args[n], XmNpageIncrement, drawAreaHeight); ++n;
1824 XtSetValues(vScrollBar, args, n);
1827void XPDFCore::setCursor(Cursor cursor) {
1830 if (cursor == currentCursor) {
1833 if (!(topWin = XtWindow(shell))) {
1836 if (cursor == None) {
1837 XUndefineCursor(display, topWin);
1839 XDefineCursor(display, topWin, cursor);
1842 currentCursor = cursor;
1845GBool XPDFCore::doQuestionDialog(
char *title, GString *msg) {
1846 return doDialog(XmDIALOG_QUESTION, gTrue, title, msg);
1849void XPDFCore::doInfoDialog(
char *title, GString *msg) {
1850 doDialog(XmDIALOG_INFORMATION, gFalse, title, msg);
1853void XPDFCore::doErrorDialog(
char *title, GString *msg) {
1854 doDialog(XmDIALOG_ERROR, gFalse, title, msg);
1857GBool XPDFCore::doDialog(
int type, GBool hasCancel,
1858 char *title, GString *msg) {
1860 XtAppContext appContext;
1867 XtSetArg(args[n], XmNdialogType, type); ++n;
1868 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n;
1869 s1 = XmStringCreateLocalized(title);
1870 XtSetArg(args[n], XmNdialogTitle, s1); ++n;
1871 s2 = XmStringCreateLocalized(msg->getCString());
1872 XtSetArg(args[n], XmNmessageString, s2); ++n;
1873 dialog = XmCreateMessageDialog(drawArea,
"questionDialog", args, n);
1876 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
1877 XtAddCallback(dialog, XmNokCallback,
1878 &dialogOkCbk, (XtPointer)
this);
1880 XtAddCallback(dialog, XmNcancelCallback,
1881 &dialogCancelCbk, (XtPointer)
this);
1883 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
1886 XtManageChild(dialog);
1888 appContext = XtWidgetToApplicationContext(dialog);
1891 XtAppNextEvent(appContext, &event);
1892 XtDispatchEvent(&event);
1893 }
while (!dialogDone);
1895 XtUnmanageChild(dialog);
1896 XtDestroyWidget(dialog);
1898 return dialogDone > 0;
1901void XPDFCore::dialogOkCbk(Widget widget, XtPointer ptr,
1902 XtPointer callData) {
1903 XPDFCore *core = (XPDFCore *)ptr;
1905 core->dialogDone = 1;
1908void XPDFCore::dialogCancelCbk(Widget widget, XtPointer ptr,
1909 XtPointer callData) {
1910 XPDFCore *core = (XPDFCore *)ptr;
1912 core->dialogDone = -1;