1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
23 //------------------------------------------------------------------------
25 static GString *getFileSpecName(Object *fileSpecObj);
27 //------------------------------------------------------------------------
29 //------------------------------------------------------------------------
31 LinkDest::LinkDest(Array *a, GBool pageIsRef1) {
35 pageIsRef = pageIsRef1;
36 left = bottom = right = top = zoom = 0;
41 if (!a->getNF(0, &obj1)->isRef()) {
42 if(obj1.getType()!=objInt)
43 error(-1, "Bad annotation destination (1) type=%d", obj1.getType());
46 pageRef.num = obj1.getRefNum();
47 pageRef.gen = obj1.getRefGen();
50 if (!a->get(0, &obj1)->isInt()) {
51 error(-1, "Bad annotation destination (2)");
54 pageNum = obj1.getInt() + 1;
58 // get destination type
62 if (obj1.isName("XYZ")) {
67 } else if (obj2.isNum()) {
71 error(-1, "Bad annotation destination position");
78 } else if (obj2.isNum()) {
82 error(-1, "Bad annotation destination position");
89 } else if (obj2.isNum()) {
93 error(-1, "Bad annotation destination position");
99 } else if (obj1.isName("Fit")) {
103 } else if (obj1.isName("FitH")) {
105 if (!a->get(2, &obj2)->isNum()) {
106 error(-1, "Bad annotation destination position");
113 } else if (obj1.isName("FitV")) {
115 if (!a->get(2, &obj2)->isNum()) {
116 error(-1, "Bad annotation destination position");
119 left = obj2.getNum();
123 } else if (obj1.isName("FitR")) {
125 if (!a->get(2, &obj2)->isNum()) {
126 error(-1, "Bad annotation destination position");
129 left = obj2.getNum();
131 if (!a->get(3, &obj2)->isNum()) {
132 error(-1, "Bad annotation destination position");
135 bottom = obj2.getNum();
137 if (!a->get(4, &obj2)->isNum()) {
138 error(-1, "Bad annotation destination position");
141 right = obj2.getNum();
143 if (!a->get(5, &obj2)->isNum()) {
144 error(-1, "Bad annotation destination position");
151 } else if (obj1.isName("FitB")) {
155 } else if (obj1.isName("FitBH")) {
157 if (!a->get(2, &obj2)->isNum()) {
158 error(-1, "Bad annotation destination position");
165 } else if (obj1.isName("FitBV")) {
167 if (!a->get(2, &obj2)->isNum()) {
168 error(-1, "Bad annotation destination position");
171 left = obj2.getNum();
176 error(-1, "Unknown annotation destination type");
190 LinkDest::LinkDest(LinkDest *dest) {
192 pageIsRef = dest->pageIsRef;
194 pageRef = dest->pageRef;
196 pageNum = dest->pageNum;
198 bottom = dest->bottom;
202 changeLeft = dest->changeLeft;
203 changeTop = dest->changeTop;
204 changeZoom = dest->changeZoom;
208 //------------------------------------------------------------------------
210 //------------------------------------------------------------------------
212 LinkGoTo::LinkGoTo(Object *destObj) {
217 if (destObj->isName()) {
218 namedDest = new GString(destObj->getName());
219 } else if (destObj->isString()) {
220 namedDest = destObj->getString()->copy();
222 // destination dictionary
223 } else if (destObj->isArray()) {
224 dest = new LinkDest(destObj->getArray(), gTrue);
232 error(-1, "Illegal annotation destination");
236 LinkGoTo::~LinkGoTo() {
243 //------------------------------------------------------------------------
245 //------------------------------------------------------------------------
247 LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
252 fileName = getFileSpecName(fileSpecObj);
255 if (destObj->isName()) {
256 namedDest = new GString(destObj->getName());
257 } else if (destObj->isString()) {
258 namedDest = destObj->getString()->copy();
260 // destination dictionary
261 } else if (destObj->isArray()) {
262 dest = new LinkDest(destObj->getArray(), gFalse);
270 error(-1, "Illegal annotation destination");
274 LinkGoToR::~LinkGoToR() {
284 //------------------------------------------------------------------------
286 //------------------------------------------------------------------------
288 LinkLaunch::LinkLaunch(Object *actionObj) {
294 if (actionObj->isDict()) {
295 if (!actionObj->dictLookup("F", &obj1)->isNull()) {
296 fileName = getFileSpecName(&obj1);
299 //~ This hasn't been defined by Adobe yet, so assume it looks
300 //~ just like the Win dictionary until they say otherwise.
301 if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
302 obj1.dictLookup("F", &obj2);
303 fileName = getFileSpecName(&obj2);
305 if (obj1.dictLookup("P", &obj2)->isString())
306 params = obj2.getString()->copy();
309 error(-1, "Bad launch-type link action");
316 LinkLaunch::~LinkLaunch() {
323 //------------------------------------------------------------------------
325 //------------------------------------------------------------------------
327 LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
333 if (uriObj->isString()) {
334 uri2 = uriObj->getString()->copy();
336 n = strcspn(uri2->getCString(), "/:");
337 if (n == uri2->getLength() || uri2->getChar(n) == '/') {
338 uri = baseURI->copy();
339 c = uri->getChar(uri->getLength() - 1);
340 if (c == '/' || c == '?') {
341 if (uri2->getChar(0) == '/') {
345 if (uri2->getChar(0) != '/') {
358 error(-1, "Illegal URI-type link");
362 LinkURI::~LinkURI() {
367 //------------------------------------------------------------------------
369 //------------------------------------------------------------------------
371 LinkNamed::LinkNamed(Object *nameObj) {
373 if (nameObj->isName()) {
374 name = new GString(nameObj->getName());
378 LinkNamed::~LinkNamed() {
384 //------------------------------------------------------------------------
386 //------------------------------------------------------------------------
388 LinkUnknown::LinkUnknown(char *action1) {
389 action = new GString(action1);
392 LinkUnknown::~LinkUnknown() {
396 //------------------------------------------------------------------------
398 //------------------------------------------------------------------------
400 Link::Link(Dict *dict, GString *baseURI) {
401 Object obj1, obj2, obj3, obj4;
408 if (!dict->lookup("Rect", &obj1)->isArray()) {
409 error(-1, "Annotation rectangle is wrong type");
412 if (!obj1.arrayGet(0, &obj2)->isNum()) {
413 error(-1, "Bad annotation rectangle");
418 if (!obj1.arrayGet(1, &obj2)->isNum()) {
419 error(-1, "Bad annotation rectangle");
424 if (!obj1.arrayGet(2, &obj2)->isNum()) {
425 error(-1, "Bad annotation rectangle");
430 if (!obj1.arrayGet(3, &obj2)->isNum()) {
431 error(-1, "Bad annotation rectangle");
450 if (!dict->lookup("Border", &obj1)->isNull()) {
451 if (obj1.isArray() && obj1.arrayGet(2, &obj2)->isNum())
452 borderW = obj2.getNum();
454 error(-1, "Bad annotation border");
459 // look for destination
460 if (!dict->lookup("Dest", &obj1)->isNull()) {
461 action = new LinkGoTo(&obj1);
466 if (dict->lookup("A", &obj1)->isDict()) {
467 obj1.dictLookup("S", &obj2);
470 if (obj2.isName("GoTo")) {
471 obj1.dictLookup("D", &obj3);
472 action = new LinkGoTo(&obj3);
476 } else if (obj2.isName("GoToR")) {
477 obj1.dictLookup("F", &obj3);
478 obj1.dictLookup("D", &obj4);
479 action = new LinkGoToR(&obj3, &obj4);
484 } else if (obj2.isName("Launch")) {
485 action = new LinkLaunch(&obj1);
488 } else if (obj2.isName("URI")) {
489 obj1.dictLookup("URI", &obj3);
490 action = new LinkURI(&obj3, baseURI);
494 } else if (obj2.isName("Named")) {
495 obj1.dictLookup("N", &obj3);
496 action = new LinkNamed(&obj3);
500 } else if (obj2.isName()) {
501 action = new LinkUnknown(obj2.getName());
503 // action is missing or wrong type
505 error(-1, "Bad annotation action");
512 error(-1, "Missing annotation destination/action");
518 // check for bad action
519 if (action && action->isOk())
535 //------------------------------------------------------------------------
537 //------------------------------------------------------------------------
539 Links::Links(Object *annots, GString *baseURI) {
549 if (annots->isArray()) {
550 for (i = 0; i < annots->arrayGetLength(); ++i) {
551 if (annots->arrayGet(i, &obj1)->isDict()) {
552 if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
553 link = new Link(obj1.getDict(), baseURI);
555 if (numLinks >= size) {
557 links = (Link **)grealloc(links, size * sizeof(Link *));
559 links[numLinks++] = link;
574 for (i = 0; i < numLinks; ++i)
579 LinkAction *Links::find(double x, double y) {
582 for (i = 0; i < numLinks; ++i) {
583 if (links[i]->inRect(x, y)) {
584 return links[i]->getAction();
590 GBool Links::onLink(double x, double y) {
593 for (i = 0; i < numLinks; ++i) {
594 if (links[i]->inRect(x, y))
600 //------------------------------------------------------------------------
602 // Extract a file name from a file specification (string or dictionary).
603 static GString *getFileSpecName(Object *fileSpecObj) {
610 if (fileSpecObj->isString()) {
611 name = fileSpecObj->getString()->copy();
614 } else if (fileSpecObj->isDict()) {
615 if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
617 fileSpecObj->dictLookup("F", &obj1);
620 name = obj1.getString()->copy();
622 error(-1, "Illegal file spec in link");
627 error(-1, "Illegal file spec in link");