Coverage Report

Created: 2026-05-30 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xpdf-4.06/xpdf/Outline.cc
Line
Count
Source
1
//========================================================================
2
//
3
// Outline.cc
4
//
5
// Copyright 2002-2013 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#include "gmem.h"
12
#include "gmempp.h"
13
#include "GString.h"
14
#include "GList.h"
15
#include "Error.h"
16
#include "Link.h"
17
#include "TextString.h"
18
#include "Outline.h"
19
20
//------------------------------------------------------------------------
21
22
14.7k
Outline::Outline(Object *outlineObj, XRef *xref) {
23
14.7k
  Object first, last;
24
25
14.7k
  items = NULL;
26
14.7k
  if (!outlineObj->isDict()) {
27
14.3k
    return;
28
14.3k
  }
29
447
  outlineObj->dictLookupNF("First", &first);
30
447
  outlineObj->dictLookupNF("Last", &last);
31
447
  if (first.isRef() && last.isRef()) {
32
285
    items = OutlineItem::readItemList(&first, &last, NULL, xref);
33
285
  }
34
447
  first.free();
35
447
  last.free();
36
447
}
37
38
14.7k
Outline::~Outline() {
39
14.7k
  if (items) {
40
285
    deleteGList(items, OutlineItem);
41
285
  }
42
14.7k
}
43
44
//------------------------------------------------------------------------
45
46
OutlineItem::OutlineItem(Object *itemRefA, Dict *dict,
47
932
       OutlineItem *parentA, XRef *xrefA) {
48
932
  Object obj1;
49
50
932
  xref = xrefA;
51
932
  title = NULL;
52
932
  action = NULL;
53
932
  kids = NULL;
54
932
  parent = parentA;
55
56
932
  if (dict->lookup("Title", &obj1)->isString()) {
57
362
    title = new TextString(obj1.getString());
58
362
  }
59
932
  obj1.free();
60
61
932
  if (!dict->lookup("Dest", &obj1)->isNull()) {
62
387
    action = LinkAction::parseDest(&obj1);
63
545
  } else {
64
545
    obj1.free();
65
545
    if (!dict->lookup("A", &obj1)->isNull()) {
66
484
      action = LinkAction::parseAction(&obj1);
67
484
    }
68
545
  }
69
932
  obj1.free();
70
71
932
  itemRefA->copy(&itemRef);
72
932
  dict->lookupNF("First", &firstRef);
73
932
  dict->lookupNF("Last", &lastRef);
74
932
  dict->lookupNF("Next", &nextRef);
75
76
932
  startsOpen = gFalse;
77
932
  if (dict->lookup("Count", &obj1)->isInt()) {
78
199
    if (obj1.getInt() > 0) {
79
141
      startsOpen = gTrue;
80
141
    }
81
199
  }
82
932
  obj1.free();
83
84
932
  pageNum = -1;
85
932
}
86
87
932
OutlineItem::~OutlineItem() {
88
932
  close();
89
932
  if (title) {
90
362
    delete title;
91
362
  }
92
932
  if (action) {
93
483
    delete action;
94
483
  }
95
932
  itemRef.free();
96
932
  firstRef.free();
97
932
  lastRef.free();
98
932
  nextRef.free();
99
932
}
100
101
GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
102
285
         OutlineItem *parentA, XRef *xrefA) {
103
285
  GList *items;
104
285
  OutlineItem *item, *sibling;
105
285
  Object obj;
106
285
  Object *p;
107
285
  OutlineItem *ancestor;
108
285
  int i;
109
110
285
  items = new GList();
111
285
  if (!firstItemRef->isRef() || !lastItemRef->isRef()) {
112
0
    return items;
113
0
  }
114
285
  p = firstItemRef;
115
981
  do {
116
981
    if (!p->fetch(xrefA, &obj)->isDict()) {
117
49
      obj.free();
118
49
      break;
119
49
    }
120
932
    item = new OutlineItem(p, obj.getDict(), parentA, xrefA);
121
932
    obj.free();
122
123
    // check for loops with parents
124
932
    for (ancestor = parentA; ancestor; ancestor = ancestor->parent) {
125
0
      if (p->getRefNum() == ancestor->itemRef.getRefNum() &&
126
0
    p->getRefGen() == ancestor->itemRef.getRefGen()) {
127
0
  error(errSyntaxError, -1, "Loop detected in outline");
128
0
  break;
129
0
      }
130
0
    }
131
932
    if (ancestor) {
132
0
      delete item;
133
0
      break;
134
0
    }
135
136
    // check for loops with siblings
137
2.65k
    for (i = 0; i < items->getLength(); ++i) {
138
1.83k
      sibling = (OutlineItem *)items->get(i);
139
1.83k
      if (p->getRefNum() == sibling->itemRef.getRefNum() &&
140
129
    p->getRefGen() == sibling->itemRef.getRefGen()) {
141
120
  error(errSyntaxError, -1, "Loop detected in outline");
142
120
  break;
143
120
      }
144
1.83k
    }
145
932
    if (i < items->getLength()) {
146
120
      delete item;
147
120
      break;
148
120
    }
149
150
812
    items->append(item);
151
812
    if (p->getRefNum() == lastItemRef->getRef().num &&
152
57
  p->getRefGen() == lastItemRef->getRef().gen) {
153
56
      break;
154
56
    }
155
756
    p = &item->nextRef;
156
756
    if (!p->isRef()) {
157
60
      break;
158
60
    }
159
756
  } while (p);
160
285
  return items;
161
285
}
162
163
0
void OutlineItem::open() {
164
0
  if (!kids) {
165
0
    kids = readItemList(&firstRef, &lastRef, this, xref);
166
0
  }
167
0
}
168
169
932
void OutlineItem::close() {
170
932
  if (kids) {
171
0
    deleteGList(kids, OutlineItem);
172
0
    kids = NULL;
173
0
  }
174
932
}
175
176
0
Unicode *OutlineItem::getTitle() {
177
0
  return title ? title->getUnicode() : (Unicode *)NULL;
178
0
}
179
180
0
int OutlineItem::getTitleLength() {
181
0
  return title ? title->getLength() : 0;
182
0
}