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 error(-1, "Bad annotation destination");
45 pageRef.num = obj1.getRefNum();
46 pageRef.gen = obj1.getRefGen();
49 if (!a->get(0, &obj1)->isInt()) {
50 error(-1, "Bad annotation destination");
53 pageNum = obj1.getInt() + 1;
57 // get destination type
61 if (obj1.isName("XYZ")) {
66 } else if (obj2.isNum()) {
70 error(-1, "Bad annotation destination position");
77 } else if (obj2.isNum()) {
81 error(-1, "Bad annotation destination position");
88 } else if (obj2.isNum()) {
92 error(-1, "Bad annotation destination position");
98 } else if (obj1.isName("Fit")) {
102 } else if (obj1.isName("FitH")) {
104 if (!a->get(2, &obj2)->isNum()) {
105 error(-1, "Bad annotation destination position");
112 } else if (obj1.isName("FitV")) {
114 if (!a->get(2, &obj2)->isNum()) {
115 error(-1, "Bad annotation destination position");
118 left = obj2.getNum();
122 } else if (obj1.isName("FitR")) {
124 if (!a->get(2, &obj2)->isNum()) {
125 error(-1, "Bad annotation destination position");
128 left = obj2.getNum();
130 if (!a->get(3, &obj2)->isNum()) {
131 error(-1, "Bad annotation destination position");
134 bottom = obj2.getNum();
136 if (!a->get(4, &obj2)->isNum()) {
137 error(-1, "Bad annotation destination position");
140 right = obj2.getNum();
142 if (!a->get(5, &obj2)->isNum()) {
143 error(-1, "Bad annotation destination position");
150 } else if (obj1.isName("FitB")) {
154 } else if (obj1.isName("FitBH")) {
156 if (!a->get(2, &obj2)->isNum()) {
157 error(-1, "Bad annotation destination position");
164 } else if (obj1.isName("FitBV")) {
166 if (!a->get(2, &obj2)->isNum()) {
167 error(-1, "Bad annotation destination position");
170 left = obj2.getNum();
175 error(-1, "Unknown annotation destination type");
189 LinkDest::LinkDest(LinkDest *dest) {
191 pageIsRef = dest->pageIsRef;
193 pageRef = dest->pageRef;
195 pageNum = dest->pageNum;
197 bottom = dest->bottom;
201 changeLeft = dest->changeLeft;
202 changeTop = dest->changeTop;
203 changeZoom = dest->changeZoom;
207 //------------------------------------------------------------------------
209 //------------------------------------------------------------------------
211 LinkGoTo::LinkGoTo(Object *destObj) {
216 if (destObj->isName()) {
217 namedDest = new GString(destObj->getName());
218 } else if (destObj->isString()) {
219 namedDest = destObj->getString()->copy();
221 // destination dictionary
222 } else if (destObj->isArray()) {
223 dest = new LinkDest(destObj->getArray(), gTrue);
231 error(-1, "Illegal annotation destination");
235 LinkGoTo::~LinkGoTo() {
242 //------------------------------------------------------------------------
244 //------------------------------------------------------------------------
246 LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
251 fileName = getFileSpecName(fileSpecObj);
254 if (destObj->isName()) {
255 namedDest = new GString(destObj->getName());
256 } else if (destObj->isString()) {
257 namedDest = destObj->getString()->copy();
259 // destination dictionary
260 } else if (destObj->isArray()) {
261 dest = new LinkDest(destObj->getArray(), gFalse);
269 error(-1, "Illegal annotation destination");
273 LinkGoToR::~LinkGoToR() {
283 //------------------------------------------------------------------------
285 //------------------------------------------------------------------------
287 LinkLaunch::LinkLaunch(Object *actionObj) {
293 if (actionObj->isDict()) {
294 if (!actionObj->dictLookup("F", &obj1)->isNull()) {
295 fileName = getFileSpecName(&obj1);
298 //~ This hasn't been defined by Adobe yet, so assume it looks
299 //~ just like the Win dictionary until they say otherwise.
300 if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
301 obj1.dictLookup("F", &obj2);
302 fileName = getFileSpecName(&obj2);
304 if (obj1.dictLookup("P", &obj2)->isString())
305 params = obj2.getString()->copy();
308 error(-1, "Bad launch-type link action");
315 LinkLaunch::~LinkLaunch() {
322 //------------------------------------------------------------------------
324 //------------------------------------------------------------------------
326 LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
332 if (uriObj->isString()) {
333 uri2 = uriObj->getString()->copy();
335 n = strcspn(uri2->getCString(), "/:");
336 if (n == uri2->getLength() || uri2->getChar(n) == '/') {
337 uri = baseURI->copy();
338 c = uri->getChar(uri->getLength() - 1);
339 if (c == '/' || c == '?') {
340 if (uri2->getChar(0) == '/') {
344 if (uri2->getChar(0) != '/') {
357 error(-1, "Illegal URI-type link");
361 LinkURI::~LinkURI() {
366 //------------------------------------------------------------------------
368 //------------------------------------------------------------------------
370 LinkNamed::LinkNamed(Object *nameObj) {
372 if (nameObj->isName()) {
373 name = new GString(nameObj->getName());
377 LinkNamed::~LinkNamed() {
383 //------------------------------------------------------------------------
385 //------------------------------------------------------------------------
387 LinkUnknown::LinkUnknown(char *action1) {
388 action = new GString(action1);
391 LinkUnknown::~LinkUnknown() {
395 //------------------------------------------------------------------------
397 //------------------------------------------------------------------------
399 Link::Link(Dict *dict, GString *baseURI) {
400 Object obj1, obj2, obj3, obj4;
407 if (!dict->lookup("Rect", &obj1)->isArray()) {
408 error(-1, "Annotation rectangle is wrong type");
411 if (!obj1.arrayGet(0, &obj2)->isNum()) {
412 error(-1, "Bad annotation rectangle");
417 if (!obj1.arrayGet(1, &obj2)->isNum()) {
418 error(-1, "Bad annotation rectangle");
423 if (!obj1.arrayGet(2, &obj2)->isNum()) {
424 error(-1, "Bad annotation rectangle");
429 if (!obj1.arrayGet(3, &obj2)->isNum()) {
430 error(-1, "Bad annotation rectangle");
449 if (!dict->lookup("Border", &obj1)->isNull()) {
450 if (obj1.isArray() && obj1.arrayGet(2, &obj2)->isNum())
451 borderW = obj2.getNum();
453 error(-1, "Bad annotation border");
458 // look for destination
459 if (!dict->lookup("Dest", &obj1)->isNull()) {
460 action = new LinkGoTo(&obj1);
465 if (dict->lookup("A", &obj1)->isDict()) {
466 obj1.dictLookup("S", &obj2);
469 if (obj2.isName("GoTo")) {
470 obj1.dictLookup("D", &obj3);
471 action = new LinkGoTo(&obj3);
475 } else if (obj2.isName("GoToR")) {
476 obj1.dictLookup("F", &obj3);
477 obj1.dictLookup("D", &obj4);
478 action = new LinkGoToR(&obj3, &obj4);
483 } else if (obj2.isName("Launch")) {
484 action = new LinkLaunch(&obj1);
487 } else if (obj2.isName("URI")) {
488 obj1.dictLookup("URI", &obj3);
489 action = new LinkURI(&obj3, baseURI);
493 } else if (obj2.isName("Named")) {
494 obj1.dictLookup("N", &obj3);
495 action = new LinkNamed(&obj3);
499 } else if (obj2.isName()) {
500 action = new LinkUnknown(obj2.getName());
502 // action is missing or wrong type
504 error(-1, "Bad annotation action");
511 error(-1, "Missing annotation destination/action");
517 // check for bad action
518 if (action && action->isOk())
534 //------------------------------------------------------------------------
536 //------------------------------------------------------------------------
538 Links::Links(Object *annots, GString *baseURI) {
548 if (annots->isArray()) {
549 for (i = 0; i < annots->arrayGetLength(); ++i) {
550 if (annots->arrayGet(i, &obj1)->isDict()) {
551 if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
552 link = new Link(obj1.getDict(), baseURI);
554 if (numLinks >= size) {
556 links = (Link **)grealloc(links, size * sizeof(Link *));
558 links[numLinks++] = link;
573 for (i = 0; i < numLinks; ++i)
578 LinkAction *Links::find(double x, double y) {
581 for (i = 0; i < numLinks; ++i) {
582 if (links[i]->inRect(x, y)) {
583 return links[i]->getAction();
589 GBool Links::onLink(double x, double y) {
592 for (i = 0; i < numLinks; ++i) {
593 if (links[i]->inRect(x, y))
599 //------------------------------------------------------------------------
601 // Extract a file name from a file specification (string or dictionary).
602 static GString *getFileSpecName(Object *fileSpecObj) {
609 if (fileSpecObj->isString()) {
610 name = fileSpecObj->getString()->copy();
613 } else if (fileSpecObj->isDict()) {
614 if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
616 fileSpecObj->dictLookup("F", &obj1);
619 name = obj1.getString()->copy();
621 error(-1, "Illegal file spec in link");
626 error(-1, "Illegal file spec in link");