]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/XPDFCore.cc
Import of Xpdf 2.03
[evince.git] / pdf / xpdf / XPDFCore.cc
index 9e359dae97f2d5d946d4f9387973c51c5de64b60..d4d8fa6b86124e007ecf64721e8c5d27fe6c84f3 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <X11/keysym.h>
 #include <X11/cursorfont.h>
+#include <string.h>
 #include "gmem.h"
 #include "GString.h"
 #include "GList.h"
 
 //------------------------------------------------------------------------
 
-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;
@@ -146,10 +139,8 @@ 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;
@@ -397,11 +388,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;
@@ -441,7 +432,7 @@ 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;
@@ -525,10 +516,10 @@ 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);
   oldScrollX = scrollX;
   oldScrollY = scrollY;
   updateScrollBars();
@@ -576,7 +567,7 @@ void XPDFCore::displayPage(int pageA, int zoomA, int rotateA,
   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;
@@ -685,7 +676,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;
@@ -704,7 +695,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;
@@ -1045,7 +1036,7 @@ GString *XPDFCore::extractText(int pageNum,
     delete textOut;
     return NULL;
   }
-  doc->displayPage(textOut, pageNum, dpi, rotate, gFalse);
+  doc->displayPage(textOut, pageNum, dpi, dpi, rotate, gFalse);
   s = textOut->getText(xMin, yMin, xMax, yMax);
   delete textOut;
   return s;
@@ -1055,7 +1046,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;
 
@@ -1063,7 +1054,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) {
@@ -1271,26 +1264,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);
@@ -1308,18 +1284,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
@@ -1341,15 +1342,12 @@ 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;
   }
 
@@ -1360,8 +1358,8 @@ void XPDFCore::find(char *s) {
     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, gFalse);
+    if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
                          &xMin1, &yMin1, &xMax1, &yMax1)) {
       goto foundPage;
     }
@@ -1369,8 +1367,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, gFalse);
+    if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse,
                          &xMin1, &yMin1, &xMax1, &yMax1)) {
       goto foundPage;
     }
@@ -1378,10 +1376,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;
     }
   }
@@ -1394,7 +1394,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;
   }
@@ -1942,7 +1943,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;
@@ -1954,11 +1955,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);