Dillo v3.1.1-46-g8a360e32
Loading...
Searching...
No Matches
textblock_iterator.cc
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2005-2007, 2012-2013 Sebastian Geerken <sgeerken@dillo.org>
5 *
6 * (Parts of this file were originally part of textblock.cc.)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "textblock.hh"
23#include "../lout/msg.h"
24#include "../lout/misc.hh"
25
26#include <stdio.h>
27#include <math.h>
28
29using namespace lout;
30
31namespace dw {
32
35 bool atEnd):
36 OOFAwareWidgetIterator (textblock, mask, atEnd, textblock->words->size ())
37{
38}
39
43 mask,
44 int wordIndex)
45{
46 TextblockIterator *tbIt = new TextblockIterator (textblock, mask, false);
47 tbIt->setValues (0, wordIndex);
48 return tbIt;
49}
50
52{
53 TextblockIterator *tbIt =
54 new TextblockIterator ((Textblock*)getWidget(), getMask(), false);
55 cloneValues (tbIt);
56 return tbIt;
57}
58
61{
62 DBG_OBJ_ENTER_O ("iterator", 0, getWidget (), "TextblockIterator::highlight",
63 "..., %d, %d, %d", start, end, layer);
64
67 intoStringBuffer (&sb);
68 DBG_OBJ_MSGF_O ("iterator", 1, getWidget (), "iterator: %s",
69 sb.getChars ());
70 }
71
72 if (inFlow ()) {
73 DBG_OBJ_MSGF_O ("iterator", 1, getWidget (), "in-flow index: %d",
74 getInFlowIndex ());
75
76 Textblock *textblock = (Textblock*)getWidget();
77 int index = getInFlowIndex (), index1 = index, index2 = index;
78
79 int oldStartIndex = textblock->hlStart[layer].index;
80 int oldStartChar = textblock->hlStart[layer].nChar;
81 int oldEndIndex = textblock->hlEnd[layer].index;
82 int oldEndChar = textblock->hlEnd[layer].nChar;
83
84 if (textblock->hlStart[layer].index > textblock->hlEnd[layer].index) {
85 /* nothing is highlighted */
86 textblock->hlStart[layer].index = index;
87 textblock->hlEnd[layer].index = index;
88 }
89
90 if (textblock->hlStart[layer].index >= index) {
91 index2 = textblock->hlStart[layer].index;
92 textblock->hlStart[layer].index = index;
93 textblock->hlStart[layer].nChar = start;
94 }
95
96 if (textblock->hlEnd[layer].index <= index) {
97 index2 = textblock->hlEnd[layer].index;
98 textblock->hlEnd[layer].index = index;
99 textblock->hlEnd[layer].nChar = end;
100 }
101
102 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlStart", layer, "index",
103 textblock->hlStart[layer].index);
104 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlStart", layer, "nChar",
105 textblock->hlStart[layer].nChar);
106 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlEnd", layer, "index",
107 textblock->hlEnd[layer].index);
108 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlEnd", layer, "nChar",
109 textblock->hlEnd[layer].nChar);
110
111 if (oldStartIndex != textblock->hlStart[layer].index ||
112 oldStartChar != textblock->hlStart[layer].nChar ||
113 oldEndIndex != textblock->hlEnd[layer].index ||
114 oldEndChar != textblock->hlEnd[layer].nChar)
115 textblock->queueDrawRange (index1, index2);
116 } else {
117 highlightOOF (start, end, layer);
118 }
119
120 DBG_OBJ_LEAVE_O (getWidget ());
121}
122
125{
126 DBG_OBJ_ENTER_O ("iterator", 0, getWidget (),
127 "TextblockIterator/unhighlight", "..., %d, %d",
128 direction, layer);
129
132 intoStringBuffer (&sb);
133 DBG_OBJ_MSGF_O ("iterator", 1, getWidget (), "iterator: %s",
134 sb.getChars ());
135 }
136
137 if (inFlow ()) {
138 DBG_OBJ_MSGF_O ("iterator", 1, getWidget (), "in-flow index: %d",
139 getInFlowIndex ());
140
141 Textblock *textblock = (Textblock*)getWidget();
142 int index = getInFlowIndex (), index1 = index, index2 = index;
143
144 if (textblock->hlStart[layer].index > textblock->hlEnd[layer].index)
145 return;
146
147 int oldStartIndex = textblock->hlStart[layer].index;
148 int oldStartChar = textblock->hlStart[layer].nChar;
149 int oldEndIndex = textblock->hlEnd[layer].index;
150 int oldEndChar = textblock->hlEnd[layer].nChar;
151
152 if (direction == 0) {
153 index1 = textblock->hlStart[layer].index;
154 index2 = textblock->hlEnd[layer].index;
155 textblock->hlStart[layer].index = 1;
156 textblock->hlEnd[layer].index = 0;
157 } else if (direction > 0 && textblock->hlStart[layer].index <= index) {
158 index1 = textblock->hlStart[layer].index;
159 textblock->hlStart[layer].index = index + 1;
160 textblock->hlStart[layer].nChar = 0;
161 } else if (direction < 0 && textblock->hlEnd[layer].index >= index) {
162 index1 = textblock->hlEnd[layer].index;
163 textblock->hlEnd[layer].index = index - 1;
164 textblock->hlEnd[layer].nChar = INT_MAX;
165 }
166
167 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlStart", layer, "index",
168 textblock->hlStart[layer].index);
169 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlStart", layer, "nChar",
170 textblock->hlStart[layer].nChar);
171 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlEnd", layer, "index",
172 textblock->hlEnd[layer].index);
173 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlEnd", layer, "nChar",
174 textblock->hlEnd[layer].nChar);
175
176 if (oldStartIndex != textblock->hlStart[layer].index ||
177 oldStartChar != textblock->hlStart[layer].nChar ||
178 oldEndIndex != textblock->hlEnd[layer].index ||
179 oldEndChar != textblock->hlEnd[layer].nChar)
180 textblock->queueDrawRange (index1, index2);
181 } else
182 unhighlightOOF (direction, layer);
183
184 DBG_OBJ_LEAVE_O (getWidget ());
185}
186
189{
190 if (inFlow ()) {
191 Textblock *textblock = (Textblock*)getWidget();
192
193 int index = getInFlowIndex ();
194 Word *word = textblock->words->getRef (index);
195 int firstWordOfLine, textOffset, lineYOffsetCanvas, lineBorderAscent;
196
197 int lineIndex = textblock->findLineOfWord (index);
198
199 // It may be that the line does not exist yet.
200 if (lineIndex != -1) {
201 // Line exists: simple.
202 Line *line = textblock->lines->getRef (lineIndex);
203 firstWordOfLine = line->firstWord;
204 textOffset = line->textOffset;
205 lineYOffsetCanvas = textblock->lineYOffsetCanvas (line);
206 lineBorderAscent = line->borderAscent;
207 } else {
208 // Line does not exist. Calculate the values in a similar way as in
209 // Textblock::addLine().
210 Line *prevLine = textblock->lines->size () > 0 ?
211 textblock->lines->getLastRef () : NULL;
212 firstWordOfLine = prevLine ? prevLine->lastWord + 1 : 0;
213
214 // The variable textOffset, defined below, is what Line::leftOffset
215 // will be for the next line; Line::textOffset itself cannot be
216 // calculated before the line is complete.
217 bool regardBorder =
218 textblock->mustBorderBeRegarded (textblock->lines->size ());
219 textOffset =
220 misc::max (regardBorder ? textblock->newLineLeftBorder : 0,
221 textblock->boxOffsetX () + textblock->leftInnerPadding
222 + (textblock->lines->size () == 0 ?
223 textblock->line1OffsetEff : 0));
224
226
227 lineBorderAscent = 0;
228 for (int i = firstWordOfLine; i < textblock->words->size (); i++) {
229 Word *w = textblock->words->getRef (i);
230 int borderAscent =
233 w->size.ascent;
234 lineBorderAscent = misc::max (lineBorderAscent, borderAscent);
235 }
236 }
237
238 allocation->x = textblock->allocation.x + textOffset;
239 for (int i = firstWordOfLine; i < index; i++) {
240 Word *w = textblock->words->getRef(i);
241 allocation->x += w->size.width + w->effSpace;
242 }
243 if (start > 0 && word->content.type == core::Content::TEXT) {
244 allocation->x += textblock->textWidth (word->content.text, 0, start,
245 word->style,
246 word->flags & Word::WORD_START,
247 (word->flags & Word::WORD_END)
248 && word->content.text[start]
249 == 0);
250 }
251 allocation->y = lineYOffsetCanvas + lineBorderAscent - word->size.ascent;
252
253 allocation->width = word->size.width;
254 if (word->content.type == core::Content::TEXT) {
255 int wordEnd = strlen(word->content.text);
256
257 if (start > 0 || end < wordEnd) {
258 end = misc::min(end, wordEnd); /* end could be INT_MAX */
260 textblock->textWidth (word->content.text, start, end - start,
261 word->style,
262 (word->flags & Word::WORD_START)
263 && start == 0,
264 (word->flags & Word::WORD_END)
265 && word->content.text[end] == 0);
266 }
267 }
268 allocation->ascent = word->size.ascent;
270 } else
271 getAllocationOOF (start, end, allocation);
272}
273
275{
276 return ((Textblock*)getWidget())->words->size ();
277}
278
280 core::Content *content)
281{
282 *content = ((Textblock*)getWidget())->words->getRef(index)->content;
283}
284
285} // namespace dw
void unhighlight(int direction, core::HighlightLayer layer)
Shrink highlighted region to no longer contain the current content.
lout::object::Object * clone()
Return an exact copy of the object.
static TextblockIterator * createWordIndexIterator(Textblock *textblock, core::Content::Type mask, int wordIndex)
TextblockIterator(Textblock *textblock, core::Content::Type mask, bool atEnd)
void highlight(int start, int end, core::HighlightLayer layer)
Extend highlighted region to contain part of the current content.
void getAllocation(int start, int end, core::Allocation *allocation)
Return the shape, which a part of the item, the iterator points on, allocates.
void getContentInFlow(int index, core::Content *content)
A Widget for rendering text blocks, i.e.
Definition textblock.hh:206
struct dw::Textblock::@28 hlEnd[core::HIGHLIGHT_NUM_LAYERS]
lout::misc::NotSoSimpleVector< Word > * words
Definition textblock.hh:611
int newLineLeftBorder
Definition textblock.hh:596
int yOffsetOfLineToBeCreated(int *lastMargin=NULL)
Includes margin, border, and padding.
bool mustBorderBeRegarded(Line *line)
Of nested text blocks, only the most inner one must regard the borders of floats.
Definition textblock.hh:696
struct dw::Textblock::@28 hlStart[core::HIGHLIGHT_NUM_LAYERS]
int findLineOfWord(int wordIndex)
Find the line of word wordIndex.
int textWidth(const char *text, int start, int len, core::style::Style *style, bool isStart, bool isEnd)
void queueDrawRange(int index1, int index2)
int lineYOffsetCanvas(Line *line, core::Allocation *allocation)
Definition textblock.hh:722
lout::misc::SimpleVector< Line > * lines
Definition textblock.hh:608
Allocation allocation
The current allocation: size and position, always relative to the canvas.
Definition widget.hh:203
style::Style * getStyle()
Definition widget.hh:468
void intoStringBuffer(misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Definition identity.cc:70
A class for fast concatenation of a large number of strings.
Definition misc.hh:567
const char * getChars()
Return a NUL-terminated strings containing all appended strings.
Definition misc.cc:86
This is the base class for many other classes, which defines very common virtual methods.
Definition object.hh:25
#define DBG_IF_RTFL
Definition debug.hh:73
#define DBG_OBJ_LEAVE_O(obj)
#define DBG_OBJ_MSGF_O(aspect, prio, obj, fmt,...)
#define DBG_OBJ_ENTER_O(aspect, prio, obj, funname, fmt,...)
#define DBG_OBJ_ARRATTRSET_NUM_O(obj, var, ind, attr, val)
HighlightLayer
Definition types.hh:43
Dw is in this namespace, or sub namespaces of this one.
T min(T a, T b)
Definition misc.hh:20
T max(T a, T b)
Definition misc.hh:21
core::style::Style * style
Definition textblock.hh:492
core::Requisition size
Definition textblock.hh:463
core::Content content
Definition textblock.hh:475
Represents the allocation, i.e.
Definition types.hh:164
@ WIDGET_IN_FLOW
widget in normal flow, so that this widget (containing this content) is both container (parent) and g...
Definition types.hh:207
const char * text
Definition types.hh:236
Widget * widget
Definition types.hh:237