00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef __GNUC__
00010 #pragma implementation
00011 #endif
00012
00013 #include <aconf.h>
00014 #include <stddef.h>
00015 #include <string.h>
00016 #include "gmem.h"
00017 #include "GString.h"
00018 #include "Error.h"
00019 #include "Object.h"
00020 #include "Array.h"
00021 #include "Dict.h"
00022 #include "Link.h"
00023
00024
00025
00026 static GString *getFileSpecName(Object *fileSpecObj);
00027
00028
00029
00030
00031
00032 LinkDest::LinkDest(Array *a) {
00033 Object obj1, obj2;
00034
00035
00036 left = bottom = right = top = zoom = 0;
00037 ok = gFalse;
00038
00039
00040 a->getNF(0, &obj1);
00041 if (obj1.isInt()) {
00042 pageNum = obj1.getInt() + 1;
00043 pageIsRef = gFalse;
00044 } else if (obj1.isRef()) {
00045 pageRef.num = obj1.getRefNum();
00046 pageRef.gen = obj1.getRefGen();
00047 pageIsRef = gTrue;
00048 } else {
00049 error(-1, "Bad annotation destination");
00050 goto err2;
00051 }
00052 obj1.free();
00053
00054
00055 a->get(1, &obj1);
00056
00057
00058 if (obj1.isName("XYZ")) {
00059 kind = destXYZ;
00060 a->get(2, &obj2);
00061 if (obj2.isNull()) {
00062 changeLeft = gFalse;
00063 } else if (obj2.isNum()) {
00064 changeLeft = gTrue;
00065 left = obj2.getNum();
00066 } else {
00067 error(-1, "Bad annotation destination position");
00068 goto err1;
00069 }
00070 obj2.free();
00071 a->get(3, &obj2);
00072 if (obj2.isNull()) {
00073 changeTop = gFalse;
00074 } else if (obj2.isNum()) {
00075 changeTop = gTrue;
00076 top = obj2.getNum();
00077 } else {
00078 error(-1, "Bad annotation destination position");
00079 goto err1;
00080 }
00081 obj2.free();
00082 a->get(4, &obj2);
00083 if (obj2.isNull()) {
00084 changeZoom = gFalse;
00085 } else if (obj2.isNum()) {
00086 changeZoom = gTrue;
00087 zoom = obj2.getNum();
00088 } else {
00089 error(-1, "Bad annotation destination position");
00090 goto err1;
00091 }
00092 obj2.free();
00093
00094
00095 } else if (obj1.isName("Fit")) {
00096 kind = destFit;
00097
00098
00099 } else if (obj1.isName("FitH")) {
00100 kind = destFitH;
00101 if (!a->get(2, &obj2)->isNum()) {
00102 error(-1, "Bad annotation destination position");
00103 goto err1;
00104 }
00105 top = obj2.getNum();
00106 obj2.free();
00107
00108
00109 } else if (obj1.isName("FitV")) {
00110 kind = destFitV;
00111 if (!a->get(2, &obj2)->isNum()) {
00112 error(-1, "Bad annotation destination position");
00113 goto err1;
00114 }
00115 left = obj2.getNum();
00116 obj2.free();
00117
00118
00119 } else if (obj1.isName("FitR")) {
00120 kind = destFitR;
00121 if (!a->get(2, &obj2)->isNum()) {
00122 error(-1, "Bad annotation destination position");
00123 goto err1;
00124 }
00125 left = obj2.getNum();
00126 obj2.free();
00127 if (!a->get(3, &obj2)->isNum()) {
00128 error(-1, "Bad annotation destination position");
00129 goto err1;
00130 }
00131 bottom = obj2.getNum();
00132 obj2.free();
00133 if (!a->get(4, &obj2)->isNum()) {
00134 error(-1, "Bad annotation destination position");
00135 goto err1;
00136 }
00137 right = obj2.getNum();
00138 obj2.free();
00139 if (!a->get(5, &obj2)->isNum()) {
00140 error(-1, "Bad annotation destination position");
00141 goto err1;
00142 }
00143 top = obj2.getNum();
00144 obj2.free();
00145
00146
00147 } else if (obj1.isName("FitB")) {
00148 kind = destFitB;
00149
00150
00151 } else if (obj1.isName("FitBH")) {
00152 kind = destFitBH;
00153 if (!a->get(2, &obj2)->isNum()) {
00154 error(-1, "Bad annotation destination position");
00155 goto err1;
00156 }
00157 top = obj2.getNum();
00158 obj2.free();
00159
00160
00161 } else if (obj1.isName("FitBV")) {
00162 kind = destFitBV;
00163 if (!a->get(2, &obj2)->isNum()) {
00164 error(-1, "Bad annotation destination position");
00165 goto err1;
00166 }
00167 left = obj2.getNum();
00168 obj2.free();
00169
00170
00171 } else {
00172 error(-1, "Unknown annotation destination type");
00173 goto err2;
00174 }
00175
00176 obj1.free();
00177 ok = gTrue;
00178 return;
00179
00180 err1:
00181 obj2.free();
00182 err2:
00183 obj1.free();
00184 }
00185
00186 LinkDest::LinkDest(LinkDest *dest) {
00187 kind = dest->kind;
00188 pageIsRef = dest->pageIsRef;
00189 if (pageIsRef)
00190 pageRef = dest->pageRef;
00191 else
00192 pageNum = dest->pageNum;
00193 left = dest->left;
00194 bottom = dest->bottom;
00195 right = dest->right;
00196 top = dest->top;
00197 zoom = dest->zoom;
00198 changeLeft = dest->changeLeft;
00199 changeTop = dest->changeTop;
00200 changeZoom = dest->changeZoom;
00201 ok = gTrue;
00202 }
00203
00204
00205
00206
00207
00208 LinkGoTo::LinkGoTo(Object *destObj) {
00209 dest = NULL;
00210 namedDest = NULL;
00211
00212
00213 if (destObj->isName()) {
00214 namedDest = new GString(destObj->getName());
00215 } else if (destObj->isString()) {
00216 namedDest = destObj->getString()->copy();
00217
00218
00219 } else if (destObj->isArray()) {
00220 dest = new LinkDest(destObj->getArray());
00221 if (!dest->isOk()) {
00222 delete dest;
00223 dest = NULL;
00224 }
00225
00226
00227 } else {
00228 error(-1, "Illegal annotation destination");
00229 }
00230 }
00231
00232 LinkGoTo::~LinkGoTo() {
00233 if (dest)
00234 delete dest;
00235 if (namedDest)
00236 delete namedDest;
00237 }
00238
00239
00240
00241
00242
00243 LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
00244 dest = NULL;
00245 namedDest = NULL;
00246
00247
00248 fileName = getFileSpecName(fileSpecObj);
00249
00250
00251 if (destObj->isName()) {
00252 namedDest = new GString(destObj->getName());
00253 } else if (destObj->isString()) {
00254 namedDest = destObj->getString()->copy();
00255
00256
00257 } else if (destObj->isArray()) {
00258 dest = new LinkDest(destObj->getArray());
00259 if (!dest->isOk()) {
00260 delete dest;
00261 dest = NULL;
00262 }
00263
00264
00265 } else {
00266 error(-1, "Illegal annotation destination");
00267 }
00268 }
00269
00270 LinkGoToR::~LinkGoToR() {
00271 if (fileName)
00272 delete fileName;
00273 if (dest)
00274 delete dest;
00275 if (namedDest)
00276 delete namedDest;
00277 }
00278
00279
00280
00281
00282
00283
00284 LinkLaunch::LinkLaunch(Object *actionObj) {
00285 Object obj1, obj2;
00286
00287 fileName = NULL;
00288 params = NULL;
00289
00290 if (actionObj->isDict()) {
00291 if (!actionObj->dictLookup("F", &obj1)->isNull()) {
00292 fileName = getFileSpecName(&obj1);
00293 } else {
00294 obj1.free();
00295
00296
00297 if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
00298 obj1.dictLookup("F", &obj2);
00299 fileName = getFileSpecName(&obj2);
00300 obj2.free();
00301 if (obj1.dictLookup("P", &obj2)->isString())
00302 params = obj2.getString()->copy();
00303 obj2.free();
00304 } else {
00305 error(-1, "Bad launch-type link action");
00306 }
00307 }
00308 obj1.free();
00309 }
00310 }
00311
00312 LinkLaunch::~LinkLaunch() {
00313 if (fileName)
00314 delete fileName;
00315 if (params)
00316 delete params;
00317 }
00318
00319
00320
00321
00322
00323 LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
00324 GString *uri2;
00325 int n;
00326 char c;
00327
00328 uri = NULL;
00329 if (uriObj->isString()) {
00330 uri2 = uriObj->getString()->copy();
00331 if (baseURI) {
00332 n = strcspn(uri2->getCString(), "/:");
00333 if (n == uri2->getLength() || uri2->getChar(n) == '/') {
00334 uri = baseURI->copy();
00335 c = uri->getChar(uri->getLength() - 1);
00336 if (c == '/' || c == '?') {
00337 if (uri2->getChar(0) == '/') {
00338 uri2->del(0);
00339 }
00340 } else {
00341 if (uri2->getChar(0) != '/') {
00342 uri->append('/');
00343 }
00344 }
00345 uri->append(uri2);
00346 delete uri2;
00347 } else {
00348 uri = uri2;
00349 }
00350 } else {
00351 uri = uri2;
00352 }
00353 } else {
00354 error(-1, "Illegal URI-type link");
00355 }
00356 }
00357
00358 LinkURI::~LinkURI() {
00359 if (uri)
00360 delete uri;
00361 }
00362
00363
00364
00365
00366
00367 LinkNamed::LinkNamed(Object *nameObj) {
00368 name = NULL;
00369 if (nameObj->isName()) {
00370 name = new GString(nameObj->getName());
00371 }
00372 }
00373
00374 LinkNamed::~LinkNamed() {
00375 if (name) {
00376 delete name;
00377 }
00378 }
00379
00380
00381
00382
00383
00384 LinkUnknown::LinkUnknown(char *actionA) {
00385 action = new GString(actionA);
00386 }
00387
00388 LinkUnknown::~LinkUnknown() {
00389 delete action;
00390 }
00391
00392
00393
00394
00395
00396 Link::Link(Dict *dict, GString *baseURI) {
00397 Object obj1, obj2, obj3, obj4;
00398 fouble t;
00399
00400 action = NULL;
00401 ok = gFalse;
00402
00403
00404 if (!dict->lookup("Rect", &obj1)->isArray()) {
00405 error(-1, "Annotation rectangle is wrong type");
00406 goto err2;
00407 }
00408 if (!obj1.arrayGet(0, &obj2)->isNum()) {
00409 error(-1, "Bad annotation rectangle");
00410 goto err1;
00411 }
00412 x1 = obj2.getNum();
00413 obj2.free();
00414 if (!obj1.arrayGet(1, &obj2)->isNum()) {
00415 error(-1, "Bad annotation rectangle");
00416 goto err1;
00417 }
00418 y1 = obj2.getNum();
00419 obj2.free();
00420 if (!obj1.arrayGet(2, &obj2)->isNum()) {
00421 error(-1, "Bad annotation rectangle");
00422 goto err1;
00423 }
00424 x2 = obj2.getNum();
00425 obj2.free();
00426 if (!obj1.arrayGet(3, &obj2)->isNum()) {
00427 error(-1, "Bad annotation rectangle");
00428 goto err1;
00429 }
00430 y2 = obj2.getNum();
00431 obj2.free();
00432 obj1.free();
00433 if (x1 > x2) {
00434 t = x1;
00435 x1 = x2;
00436 x2 = t;
00437 }
00438 if (y1 > y2) {
00439 t = y1;
00440 y1 = y2;
00441 y2 = t;
00442 }
00443
00444
00445 borderW = 1;
00446 if (!dict->lookup("Border", &obj1)->isNull()) {
00447 if (obj1.isArray() && obj1.arrayGetLength() >= 3) {
00448 if (obj1.arrayGet(2, &obj2)->isNum()) {
00449 borderW = obj2.getNum();
00450 } else {
00451 error(-1, "Bad annotation border");
00452 }
00453 obj2.free();
00454 }
00455 }
00456 obj1.free();
00457
00458
00459 if (!dict->lookup("Dest", &obj1)->isNull()) {
00460 action = new LinkGoTo(&obj1);
00461
00462
00463 } else {
00464 obj1.free();
00465 if (dict->lookup("A", &obj1)->isDict()) {
00466 obj1.dictLookup("S", &obj2);
00467
00468
00469 if (obj2.isName("GoTo")) {
00470 obj1.dictLookup("D", &obj3);
00471 action = new LinkGoTo(&obj3);
00472 obj3.free();
00473
00474
00475 } else if (obj2.isName("GoToR")) {
00476 obj1.dictLookup("F", &obj3);
00477 obj1.dictLookup("D", &obj4);
00478 action = new LinkGoToR(&obj3, &obj4);
00479 obj3.free();
00480 obj4.free();
00481
00482
00483 } else if (obj2.isName("Launch")) {
00484 action = new LinkLaunch(&obj1);
00485
00486
00487 } else if (obj2.isName("URI")) {
00488 obj1.dictLookup("URI", &obj3);
00489 action = new LinkURI(&obj3, baseURI);
00490 obj3.free();
00491
00492
00493 } else if (obj2.isName("Named")) {
00494 obj1.dictLookup("N", &obj3);
00495 action = new LinkNamed(&obj3);
00496 obj3.free();
00497
00498
00499 } else if (obj2.isName()) {
00500 action = new LinkUnknown(obj2.getName());
00501
00502
00503 } else {
00504 error(-1, "Bad annotation action");
00505 action = NULL;
00506 }
00507
00508 obj2.free();
00509
00510 } else {
00511 error(-1, "Missing annotation destination/action");
00512 action = NULL;
00513 }
00514 }
00515 obj1.free();
00516
00517
00518 if (action && action->isOk())
00519 ok = gTrue;
00520
00521 return;
00522
00523 err1:
00524 obj2.free();
00525 err2:
00526 obj1.free();
00527 }
00528
00529 Link::~Link() {
00530 if (action)
00531 delete action;
00532 }
00533
00534
00535
00536
00537
00538 Links::Links(Object *annots, GString *baseURI) {
00539 Link *link;
00540 Object obj1, obj2;
00541 int size;
00542 int i;
00543
00544 links = NULL;
00545 size = 0;
00546 numLinks = 0;
00547
00548 if (annots->isArray()) {
00549 for (i = 0; i < annots->arrayGetLength(); ++i) {
00550 if (annots->arrayGet(i, &obj1)->isDict()) {
00551 if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
00552 link = new Link(obj1.getDict(), baseURI);
00553 if (link->isOk()) {
00554 if (numLinks >= size) {
00555 size += 16;
00556 links = (Link **)grealloc(links, size * sizeof(Link *));
00557 }
00558 links[numLinks++] = link;
00559 } else {
00560 delete link;
00561 }
00562 }
00563 obj2.free();
00564 }
00565 obj1.free();
00566 }
00567 }
00568 }
00569
00570 Links::~Links() {
00571 int i;
00572
00573 for (i = 0; i < numLinks; ++i)
00574 delete links[i];
00575 gfree(links);
00576 }
00577
00578 LinkAction *Links::find(fouble x, fouble y) {
00579 int i;
00580
00581 for (i = numLinks - 1; i >= 0; --i) {
00582 if (links[i]->inRect(x, y)) {
00583 return links[i]->getAction();
00584 }
00585 }
00586 return NULL;
00587 }
00588
00589 GBool Links::onLink(fouble x, fouble y) {
00590 int i;
00591
00592 for (i = 0; i < numLinks; ++i) {
00593 if (links[i]->inRect(x, y))
00594 return gTrue;
00595 }
00596 return gFalse;
00597 }
00598
00599
00600
00601
00602 static GString *getFileSpecName(Object *fileSpecObj) {
00603 GString *name;
00604 Object obj1;
00605
00606 name = NULL;
00607
00608
00609 if (fileSpecObj->isString()) {
00610 name = fileSpecObj->getString()->copy();
00611
00612
00613 } else if (fileSpecObj->isDict()) {
00614 if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
00615 obj1.free();
00616 fileSpecObj->dictLookup("F", &obj1);
00617 }
00618 if (obj1.isString())
00619 name = obj1.getString()->copy();
00620 else
00621 error(-1, "Illegal file spec in link");
00622 obj1.free();
00623
00624
00625 } else {
00626 error(-1, "Illegal file spec in link");
00627 }
00628
00629 return name;
00630 }