]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/Link.cc
kill traces of ltk, incorporate new sources
[evince.git] / pdf / xpdf / Link.cc
index eb9d033635bc67bc60a17f991efead4102357ef4..b16563a925de3957cb3dc6a87995e45fbcf06117 100644 (file)
@@ -6,11 +6,12 @@
 //
 //========================================================================
 
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
 #pragma implementation
 #endif
 
-#include <aconf.h>
 #include <stddef.h>
 #include <string.h>
 #include "gmem.h"
 #include "Link.h"
 
 //------------------------------------------------------------------------
+// LinkAction
+//------------------------------------------------------------------------
+
+LinkAction *LinkAction::parseDest(Object *obj) {
+  LinkAction *action;
+
+  action = new LinkGoTo(obj);
+  if (!action->isOk()) {
+    delete action;
+    return NULL;
+  }
+  return action;
+}
+
+LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
+  LinkAction *action;
+  Object obj2, obj3, obj4;
+
+  if (!obj->isDict()) {
+    error(-1, "Bad annotation action");
+    return NULL;
+  }
+
+  obj->dictLookup("S", &obj2);
+
+  // GoTo action
+  if (obj2.isName("GoTo")) {
+    obj->dictLookup("D", &obj3);
+    action = new LinkGoTo(&obj3);
+    obj3.free();
+
+  // GoToR action
+  } else if (obj2.isName("GoToR")) {
+    obj->dictLookup("F", &obj3);
+    obj->dictLookup("D", &obj4);
+    action = new LinkGoToR(&obj3, &obj4);
+    obj3.free();
+    obj4.free();
+
+  // Launch action
+  } else if (obj2.isName("Launch")) {
+    action = new LinkLaunch(obj);
+
+  // URI action
+  } else if (obj2.isName("URI")) {
+    obj->dictLookup("URI", &obj3);
+    action = new LinkURI(&obj3, baseURI);
+    obj3.free();
+
+  // Named action
+  } else if (obj2.isName("Named")) {
+    obj->dictLookup("N", &obj3);
+    action = new LinkNamed(&obj3);
+    obj3.free();
+
+  // Movie action
+  } else if (obj2.isName("Movie")) {
+    obj->dictLookupNF("Annot", &obj3);
+    obj->dictLookup("T", &obj4);
+    action = new LinkMovie(&obj3, &obj4);
+    obj3.free();
+    obj4.free();
+
+  // unknown action
+  } else if (obj2.isName()) {
+    action = new LinkUnknown(obj2.getName());
+
+  // action is missing or wrong type
+  } else {
+    error(-1, "Bad annotation action");
+    action = NULL;
+  }
 
-static GString *getFileSpecName(Object *fileSpecObj);
+  obj2.free();
+
+  if (action && !action->isOk()) {
+    delete action;
+    return NULL;
+  }
+  return action;
+}
+
+GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
+  GString *name;
+  Object obj1;
+
+  name = NULL;
+
+  // string
+  if (fileSpecObj->isString()) {
+    name = fileSpecObj->getString()->copy();
+
+  // dictionary
+  } else if (fileSpecObj->isDict()) {
+    if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
+      obj1.free();
+      fileSpecObj->dictLookup("F", &obj1);
+    }
+    if (obj1.isString())
+      name = obj1.getString()->copy();
+    else
+      error(-1, "Illegal file spec in link");
+    obj1.free();
+
+  // error
+  } else {
+    error(-1, "Illegal file spec in link");
+  }
+
+  return name;
+}
 
 //------------------------------------------------------------------------
 // LinkDest
