Coverage Report

Created: 2026-07-20 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwpd/src/lib/WPXPageSpan.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwpd
3
 * Version: MPL 2.0 / LGPLv2.1+
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * Major Contributor(s):
10
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
11
 * Copyright (C) 2002 Marc Maurer (uwog@uwog.net)
12
 * Copyright (C) 2006-2007 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 *
14
 * For minor contributions see the git repository.
15
 *
16
 * Alternatively, the contents of this file may be used under the terms
17
 * of the GNU Lesser General Public License Version 2.1 or later
18
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
19
 * applicable instead of those above.
20
 *
21
 * For further information visit http://libwpd.sourceforge.net
22
 */
23
24
/* "This product is not manufactured, approved, or supported by
25
 * Corel Corporation or Corel Corporation Limited."
26
 */
27
28
#include <algorithm>
29
#include "WPXPageSpan.h"
30
31
const double WPX_DEFAULT_PAGE_MARGIN_TOP = 1.0;
32
const double WPX_DEFAULT_PAGE_MARGIN_BOTTOM = 1.0;
33
34
const unsigned char DUMMY_INTERNAL_HEADER_FOOTER = 16;
35
36
WPXPageSpan::WPXPageSpan() :
37
0
  m_isPageNumberSuppressed(false),
38
0
  m_formLength(11.0),
39
0
  m_formWidth(8.5f),
40
0
  m_formOrientation(PORTRAIT),
41
0
  m_marginLeft(1.0),
42
0
  m_marginRight(1.0),
43
0
  m_marginTop(WPX_DEFAULT_PAGE_MARGIN_TOP),
44
0
  m_marginBottom(WPX_DEFAULT_PAGE_MARGIN_BOTTOM),
45
0
  m_pageNumberPosition(PAGENUMBER_POSITION_NONE),
46
0
  m_isPageNumberOverridden(false),
47
0
  m_pageNumberOverride(0),
48
0
  m_pageNumberingType(ARABIC),
49
0
  m_pageNumberingFontName(/*WP6_DEFAULT_FONT_NAME*/"Times New Roman"), // EN PAS DEFAULT FONT AAN VOOR WP5/6/etc
50
0
  m_pageNumberingFontSize(12.0/*WP6_DEFAULT_FONT_SIZE*/), // FIXME ME!!!!!!!!!!!!!!!!!!! HELP WP6_DEFAULT_FONT_SIZE
51
0
  m_headerFooterList(),
52
0
  m_pageSpan(1)
53
0
{
54
0
  for (bool &i : m_isHeaderFooterSuppressed)
55
0
    i=false;
56
0
}
57
58
// NB: this is not a literal "clone" function: it is contingent on the side margins that are passed,
59
// and suppression and override variables are not copied
60
WPXPageSpan::WPXPageSpan(const WPXPageSpan &page, double paragraphMarginLeft, double paragraphMarginRight) :
61
0
  m_isPageNumberSuppressed(false),
62
0
  m_formLength(page.getFormLength()),
63
0
  m_formWidth(page.getFormWidth()),
64
0
  m_formOrientation(page.getFormOrientation()),
65
0
  m_marginLeft(page.getMarginLeft()+paragraphMarginLeft),
66
0
  m_marginRight(page.getMarginRight()+paragraphMarginRight),
67
0
  m_marginTop(page.getMarginTop()),
68
0
  m_marginBottom(page.getMarginBottom()),
69
0
  m_pageNumberPosition(page.getPageNumberPosition()),
70
0
  m_isPageNumberOverridden(false),
71
0
  m_pageNumberOverride(0),
72
0
  m_pageNumberingType(page.getPageNumberingType()),
73
0
  m_pageNumberingFontName(page.getPageNumberingFontName()),
74
0
  m_pageNumberingFontSize(page.getPageNumberingFontSize()),
75
0
  m_headerFooterList(page.getHeaderFooterList()),
76
0
  m_pageSpan(page.getPageSpan())
77
0
{
78
0
  for (bool &i : m_isHeaderFooterSuppressed)
79
0
    i = false;
80
0
}
81
82
WPXPageSpan::~WPXPageSpan()
83
0
{
84
0
}
85
86
87
void WPXPageSpan::setHeaderFooter(const WPXHeaderFooterType type, const unsigned char headerFooterType, const WPXHeaderFooterOccurrence occurrence,
88
                                  const  std::shared_ptr<WPXSubDocument> &subDocument, WPXTableList tableList)
