Coverage Report

Created: 2026-10-31 06:21

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
3.71k
Outline::Outline(Object *outlineObj, XRef *xref) {
23
3.71k
  Object first, last;
24
25
3.71k
  items = NULL;
26
3.71k
  if (!outlineObj->isDict()) {
27
3.40k
    return;
28
3.40k
  }
29
308
  outlineObj->dictLookupNF("First", &first);
30
308
  outlineObj->dictLookupNF("Last", &last);
31
308
  if (first.isRef() && last.isRef()) {
32
304
    items = OutlineItem::readItemList(&first, &last, NULL, xref);
33
304
  }
34
308
  first.free();
35
308
  last.free();
36
308
}
37
38
3.71k
Outline::~Outline() {
39
3.71k
  if (items) {
40
304
    deleteGList(items, OutlineItem);
41
304
  }
42
3.71k
}
43
44
//------------------------------------------------------------------------
45
46
OutlineItem::OutlineItem(Object *itemRefA, Dict *dict,
47
928
       OutlineItem *parentA, XRef *xrefA) {
48
928
  Object obj1;
49
50
928
  xref = xrefA;
51
928
  title = NULL;
52
928
  action = NULL;
53
928
  kids = NULL;
54
928
  parent = parentA;
55
56
928
  if (dict->lookup("Title", &obj1)->isString()) {
57
194
    title = new TextString(obj1.getString());
58
194
  }
59
928
  obj1.free();
60
61
928
  if (!dict->lookup("Dest", &obj1)->isNull()) {
62
440
    action = LinkAction::parseDest(&obj1);
63
488
  } else {
64
488
    obj1.free();
65
488
    if (!dict->lookup("A", &obj1)->isNull()) {
66
460
      action = LinkAction::parseAction(&obj1);
67
460
    }
68
488
  }
69
928
  obj1.free();
70
71
928
  itemRefA->copy(&itemRef);
72
928
  dict->lookupNF("First", &firstRef);
73
928
  dict->lookupNF("Last", &lastRef);
74
928
  dict->lookupNF("Next", &nextRef);
75
76
928
  startsOpen = gFalse;
77
928
  if (dict->lookup("Count", &obj1)->isInt()) {
78
174
    if (obj1.getInt() > 0) {
79
140
      startsOpen = gTrue;
80
140
    }
81
174
  }
82
928
  obj1.free();
83
84
928
  pageNum = -1;
85
928
}
86
87
928
OutlineItem::~OutlineItem() {
88
928
  close();
89
928
  if (title) {
90
194
    delete title;
91
194
  }
92
928
  if (action) {
93
480
    delete action;
94
480
  }
95
928
  itemRef.free();
96
928
  firstRef.free();
97
928
  lastRef.free();
98
928
  nextRef.free();
99
928
}
100
101
GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
102
304
         OutlineItem *parentA, XRef *xrefA) {
103
304
  GList *items;
104
304
  OutlineItem *item, *sibling;
105
304
  Object obj;
106
304
  Object *p;
107
304
  OutlineItem *ancestor;
108
304
  int i;
109
110
304
  items = new GList();
111
304
  if (!firstItemRef->isRef() || !lastItemRef->isRef()) {
112
0
    return items;
113
0
  }
114
304
  p = firstItemRef;
115
976
  do {
116
976
    if (!p->fetch(xrefA, &obj)->isDict()) {
117
48
      obj.free();
118
48
      break;
119
48
    }
120
928
    item = new OutlineItem(p, obj.getDict(), parentA, xrefA);
121
928
    obj.free();
122
123
    // check for loops with parents
124
928
    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
928
    if (ancestor) {
132
0
      delete item;
133
0
      break;
134
0
    }
135
136
    // check for loops with siblings
137
1.99k
    for (i = 0; i < items->getLength(); ++i) {
138
1.21k
      sibling = (OutlineItem *)items->get(i);
139
1.21k
      if (p->getRefNum() == sibling->itemRef.getRefNum() &&
140
144
    p->getRefGen() == sibling->itemRef.getRefGen()) {
141
144
  error(errSyntaxError, -1, "Loop detected in outline");
142
144
  break;
143
144
      }
144
1.21k
    }
145
928
    if (i < items->getLength()) {
146
144
      delete item;
147
144
      break;
148
144
    }
149
150
784
    items->append(item);
151
784
    if (p->getRefNum() == lastItemRef->getRef().num &&
152
4
  p->getRefGen() == lastItemRef->getRef().gen) {
153
3
      break;
154
3
    }
155
781
    p = &item->nextRef;
156
781
    if (!p->isRef()) {
157
109
      break;
158
109
    }
159
781
  } while (p);
160
304
  return items;
161
304
}
162
163
0
void OutlineItem::open() {
164
0
  if (!kids) {
165
0
    kids = readItemList(&firstRef, &lastRef, this, xref);
166
0
  }
167
0
}
168
169
928
void OutlineItem::close() {
170
928
  if (kids) {
171
0
    deleteGList(kids, OutlineItem);
172
0
    kids = NULL;
173
0
  }
174
928
}
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
}