home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / pdftops / xpdf / c++ / Link < prev    next >
Encoding:
Text File  |  1996-06-08  |  9.0 KB  |  422 lines

  1. //========================================================================
  2. //
  3. // Link.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. //#pragma implementation
  11. #endif
  12.  
  13. #include <stddef.h>
  14. #include "gmem.h"
  15. #include "GString.h"
  16. #include "Error.h"
  17. #include "Object.h"
  18. #include "Array.h"
  19. #include "Dict.h"
  20. #include "Catalog.h"
  21. #include "Link.h"
  22.  
  23. //------------------------------------------------------------------------
  24. // LinkGoto
  25. //------------------------------------------------------------------------
  26.  
  27. LinkGoto::LinkGoto(Array *a, Catalog *catalog) {
  28.   remote = gFalse;
  29.   fileName = NULL;
  30.   ok = getPosition(a, catalog);
  31. }
  32.  
  33. LinkGoto::LinkGoto(GString *fileName1, Array *a, Catalog *catalog) {
  34.   remote = gTrue;
  35.   fileName = fileName1->copy();
  36.   ok = getPosition(a, catalog);
  37. }
  38.  
  39. LinkGoto::LinkGoto(Dict *fileSpec, Array *a, Catalog *catalog) {
  40.   Object obj1;
  41.  
  42.   remote = gTrue;
  43.   fileName = NULL;
  44.   if (!fileSpec->lookup("Unix", &obj1)->isString()) {
  45.     obj1.free();
  46.     fileSpec->lookup("F", &obj1);
  47.   }
  48.   if (obj1.isString()) {
  49.     fileName = obj1.getString()->copy();
  50.   } else {
  51.     error(0, "Can't get remote file name for link");
  52.     ok = gFalse;
  53.   }
  54.   obj1.free();
  55.   ok = ok && getPosition(a, catalog);
  56. }
  57.  
  58. GBool LinkGoto::getPosition(Array *a, Catalog *catalog) {
  59.   Object obj1, obj2;
  60.  
  61.   // get page
  62.   if (!a->getNF(0, &obj1)->isRef()) {
  63.     error(0, "Bad annotation destination");
  64.     goto err2;
  65.   }
  66.   pageNum = catalog->findPage(obj1.getRefNum(), obj1.getRefGen());
  67.   if (pageNum == 0) {
  68.     error(0, "Bad annotation destination page number");
  69.     goto err2;
  70.   }
  71.   obj1.free();
  72.  
  73.   // get destination info
  74.   a->get(1, &obj1);
  75.  
  76.   // XYZ link
  77.   if (obj1.isName("XYZ")) {
  78.     kind = gotoXYZ;
  79.     a->get(2, &obj2);
  80.     if (obj2.isNull()) {
  81.       changeLeft = gFalse;
  82.     } else if (obj2.isNum()) {
  83.       changeLeft = gTrue;
  84.       left = obj2.getNum();
  85.     } else {
  86.       error(0, "Bad annotation destination position");
  87.       goto err1;
  88.     }
  89.     obj2.free();
  90.     a->get(3, &obj2);
  91.     if (obj2.isNull()) {
  92.       changeTop = gFalse;
  93.     } else if (obj2.isNum()) {
  94.       changeTop = gTrue;
  95.       top = obj2.getNum();
  96.     } else {
  97.       error(0, "Bad annotation destination position");
  98.       goto err1;
  99.     }
  100.     obj2.free();
  101.     a->get(4, &obj2);
  102.     if (obj2.isNull()) {
  103.       changeZoom = gFalse;
  104.     } else if (obj2.isNum()) {
  105.       changeZoom = gTrue;
  106.       zoom = obj2.getNum();
  107.     } else {
  108.       error(0, "Bad annotation destination position");
  109.       goto err1;
  110.     }
  111.     obj2.free();
  112.  
  113.   // Fit link
  114.   } else if (obj1.isName("Fit")) {
  115.     kind = gotoFit;
  116.  
  117.   // FitH link
  118.   } else if (obj1.isName("FitH")) {
  119.     kind = gotoFitH;
  120.     if (!a->get(2, &obj2)->isNum()) {
  121.       error(0, "Bad annotation destination position");
  122.       goto err1;
  123.     }
  124.     top = obj2.getNum();
  125.     obj2.free();
  126.  
  127.   // FitV link
  128.   } else if (obj1.isName("FitV")) {
  129.     kind = gotoFitV;
  130.     if (!a->get(2, &obj2)->isNum()) {
  131.       error(0, "Bad annotation destination position");
  132.       goto err1;
  133.     }
  134.     left = obj2.getNum();
  135.     obj2.free();
  136.  
  137.   // FitR link
  138.   } else if (obj1.isName("FitR")) {
  139.     kind = gotoFitR;
  140.     if (!a->get(2, &obj2)->isNum()) {
  141.       error(0, "Bad annotation destination position");
  142.       goto err1;
  143.     }
  144.     left = obj2.getNum();
  145.     obj2.free();
  146.     if (!a->get(3, &obj2)->isNum()) {
  147.       error(0, "Bad annotation destination position");
  148.       goto err1;
  149.     }
  150.     bottom = obj2.getNum();
  151.     obj2.free();
  152.     if (!a->get(4, &obj2)->isNum()) {
  153.       error(0, "Bad annotation destination position");
  154.       goto err1;
  155.     }
  156.     right = obj2.getNum();
  157.     obj2.free();
  158.     if (!a->get(5, &obj2)->isNum()) {
  159.       error(0, "Bad annotation destination position");
  160.       goto err1;
  161.     }
  162.     top = obj2.getNum();
  163.     obj2.free();
  164.  
  165.   // FitB link
  166.   } else if (obj1.isName("FitB")) {
  167.     kind = gotoFitB;
  168.  
  169.   // FitBH link
  170.   } else if (obj1.isName("FitBH")) {
  171.     kind = gotoFitBH;
  172.     if (!a->get(2, &obj2)->isNum()) {
  173.       error(0, "Bad annotation destination position");
  174.       goto err1;
  175.     }
  176.     top = obj2.getNum();
  177.     obj2.free();
  178.  
  179.   // FitBV link
  180.   } else if (obj1.isName("FitBV")) {
  181.     kind = gotoFitBV;
  182.     if (!a->get(2, &obj2)->isNum()) {
  183.       error(0, "Bad annotation destination position");
  184.       goto err1;
  185.     }
  186.     left = obj2.getNum();
  187.     obj2.free();
  188.  
  189.   // unknown link kind
  190.   } else {
  191.     error(0, "Unknown annotation destination type");
  192.     goto err2;
  193.   }
  194.  
  195.   obj1.free();
  196.   return gTrue;
  197.  
  198.  err1:
  199.   obj2.free();
  200.  err2:
  201.   obj1.free();
  202.   return gFalse;
  203. }
  204.  
  205. LinkGoto::~LinkGoto() {
  206.   if (fileName)
  207.     delete fileName;
  208. }
  209.  
  210. //------------------------------------------------------------------------
  211. // LinkURI
  212. //------------------------------------------------------------------------
  213.  
  214. LinkURI::LinkURI(GString *uri1) {
  215.   uri = uri1->copy();
  216. }
  217.  
  218. LinkURI::~LinkURI() {
  219.   delete uri;
  220. }
  221.  
  222. //------------------------------------------------------------------------
  223. // LinkUnknown
  224. //------------------------------------------------------------------------
  225.  
  226. LinkUnknown::LinkUnknown(char *action1) {
  227.   action = new GString(action1);
  228. }
  229.  
  230. LinkUnknown::~LinkUnknown() {
  231.   delete action;
  232. }
  233.  
  234. //------------------------------------------------------------------------
  235. // Link
  236. //------------------------------------------------------------------------
  237.  
  238. Link::Link(Dict *dict, Catalog *catalog) {
  239.   Object obj1, obj2, obj3;
  240.  
  241.   action = NULL;
  242.  
  243.   // get rectangle
  244.   if (!dict->lookup("Rect", &obj1)->isArray()) {
  245.     error(0, "Annotation rectangle is wrong type");
  246.     goto err5;
  247.   }
  248.   if (!obj1.arrayGet(0, &obj2)->isInt()) {
  249.     error(0, "Bad annotation rectangle");
  250.     goto err4;
  251.   }
  252.   x1 = obj2.getInt();
  253.   obj2.free();
  254.   if (!obj1.arrayGet(1, &obj2)->isInt()) {
  255.     error(0, "Bad annotation rectangle");
  256.     goto err4;
  257.   }
  258.   y1 = obj2.getInt();
  259.   obj2.free();
  260.   if (!obj1.arrayGet(2, &obj2)->isInt()) {
  261.     error(0, "Bad annotation rectangle");
  262.     goto err4;
  263.   }
  264.   x2 = obj2.getInt();
  265.   obj2.free();
  266.   if (!obj1.arrayGet(3, &obj2)->isInt()) {
  267.     error(0, "Bad annotation rectangle");
  268.     goto err4;
  269.   }
  270.   y2 = obj2.getInt();
  271.   obj2.free();
  272.   obj1.free();
  273.  
  274.   // get border
  275.   dict->lookup("Border", &obj1);
  276.   if (!obj1.isArray()) {
  277.     error(0, "Annotation border is wrong type");
  278.     goto err5;
  279.   }
  280.   if (!obj1.arrayGet(2, &obj2)->isNum()) {
  281.     error(0, "Bad annotation border");
  282.     goto err4;
  283.   }
  284.   borderW = obj2.getNum();
  285.   obj2.free();
  286.   obj1.free();
  287.  
  288.   // look for destination
  289.   if (dict->lookup("Dest", &obj1)->isArray()) {
  290.     action = new LinkGoto(obj1.getArray(), catalog);
  291.  
  292.   // look for action
  293.   } else {
  294.     obj1.free();
  295.     if (dict->lookup("A", &obj1)->isDict()) {
  296.       obj1.dictLookup("S", &obj2);
  297.  
  298.       // GoTo action
  299.       if (obj2.isName("GoTo")) {
  300.     obj2.free();
  301.     if (obj1.dictLookup("D", &obj2)->isArray()) {
  302.       action = new LinkGoto(obj2.getArray(), catalog);
  303.     } else {
  304.       error(0, "Bad annotation action");
  305.       action = NULL;
  306.     }
  307.     obj2.free();
  308.  
  309.       // GoToR action
  310.       } else if (obj2.isName("GoToR")) {
  311.     obj2.free();
  312.     obj1.dictLookup("F", &obj2);
  313.     obj1.dictLookup("D", &obj3);
  314.     if (obj2.isString() && obj3.isArray()) {
  315.       action = new LinkGoto(obj2.getString(), obj3.getArray(), catalog);
  316.     } else if (obj2.isDict() && obj3.isArray()) {
  317.       action = new LinkGoto(obj2.getDict(), obj3.getArray(), catalog);
  318.     } else {
  319.       error(0, "Bad annotation action");
  320.       action = NULL;
  321.     }
  322.     obj2.free();
  323.     obj3.free();
  324.  
  325.       // URI action
  326.       } else if (obj2.isName("URI")) {
  327.     obj2.free();
  328.     obj1.dictLookup("URI", &obj2);
  329.     if (obj2.isString()) {
  330.       action = new LinkURI(obj2.getString());
  331.     } else {
  332.       error(0, "Bad annotation action");
  333.       action = NULL;
  334.     }
  335.     obj2.free();
  336.  
  337.       // unknown action
  338.       } else if (obj2.isName()) {
  339.     action = new LinkUnknown(obj2.getName());
  340.         obj2.free();
  341.  
  342.       // action is missing or wrong type
  343.       } else {
  344.     error(0, "Bad annotation action");
  345.     action = NULL;
  346.       }
  347.     } else {
  348.       error(0, "Missing annotation destination/action");
  349.       action = NULL;
  350.     }
  351.   }
  352.   obj1.free();
  353.  
  354.   // check for bad action
  355.   if (action && !action->isOk()) {
  356.     delete action;
  357.     action = NULL;
  358.   }
  359.  
  360.   return;
  361.  
  362.  err4:
  363.   obj2.free();
  364.  err5:
  365.   obj1.free();
  366.   x1 = y1 = 1;
  367.   x2 = y2 = 0;
  368. }
  369.  
  370. Link::~Link() {
  371.   if (action)
  372.     delete action;
  373. }
  374.  
  375. //------------------------------------------------------------------------
  376. // Links
  377. //------------------------------------------------------------------------
  378.  
  379. Links::Links(Object *annots, Catalog *catalog) {
  380.   Object obj1, obj2;
  381.   int size;
  382.   int i;
  383.  
  384.   links = NULL;
  385.   size = 0;
  386.   numLinks = 0;
  387.  
  388.   if (annots->isArray()) {
  389.     for (i = 0; i < annots->arrayGetLength(); ++i) {
  390.       if (annots->arrayGet(i, &obj1)->isDict("Annot")) {
  391.     if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
  392.       if (numLinks >= size) {
  393.         size += 16;
  394.         links = (Link **)grealloc(links, size * sizeof(Link *));
  395.       }
  396.       links[numLinks++] = new Link(obj1.getDict(), catalog);
  397.     }
  398.     obj2.free();
  399.       }
  400.       obj1.free();
  401.     }
  402.   }
  403. }
  404.  
  405. Links::~Links() {
  406.   int i;
  407.  
  408.   for (i = 0; i < numLinks; ++i)
  409.     delete links[i];
  410.   gfree(links);
  411. }
  412.  
  413. Link *Links::find(int x, int y) {
  414.   int i;
  415.  
  416.   for (i = 0; i < numLinks; ++i) {
  417.     if (links[i]->inRect(x, y))
  418.       return links[i];
  419.   }
  420.   return NULL;
  421. }
  422.