Files
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

187 lines
3.9 KiB
C++

//========================================================================
//
// Outline.cc
//
// Copyright 2002-2013 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "gmem.h"
#include "gmempp.h"
#include "GString.h"
#include "GList.h"
#include "Error.h"
#include "Link.h"
#include "TextString.h"
#include "Outline.h"
//------------------------------------------------------------------------
Outline::Outline(Object *outlineObj, XRef *xref) {
Object first, last;
items = NULL;
if (!outlineObj->isDict()) {
return;
}
outlineObj->dictLookupNF("First", &first);
outlineObj->dictLookupNF("Last", &last);
if (first.isRef() && last.isRef()) {
items = OutlineItem::readItemList(&first, &last, NULL, xref);
}
first.free();
last.free();
}
Outline::~Outline() {
if (items) {
deleteGList(items, OutlineItem);
}
}
//------------------------------------------------------------------------
OutlineItem::OutlineItem(Object *itemRefA, Dict *dict,
OutlineItem *parentA, XRef *xrefA) {
Object obj1;
xref = xrefA;
title = NULL;
action = NULL;
kids = NULL;
parent = parentA;
if (dict->lookup("Title", &obj1)->isString()) {
title = new TextString(obj1.getString());
}
obj1.free();
if (!dict->lookup("Dest", &obj1)->isNull()) {
action = LinkAction::parseDest(&obj1);
} else {
obj1.free();
if (!dict->lookup("A", &obj1)->isNull()) {
action = LinkAction::parseAction(&obj1);
}
}
obj1.free();
itemRefA->copy(&itemRef);
dict->lookupNF("First", &firstRef);
dict->lookupNF("Last", &lastRef);
dict->lookupNF("Next", &nextRef);
startsOpen = gFalse;
if (dict->lookup("Count", &obj1)->isInt()) {
if (obj1.getInt() > 0) {
startsOpen = gTrue;
}
}
obj1.free();
pageNum = -1;
}
OutlineItem::~OutlineItem() {
close();
if (title) {
delete title;
}
if (action) {
delete action;
}
itemRef.free();
firstRef.free();
lastRef.free();
nextRef.free();
}
GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
OutlineItem *parentA, XRef *xrefA) {
GList *items;
OutlineItem *item, *sibling;
Object obj;
Object *p;
OutlineItem *ancestor;
int i;
items = new GList();
if (!firstItemRef->isRef() || !lastItemRef->isRef()) {
return items;
}
p = firstItemRef;
do {
if (!p->fetch(xrefA, &obj)->isDict()) {
obj.free();
break;
}
item = new OutlineItem(p, obj.getDict(), parentA, xrefA);
obj.free();
// check for loops with parents
for (ancestor = parentA; ancestor; ancestor = ancestor->parent) {
if (p->getRefNum() == ancestor->itemRef.getRefNum() &&
p->getRefGen() == ancestor->itemRef.getRefGen()) {
error(errSyntaxError, -1, "Loop detected in outline");
break;
}
}
if (ancestor) {
delete item;
break;
}
// check for loops with siblings
for (i = 0; i < items->getLength(); ++i) {
sibling = (OutlineItem *)items->get(i);
if (p->getRefNum() == sibling->itemRef.getRefNum() &&
p->getRefGen() == sibling->itemRef.getRefGen()) {
error(errSyntaxError, -1, "Loop detected in outline");
break;
}
}
if (i < items->getLength()) {
delete item;
break;
}
items->append(item);
if (p->getRefNum() == lastItemRef->getRef().num &&
p->getRefGen() == lastItemRef->getRef().gen) {
break;
}
p = &item->nextRef;
if (!p->isRef()) {
break;
}
} while (p);
return items;
}
void OutlineItem::open() {
if (!kids) {
kids = readItemList(&firstRef, &lastRef, this, xref);
}
}
void OutlineItem::close() {
if (kids) {
deleteGList(kids, OutlineItem);
kids = NULL;
}
}
Unicode *OutlineItem::getTitle() {
return title ? title->getUnicode() : (Unicode *)NULL;
}
int OutlineItem::getTitleLength() {
return title ? title->getLength() : 0;
}