89
0
{
90
0
  WPXHeaderFooter headerFooter(type, occurrence, headerFooterType, subDocument, tableList);
91
0
  switch (occurrence)
92
0
  {
93
0
  case ALL:
94
0
  case NEVER:
95
0
    _removeHeaderFooter(type, ODD);
96
0
    _removeHeaderFooter(type, EVEN);
97
0
    _removeHeaderFooter(type, ALL);
98
0
    break;
99
0
  case ODD:
100
0
    _removeHeaderFooter(type, ODD);
101
0
    _removeHeaderFooter(type, ALL);
102
0
    break;
103
0
  case EVEN:
104
0
    _removeHeaderFooter(type, EVEN);
105
0
    _removeHeaderFooter(type, ALL);
106
0
    break;
107
0
  default:
108
0
    break;
109
0
  }
110
111
0
  if ((occurrence != NEVER) && (subDocument))
112
0
    m_headerFooterList.push_back(headerFooter);
113
114
0
  bool containsHFLeft = _containsHeaderFooter(type, ODD);
115
0
  bool containsHFRight = _containsHeaderFooter(type, EVEN);
116
117
0
  WPD_DEBUG_MSG(("Contains HFL: %i HFR: %i\n", containsHFLeft, containsHFRight));
118
0
  if (containsHFLeft && !containsHFRight)
119
0
  {
120
0
    WPD_DEBUG_MSG(("Inserting dummy header right\n"));
121
0
    WPXHeaderFooter dummyHeader(type, EVEN, DUMMY_INTERNAL_HEADER_FOOTER, nullptr);
122
0
    m_headerFooterList.push_back(dummyHeader);
123
0
  }
124
0
  else if (!containsHFLeft && containsHFRight)
125
0
  {
126
0
    WPD_DEBUG_MSG(("Inserting dummy header left\n"));
127
0
    WPXHeaderFooter dummyHeader(type, ODD, DUMMY_INTERNAL_HEADER_FOOTER, nullptr);
128
0
    m_headerFooterList.push_back(dummyHeader);
129
0
  }
130
0
}
131
132
void WPXPageSpan::_removeHeaderFooter(WPXHeaderFooterType type, WPXHeaderFooterOccurrence occurrence)
133
0
{
134
0
  for (auto iter = m_headerFooterList.begin(); iter != m_headerFooterList.end(); ++iter)
135
0
  {
136
0
    if ((*iter).getType() == type && (*iter).getOccurrence() == occurrence)
137
0
    {
138
0
      WPD_DEBUG_MSG(("WordPerfect: Removing header/footer element of type: %i since it is identical to %i\n",(*iter).getType(), type));
139
0
      m_headerFooterList.erase(iter);
140
0
      return;
141
0
    }
142
0
  }
143
0
}
144
145
bool WPXPageSpan::_containsHeaderFooter(WPXHeaderFooterType type, WPXHeaderFooterOccurrence occurrence)
146
0
{
147
0
  for (auto &iter : m_headerFooterList)
148
0
  {
149
0
    if (iter.getType()==type && iter.getOccurrence()==occurrence)
150
0
      return true;
151
0
  }
152
153
0
  return false;
154
0
}
155
156
inline bool operator==(const WPXHeaderFooter &headerFooter1, const WPXHeaderFooter &headerFooter2)
157
0
{
158
0
  return ((headerFooter1.getType() == headerFooter2.getType()) &&
159
0
          (headerFooter1.getSubDocument() == headerFooter2.getSubDocument()) &&
160
0
          (headerFooter1.getOccurrence() == headerFooter2.getOccurrence()) &&
161
0
          (headerFooter1.getInternalType() == headerFooter2.getInternalType()));
162
0
}
163
164
bool operator==(const WPXPageSpan &page1, const WPXPageSpan &page2)
165
0
{
166
0
  if ((page1.getMarginLeft() != page2.getMarginLeft()) || (page1.getMarginRight() != page2.getMarginRight()) ||
167
0
          (page1.getMarginTop() != page2.getMarginTop())|| (page1.getMarginBottom() != page2.getMarginBottom()))
168
0
    return false;
169
170
0
  if (page1.getPageNumberPosition() != page2.getPageNumberPosition())
171
0
    return false;
172
173
0
  if (page1.getPageNumberSuppression() != page2.getPageNumberSuppression())
174
0
    return false;
175
176
0
  if (page1.getPageNumberOverriden() != page2.getPageNumberOverriden() ||
177
0
          page1.getPageNumberOverride() != page2.getPageNumberOverride())
178
0
    return false;
179
180
0
  if (page1.getPageNumberingType() != page2.getPageNumberingType())
181
0
    return false;
182
183
0
  if (page1.getPageNumberingFontName() != page2.getPageNumberingFontName() ||
184
0
          page1.getPageNumberingFontSize() != page2.getPageNumberingFontSize())
185
0
    return false;
186
187
0
  for (unsigned char i=0; i<WPX_NUM_HEADER_FOOTER_TYPES; i++)
188
0
  {
189
0
    if (page1.getHeaderFooterSuppression(i) != page2.getHeaderFooterSuppression(i))
190
0
      return false;
191
0
  }
192
193
  // NOTE: yes this is O(n^2): so what? n=4 at most
194
0
  const std::vector<WPXHeaderFooter> headerFooterList1 = page1.getHeaderFooterList();
195
0
  const std::vector<WPXHeaderFooter> headerFooterList2 = page2.getHeaderFooterList();
196
0
  std::vector<WPXHeaderFooter>::const_iterator iter1;
197
0
  std::vector<WPXHeaderFooter>::const_iterator iter2;
198
199
0
  for (iter1 = headerFooterList1.begin(); iter1 != headerFooterList1.end(); ++iter1)
200
0
  {
201
0
    if (std::find(headerFooterList2.begin(), headerFooterList2.end(), (*iter1)) == headerFooterList2.end())
202
0
      return false;
203
0
  }
204
205
  // If we came here, we know that every header/footer that is found in the first page span is in the second too.
206
  // But this is not enought for us to know whether the page spans are equal. Now we have to check in addition
207
  // whether every header/footer that is in the second one is in the first too. If someone wants to optimize this,
208
  // (s)he is most welcome :-)
209
210
0
  for (iter2 = headerFooterList2.begin(); iter2 != headerFooterList2.end(); ++iter2)
211
0
  {
212
0
    if (std::find(headerFooterList1.begin(), headerFooterList1.end(), (*iter2)) == headerFooterList1.end())
213
0
      return false;
214
0
  }
215
216
217
0
  WPD_DEBUG_MSG(("WordPerfect: WPXPageSpan == comparison finished, found no differences\n"));
218
219
0
  return true;
220
0
}
221
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */