Coverage Report

Created: 2026-03-07 06:39

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