home *** CD-ROM | disk | FTP | other *** search
- //========================================================================
- //
- // Link.cc
- //
- // Copyright 1996 Derek B. Noonburg
- //
- //========================================================================
- //
- // Ported to EPOC by Sander van der Wal
- //
- // $Log: Link.cpp $
- // Revision 1.3 2000-09-20 20:06:26+02 svdwal
- // xpdf 0.91 changes added
- //
- // Revision 1.2 2000-09-17 13:38:22+02 svdwal
- // Ported
- //
-
- #ifdef __GNUC__
- #pragma implementation
- #endif
-
- #ifndef __E32DEF_H__
- #include <e32def.h> // remove warning about NULL redefinition
- #endif
-
-
- #include "gmem.h"
- #include "GString.h"
-
- #include "Error.h"
- #include "Object.h"
- #include "Array.h"
- #include "Dict.h"
- #include "Link.h"
-
- #include "Pdf.rsg"
-
- //------------------------------------------------------------------------
-
- static TFileName* getFileSpecName(Object *fileSpecObj);
-
-
- //------------------------------------------------------------------------
- // LinkAction
- //------------------------------------------------------------------------
- LinkAction* LinkAction::NewL(Object* aActionObj, GString *aBaseURI)
- {
- RAutoObject obj1, obj2;
-
- aActionObj->dictLookupL("S", &obj1);
-
- if (obj1.isName("GoTo")) {
- aActionObj->dictLookupL("D", &obj2);
- return LinkGoTo::NewL(&obj2);
- }
- else if (obj1.isName("GoToR")) {
- RAutoObject obj3;
- aActionObj->dictLookupL("F", &obj2);
- aActionObj->dictLookupL("D", &obj3);
- return LinkGoToR::NewL(&obj2, &obj3);
- }
- else if (obj1.isName("Launch")) {
- return LinkLaunch::NewL(aActionObj);
- }
- else if (obj1.isName("URI")) {
- aActionObj->dictLookupL("URI", &obj2);
- return LinkURI::NewL(&obj2, aBaseURI);
- }
- else if (obj1.isName("Thread") ||
- obj1.isName("Sound") ||
- obj1.isName("Movie") ||
- obj1.isName("SetState") ||
- obj1.isName("Hide") ||
- obj1.isName("Named") ||
- obj1.isName("SubmitForm")||
- obj1.isName("ResetForm") ||
- obj1.isName("ImportData")||
- obj1.isName("JavaScript")) {
- return LinkUnknown::NewL(obj1.getName());
- }
- else
- // action is missing or wrong type
- return 0;
- }
-
- //------------------------------------------------------------------------
- // LinkDest
- //------------------------------------------------------------------------
- LinkDest::LinkDest() {}
-
-
- void LinkDest::ConstructL(Array *a, GBool pageIsRef1) {
- RAutoObject obj1, obj2;
-
- // initialize fields
- pageIsRef = pageIsRef1;
- left = bottom = right = top = zoom = 0;
- ok = gFalse;
-
- // get page
- if (pageIsRef) {
- if (!a->getNFL(0, &obj1)->isRef()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION);
- goto err2;
- }
- pageRef.num = obj1.getRefNum();
- pageRef.gen = obj1.getRefGen();
- obj1.free();
- } else {
- if (!a->getL(0, &obj1)->isInt()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION);
- goto err2;
- }
- pageNum = obj1.getInt() + 1;
- obj1.free();
- }
-
- // get destination type
- a->getL(1, &obj1);
-
- // XYZ link
- if (obj1.isName("XYZ")) {
- kind = destXYZ;
- a->getL(2, &obj2);
- if (obj2.isNull()) {
- changeLeft = gFalse;
- } else if (obj2.isNum()) {
- changeLeft = gTrue;
- left = obj2.getNum();
- } else {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- obj2.free();
- a->getL(3, &obj2);
- if (obj2.isNull()) {
- changeTop = gFalse;
- } else if (obj2.isNum()) {
- changeTop = gTrue;
- top = obj2.getNum();
- } else {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- obj2.free();
- a->getL(4, &obj2);
- if (obj2.isNull()) {
- changeZoom = gFalse;
- } else if (obj2.isNum()) {
- changeZoom = gTrue;
- zoom = obj2.getNum();
- } else {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- obj2.free();
-
- // Fit link
- } else if (obj1.isName("Fit")) {
- kind = destFit;
-
- // FitH link
- } else if (obj1.isName("FitH")) {
- kind = destFitH;
- if (!a->getL(2, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- top = obj2.getNum();
- obj2.free();
-
- // FitV link
- } else if (obj1.isName("FitV")) {
- kind = destFitV;
- if (!a->getL(2, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- left = obj2.getNum();
- obj2.free();
-
- // FitR link
- } else if (obj1.isName("FitR")) {
- kind = destFitR;
- if (!a->getL(2, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- left = obj2.getNum();
- obj2.free();
- if (!a->getL(3, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- bottom = obj2.getNum();
- obj2.free();
- if (!a->getL(4, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- right = obj2.getNum();
- obj2.free();
- if (!a->getL(5, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- top = obj2.getNum();
- obj2.free();
-
- // FitB link
- } else if (obj1.isName("FitB")) {
- kind = destFitB;
-
- // FitBH link
- } else if (obj1.isName("FitBH")) {
- kind = destFitBH;
- if (!a->getL(2, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- top = obj2.getNum();
- obj2.free();
-
- // FitBV link
- } else if (obj1.isName("FitBV")) {
- kind = destFitBV;
- if (!a->getL(2, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_DESTINATION_POSITION);
- goto err1;
- }
- left = obj2.getNum();
- obj2.free();
-
- // unknown link kind
- } else {
- error(-1, R_UNKNOWN_ANNOTATION_DESTINATION_TYPE);
- goto err2;
- }
-
- obj1.free();
- ok = gTrue;
- return;
-
- err1:
- obj2.free();
- err2:
- obj1.free();
- }
-
-
- LinkDest::LinkDest(LinkDest *dest) {
- kind = dest->kind;
- pageIsRef = dest->pageIsRef;
- if (pageIsRef)
- pageRef = dest->pageRef;
- else
- pageNum = dest->pageNum;
- left = dest->left;
- bottom = dest->bottom;
- right = dest->right;
- top = dest->top;
- zoom = dest->zoom;
- changeLeft = dest->changeLeft;
- changeTop = dest->changeTop;
- changeZoom = dest->changeZoom;
- ok = gTrue;
- }
-
- //------------------------------------------------------------------------
- // LinkGoTo
- //------------------------------------------------------------------------
-
- void LinkGoTo::ConstructL(Object *destObj) {
-
- // named destination
- if (destObj->isName()) {
- namedDest = GString::NewL(destObj->getName());
- } else if (destObj->isString()) {
- namedDest = destObj->getString()->copyL();
-
- // destination dictionary
- } else if (destObj->isArray()) {
- dest = new(ELeave) LinkDest();
- dest->ConstructL(destObj->getArray(), gTrue);
- if (!dest->isOk()) {
- delete dest;
- dest = NULL;
- }
-
- // error
- } else {
- error(-1, R_ILLEGAL_ANNOTATION_DESTINATION);
- }
- }
-
- LinkGoTo* LinkGoTo::NewL(Object *destObj)
- {
- LinkGoTo* self = new(ELeave) LinkGoTo();
- CleanupStack::PushL(self);
- self->ConstructL(destObj);
- CleanupStack::Pop(); // self
- return self;
- }
-
- LinkGoTo::~LinkGoTo() {
- delete dest;
- delete namedDest;
- }
-
- //------------------------------------------------------------------------
- // LinkGoToR
- //------------------------------------------------------------------------
-
- void LinkGoToR::ConstructL(Object *fileSpecObj, Object *destObj) {
-
- // get file name
- fileName = getFileSpecName(fileSpecObj);
-
- // named destination
- if (destObj->isName()) {
- namedDest = GString::NewL(destObj->getName());
- } else if (destObj->isString()) {
- namedDest = destObj->getString()->copyL();
-
- // destination dictionary
- } else if (destObj->isArray()) {
- dest = new(ELeave) LinkDest();
- dest->ConstructL(destObj->getArray(), gFalse);
- if (!dest->isOk()) {
- delete dest;
- dest = NULL;
- }
-
- // error
- } else {
- error(-1, R_ILLEGAL_ANNOTATION_DESTINATION);
- }
- }
-
- LinkGoToR* LinkGoToR::NewL(Object *fileSpecObj,Object *destObj)
- {
- LinkGoToR* self = new(ELeave) LinkGoToR();
- CleanupStack::PushL(self);
- self->ConstructL(fileSpecObj, destObj);
- CleanupStack::Pop(); // self
- return self;
- }
-
- LinkGoToR::~LinkGoToR() {
- delete fileName;
- delete dest;
- delete namedDest;
- }
-
-
- //------------------------------------------------------------------------
- // LinkLaunch
- //------------------------------------------------------------------------
-
- void LinkLaunch::ConstructL(Object *actionObj) {
- RAutoObject obj1, obj2;
-
- if (actionObj->isDict()) {
- if (!actionObj->dictLookupL("F", &obj1)->isNull()) {
- fileName = getFileSpecName(&obj1);
- } else {
- obj1.free();
- //~ This hasn't been defined by Adobe yet, so assume it looks
- //~ just like the Win dictionary until they say otherwise.
- if (actionObj->dictLookupL("Unix", &obj1)->isDict()) {
- obj1.dictLookupL("F", &obj2);
- fileName = getFileSpecName(&obj2);
- obj2.free();
- if (obj1.dictLookupL("P", &obj2)->isString())
- params = obj2.getString()->copyL();
- obj2.free();
- } else {
- error(-1, R_BAD_LAUNCH_TYPE_LINK_ACTION);
- }
- }
- obj1.free();
- }
- }
-
- LinkLaunch* LinkLaunch::NewL(Object *actionObj)
- {
- LinkLaunch* self = new(ELeave) LinkLaunch();
- CleanupStack::PushL(self);
- self->ConstructL(actionObj);
- CleanupStack::Pop(); // self
- return self;
- }
-
- LinkLaunch::~LinkLaunch() {
- delete fileName;
- delete params;
- }
-
- //------------------------------------------------------------------------
- // LinkURI
- //------------------------------------------------------------------------
-
- void LinkURI::ConstructL(Object *uriObj, GString *baseURI) {
- GString *uri2;
- int n;
- char c;
-
- if (uriObj->isString()) {
- uri2 = uriObj->getString()->copyL();
- if (baseURI) {
- n = strcspn(uri2->getCString(), "/:");
- if (n == uri2->getLength() || uri2->getChar(n) == '/') {
- CleanupStack::PushL(uri2);
- uri = baseURI->copyL();
- c = uri->getChar(uri->getLength() - 1);
- if (c == '/' || c == '?') {
- if (uri2->getChar(0) == '/') {
- uri2->delL(0);
- }
- }
- else {
- if (uri2->getChar(0) != '/') {
- uri->appendL('/');
- }
- }
- uri->appendL(uri2);
- CleanupStack::PopAndDestroy(); // delete uri2;
- }
- else {
- uri = uri2;
- }
- }
- else {
- uri = uri2;
- }
- }
- else {
- error(-1, R_ILLEGAL_URI_TYPE_LINK);
- }
- }
-
- LinkURI* LinkURI::NewL(Object *uriObj, GString *baseURI)
- {
- LinkURI* self = new(ELeave) LinkURI();
- CleanupStack::PushL(self);
- self->ConstructL(uriObj, baseURI);
- CleanupStack::Pop(); // self
- return self;
- }
-
- LinkURI::~LinkURI() {
- delete uri;
- }
-
- //------------------------------------------------------------------------
- // LinkUnknown
- //------------------------------------------------------------------------
-
- void LinkUnknown::ConstructL(char *action1) {
- action = GString::NewL(action1);
- }
-
- LinkUnknown* LinkUnknown::NewL(char *action1)
- {
- LinkUnknown* self = new(ELeave) LinkUnknown();
- CleanupStack::PushL(self);
- self->ConstructL(action1);
- CleanupStack::Pop(); // self
- return self;
- }
-
- LinkUnknown::~LinkUnknown() {
- delete action;
- }
-
- //------------------------------------------------------------------------
- // Link
- //------------------------------------------------------------------------
-
- void Link::ConstructL(Dict *dict, GString *baseURI) {
- RAutoObject obj1, obj2;
- double t;
-
- action = NULL;
- ok = gFalse;
-
- // get rectangle
- if (!dict->lookupL("Rect", &obj1)->isArray()) {
- error(-1, R_ANNOTATION_RECTANGLE_IS_WRONG_TYPE);
- goto err2;
- }
- if (!obj1.arrayGetL(0, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_RECTANGLE);
- goto err1;
- }
- x1 = obj2.getNum();
- obj2.free();
- if (!obj1.arrayGetL(1, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_RECTANGLE);
- goto err1;
- }
- y1 = obj2.getNum();
- obj2.free();
- if (!obj1.arrayGetL(2, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_RECTANGLE);
- goto err1;
- }
- x2 = obj2.getNum();
- obj2.free();
- if (!obj1.arrayGetL(3, &obj2)->isNum()) {
- error(-1, R_BAD_ANNOTATION_RECTANGLE);
- goto err1;
- }
- y2 = obj2.getNum();
- obj2.free();
- obj1.free();
- if (x1 > x2) {
- t = x1;
- x1 = x2;
- x2 = t;
- }
- if (y1 > y2) {
- t = y1;
- y1 = y2;
- y2 = t;
- }
-
- // get border
- borderW = 0;
- if (!dict->lookupL("Border", &obj1)->isNull()) {
- if (obj1.isArray() && obj1.arrayGetL(2, &obj2)->isNum())
- borderW = obj2.getNum();
- else
- error(-1, R_BAD_ANNOTATION_BORDER);
- obj2.free();
- }
- obj1.free();
-
- // look for destination
- if (!dict->lookupL("Dest", &obj1)->isNull()) {
- action = LinkGoTo::NewL(&obj1);
- }
- else { // look for action
- obj1.free();
- if (dict->lookupL("A", &obj1)->isDict()) {
- action = LinkAction::NewL(&obj1, baseURI);
- } else {
- error(-1, R_MISSING_ANNOTATION_DESTINATION_ACTION);
- action = NULL;
- }
- }
- obj1.free();
-
- // check for bad action
- if (action && action->isOk())
- ok = gTrue;
-
- return;
-
- err1:
- obj2.free();
- err2:
- obj1.free();
- }
-
- Link::~Link() {
- delete action;
- }
-
- //------------------------------------------------------------------------
- // Links
- //------------------------------------------------------------------------
-
- void Links::ConstructL(Object *annots, GString *baseURI) {
- Link *link;
- RAutoObject obj1, obj2;
- int size=0;
- int i;
-
- if (annots->isArray()) {
- for (i = 0; i < annots->arrayGetLength(); ++i) {
- if (annots->arrayGetL(i, &obj1)->isDict()) {
- if (obj1.dictLookupL("Subtype", &obj2)->isName("Link")) {
- link = new(ELeave) Link();
- CleanupStack::PushL(link);
- link->ConstructL(obj1.getDict(), baseURI);
- if (link->isOk()) {
- if (numLinks >= size) {
- size += 16;
- links = (Link **)User::ReAllocL(links, size * sizeof(Link *));
- }
- CleanupStack::Pop(); // link
- links[numLinks++] = link;
- } else {
- CleanupStack::PopAndDestroy(); // delete link;
- }
- }
- obj2.free();
- }
- obj1.free();
- }
- }
- }
-
- Links::~Links() {
- int i;
- if (links) {
- for (i = 0; i < numLinks; ++i)
- delete links[i];
- }
- User::Free(links);
- }
-
- LinkAction *Links::find(double x, double y) {
- int i;
-
- for (i = 0; i < numLinks; ++i) {
- if (links[i]->inRect(x, y)) {
- return links[i]->getAction();
- }
- }
- return NULL;
- }
-
- GBool Links::onLink(double x, double y) {
- int i;
-
- for (i = 0; i < numLinks; ++i) {
- if (links[i]->inRect(x, y))
- return gTrue;
- }
- return gFalse;
- }
-
- //------------------------------------------------------------------------
-
- // Extract a file name from a file specification (string or dictionary).
- static TFileName* getFileSpecName(Object *fileSpecObj) {
- TFileName *name;
- RAutoObject obj1;
-
- name = NULL;
-
- // string
- if (fileSpecObj->isString()) {
- name = new(ELeave) TFileName((const TText8*) fileSpecObj->getString()->getCString());
-
- // dictionary
- } else if (fileSpecObj->isDict()) {
- if (!fileSpecObj->dictLookupL("Unix", &obj1)->isString()) {
- obj1.free();
- fileSpecObj->dictLookupL("F", &obj1);
- }
- if (obj1.isString())
- name = new(ELeave) TFileName((const TText8*)obj1.getString()->getCString());
- else
- error(-1, R_ILLEGAL_FILE_SPEC_IN_LINK);
- obj1.free();
-
- // error
- } else {
- error(-1, R_ILLEGAL_FILE_SPEC_IN_LINK);
- }
-
- return name;
- }
-