@@ -37,6 +147,10 @@ LinkDest::LinkDest(Array *a) {
   ok = gFalse;
 
   // get page
+  if (a->getLength() < 2) {
+    error(-1, "Annotation destination array has wrong length");
+    return;
+  }
   a->getNF(0, &obj1);
   if (obj1.isInt()) {
     pageNum = obj1.getInt() + 1;
@@ -56,6 +170,10 @@ LinkDest::LinkDest(Array *a) {
 
   // XYZ link
   if (obj1.isName("XYZ")) {
+    if (a->getLength() != 5) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destXYZ;
     a->get(2, &obj2);
     if (obj2.isNull()) {
@@ -93,10 +211,18 @@ LinkDest::LinkDest(Array *a) {
 
   // Fit link
   } else if (obj1.isName("Fit")) {
+    if (a->getLength() != 2) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFit;
 
   // FitH link
   } else if (obj1.isName("FitH")) {
+    if (a->getLength() != 3) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFitH;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
@@ -107,6 +233,10 @@ LinkDest::LinkDest(Array *a) {
 
   // FitV link
   } else if (obj1.isName("FitV")) {
+    if (a->getLength() != 3) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFitV;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
@@ -117,6 +247,10 @@ LinkDest::LinkDest(Array *a) {
 
   // FitR link
   } else if (obj1.isName("FitR")) {
+    if (a->getLength() != 6) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFitR;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
@@ -145,10 +279,18 @@ LinkDest::LinkDest(Array *a) {
 
   // FitB link
   } else if (obj1.isName("FitB")) {
+    if (a->getLength() != 2) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFitB;
 
   // FitBH link
   } else if (obj1.isName("FitBH")) {
+    if (a->getLength() != 3) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFitBH;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
@@ -159,6 +301,10 @@ LinkDest::LinkDest(Array *a) {
 
   // FitBV link
   } else if (obj1.isName("FitBV")) {
+    if (a->getLength() != 3) {
+      error(-1, "Annotation destination array has wrong length");
+      goto err2;
+    }
     kind = destFitBV;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
@@ -292,18 +438,33 @@ LinkLaunch::LinkLaunch(Object *actionObj) {
       fileName = getFileSpecName(&obj1);
     } else {
       obj1.free();
+#ifdef WIN32
+      if (actionObj->dictLookup("Win", &obj1)->isDict()) {
+       obj1.dictLookup("F", &obj2);
+       fileName = getFileSpecName(&obj2);
+       obj2.free();
+       if (obj1.dictLookup("P", &obj2)->isString()) {
+         params = obj2.getString()->copy();
+       }
+       obj2.free();
+      } else {
+       error(-1, "Bad launch-type link action");
+      }
+#else
       //~ This hasn't been defined by Adobe yet, so assume it looks
       //~ just like the Win dictionary until they say otherwise.
       if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
        obj1.dictLookup("F", &obj2);
        fileName = getFileSpecName(&obj2);
        obj2.free();
-       if (obj1.dictLookup("P", &obj2)->isString())
+       if (obj1.dictLookup("P", &obj2)->isString()) {
          params = obj2.getString()->copy();
+       }
        obj2.free();
       } else {
        error(-1, "Bad launch-type link action");
       }
+#endif
     }
     obj1.free();
   }
@@ -377,6 +538,28 @@ LinkNamed::~LinkNamed() {
   }
 }
 
+//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
+  annotRef.num = -1;
+  title = NULL;
+  if (annotObj->isRef()) {
+    annotRef = annotObj->getRef();
+  } else if (titleObj->isString()) {
+    title = titleObj->getString()->copy();
+  } else {
+    error(-1, "Movie action is missing both the Annot and T keys");
+  }
+}
+
+LinkMovie::~LinkMovie() {
+  if (title) {
+    delete title;
+  }
+}
+
 //------------------------------------------------------------------------
 // LinkUnknown
 //------------------------------------------------------------------------
@@ -394,7 +577,7 @@ LinkUnknown::~LinkUnknown() {
 //------------------------------------------------------------------------
 
 Link::Link(Dict *dict, GString *baseURI) {
-  Object obj1, obj2, obj3, obj4;
+  Object obj1, obj2;
   double t;
 
   action = NULL;
@@ -457,66 +640,21 @@ Link::Link(Dict *dict, GString *baseURI) {
 
   // look for destination
   if (!dict->lookup("Dest", &obj1)->isNull()) {
-    action = new LinkGoTo(&obj1);
+    action = LinkAction::parseDest(&obj1);
 
   // look for action
   } else {
     obj1.free();
     if (dict->lookup("A", &obj1)->isDict()) {
-      obj1.dictLookup("S", &obj2);
-
-      // GoTo action
-      if (obj2.isName("GoTo")) {
-       obj1.dictLookup("D", &obj3);
-       action = new LinkGoTo(&obj3);
-       obj3.free();
-
-      // GoToR action
-      } else if (obj2.isName("GoToR")) {
-       obj1.dictLookup("F", &obj3);
-       obj1.dictLookup("D", &obj4);
-       action = new LinkGoToR(&obj3, &obj4);
-       obj3.free();
-       obj4.free();
-
-      // Launch action
-      } else if (obj2.isName("Launch")) {
-       action = new LinkLaunch(&obj1);
-
-      // URI action
-      } else if (obj2.isName("URI")) {
-       obj1.dictLookup("URI", &obj3);
-       action = new LinkURI(&obj3, baseURI);
-       obj3.free();
-
-      // Named action
-      } else if (obj2.isName("Named")) {
-       obj1.dictLookup("N", &obj3);
-       action = new LinkNamed(&obj3);
-       obj3.free();
-
-      // unknown action
-      } else if (obj2.isName()) {
-       action = new LinkUnknown(obj2.getName());
-
-      // action is missing or wrong type
-      } else {
-       error(-1, "Bad annotation action");
-       action = NULL;
-      }
-
-      obj2.free();
-
-    } else {
-      error(-1, "Missing annotation destination/action");
-      action = NULL;
+      action = LinkAction::parseAction(&obj1, baseURI);
     }
   }
   obj1.free();
 
   // check for bad action
-  if (action && action->isOk())
+  if (action) {
     ok = gTrue;
+  }
 
   return;
 
@@ -595,36 +733,3 @@ GBool Links::onLink(double x, double y) const {
   }
   return gFalse;
 }
-
-//------------------------------------------------------------------------
-
-// Extract a file name from a file specification (string or dictionary).
-static GString *getFileSpecName(Object *fileSpecObj) {
-  GString *name;
-  Object obj1;
-
-  name = NULL;
-
-  // string
-  if (fileSpecObj->isString()) {
-    name = fileSpecObj->getString()->copy();
-
-  // dictionary
-  } else if (fileSpecObj->isDict()) {
-    if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
-      obj1.free();
-      fileSpecObj->dictLookup("F", &obj1);
-    }
-    if (obj1.isString())
-      name = obj1.getString()->copy();
-    else
-      error(-1, "Illegal file spec in link");
-    obj1.free();
-
-  // error
-  } else {
-    error(-1, "Illegal file spec in link");
-  }
-
-  return name;
-}