X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=pdf%2Fxpdf%2FXPDFCore.cc;h=3b9c21e47e819d31b48e84bc41c1023201576fce;hb=1cb865554fcb40760784a30c7700b6a751567762;hp=8376ce97d5b5ce85bf352f426cfdea45342fe399;hpb=6112dfe4b45b0305c7a6f61bd8a847f69f892cbb;p=evince.git diff --git a/pdf/xpdf/XPDFCore.cc b/pdf/xpdf/XPDFCore.cc index 8376ce97..3b9c21e4 100644 --- a/pdf/xpdf/XPDFCore.cc +++ b/pdf/xpdf/XPDFCore.cc @@ -2,7 +2,7 @@ // // XPDFCore.cc // -// Copyright 2002 Glyph & Cog, LLC +// Copyright 2002-2003 Glyph & Cog, LLC // //======================================================================== @@ -14,6 +14,7 @@ #include #include +#include #include "gmem.h" #include "GString.h" #include "GList.h" @@ -24,7 +25,8 @@ #include "GfxState.h" #include "PSOutputDev.h" #include "TextOutputDev.h" -#include "XPixmapOutputDev.h" +#include "SplashPattern.h" +#include "XSplashOutputDev.h" #include "XPDFCore.h" // these macro defns conflict with xpdf's Object class @@ -91,31 +93,26 @@ //------------------------------------------------------------------------ -static int zoomDPI[maxZoom - minZoom + 1] = { - 29, 35, 42, 50, 60, - 72, - 86, 104, 124, 149, 179 -}; - -//------------------------------------------------------------------------ - GString *XPDFCore::currentSelection = NULL; XPDFCore *XPDFCore::currentSelectionOwner = NULL; +Atom XPDFCore::targetsAtom; //------------------------------------------------------------------------ // XPDFCore //------------------------------------------------------------------------ XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA, - Gulong paperColorA, GBool fullScreenA, GBool reverseVideo, - GBool installCmap, int rgbCubeSize) { + SplashRGB8 paperColorA, GBool fullScreenA, + GBool reverseVideo, GBool installCmap, int rgbCubeSize) { GString *initialZoom; + SplashColor paperColor2; int i; shell = shellA; parentWidget = parentWidgetA; display = XtDisplay(parentWidget); screenNum = XScreenNumberOfScreen(XtScreen(parentWidget)); + targetsAtom = XInternAtom(display, "TARGETS", False); paperColor = paperColorA; fullScreen = fullScreenA; @@ -144,12 +141,11 @@ XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA, zoom = zoomWidth; } else { zoom = atoi(initialZoom->getCString()); - if (zoom < minZoom) { - zoom = minZoom; - } else if (zoom > maxZoom) { - zoom = maxZoom; + if (zoom <= 0) { + zoom = defZoom; } } + delete initialZoom; scrollX = 0; scrollY = 0; @@ -183,8 +179,9 @@ XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA, initWindow(); // create the OutputDev - out = new XPixmapOutputDev(display, screenNum, visual, colormap, - reverseVideo, paperColor, + paperColor2.rgb8 = paperColor; + out = new XSplashOutputDev(display, screenNum, visual, colormap, + reverseVideo, paperColor2, installCmap, rgbCubeSize, gTrue, &outputDevRedrawCbk, this); out->startDoc(NULL); @@ -209,25 +206,9 @@ XPDFCore::~XPDFCore() { delete history[i].fileName; } } - if (selectGC) { - XFreeGC(display, selectGC); - XFreeGC(display, highlightGC); - } if (drawAreaGC) { XFreeGC(display, drawAreaGC); } - if (drawArea) { - XtDestroyWidget(drawArea); - } - if (drawAreaFrame) { - XtDestroyWidget(drawAreaFrame); - } - if (vScrollBar) { - XtDestroyWidget(vScrollBar); - } - if (hScrollBar) { - XtDestroyWidget(hScrollBar); - } if (scrolledWin) { XtDestroyWidget(scrolledWin); } @@ -314,6 +295,74 @@ int XPDFCore::loadFile(GString *fileName, GString *ownerPassword, return errNone; } +int XPDFCore::loadFile(BaseStream *stream, GString *ownerPassword, + GString *userPassword) { + PDFDoc *newDoc; + GString *password; + GBool again; + int err; + + // busy cursor + setCursor(busyCursor); + + // open the PDF file + newDoc = new PDFDoc(stream, ownerPassword, userPassword); + if (!newDoc->isOk()) { + err = newDoc->getErrorCode(); + delete newDoc; + if (err != errEncrypted || !reqPasswordCbk) { + setCursor(None); + return err; + } + + // try requesting a password + again = ownerPassword != NULL || userPassword != NULL; + while (1) { + if (!(password = (*reqPasswordCbk)(reqPasswordCbkData, again))) { + setCursor(None); + return errEncrypted; + } + newDoc = new PDFDoc(stream, password, password); + if (newDoc->isOk()) { + break; + } + err = newDoc->getErrorCode(); + delete newDoc; + if (err != errEncrypted) { + setCursor(None); + return err; + } + again = gTrue; + } + } + + // replace old document + if (doc) { + delete doc; + } + doc = newDoc; + if (out) { + out->startDoc(doc->getXRef()); + } + + // nothing displayed yet + page = -99; + + // save the modification time + modTime = getModTime(doc->getFileName()->getCString()); + + // update the parent window + if (updateCbk) { + (*updateCbk)(updateCbkData, doc->getFileName(), -1, + doc->getNumPages(), NULL); + } + + // back to regular cursor + setCursor(None); + + return errNone; +} + void XPDFCore::resizeToPage(int pg) { Dimension width, height; double width1, height1; @@ -338,11 +387,11 @@ void XPDFCore::resizeToPage(int pg) { height1 = doc->getPageHeight(pg); } if (zoom == zoomPage || zoom == zoomWidth) { - width = (Dimension)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5); - height = (Dimension)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5); + width = (Dimension)(width1 * 0.01 * defZoom + 0.5); + height = (Dimension)(height1 * 0.01 * defZoom + 0.5); } else { - width = (Dimension)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5); - height = (Dimension)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5); + width = (Dimension)(width1 * 0.01 * zoom + 0.5); + height = (Dimension)(height1 * 0.01 * zoom + 0.5); } if (width > displayW - 100) { width = displayW - 100; @@ -382,13 +431,12 @@ void XPDFCore::clear() { redrawRectangle(scrollX, scrollY, drawAreaWidth, drawAreaHeight); } -void XPDFCore::displayPage(int pageA, int zoomA, int rotateA, +void XPDFCore::displayPage(int pageA, double zoomA, int rotateA, GBool scrollToTop, GBool addToHist) { double hDPI, vDPI; int rot; XPDFHistory *h; GBool newZoom; - XGCValues gcValues; time_t newModTime; int oldScrollX, oldScrollY; @@ -417,12 +465,6 @@ void XPDFCore::displayPage(int pageA, int zoomA, int rotateA, modTime = newModTime; } - // free the old GCs - if (selectGC) { - XFreeGC(display, selectGC); - XFreeGC(display, highlightGC); - } - // new page number page = pageA; @@ -466,10 +508,9 @@ void XPDFCore::displayPage(int pageA, int zoomA, int rotateA, dpi = (drawAreaWidth / doc->getPageWidth(page)) * 72; } } else { - dpi = zoomDPI[zoom - minZoom]; + dpi = 0.01 * zoom * 72; } - out->setWindow(XtWindow(drawArea)); - doc->displayPage(out, page, dpi, rotate, gTrue); + doc->displayPage(out, page, dpi, dpi, rotate, gTrue, gTrue); oldScrollX = scrollX; oldScrollY = scrollY; updateScrollBars(); @@ -487,7 +528,11 @@ void XPDFCore::displayPage(int pageA, int zoomA, int rotateA, if (h->fileName) { delete h->fileName; } - h->fileName = doc->getFileName()->copy(); + if (doc->getFileName()) { + h->fileName = doc->getFileName()->copy(); + } else { + h->fileName = NULL; + } h->page = page; if (historyBLen < xpdfHistorySize) { ++historyBLen; @@ -500,20 +545,11 @@ void XPDFCore::displayPage(int pageA, int zoomA, int rotateA, (*updateCbk)(updateCbkData, NULL, page, -1, ""); } - // allocate new GCs - gcValues.foreground = BlackPixel(display, screenNum) ^ - WhitePixel(display, screenNum); - gcValues.function = GXxor; - selectGC = XCreateGC(display, out->getPixmap(), - GCForeground | GCFunction, &gcValues); - highlightGC = XCreateGC(display, out->getPixmap(), - GCForeground | GCFunction, &gcValues); - // back to regular cursor setCursor(None); } -void XPDFCore::displayDest(LinkDest *dest, int zoomA, int rotateA, +void XPDFCore::displayDest(LinkDest *dest, double zoomA, int rotateA, GBool addToHist) { Ref pageRef; int pg; @@ -597,7 +633,7 @@ void XPDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) { } if (page > 1) { if (!fullScreen && bottom) { - scrollY = out->getPixmapHeight() - drawAreaHeight; + scrollY = out->getBitmapHeight() - drawAreaHeight; if (scrollY < 0) { scrollY = 0; } @@ -622,7 +658,7 @@ void XPDFCore::goForward() { } --historyFLen; ++historyBLen; - if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) { if (loadFile(history[historyCur].fileName) != errNone) { XBell(display, 0); return; @@ -641,7 +677,7 @@ void XPDFCore::goBackward() { } --historyBLen; ++historyFLen; - if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) { if (loadFile(history[historyCur].fileName) != errNone) { XBell(display, 0); return; @@ -675,7 +711,7 @@ void XPDFCore::scrollPageUp() { } void XPDFCore::scrollPageDown() { - if (scrollY >= out->getPixmapHeight() - drawAreaHeight) { + if (scrollY >= out->getBitmapHeight() - drawAreaHeight) { gotoNextPage(1, gTrue); } else { scrollTo(scrollX, scrollY + drawAreaHeight); @@ -688,7 +724,7 @@ void XPDFCore::scrollTo(int x, int y) { needRedraw = gFalse; - maxPos = out ? out->getPixmapWidth() : 1; + maxPos = out ? out->getBitmapWidth() : 1; if (maxPos < drawAreaWidth) { maxPos = drawAreaWidth; } @@ -706,7 +742,7 @@ void XPDFCore::scrollTo(int x, int y) { needRedraw = gTrue; } - maxPos = out ? out->getPixmapHeight() : 1; + maxPos = out ? out->getBitmapHeight() : 1; if (maxPos < drawAreaHeight) { maxPos = drawAreaHeight; } @@ -735,28 +771,26 @@ void XPDFCore::scrollTo(int x, int y) { void XPDFCore::setSelection(int newXMin, int newYMin, int newXMax, int newYMax) { - Pixmap pixmap; int x, y; GBool needRedraw, needScroll; GBool moveLeft, moveRight, moveTop, moveBottom; - - pixmap = out->getPixmap(); + SplashColor xorColor; // erase old selection on off-screen bitmap needRedraw = gFalse; if (selectXMin < selectXMax && selectYMin < selectYMax) { - XFillRectangle(display, pixmap, - selectGC, selectXMin, selectYMin, - selectXMax - selectXMin, selectYMax - selectYMin); + xorColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff); + out->xorRectangle(selectXMin, selectYMin, selectXMax, selectYMax, + new SplashSolidColor(xorColor)); needRedraw = gTrue; } // draw new selection on off-screen bitmap if (newXMin < newXMax && newYMin < newYMax) { - XFillRectangle(display, pixmap, - selectGC, newXMin, newYMin, - newXMax - newXMin, newYMax - newYMin); + xorColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff); + out->xorRectangle(newXMin, newYMin, newXMax, newYMax, + new SplashSolidColor(xorColor)); needRedraw = gTrue; } @@ -844,13 +878,13 @@ void XPDFCore::moveSelection(int mx, int my) { // clip mouse coords if (mx < 0) { mx = 0; - } else if (mx >= out->getPixmapWidth()) { - mx = out->getPixmapWidth() - 1; + } else if (mx >= out->getBitmapWidth()) { + mx = out->getBitmapWidth() - 1; } if (my < 0) { my = 0; - } else if (my >= out->getPixmapHeight()) { - my = out->getPixmapHeight() - 1; + } else if (my >= out->getBitmapHeight()) { + my = out->getBitmapHeight() - 1; } // move appropriate edges of selection @@ -924,15 +958,31 @@ Boolean XPDFCore::convertSelectionCbk(Widget widget, Atom *selection, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format) { - if (*target != XA_STRING) { - return False; - } - //~ for multithreading: need a mutex here - *value = XtNewString(currentSelection->getCString()); - *length = currentSelection->getLength(); - *type = XA_STRING; - *format = 8; // 8-bit elements - return True; + Atom *array; + + // send back a list of supported conversion targets + if (*target == targetsAtom) { + if (!(array = (Atom *)XtMalloc(sizeof(Atom)))) { + return False; + } + array[0] = XA_STRING; + *value = (XtPointer)array; + *type = XA_ATOM; + *format = 32; + *length = 1; + return True; + + // send the selected text + } else if (*target == XA_STRING) { + //~ for multithreading: need a mutex here + *value = XtNewString(currentSelection->getCString()); + *length = currentSelection->getLength(); + *type = XA_STRING; + *format = 8; // 8-bit elements + return True; + } + + return False; } GBool XPDFCore::getSelection(int *xMin, int *yMin, int *xMax, int *yMax) { @@ -961,12 +1011,12 @@ GString *XPDFCore::extractText(int pageNum, if (!doc->okToCopy()) { return NULL; } - textOut = new TextOutputDev(NULL, gFalse, gFalse); + textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse); if (!textOut->isOk()) { delete textOut; return NULL; } - doc->displayPage(textOut, pageNum, dpi, rotate, gFalse); + doc->displayPage(textOut, pageNum, dpi, dpi, rotate, gTrue, gFalse); s = textOut->getText(xMin, yMin, xMax, yMax); delete textOut; return s; @@ -976,7 +1026,7 @@ GString *XPDFCore::extractText(int pageNum, // hyperlinks //------------------------------------------------------------------------ -void XPDFCore::doLink(int mx, int my) { +GBool XPDFCore::doLink(int mx, int my) { double x, y; LinkAction *action; @@ -984,7 +1034,9 @@ void XPDFCore::doLink(int mx, int my) { out->cvtDevToUser(mx, my, &x, &y); if ((action = doc->findLink(x, y))) { doAction(action); + return gTrue; } + return gFalse; } void XPDFCore::doAction(LinkAction *action) { @@ -1192,26 +1244,9 @@ void XPDFCore::doAction(LinkAction *action) { void XPDFCore::runCommand(GString *cmdFmt, GString *arg) { GString *cmd; char *s; - int i; if ((s = strstr(cmdFmt->getCString(), "%s"))) { - cmd = arg->copy(); - // filter out any quote marks (' or ") to avoid a potential - // security hole - i = 0; - while (i < cmd->getLength()) { - if (cmd->getChar(i) == '"') { - cmd->del(i); - cmd->insert(i, "%22"); - i += 3; - } else if (cmd->getChar(i) == '\'') { - cmd->del(i); - cmd->insert(i, "%27"); - i += 3; - } else { - ++i; - } - } + cmd = mungeURL(arg); cmd->insert(0, cmdFmt->getCString(), s - cmdFmt->getCString()); cmd->append(s + 2); @@ -1229,18 +1264,43 @@ void XPDFCore::runCommand(GString *cmdFmt, GString *arg) { delete cmd; } +// Escape any characters in a URL which might cause problems when +// calling system(). +GString *XPDFCore::mungeURL(GString *url) { + static char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "-_.~/?:@&=+,#%"; + GString *newURL; + char c; + char buf[4]; + int i; + + newURL = new GString(); + for (i = 0; i < url->getLength(); ++i) { + c = url->getChar(i); + if (strchr(allowed, c)) { + newURL->append(c); + } else { + sprintf(buf, "%%%02x", c & 0xff); + newURL->append(buf); + } + } + return newURL; +} + //------------------------------------------------------------------------ // find //------------------------------------------------------------------------ -void XPDFCore::find(char *s) { +void XPDFCore::find(char *s, GBool next) { Unicode *u; TextOutputDev *textOut; int xMin, yMin, xMax, yMax; double xMin1, yMin1, xMax1, yMax1; int pg; - GBool top; + GBool startAtTop; int len, i; // check for zero-length string @@ -1262,27 +1322,24 @@ void XPDFCore::find(char *s) { #endif // search current page starting at current selection or top of page - xMin = yMin = xMax = yMax = 0; - if (selectXMin < selectXMax && selectYMin < selectYMax) { - xMin = selectXMax; - yMin = (selectYMin + selectYMax) / 2; - top = gFalse; - } else { - top = gTrue; - } - if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) { + startAtTop = !next && !(selectXMin < selectXMax && selectYMin < selectYMax); + xMin = selectXMin + 1; + yMin = selectYMin + 1; + xMax = yMax = 0; + if (out->findText(u, len, startAtTop, gTrue, next, gFalse, + &xMin, &yMin, &xMax, &yMax)) { goto found; } // search following pages - textOut = new TextOutputDev(NULL, gFalse, gFalse); + textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse); if (!textOut->isOk()) { delete textOut; goto done; } for (pg = page+1; pg <= doc->getNumPages(); ++pg) { - doc->displayPage(textOut, pg, 72, 0, gFalse); - if (textOut->findText(u, len, gTrue, gTrue, + doc->displayPage(textOut, pg, 72, 72, 0, gTrue, gFalse); + if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse, &xMin1, &yMin1, &xMax1, &yMax1)) { goto foundPage; } @@ -1290,8 +1347,8 @@ void XPDFCore::find(char *s) { // search previous pages for (pg = 1; pg < page; ++pg) { - doc->displayPage(textOut, pg, 72, 0, gFalse); - if (textOut->findText(u, len, gTrue, gTrue, + doc->displayPage(textOut, pg, 72, 72, 0, gTrue, gFalse); + if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse, &xMin1, &yMin1, &xMax1, &yMax1)) { goto foundPage; } @@ -1299,10 +1356,12 @@ void XPDFCore::find(char *s) { delete textOut; // search current page ending at current selection - if (selectXMin < selectXMax && selectYMin < selectYMax) { + if (!startAtTop) { + xMin = yMin = 0; xMax = selectXMin; - yMax = (selectYMin + selectYMax) / 2; - if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) { + yMax = selectYMin; + if (out->findText(u, len, gTrue, gFalse, gFalse, next, + &xMin, &yMin, &xMax, &yMax)) { goto found; } } @@ -1315,7 +1374,8 @@ void XPDFCore::find(char *s) { foundPage: delete textOut; displayPage(pg, zoom, rotate, gTrue, gTrue); - if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) { + if (!out->findText(u, len, gTrue, gTrue, gFalse, gFalse, + &xMin, &yMin, &xMax, &yMax)) { // this can happen if coalescing is bad goto done; } @@ -1411,7 +1471,6 @@ void XPDFCore::initWindow() { XtManageChild(drawAreaFrame); n = 0; XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n; - XtSetArg(args[n], XmNbackground, paperColor); ++n; XtSetArg(args[n], XmNwidth, 700); ++n; XtSetArg(args[n], XmNheight, 500); ++n; drawArea = XmCreateDrawingArea(drawAreaFrame, "drawArea", args, n); @@ -1430,8 +1489,6 @@ void XPDFCore::initWindow() { // can't create a GC until the window gets mapped drawAreaGC = NULL; - selectGC = NULL; - highlightGC = NULL; } void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr, @@ -1471,6 +1528,7 @@ void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) { Arg args[2]; int n; Dimension w, h; + int oldScrollX, oldScrollY; n = 0; XtSetArg(args[n], XmNwidth, &w); ++n; @@ -1483,7 +1541,13 @@ void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) { core->displayPage(core->page, core->zoom, core->rotate, gFalse, gFalse); } else { + oldScrollX = core->scrollX; + oldScrollY = core->scrollY; core->updateScrollBars(); + if (core->scrollX != oldScrollX || core->scrollY != oldScrollY) { + core->redrawRectangle(core->scrollX, core->scrollY, + core->drawAreaWidth, core->drawAreaHeight); + } } } @@ -1554,18 +1618,18 @@ void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) { } else if (data->event->xbutton.button == 5) { // mouse wheel down if (core->fullScreen || core->scrollY >= - core->out->getPixmapHeight() - core->drawAreaHeight) { + core->out->getBitmapHeight() - core->drawAreaHeight) { core->gotoNextPage(1, gTrue); } else { core->scrollDown(1); } - } else if (data->event->xbutton.button == 6) { // second mouse wheel right + } else if (data->event->xbutton.button == 6) { // second mouse wheel left if (!core->fullScreen) { - core->scrollRight(1); + core->scrollLeft(1); } - } else if (data->event->xbutton.button == 7) { // second mouse wheel left + } else if (data->event->xbutton.button == 7) { // second mouse wheel right if (!core->fullScreen) { - core->scrollLeft(1); + core->scrollRight(1); } } else { if (*core->mouseCbk) { @@ -1689,8 +1753,8 @@ void XPDFCore::keyPress(char *s, KeySym key, Guint modifiers) { if (modifiers & ControlMask) { displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue); } else if (!fullScreen) { - scrollTo(out->getPixmapWidth() - drawAreaWidth, - out->getPixmapHeight() - drawAreaHeight); + scrollTo(out->getBitmapWidth() - drawAreaWidth, + out->getBitmapHeight() - drawAreaHeight); } return; case XK_Page_Up: @@ -1768,23 +1832,22 @@ void XPDFCore::redrawRectangle(int x, int y, int w, int h) { } // draw white background past the edges of the document - if (x + w > out->getPixmapWidth()) { + if (x + w > out->getBitmapWidth()) { XFillRectangle(display, drawAreaWin, drawAreaGC, - out->getPixmapWidth() - scrollX, y - scrollY, - x + w - out->getPixmapWidth(), h); - w = out->getPixmapWidth() - x; + out->getBitmapWidth() - scrollX, y - scrollY, + x + w - out->getBitmapWidth(), h); + w = out->getBitmapWidth() - x; } - if (y + h > out->getPixmapHeight()) { + if (y + h > out->getBitmapHeight()) { XFillRectangle(display, drawAreaWin, drawAreaGC, - x - scrollX, out->getPixmapHeight() - scrollY, - w, y + h - out->getPixmapHeight()); - h = out->getPixmapHeight() - y; + x - scrollX, out->getBitmapHeight() - scrollY, + w, y + h - out->getBitmapHeight()); + h = out->getBitmapHeight() - y; } - // redraw (checking to see if pixmap has been allocated yet) - if (out->getPixmapWidth() > 0) { - XCopyArea(display, out->getPixmap(), drawAreaWin, drawAreaGC, - x, y, w, h, x - scrollX, y - scrollY); + // redraw + if (w >= 0 && h >= 0) { + out->redraw(x, y, drawAreaWin, drawAreaGC, x - scrollX, y - scrollY, w, h); } } @@ -1793,7 +1856,7 @@ void XPDFCore::updateScrollBars() { int n; int maxPos; - maxPos = out ? out->getPixmapWidth() : 1; + maxPos = out ? out->getBitmapWidth() : 1; if (maxPos < drawAreaWidth) { maxPos = drawAreaWidth; } @@ -1808,7 +1871,7 @@ void XPDFCore::updateScrollBars() { XtSetArg(args[n], XmNpageIncrement, drawAreaWidth); ++n; XtSetValues(hScrollBar, args, n); - maxPos = out ? out->getPixmapHeight() : 1; + maxPos = out ? out->getBitmapHeight() : 1; if (maxPos < drawAreaHeight) { maxPos = drawAreaHeight; } @@ -1856,7 +1919,7 @@ void XPDFCore::doErrorDialog(char *title, GString *msg) { GBool XPDFCore::doDialog(int type, GBool hasCancel, char *title, GString *msg) { - Widget dialog; + Widget dialog, scroll, text; XtAppContext appContext; Arg args[20]; int n; @@ -1868,11 +1931,31 @@ GBool XPDFCore::doDialog(int type, GBool hasCancel, XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; s1 = XmStringCreateLocalized(title); XtSetArg(args[n], XmNdialogTitle, s1); ++n; - s2 = XmStringCreateLocalized(msg->getCString()); - XtSetArg(args[n], XmNmessageString, s2); ++n; + s2 = NULL; // make gcc happy + if (msg->getLength() <= 80) { + s2 = XmStringCreateLocalized(msg->getCString()); + XtSetArg(args[n], XmNmessageString, s2); ++n; + } dialog = XmCreateMessageDialog(drawArea, "questionDialog", args, n); XmStringFree(s1); - XmStringFree(s2); + if (msg->getLength() <= 80) { + XmStringFree(s2); + } else { + n = 0; + XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n; + if (drawAreaWidth > 300) { + XtSetArg(args[n], XmNwidth, drawAreaWidth - 100); ++n; + } + scroll = XmCreateScrolledWindow(dialog, "scroll", args, n); + XtManageChild(scroll); + n = 0; + XtSetArg(args[n], XmNeditable, False); ++n; + XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); ++n; + XtSetArg(args[n], XmNvalue, msg->getCString()); ++n; + XtSetArg(args[n], XmNshadowThickness, 0); ++n; + text = XmCreateText(scroll, "text", args, n); + XtManageChild(text); + } XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); XtAddCallback(dialog, XmNokCallback, &dialogOkCbk, (XtPointer)this);