From 835e373b3eeaabcd0621ed6798ab500f37982fae Mon Sep 17 00:00:00 2001 From: Calvin Morrison Date: Wed, 5 Apr 2023 14:13:39 -0400 Subject: xpdf-no-select-disable --- xpdf-qt/XpdfWidget.cc | 2256 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2256 insertions(+) create mode 100644 xpdf-qt/XpdfWidget.cc (limited to 'xpdf-qt/XpdfWidget.cc') diff --git a/xpdf-qt/XpdfWidget.cc b/xpdf-qt/XpdfWidget.cc new file mode 100644 index 0000000..f5ad763 --- /dev/null +++ b/xpdf-qt/XpdfWidget.cc @@ -0,0 +1,2256 @@ +//======================================================================== +// +// XpdfWidget.cc +// +// Copyright 2009 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#ifdef _WIN32 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#if XPDFWIDGET_PRINTING +# include +# include +#endif +#include "gmem.h" +#include "gmempp.h" +#include "gfile.h" +#include "GString.h" +#include "GList.h" +#include "SplashBitmap.h" +#include "config.h" +#include "GlobalParams.h" +#include "PDFDoc.h" +#include "Object.h" +#include "SplashOutputDev.h" +#include "Outline.h" +#include "OptionalContent.h" +#include "Link.h" +#include "Annot.h" +#include "AcroForm.h" +#include "TextString.h" +#include "QtPDFCore.h" +#include "XpdfWidget.h" +#if XPDFWIDGET_PRINTING +# include "XpdfWidgetPrint.h" +#endif + +//------------------------------------------------------------------------ + +// Time (in ms) between incremental updates. +#define incrementalUpdateInterval 100 + +//------------------------------------------------------------------------ + +QMutex XpdfWidget::initMutex; + +//------------------------------------------------------------------------ + +XpdfWidget::XpdfWidget(const QColor &paperColor, const QColor &matteColor, + bool reverseVideo, QWidget *parentA): + QAbstractScrollArea(parentA) +{ + setup(paperColor, matteColor, reverseVideo); +} + +XpdfWidget::XpdfWidget(QWidget *parentA, const QColor &paperColor, + const QColor &matteColor, bool reverseVideo): + QAbstractScrollArea(parentA) +{ + setup(paperColor, matteColor, reverseVideo); +} + +void XpdfWidget::setup(const QColor &paperColor, const QColor &matteColor, + bool reverseVideo) { + SplashColor paperColor2, matteColor2; + + init(); + + paperColor2[0] = (Guchar)paperColor.red(); + paperColor2[1] = (Guchar)paperColor.green(); + paperColor2[2] = (Guchar)paperColor.blue(); + matteColor2[0] = (Guchar)matteColor.red(); + matteColor2[1] = (Guchar)matteColor.green(); + matteColor2[2] = (Guchar)matteColor.blue(); + try { + core = new QtPDFCore(viewport(), horizontalScrollBar(), + verticalScrollBar(), + paperColor2, matteColor2, (GBool)reverseVideo); + core->setUpdateCbk(updateCbk, this); + core->setMidPageChangedCbk(midPageChangedCbk, this); + core->setPreLoadCbk(preLoadCbk, this); + core->setPostLoadCbk(postLoadCbk, this); + core->setLinkCbk(linkCbk, this); + core->setSelectDoneCbk(selectDoneCbk, this); + core->setPaintDoneCbk(paintDoneCbk, this); + core->setTileDoneCbk(tileDoneCbk, this); + connect(this, SIGNAL(tileDone()), viewport(), SLOT(update())); + scaleFactor = core->getScaleFactor(); + } catch (GMemException e) { + //~ what should this do? + core = NULL; + } + +#if XPDFWIDGET_PRINTING + printerForDialog = NULL; + printDialog = NULL; + printHDPI = printVDPI = 0; +#endif + + keyPassthrough = false; + mousePassthrough = false; + lastMousePressX[0] = lastMousePressX[1] = lastMousePressX[2] = 0; + lastMousePressY[0] = lastMousePressY[1] = lastMousePressY[2] = 0; + lastMousePressTime[0] = lastMousePressTime[1] = lastMousePressTime[2] = 0; + lastMouseEventWasPress = false; + + viewport()->installEventFilter(this); + touchPanEnabled = false; + touchZoomEnabled = false; + pinchZoomStart = 100; + + tickTimer = new QTimer(this); + connect(tickTimer, SIGNAL(timeout()), this, SLOT(tick())); + tickTimer->start(incrementalUpdateInterval); +} + +XpdfWidget::~XpdfWidget() { +#if XPDFWIDGET_PRINTING + delete printerForDialog; + delete printDialog; +#endif + delete tickTimer; + delete core; +} + +void XpdfWidget::init(const QString &configFileName) { +#ifdef _WIN32 + char buf[512]; + GString *dir, *path; + char *configFileName2; + int n; +#endif + + initMutex.lock(); + if (!globalParams) { + try { +#ifdef _WIN32 + // get the executable directory + n = GetModuleFileNameA(NULL, buf, sizeof(buf)); + if (n <= 0 || n >= sizeof(buf)) { + // error or path too long for buffer - just use the current dir + buf[0] = '\0'; + } + dir = grabPath(buf); + + // load the config file + path = NULL; + if (configFileName.isEmpty()) { + path = appendToPath(dir->copy(), xpdfSysConfigFile); + configFileName2 = path->getCString(); + } else { + configFileName2 = (char *)configFileName.toLocal8Bit().constData(); + } + globalParams = new GlobalParams(configFileName2); + globalParams->setBaseDir(dir->getCString()); + globalParams->setErrQuiet(gTrue); + if (path) { + delete path; + } + + // set up the base fonts + appendToPath(dir, "t1fonts"); + globalParams->setupBaseFonts(dir->getCString()); + delete dir; +#else + globalParams = new GlobalParams( + (char *)configFileName.toLocal8Bit().constData()); + globalParams->setErrQuiet(gTrue); + globalParams->setupBaseFonts(NULL); +#endif + } catch (GMemException e) { + // there's no way to return an error code here + return; + } + } + initMutex.unlock(); +} + +void XpdfWidget::setConfig(const QString &command) { + GString *fileName; + + init(); + try { + fileName = new GString("(none)"); + globalParams->parseLine((char *)command.toLocal8Bit().constData(), + fileName, 1); + delete fileName; + } catch (GMemException e) { + } +} + +void XpdfWidget::enableHyperlinks(bool on) { + try { + core->enableHyperlinks((GBool)on); + } catch (GMemException e) { + } +} + +void XpdfWidget::enableExternalHyperlinks(bool on) { + try { + core->enableExternalHyperlinks((GBool)on); + } catch (GMemException e) { + } +} + +void XpdfWidget::enableSelect(bool on) { + try { + core->enableSelect((GBool)on); + } catch (GMemException e) { + } +} + +void XpdfWidget::enablePan(bool on) { + try { + core->enablePan((GBool)on); + } catch (GMemException e) { + } +} + +void XpdfWidget::enableTouchPan(bool on) { + touchPanEnabled = on; + if (touchPanEnabled) { + viewport()->grabGesture(Qt::PanGesture); + } else { + viewport()->ungrabGesture(Qt::PanGesture); + } +} + +void XpdfWidget::enableTouchZoom(bool on) { + touchZoomEnabled = on; + if (touchZoomEnabled) { + viewport()->grabGesture(Qt::PinchGesture); + } else { + viewport()->ungrabGesture(Qt::PinchGesture); + } +} + +void XpdfWidget::showPasswordDialog(bool showDlg) { + try { + core->setShowPasswordDialog((GBool)showDlg); + } catch (GMemException e) { + } +} + +void XpdfWidget::setMatteColor(const QColor &matteColor) { + SplashColor matteColor2; + + matteColor2[0] = (Guchar)matteColor.red(); + matteColor2[1] = (Guchar)matteColor.green(); + matteColor2[2] = (Guchar)matteColor.blue(); + try { + core->setMatteColor(matteColor2); + } catch (GMemException e) { + } +} + +void XpdfWidget::setReverseVideo(bool reverse) { + try { + core->setReverseVideo((GBool)reverse); + } catch (GMemException e) { + } +} + +void XpdfWidget::setCursor(const QCursor &cursor) { + core->doSetCursor(cursor); +} + +void XpdfWidget::unsetCursor() { + core->doUnsetCursor(); +} + +XpdfWidget::ErrorCode XpdfWidget::loadFile(const QString &fileName, + const QString &password) { + GString *passwordStr; +#ifdef _WIN32 + wchar_t *fileNameStr; + int n, i; +#else + GString *fileNameStr; +#endif + int err; + + try { + if (password.isEmpty()) { + passwordStr = NULL; + } else { + passwordStr = new GString(password.toLocal8Bit().constData()); + } +#ifdef _WIN32 + // this should use QString::toWCharArray(), but Qt builds their + // library with /Zc:wchar_t-, which confuses things + n = fileName.length(); + fileNameStr = (wchar_t *)gmallocn(n, sizeof(wchar_t)); + for (i = 0; i < n; ++i) { + fileNameStr[i] = (wchar_t)fileName[i].unicode(); + } + err = core->loadFile(fileNameStr, n, passwordStr, passwordStr); + gfree(fileNameStr); +#else + fileNameStr = new GString(fileName.toLocal8Bit().constData()); + err = core->loadFile(fileNameStr, passwordStr, passwordStr); + delete fileNameStr; +#endif + if (passwordStr) { + delete passwordStr; + } + if (!err) { + core->displayPage(1, gTrue, gFalse); + } + return (ErrorCode)err; + } catch (GMemException e) { + return pdfErrOutOfMemory; + } +} + +XpdfWidget::ErrorCode XpdfWidget::loadMem(const char *buffer, + unsigned int bufferLength, + const QString &password) { + Object obj; + MemStream *stream; + GString *passwordStr; + int err; + + try { + obj.initNull(); + stream = new MemStream((char *)buffer, 0, bufferLength, &obj); + if (password.isEmpty()) { + passwordStr = NULL; + } else { + passwordStr = new GString(password.toLocal8Bit().constData()); + } + err = core->loadFile(stream, passwordStr, passwordStr); + if (passwordStr) { + delete passwordStr; + } + if (!err) { + core->displayPage(1, gTrue, gFalse); + } + return (ErrorCode)err; + } catch (GMemException e) { + return pdfErrOutOfMemory; + } +} + +XpdfWidget::ErrorCode XpdfWidget::readDoc(XpdfDocHandle *docPtr, + const QString &fileName, + const QString &password) { + GString *passwordStr; +#ifdef _WIN32 + wchar_t *fileNameStr; + int n, i; +#else + GString *fileNameStr; +#endif + PDFDoc *doc; + ErrorCode err; + + *docPtr = NULL; + try { + if (password.isEmpty()) { + passwordStr = NULL; + } else { + passwordStr = new GString(password.toLocal8Bit().constData()); + } +#ifdef _WIN32 + // this should use QString::toWCharArray(), but Qt builds their + // library with /Zc:wchar_t-, which confuses things + n = fileName.length(); + fileNameStr = (wchar_t *)gmallocn(n, sizeof(wchar_t)); + for (i = 0; i < n; ++i) { + fileNameStr[i] = (wchar_t)fileName[i].unicode(); + } + doc = new PDFDoc(fileNameStr, n, passwordStr, passwordStr, core); + gfree(fileNameStr); +#else + fileNameStr = new GString(fileName.toLocal8Bit().constData()); + doc = new PDFDoc(fileNameStr, passwordStr, passwordStr, core); +#endif + if (passwordStr) { + delete passwordStr; + } + if (doc->isOk()) { + *docPtr = doc; + err = pdfOk; + } else { + err = (ErrorCode)doc->getErrorCode(); + delete doc; + } + } catch (GMemException e) { + err = pdfErrOutOfMemory; + } + return err; +} + +XpdfWidget::ErrorCode XpdfWidget::loadDoc(XpdfDocHandle doc) { + if (!doc) { + return pdfErrNoHandle; + } + core->loadDoc((PDFDoc *)doc); + core->displayPage(1, gTrue, gFalse, gTrue); + return pdfOk; +} + +void XpdfWidget::freeDoc(XpdfDocHandle doc) { + if (!doc) { + return; + } + delete (PDFDoc *)doc; +} + +XpdfWidget::ErrorCode XpdfWidget::reload() { + try { + return (ErrorCode)core->reload(); + } catch (GMemException e) { + return pdfErrOutOfMemory; + } +} + +void XpdfWidget::closeFile() { + try { + core->clear(); + } catch (GMemException e) { + } +} + +XpdfWidget::ErrorCode XpdfWidget::saveAs(const QString &fileName) { + GString *s; + + try { + if (!core->getDoc()) { + return pdfErrNoHandle; + } + s = new GString(fileName.toLocal8Bit().constData()); + if (!core->getDoc()->saveAs(s)) { + delete s; + return pdfErrOpenFile; + } + delete s; + return pdfOk; + } catch (GMemException e) { + return pdfErrOutOfMemory; + } +} + +bool XpdfWidget::hasOpenDocument() const { + try { + return core->getDoc() != NULL; + } catch (GMemException e) { + return false; + } +} + +QString XpdfWidget::getFileName() const { + try { + if (!core->getDoc() || !core->getDoc()->getFileName()) { + return QString(); + } +#ifdef _WIN32 + return QString::fromWCharArray(core->getDoc()->getFileNameU()); +#else + return QString::fromLocal8Bit(core->getDoc()->getFileName()->getCString()); +#endif + } catch (GMemException e) { + return QString(); + } +} + +int XpdfWidget::getNumPages() const { + try { + if (!core->getDoc()) { + return -1; + } + return core->getDoc()->getNumPages(); + } catch (GMemException e) { + return -1; + } +} + +int XpdfWidget::getCurrentPage() const { + try { + return core->getPageNum(); + } catch (GMemException e) { + return -1; + } +} + +int XpdfWidget::getMidPage() const { + try { + return core->getMidPageNum(); + } catch (GMemException e) { + return -1; + } +} + +void XpdfWidget::gotoPage(int pageNum) { + try { + core->displayPage(pageNum, gTrue, gFalse); + } catch (GMemException e) { + } +} + +void XpdfWidget::gotoFirstPage() { + try { + core->displayPage(1, gTrue, gFalse); + } catch (GMemException e) { + } +} + +void XpdfWidget::gotoLastPage() { + try { + if (!core->getDoc()) { + return; + } + core->displayPage(core->getDoc()->getNumPages(), gTrue, gFalse); + } catch (GMemException e) { + } +} + +void XpdfWidget::gotoNextPage(bool scrollToTop) { + try { + core->gotoNextPage(1, scrollToTop); + } catch (GMemException e) { + } +} + +void XpdfWidget::gotoPreviousPage(bool scrollToTop) { + try { + core->gotoPrevPage(1, scrollToTop, gFalse); + } catch (GMemException e) { + } +} + +bool XpdfWidget::gotoNamedDestination(const QString &dest) { + GString *destStr; + + try { + destStr = new GString(dest.toLocal8Bit().constData()); + if (!core->gotoNamedDestination(destStr)) { + delete destStr; + return false; + } + delete destStr; + return true; + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::goForward() { + try { + core->goForward(); + } catch (GMemException e) { + } +} + +void XpdfWidget::goBackward() { + try { + core->goBackward(); + } catch (GMemException e) { + } +} + +void XpdfWidget::scrollPageUp() { + try { + core->scrollPageUp(); + } catch (GMemException e) { + } +} + +void XpdfWidget::scrollPageDown() { + try { + core->scrollPageDown(); + } catch (GMemException e) { + } +} + +void XpdfWidget::scrollTo(int xx, int yy) { + try { + core->scrollTo(xx, yy); + } catch (GMemException e) { + } +} + +void XpdfWidget::scrollBy(int dx, int dy) { + try { + core->scrollTo(core->getScrollX() + dx, core->getScrollY()+ dy); + } catch (GMemException e) { + } +} + +int XpdfWidget::getScrollX() const { + try { + return core->getScrollX(); + } catch (GMemException e) { + return 0; + } +} + +int XpdfWidget::getScrollY() const { + try { + return core->getScrollY(); + } catch (GMemException e) { + return 0; + } +} + +void XpdfWidget::setZoom(double zoom) { + try { + core->setZoom(zoom); + } catch (GMemException e) { + } +} + +double XpdfWidget::getZoom() const { + try { + return core->getZoom(); + } catch (GMemException e) { + return 0; + } +} + +double XpdfWidget::getZoomPercent(int page) const { + double zoom; + + try { + if (!core->getDoc() || + page < 1 || page > core->getDoc()->getNumPages()) { + return 0; + } + zoom = core->getZoom(); + if (zoom <= 0) { + zoom = 100 * core->getZoomDPI(page) / 72; + } + return zoom; + } catch (GMemException e) { + return 0; + } +} + +void XpdfWidget::zoomToRect(int page, double xMin, double yMin, + double xMax, double yMax) { + try { + core->zoomToRect(page, xMin, yMin, xMax, yMax); + } catch (GMemException e) { + } +} + +void XpdfWidget::zoomCentered(double zoom) { + try { + core->zoomCentered(zoom); + } catch (GMemException e) { + } +} + +void XpdfWidget::zoomToCurrentWidth() { + try { + core->zoomToCurrentWidth(); + } catch (GMemException e) { + } +} + +void XpdfWidget::setRotate(int rotate) { + if (!(rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270)) { + return; + } + try { + core->setRotate(rotate); + } catch (GMemException e) { + } +} + +int XpdfWidget::getRotate() const { + try { + return core->getRotate(); + } catch (GMemException e) { + return 0; + } +} + +void XpdfWidget::setContinuousMode(bool continuous) { + try { + core->setDisplayMode(continuous ? displayContinuous + : displaySingle); + } catch (GMemException e) { + } +} + +bool XpdfWidget::getContinuousMode() const { + try { + return core->getDisplayMode() == displayContinuous; + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::setDisplayMode(XpdfWidget::DisplayMode mode) { + try { + core->setDisplayMode((::DisplayMode)mode); + } catch (GMemException e) { + } +} + +XpdfWidget::DisplayMode XpdfWidget::getDisplayMode() { + try { + return (XpdfWidget::DisplayMode)core->getDisplayMode(); + } catch (GMemException e) { + return pdfDisplaySingle; + } +} + +bool XpdfWidget::mouseOverLink() { + QPoint pt; + int page; + double xx, yy; + + try { + if (core->getHyperlinksEnabled()) { + return core->getLinkAction() != NULL; + } else { + pt = mapFromGlobal(QCursor::pos()); + if (!convertWindowToPDFCoords(pt.x(), pt.y(), &page, &xx, &yy)) { + return false; + } + return core->findLink(page, xx, yy) != NULL; + } + } catch (GMemException e) { + return false; + } +} + +bool XpdfWidget::onLink(int page, double xx, double yy) { + try { + if (!core->getDoc()) { + return false; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return false; + } + return core->findLink(page, xx, yy) != NULL; + } catch (GMemException e) { + return false; + } +} + +QString XpdfWidget::getLinkInfo(int page, double xx, double yy) { + LinkAction *action; + + try { + if (!core->getDoc()) { + return QString(); + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return QString(); + } + if (!(action = core->findLink(page, xx, yy))) { + return QString(); + } + return core->getLinkInfo(action); + } catch (GMemException e) { + return QString(); + } +} + +QString XpdfWidget::getMouseLinkInfo() { + try { + if (!core->getLinkAction()) { + return QString(); + } + return core->getLinkInfo(core->getLinkAction()); + } catch (GMemException e) { + return QString(); + } +} + +bool XpdfWidget::gotoLinkAt(int page, double xx, double yy) { + LinkAction *action; + + try { + if (!core->getDoc()) { + return false; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return false; + } + if ((action = core->findLink(page, xx, yy))) { + if (!core->doAction(action)) { + return false; + } + } + } catch (GMemException e) { + } + return true; +} + +bool XpdfWidget::getLinkTarget(int page, double xx, double yy, + QString &targetFileName, int &targetPage, + QString &targetDest) { + LinkAction *action; + LinkDest *dest; + GString *fileName, *namedDest, *path; + Ref pageRef; + char *s; + + try { + if (!core->getDoc()) { + return false; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return false; + } + if (!(action = core->findLink(page, xx, yy))) { + return false; + } + switch (action->getKind()) { + case actionGoTo: + if (!core->getDoc()->getFileName()) { + return false; + } + targetFileName = core->getDoc()->getFileName()->getCString(); + if ((dest = ((LinkGoTo *)action)->getDest())) { + if (dest->isPageRef()) { + pageRef = dest->getPageRef(); + targetPage = core->getDoc()->findPage(pageRef.num, pageRef.gen); + } else { + targetPage = dest->getPageNum(); + } + targetDest = ""; + } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) { + targetDest = namedDest->getCString(); + targetPage = 1; + } + return true; + case actionGoToR: + s = ((LinkGoToR *)action)->getFileName()->getCString(); + if (isAbsolutePath(s)) { + targetFileName = s; + } else { + if (!core->getDoc()->getFileName()) { + return false; + } + path = appendToPath( + grabPath(core->getDoc()->getFileName()->getCString()), s); + targetFileName = path->getCString(); + delete path; + } + if ((dest = ((LinkGoToR *)action)->getDest())) { + if (dest->isPageRef()) { + return false; + } + targetPage = dest->getPageNum(); + targetDest = ""; + } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) { + targetDest = namedDest->getCString(); + targetPage = 1; + } + return true; + case actionLaunch: + fileName = ((LinkLaunch *)action)->getFileName(); + s = fileName->getCString(); + if (!(fileName->getLength() >= 4 && + (!strcmp(s + fileName->getLength() - 4, ".pdf") || + !strcmp(s + fileName->getLength() - 4, ".PDF")))) { + return false; + } + if (isAbsolutePath(s)) { + targetFileName = s; + } else { + if (!core->getDoc()->getFileName()) { + return false; + } + path = appendToPath( + grabPath(core->getDoc()->getFileName()->getCString()), s); + targetFileName = path->getCString(); + delete path; + } + targetPage = 1; + targetDest = ""; + return true; + default: + return false; + } + } catch (GMemException e) { + return false; + } +} + +XpdfAnnotHandle XpdfWidget::onAnnot(int page, double xx, double yy) { + try { + if (!core->getDoc()) { + return NULL; + } + return (XpdfAnnotHandle)core->findAnnot(page, xx, yy); + } catch (GMemException e) { + return NULL; + } +} + +QString XpdfWidget::getAnnotType(XpdfAnnotHandle annot) { + try { + return ((Annot *)annot)->getType()->getCString(); + } catch (GMemException e) { + return QString(); + } +} + +QString XpdfWidget::getAnnotContent(XpdfAnnotHandle annot) { + QString s; + Object annotObj, contentsObj; + TextString *ts; + Unicode *u; + int i; + + try { + if (((Annot *)annot)->getObject(&annotObj)->isDict()) { + if (annotObj.dictLookup("Contents", &contentsObj)->isString()) { + ts = new TextString(contentsObj.getString()); + u = ts->getUnicode(); + for (i = 0; i < ts->getLength(); ++i) { + s.append((QChar)u[i]); + } + } + contentsObj.free(); + } + annotObj.free(); + return s; + } catch (GMemException e) { + return QString(); + } +} + +XpdfFormFieldHandle XpdfWidget::onFormField(int page, double xx, double yy) { + try { + if (!core->getDoc()) { + return NULL; + } + return (XpdfFormFieldHandle)core->findFormField(page, xx, yy); + } catch (GMemException e) { + return NULL; + } +} + +QString XpdfWidget::getFormFieldType(XpdfFormFieldHandle field) { + try { + return ((AcroFormField *)field)->getType(); + } catch (GMemException e) { + return QString(); + } +} + +QString XpdfWidget::getFormFieldName(XpdfFormFieldHandle field) { + Unicode *u; + QString s; + int length, i; + + try { + u = ((AcroFormField *)field)->getName(&length); + for (i = 0; i < length; ++i) { + s.append((QChar)u[i]); + } + gfree(u); + return s; + } catch (GMemException e) { + return QString(); + } +} + +QString XpdfWidget::getFormFieldValue(XpdfFormFieldHandle field) { + Unicode *u; + QString s; + int length, i; + + try { + u = ((AcroFormField *)field)->getValue(&length); + for (i = 0; i < length; ++i) { + s.append((QChar)u[i]); + } + gfree(u); + return s; + } catch (GMemException e) { + return QString(); + } +} + +void XpdfWidget::getFormFieldBBox(XpdfFormFieldHandle field, int *pageNum, + double *xMin, double *yMin, + double *xMax, double *yMax) { + try { + *pageNum = ((AcroFormField *)field)->getPageNum(); + ((AcroFormField *)field)->getBBox(xMin, yMin, xMax, yMax); + } catch (GMemException e) { + } +} + +bool XpdfWidget::convertWindowToPDFCoords(int winX, int winY, + int *page, + double *pdfX, double *pdfY) { + try { + return core->cvtWindowToUser(winX, winY, page, pdfX, pdfY); + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::convertPDFToWindowCoords(int page, double pdfX, double pdfY, + int *winX, int *winY) { + try { + core->cvtUserToWindow(page, pdfX, pdfY, winX, winY); + } catch (GMemException e) { + } +} + +void XpdfWidget::enableRedraw(bool enable) { + setUpdatesEnabled(enable); +} + +void XpdfWidget::getPageBox(int page, const QString &box, + double *xMin, double *yMin, + double *xMax, double *yMax) const { + PDFRectangle *r; + + *xMin = *yMin = *xMax = *yMax = 0; + try { + if (!core->getDoc()) { + return; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return; + } + if (!box.compare("media", Qt::CaseInsensitive)) { + r = core->getDoc()->getCatalog()->getPage(page)->getMediaBox(); + } else if (!box.compare("crop", Qt::CaseInsensitive)) { + r = core->getDoc()->getCatalog()->getPage(page)->getCropBox(); + } else if (!box.compare("bleed", Qt::CaseInsensitive)) { + r = core->getDoc()->getCatalog()->getPage(page)->getBleedBox(); + } else if (!box.compare("trim", Qt::CaseInsensitive)) { + r = core->getDoc()->getCatalog()->getPage(page)->getTrimBox(); + } else if (!box.compare("art", Qt::CaseInsensitive)) { + r = core->getDoc()->getCatalog()->getPage(page)->getArtBox(); + } else { + return; + } + *xMin = r->x1; + *yMin = r->y1; + *xMax = r->x2; + *yMax = r->y2; + } catch (GMemException e) { + } +} + +double XpdfWidget::getPageWidth(int page) const { + try { + if (!core->getDoc()) { + return 0; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return 0; + } + return core->getDoc()->getPageCropWidth(page); + } catch (GMemException e) { + return 0; + } +} + +double XpdfWidget::getPageHeight(int page) const { + try { + if (!core->getDoc()) { + return 0; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return 0; + } + return core->getDoc()->getPageCropHeight(page); + } catch (GMemException e) { + return 0; + } +} + +int XpdfWidget::getPageRotation(int page) const { + try { + if (!core->getDoc()) { + return 0; + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return 0; + } + return core->getDoc()->getCatalog()->getPage(page)->getRotate(); + } catch (GMemException e) { + return 0; + } +} + +bool XpdfWidget::hasSelection() { + try { + return (bool)core->hasSelection(); + } catch (GMemException e) { + return false; + } +} + +bool XpdfWidget::getCurrentSelection(int *page, double *x0, double *y0, + double *x1, double *y1) const { + try { + return (bool)core->getSelection(page, x0, y0, x1, y1); + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::setCurrentSelection(int page, double x0, double y0, + double x1, double y1) { + int ulx, uly, lrx, lry, t; + + try { + core->cvtUserToDev(page, x0, y0, &ulx, &uly); + core->cvtUserToDev(page, x1, y1, &lrx, &lry); + if (ulx > lrx) { + t = ulx; ulx = lrx; lrx = t; + } + if (uly > lry) { + t = uly; uly = lry; lry = t; + } + core->setSelection(page, ulx, uly, lrx, lry); + } catch (GMemException e) { + } +} + +void XpdfWidget::clearSelection() { + try { + core->clearSelection(); + } catch (GMemException e) { + } +} + +bool XpdfWidget::isBlockSelectMode() { + try { + return core->getSelectMode() == selectModeBlock; + } catch (GMemException e) { + return false; + } +} + +bool XpdfWidget::isLinearSelectMode() { + try { + return core->getSelectMode() == selectModeLinear; + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::setBlockSelectMode() { + try { + core->setSelectMode(selectModeBlock); + } catch (GMemException e) { + } +} + +void XpdfWidget::setLinearSelectMode() { + try { + core->setSelectMode(selectModeLinear); + } catch (GMemException e) { + } +} + +void XpdfWidget::setSelectionColor(const QColor &selectionColor) { + SplashColor col; + + try { + col[0] = (Guchar)selectionColor.red(); + col[1] = (Guchar)selectionColor.green(); + col[2] = (Guchar)selectionColor.blue(); + core->setSelectionColor(col); + } catch (GMemException e) { + } +} + + +void XpdfWidget::forceRedraw() { + try { + core->forceRedraw(); + } catch (GMemException e) { + } +} + +#if XPDFWIDGET_PRINTING + +bool XpdfWidget::okToPrint() const { + try { + if (!core->getDoc()) { + return false; + } + return (bool)core->getDoc()->okToPrint(); + } catch (GMemException e) { + return false; + } +} + +XpdfWidget::ErrorCode XpdfWidget::print(bool showDialog) { + GString *defaultPrinter; + ErrorCode err; + + try { + if (!core->getDoc()) { + return pdfErrNoHandle; + } + if (!printerForDialog) { + printerForDialog = new QPrinter(QPrinter::HighResolution); + if ((defaultPrinter = globalParams->getDefaultPrinter())) { + printerForDialog->setPrinterName( + QString::fromUtf8(defaultPrinter->getCString())); + delete defaultPrinter; + } + } + printerForDialog->setFromTo(1, core->getDoc()->getNumPages()); + if (showDialog) { + if (!printDialog) { + printDialog = new QPrintDialog(printerForDialog, this); + } + if (printDialog->exec() != QDialog::Accepted) { + return pdfErrPrinting; + } + } + printCanceled = false; + err = printPDF(core->getDoc(), printerForDialog, + printHDPI, printVDPI, this); + return err; + } catch (GMemException e) { + return pdfErrOutOfMemory; + } +} + +XpdfWidget::ErrorCode XpdfWidget::print(QPrinter *prt) { + try { + if (!core->getDoc()) { + return pdfErrNoHandle; + } + printCanceled = false; + return printPDF(core->getDoc(), prt, printHDPI, printVDPI, this); + } catch (GMemException e) { + return pdfErrOutOfMemory; + } +} + +void XpdfWidget::updatePrintStatus(int nextPage, int firstPage, int lastPage) { + emit printStatus(nextPage, firstPage, lastPage); +} + +void XpdfWidget::setPrintDPI(int hDPI, int vDPI) { + printHDPI = hDPI; + printVDPI = vDPI; +} + +#endif // XPDFWIDGET_PRINTING + +QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) { + try { + PDFDoc *doc = core->getDoc(); + if (!doc) { + return QImage(); + } + if (page < 1 || page > doc->getNumPages()) { + return QImage(); + } + if (transparent) { + SplashColor paperColor; + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused + SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse, + paperColor); + out->setNoComposite(gTrue); + out->startDoc(doc->getXRef()); + doc->displayPage(out, page, dpi, dpi, core->getRotate(), + gFalse, gTrue, gFalse); + SplashBitmap *bitmap = out->getBitmap(); + QImage img(bitmap->getWidth(), bitmap->getHeight(), + QImage::Format_ARGB32); + Guchar *pix = bitmap->getDataPtr(); + Guchar *alpha = bitmap->getAlphaPtr(); + Guint *argb = (Guint *)img.bits(); + for (int y = 0; y < bitmap->getHeight(); ++y) { + for (int x = 0; x < bitmap->getWidth(); ++x) { + *argb = (*alpha << 24) | (pix[0] << 16) | (pix[1] << 8) | pix[2]; + pix += 3; + ++alpha; + ++argb; + } + } + delete out; + return img; + } else { + SplashColor paperColor; + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse, + paperColor); + out->startDoc(doc->getXRef()); + doc->displayPage(out, page, dpi, dpi, core->getRotate(), + gFalse, gTrue, gFalse); + SplashBitmap *bitmap = out->getBitmap(); + QImage *img = new QImage((const uchar *)bitmap->getDataPtr(), + bitmap->getWidth(), bitmap->getHeight(), + QImage::Format_RGB888); + // force a copy + QImage img2(img->copy()); + delete img; + delete out; + return img2; + } + } catch (GMemException e) { + return QImage(); + } +} + +QImage XpdfWidget::convertRegionToImage(int page, double x0, double y0, + double x1, double y1, double dpi, + bool transparent) { + try { + PDFDoc *doc = core->getDoc(); + if (!doc) { + return QImage(); + } + if (page < 1 || page > doc->getNumPages()) { + return QImage(); + } + + if (x0 > x1) { + double t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + double t = y0; y0 = y1; y1 = t; + } + PDFRectangle *box = doc->getCatalog()->getPage(page)->getCropBox(); + int rot = doc->getPageRotate(page); + double k = dpi / 72.0; + int sliceX, sliceY, sliceW, sliceH; + if (rot == 90) { + sliceX = (int)(k * (y0 - box->y1)); + sliceY = (int)(k * (x0 - box->x1)); + sliceW = (int)(k * (y1 - y0)); + sliceH = (int)(k * (x1 - x0)); + } else if (rot == 180) { + sliceX = (int)(k * (box->x2 - x1)); + sliceY = (int)(k * (y0 - box->y1)); + sliceW = (int)(k * (x1 - x0)); + sliceH = (int)(k * (y1 - y0)); + } else if (rot == 270) { + sliceX = (int)(k * (box->y2 - y1)); + sliceY = (int)(k * (box->x2 - x1)); + sliceW = (int)(k * (y1 - y0)); + sliceH = (int)(k * (x1 - x0)); + } else { + sliceX = (int)(k * (x0 - box->x1)); + sliceY = (int)(k * (box->y2 - y1)); + sliceW = (int)(k * (x1 - x0)); + sliceH = (int)(k * (y1 - y0)); + } + + if (transparent) { + SplashColor paperColor; + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused + SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse, + paperColor); + out->setNoComposite(gTrue); + out->startDoc(doc->getXRef()); + doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(), + gFalse, gTrue, gFalse, + sliceX, sliceY, sliceW, sliceH); + SplashBitmap *bitmap = out->getBitmap(); + QImage img(bitmap->getWidth(), bitmap->getHeight(), + QImage::Format_ARGB32); + Guchar *pix = bitmap->getDataPtr(); + Guchar *alpha = bitmap->getAlphaPtr(); + Guint *argb = (Guint *)img.bits(); + for (int y = 0; y < bitmap->getHeight(); ++y) { + for (int x = 0; x < bitmap->getWidth(); ++x) { + *argb = (*alpha << 24) | (pix[0] << 16) | (pix[1] << 8) | pix[2]; + pix += 3; + ++alpha; + ++argb; + } + } + delete out; + return img; + } else { + SplashColor paperColor; + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse, + paperColor); + out->startDoc(doc->getXRef()); + doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(), + gFalse, gTrue, gFalse, + sliceX, sliceY, sliceW, sliceH); + SplashBitmap *bitmap = out->getBitmap(); + QImage *img = new QImage((const uchar *)bitmap->getDataPtr(), + bitmap->getWidth(), bitmap->getHeight(), + QImage::Format_RGB888); + // force a copy + QImage img2(img->copy()); + delete img; + delete out; + return img2; + } + } catch (GMemException e) { + return QImage(); + } +} + +QImage XpdfWidget::getThumbnail(int page) { + Object thumbObj, decodeObj, colorSpaceObj, obj; + Dict *thumbDict; + GfxColorSpace *colorSpace; + GfxImageColorMap *colorMap; + ImageStream *imgStream; + Guchar *line, *rgb; + int w, h, bpc, yy; + + try { + if (!core->getDoc()) { + return QImage(); + } + if (page < 1 || page > core->getDoc()->getNumPages()) { + return QImage(); + } + + // get the thumbnail image object + if (!core->getDoc()->getCatalog()->getPage(page) + ->getThumbnail(&thumbObj)->isStream()) { + thumbObj.free(); + return QImage(); + } + + // get the image parameters + thumbDict = thumbObj.streamGetDict(); + if (!thumbDict->lookup("Width", &obj)->isInt()) { + obj.free(); + thumbObj.free(); + return QImage(); + } + w = obj.getInt(); + obj.free(); + if (!thumbDict->lookup("Height", &obj)->isInt()) { + obj.free(); + thumbObj.free(); + return QImage(); + } + h = obj.getInt(); + obj.free(); + if (!thumbDict->lookup("BitsPerComponent", &obj)->isInt()) { + obj.free(); + thumbObj.free(); + return QImage(); + } + bpc = obj.getInt(); + obj.free(); + + // create the color space and color map + thumbDict->lookup("Decode", &decodeObj); + thumbDict->lookup("ColorSpace", &colorSpaceObj); + colorSpace = GfxColorSpace::parse(&colorSpaceObj + ); + colorMap = new GfxImageColorMap(bpc, &decodeObj, colorSpace); + colorSpaceObj.free(); + decodeObj.free(); + imgStream = new ImageStream(thumbObj.getStream(), + w, colorSpace->getNComps(), bpc); + + // create the QImage, and read the image data + QImage img(w, h, QImage::Format_RGB888); + rgb = (Guchar *)gmallocn(w, 3); + imgStream->reset(); + for (yy = 0; yy < h; ++yy) { + line = imgStream->getLine(); + colorMap->getRGBByteLine(line, rgb, w, gfxRenderingIntentPerceptual); + memcpy(img.scanLine(yy), rgb, 3 * w); + } + gfree(rgb); + + delete colorMap; + delete imgStream; + thumbObj.free(); + + return img; + } catch (GMemException e) { + return QImage(); + } +} + +bool XpdfWidget::okToExtractText() const { + try { + if (!core->getDoc()) { + return false; + } + return (bool)core->getDoc()->okToCopy(); + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::setTextEncoding(const QString &encodingName) { + init(); + try { + globalParams->setTextEncoding((char *)encodingName.toLatin1().constData()); + } catch (GMemException e) { + } +} + +QString XpdfWidget::extractText(int page, double x0, double y0, + double x1, double y1) { + GString *s, *enc; + GBool twoByte; + QString ret; + int i; + + try { + if (!core->getDoc()) { + return QString(); + } + if (!(s = core->extractText(page, x0, y0, x1, y1))) { + return QString(); + } + enc = globalParams->getTextEncodingName(); + twoByte = !enc->cmp("UCS-2"); + delete enc; + if (twoByte) { + for (i = 0; i+1 < s->getLength(); i += 2) { + ret.append((QChar)(((s->getChar(i) & 0xff) << 8) + + (s->getChar(i+1) & 0xff))); + } + } else { + ret.append(s->getCString()); + } + delete s; + return ret; + } catch (GMemException e) { + return QString(); + } +} + +QString XpdfWidget::getSelectedText() { + try { + return core->getSelectedTextQString(); + } catch (GMemException e) { + return ""; + } +} + +void XpdfWidget::copySelection() { + try { + core->copySelection(gTrue); + } catch (GMemException e) { + } +} + +bool XpdfWidget::find(const QString &text, int flags) { + Unicode *u; + bool ret; + int len, i; + + try { + if (!core->getDoc()) { + return false; + } + len = text.length(); + u = (Unicode *)gmallocn(len, sizeof(Unicode)); + for (i = 0; i < len; ++i) { + u[i] = (Unicode)text[i].unicode(); + } + ret = (bool)core->findU(u, len, + (flags & findCaseSensitive) ? gTrue : gFalse, + (flags & findNext) ? gTrue : gFalse, + (flags & findBackward) ? gTrue : gFalse, + (flags & findWholeWord) ? gTrue : gFalse, + (flags & findOnePageOnly) ? gTrue : gFalse); + gfree(u); + return ret; + } catch (GMemException e) { + return false; + } +} + +QVector XpdfWidget::findAll(const QString &text, int firstPage, + int lastPage, int flags) { + QVector v; + try { + if (!core->getDoc()) { + return v; + } + int len = text.length(); + Unicode *u = (Unicode *)gmallocn(len, sizeof(Unicode)); + for (int i = 0; i < len; ++i) { + u[i] = (Unicode)text[i].unicode(); + } + GList *results = core->findAll(u, len, + (flags & findCaseSensitive) ? gTrue : gFalse, + (flags & findWholeWord) ? gTrue : gFalse, + firstPage, lastPage); + gfree(u); + for (int i = 0; i < results->getLength(); ++i) { + FindResult *result = (FindResult *)results->get(i); + v.append(XpdfFindResult(result->page, result->xMin, result->yMin, + result->xMax, result->yMax)); + } + deleteGList(results, FindResult); + return v; + } catch (GMemException e) { + return v; + } +} + +bool XpdfWidget::hasPageLabels() { + try { + if (!core->getDoc()) { + return false; + } + return core->getDoc()->getCatalog()->hasPageLabels(); + } catch (GMemException e) { + return false; + } +} + +QString XpdfWidget::getPageLabelFromPageNum(int pageNum) { + try { + if (!core->getDoc()) { + return QString(); + } + TextString *ts = core->getDoc()->getCatalog()->getPageLabel(pageNum); + if (!ts) { + return QString(); + } + QString qs; + Unicode *u = ts->getUnicode(); + for (int i = 0; i < ts->getLength(); ++i) { + qs.append((QChar)u[i]); + } + delete ts; + return qs; + } catch (GMemException e) { + return QString(); + } +} + +int XpdfWidget::getPageNumFromPageLabel(QString pageLabel) { + try { + if (!core->getDoc()) { + return -1; + } + TextString *ts = new TextString(); + for (int i = 0; i < pageLabel.size(); ++i) { + ts->append((Unicode)pageLabel.at(i).unicode()); + } + int pg = core->getDoc()->getCatalog()->getPageNumFromPageLabel(ts); + delete ts; + return pg; + } catch (GMemException e) { + return -1; + } +} + +int XpdfWidget::getOutlineNumChildren(XpdfOutlineHandle outline) { + GList *items; + + try { + if (!core->getDoc()) { + return 0; + } + if (outline) { + ((OutlineItem *)outline)->open(); + items = ((OutlineItem *)outline)->getKids(); + } else { + items = core->getDoc()->getOutline()->getItems(); + } + if (!items) { + return 0; + } + return items->getLength(); + } catch (GMemException e) { + return 0; + } +} + +XpdfOutlineHandle XpdfWidget::getOutlineChild(XpdfOutlineHandle outline, + int idx) { + GList *items; + + try { + if (!core->getDoc()) { + return NULL; + } + if (outline) { + ((OutlineItem *)outline)->open(); + items = ((OutlineItem *)outline)->getKids(); + } else { + items = core->getDoc()->getOutline()->getItems(); + } + if (!items) { + return NULL; + } + if (idx < 0 || idx >= items->getLength()) { + return NULL; + } + return (XpdfOutlineHandle)items->get(idx); + } catch (GMemException e) { + return NULL; + } +} + +XpdfOutlineHandle XpdfWidget::getOutlineParent(XpdfOutlineHandle outline) { + if (!outline) { + return NULL; + } + return (XpdfOutlineHandle)((OutlineItem *)outline)->getParent(); +} + +QString XpdfWidget::getOutlineTitle(XpdfOutlineHandle outline) { + Unicode *title; + QString s; + int titleLen, i; + + if (!outline) { + return QString(); + } + try { + title = ((OutlineItem *)outline)->getTitle(); + titleLen = ((OutlineItem *)outline)->getTitleLength(); + for (i = 0; i < titleLen; ++i) { + s.append((QChar)title[i]); + } + return s; + } catch (GMemException e) { + return QString(); + } +} + +bool XpdfWidget::getOutlineStartsOpen(XpdfOutlineHandle outline) { + if (!outline) { + return false; + } + try { + return (bool)((OutlineItem *)outline)->isOpen(); + } catch (GMemException e) { + return false; + } +} + +int XpdfWidget::getOutlineTargetPage(XpdfOutlineHandle outline) { + try { + if (!outline || !core->getDoc()) { + return 0; + } + return core->getDoc()->getOutlineTargetPage((OutlineItem *)outline); + } catch (GMemException e) { + return 0; + } +} + +void XpdfWidget::gotoOutlineTarget(XpdfOutlineHandle outline) { + if (!outline) { + return; + } + try { + if (((OutlineItem *)outline)->getAction()) { + core->doAction(((OutlineItem *)outline)->getAction()); + } + } catch (GMemException e) { + } +} + +int XpdfWidget::getNumLayers() const { + try { + if (!core->getDoc()) { + return 0; + } + return core->getDoc()->getOptionalContent()->getNumOCGs(); + } catch (GMemException e) { + return 0; + } +} + +XpdfLayerHandle XpdfWidget::getLayer(int idx) const { + try { + if (!core->getDoc() || + idx < 0 || + idx >= core->getDoc()->getOptionalContent()->getNumOCGs()) { + return NULL; + } + return (XpdfLayerHandle)core->getDoc()->getOptionalContent()->getOCG(idx); + } catch (GMemException e) { + return NULL; + } +} + +QString XpdfWidget::getLayerName(XpdfLayerHandle layer) const { + Unicode *name; + QString s; + int nameLen, i; + + if (!layer) { + return QString(); + } + try { + name = ((OptionalContentGroup *)layer)->getName(); + nameLen = ((OptionalContentGroup *)layer)->getNameLength(); + for (i = 0; i < nameLen; ++i) { + s.append((QChar)name[i]); + } + return s; + } catch (GMemException e) { + return QString(); + } +} + +bool XpdfWidget::getLayerVisibility(XpdfLayerHandle layer) const { + if (!layer) { + return false; + } + try { + return (bool)((OptionalContentGroup *)layer)->getState(); + } catch (GMemException e) { + return false; + } +} + +void XpdfWidget::setLayerVisibility(XpdfLayerHandle layer, bool visibility) { + try { + if (!core->getDoc() || !layer) { + return; + } + core->setOCGState(((OptionalContentGroup *)layer), (GBool)visibility); + } catch (GMemException e) { + return; + } +} + +int XpdfWidget::getLayerViewState(XpdfLayerHandle layer) const { + int s; + + if (!layer) { + return 0; + } + try { + s = ((OptionalContentGroup *)layer)->getViewState(); + return (s == ocUsageOn) ? 1 : (s == ocUsageOff) ? 0 : -1; + } catch (GMemException e) { + return 0; + } +} + +int XpdfWidget::getLayerPrintState(XpdfLayerHandle layer) const { + int s; + + if (!layer) { + return 0; + } + try { + s = ((OptionalContentGroup *)layer)->getPrintState(); + return (s == ocUsageOn) ? 1 : (s == ocUsageOff) ? 0 : -1; + } catch (GMemException e) { + return 0; + } +} + +XpdfLayerOrderHandle XpdfWidget::getLayerOrderRoot() const { + try { + if (!core->getDoc()) { + return NULL; + } + return (XpdfLayerOrderHandle) + core->getDoc()->getOptionalContent()->getDisplayRoot(); + } catch (GMemException e) { + return NULL; + } +} + +bool XpdfWidget::getLayerOrderIsName(XpdfLayerOrderHandle order) const { + if (!order) { + return false; + } + try { + return ((OCDisplayNode *)order)->getOCG() == NULL; + } catch (GMemException e) { + return false; + } +} + +QString XpdfWidget::getLayerOrderName(XpdfLayerOrderHandle order) const { + Unicode *name; + QString s; + int nameLen, i; + + if (!order) { + return QString(); + } + try { + name = ((OCDisplayNode *)order)->getName(); + nameLen = ((OCDisplayNode *)order)->getNameLength(); + for (i = 0; i < nameLen; ++i) { + s.append((QChar)name[i]); + } + return s; + } catch (GMemException e) { + return QString(); + } +} + +XpdfLayerHandle XpdfWidget::getLayerOrderLayer(XpdfLayerOrderHandle order) { + if (!order) { + return NULL; + } + try { + return (XpdfLayerHandle)((OCDisplayNode *)order)->getOCG(); + } catch (GMemException e) { + return NULL; + } +} + +int XpdfWidget::getLayerOrderNumChildren(XpdfLayerOrderHandle order) { + if (!order) { + return 0; + } + try { + return ((OCDisplayNode *)order)->getNumChildren(); + } catch (GMemException e) { + return 0; + } +} + +XpdfLayerOrderHandle XpdfWidget::getLayerOrderChild(XpdfLayerOrderHandle order, + int idx) { + if (!order) { + return NULL; + } + try { + if (idx < 0 || idx >= ((OCDisplayNode *)order)->getNumChildren()) { + return NULL; + } + return (XpdfLayerOrderHandle)((OCDisplayNode *)order)->getChild(idx); + } catch (GMemException e) { + return NULL; + } +} + +XpdfLayerOrderHandle XpdfWidget::getLayerOrderParent( + XpdfLayerOrderHandle order) { + if (!order) { + return NULL; + } + try { + return (XpdfLayerOrderHandle)((OCDisplayNode *)order)->getParent(); + } catch (GMemException e) { + return NULL; + } +} + +int XpdfWidget::getNumEmbeddedFiles() { + try { + if (!core->getDoc()) { + return 0; + } + return core->getDoc()->getNumEmbeddedFiles(); + } catch (GMemException e) { + return 0; + } +} + +QString XpdfWidget::getEmbeddedFileName(int idx) { + Unicode *name; + QString s; + int nameLen, i; + + try { + if (!core->getDoc() || + idx < 0 || + idx >= core->getDoc()->getNumEmbeddedFiles()) { + return ""; + } + name = core->getDoc()->getEmbeddedFileName(idx); + nameLen = core->getDoc()->getEmbeddedFileNameLength(idx); + for (i = 0; i < nameLen; ++i) { + s.append((QChar)name[i]); + } + return s; + } catch (GMemException e) { + return 0; + } +} + +bool XpdfWidget::saveEmbeddedFile(int idx, QString fileName) { + try { + if (!core->getDoc() || + idx < 0 || + idx >= core->getDoc()->getNumEmbeddedFiles()) { + return false; + } + return core->getDoc()->saveEmbeddedFile( + idx, fileName.toLocal8Bit().constData()); + } catch (GMemException e) { + return false; + } +} + +QSize XpdfWidget::sizeHint() const { + try { + return core->getBestSize(); + } catch (GMemException e) { + } + return QSize(612, 792); +} + +//------------------------------------------------------------------------ +// callbacks from QtPDFCore +//------------------------------------------------------------------------ + +void XpdfWidget::updateCbk(void *data, GString *fileName, + int pageNum, int numPages, + const char *linkLabel) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + if (fileName) { + if (pageNum >= 0) { + emit xpdf->pageChange(pageNum); + } + } +} + +void XpdfWidget::midPageChangedCbk(void *data, int pageNum) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->midPageChange(pageNum); +} + +void XpdfWidget::preLoadCbk(void *data) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->preLoad(); +} + +void XpdfWidget::postLoadCbk(void *data) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->postLoad(); +} + +void XpdfWidget::linkCbk(void *data, const char *type, + const char *dest, int page) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->linkClick(type, dest, page); +} + +void XpdfWidget::selectDoneCbk(void *data) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->selectDone(); +} + +void XpdfWidget::paintDoneCbk(void *data, bool finished) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->paintDone(finished); +} + +// NB: this function is called on a worker thread. +void XpdfWidget::tileDoneCbk(void *data) { + XpdfWidget *xpdf = (XpdfWidget *)data; + + emit xpdf->tileDone(); +} + + +//------------------------------------------------------------------------ +// events from the QAbstractScrollArea +//------------------------------------------------------------------------ + +void XpdfWidget::paintEvent(QPaintEvent *eventA) { + core->paintEvent(eventA->rect().left(), + eventA->rect().top(), + eventA->rect().width(), + eventA->rect().height()); +} + +void XpdfWidget::resizeEvent(QResizeEvent *eventA) { + core->resizeEvent(); + emit resized(); +} + +void XpdfWidget::scrollContentsBy(int dx, int dy) { + core->scrollEvent(); +} + +void XpdfWidget::keyPressEvent(QKeyEvent *e) { + int key; + + if (!keyPassthrough) { + key = e->key(); + if (key == Qt::Key_Left) { + core->scrollLeft(); + return; + } else if (key == Qt::Key_Right) { + core->scrollRight(); + return; + } else if (key == Qt::Key_Up) { + core->scrollUp(); + return; + } else if (key == Qt::Key_Down) { + core->scrollDown(); + return; + } else if (key == Qt::Key_PageUp) { + core->scrollPageUp(); + return; + } else if (key == Qt::Key_PageDown || + key == Qt::Key_Space) { + core->scrollPageDown(); + return; + } + } + emit keyPress(e); +} + +void XpdfWidget::mousePressEvent(QMouseEvent *e) { + int x, y; + + lastMousePressX[0] = lastMousePressX[1]; + lastMousePressY[0] = lastMousePressY[1]; + lastMousePressTime[0] = lastMousePressTime[1]; + lastMousePressX[1] = lastMousePressX[2]; + lastMousePressY[1] = lastMousePressY[2]; + lastMousePressTime[1] = lastMousePressTime[2]; + lastMousePressX[2] = e->pos().x(); + lastMousePressY[2] = e->pos().y(); + lastMousePressTime[2] = e->timestamp(); + lastMouseEventWasPress = true; + if (!mousePassthrough) { + x = (int)(e->pos().x() * scaleFactor); + y = (int)(e->pos().y() * scaleFactor); + if (e->button() == Qt::LeftButton) { + core->startSelection(x, y, e->modifiers() & Qt::ShiftModifier); + } else if (e->button() == Qt::MiddleButton) { + core->startPan(x, y); + } + } + emit mousePress(e); +} + +void XpdfWidget::mouseReleaseEvent(QMouseEvent *e) { + int x, y; + + // some versions of Qt drop mouse press events in double-clicks (?) + if (!lastMouseEventWasPress) { + mousePressEvent(e); + } + lastMouseEventWasPress = false; + + x = y = 0; + if (!mousePassthrough) { + x = (int)(e->pos().x() * scaleFactor); + y = (int)(e->pos().y() * scaleFactor); + if (e->button() == Qt::LeftButton) { + core->endSelection(x, y); + } else if (e->button() == Qt::MiddleButton) { + core->endPan(x, y); + } + } + emit mouseRelease(e); + + // double and triple clicks have to be "quick" and "nearby"; + // single clicks just have to be "nearby" + ulong maxTime = (ulong)QApplication::doubleClickInterval(); + int maxDistance = QApplication::startDragDistance(); + if (e->timestamp() - lastMousePressTime[0] < 2 * maxTime && + abs(e->pos().x() - lastMousePressX[0]) + + abs(e->pos().y() - lastMousePressY[0]) <= maxDistance) { + if (!mousePassthrough && e->button() == Qt::LeftButton) { + core->selectLine(x, y); + } + emit mouseTripleClick(e); + } else if (e->timestamp() - lastMousePressTime[1] < maxTime && + abs(e->pos().x() - lastMousePressX[1]) + + abs(e->pos().y() - lastMousePressY[1]) <= maxDistance) { + if (!mousePassthrough && e->button() == Qt::LeftButton) { + core->selectWord(x, y); + } + emit mouseDoubleClick(e); + } else if (abs(e->pos().x() - lastMousePressX[2]) + + abs(e->pos().y() - lastMousePressY[2]) <= maxDistance) { + emit mouseClick(e); + } +} + +void XpdfWidget::mouseMoveEvent(QMouseEvent *e) { + int x, y; + + x = (int)(e->pos().x() * scaleFactor); + y = (int)(e->pos().y() * scaleFactor); + core->mouseMove(x, y); + emit mouseMove(e); +} + +void XpdfWidget::wheelEvent(QWheelEvent *e) { + if (!mousePassthrough) { + QAbstractScrollArea::wheelEvent(e); + } + emit mouseWheel(e); +} + +bool XpdfWidget::eventFilter(QObject *obj, QEvent *event) { + QGestureEvent *gestureEvent; + QPanGesture *panGesture; + QPinchGesture *pinchGesture; + double z; + + if (obj == viewport() && event->type() == QEvent::Gesture) { + gestureEvent = (QGestureEvent *)event; + if (touchPanEnabled && + (panGesture = (QPanGesture *)gestureEvent->gesture(Qt::PanGesture))) { + core->scrollTo(core->getScrollX() - (int)panGesture->delta().x(), + core->getScrollY() - (int)panGesture->delta().y()); + gestureEvent->accept(); + return true; + } else if (touchZoomEnabled && + (pinchGesture = + (QPinchGesture *)gestureEvent->gesture(Qt::PinchGesture))) { + if (pinchGesture->changeFlags() & QPinchGesture::ScaleFactorChanged) { + if (pinchGesture->state() == Qt::GestureStarted) { + pinchZoomStart = getZoomPercent(core->getMidPageNum()); + } else { + z = pinchZoomStart * pinchGesture->totalScaleFactor(); + if (z < 10) { + z = 10; + } else if (z > 800) { + z = 800; + } + core->zoomCentered(z); + } + } + gestureEvent->accept(); + return true; + } + } + return QAbstractScrollArea::eventFilter(obj, event); +} + +void XpdfWidget::tick() { + core->tick(); +} -- cgit v1.2.3