Dillo v3.1.1-14-g8f67d6e0
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 DBG_OBJ_LEAVE_O (getWidget ());
120}
121
124{
125 DBG_OBJ_ENTER_O ("iterator", 0, getWidget (),
126 "TextblockIterator/unhighlight", "..., %d, %d",
127 direction, layer);
128
131 intoStringBuffer (&sb);
132 DBG_OBJ_MSGF_O ("iterator", 1, getWidget (), "iterator: %s",
133 sb.getChars ());
134 }
135
136 if (inFlow ()) {
137 DBG_OBJ_MSGF_O ("iterator", 1, getWidget (), "in-flow index: %d",
138 getInFlowIndex ());
139
140 Textblock *textblock = (Textblock*)getWidget();
141 int index = getInFlowIndex (), index1 = index, index2 = index;
142
143 if (textblock->hlStart[layer].index > textblock->hlEnd[layer].index)
144 return;
145
146 int oldStartIndex = textblock->hlStart[layer].index;
147 int oldStartChar = textblock->hlStart[layer].nChar;
148 int oldEndIndex = textblock->hlEnd[layer].index;
149 int oldEndChar = textblock->hlEnd[layer].nChar;
150
151 if (direction == 0) {
152 index1 = textblock->hlStart[layer].index;
153 index2 = textblock->hlEnd[layer].index;
154 textblock->hlStart[layer].index = 1;
155 textblock->hlEnd[layer].index = 0;
156 } else if (direction > 0 && textblock->hlStart[layer].index <= index) {
157 index1 = textblock->hlStart[layer].index;
158 textblock->hlStart[layer].index = index + 1;
159 textblock->hlStart[layer].nChar = 0;
160 } else if (direction < 0 && textblock->hlEnd[layer].index >= index) {
161 index1 = textblock->hlEnd[layer].index;
162 textblock->hlEnd[layer].index = index - 1;
163 textblock->hlEnd[layer].nChar = INT_MAX;
164 }
165
166 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlStart", layer, "index",
167 textblock->hlStart[layer].index);
168 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlStart", layer, "nChar",
169 textblock->hlStart[layer].nChar);
170 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlEnd", layer, "index",
171 textblock->hlEnd[layer].index);
172 DBG_OBJ_ARRATTRSET_NUM_O (textblock, "hlEnd", layer, "nChar",
173 textblock->hlEnd[layer].nChar);
174
175 if (oldStartIndex != textblock->hlStart[layer].index ||
176 oldStartChar != textblock->hlStart[layer].nChar ||
177 oldEndIndex != textblock->hlEnd[layer].index ||
178 oldEndChar != textblock->hlEnd[layer].nChar)
179 textblock->queueDrawRange (index1, index2);
180 } else
181 unhighlightOOF (direction, layer);
182
183 DBG_OBJ_LEAVE_O (getWidget ());
184}
185
188{
189 if (inFlow ()) {
190 Textblock *textblock = (Textblock*)getWidget();
191
192 int index = getInFlowIndex ();
193 Word *word = textblock->words->getRef (index);
194 int firstWordOfLine, textOffset, lineYOffsetCanvas, lineBorderAscent;
195
196 int lineIndex = textblock->findLineOfWord (index);
197
198 // It may be that the line does not exist yet.
199 if (lineIndex != -1) {
200 // Line exists: simple.
201 Line *line = textblock->lines->getRef (lineIndex);
202 firstWordOfLine = line->firstWord;
203 textOffset = line->textOffset;
204 lineYOffsetCanvas = textblock->lineYOffsetCanvas (line);
205 lineBorderAscent = line->borderAscent;
206 } else {
207 // Line does not exist. Calculate the values in a similar way as in
208 // Textblock::addLine().
209 Line *prevLine = textblock->lines->size () > 0 ?
210 textblock->lines->getLastRef () : NULL;
211 firstWordOfLine = prevLine ? prevLine->lastWord + 1 : 0;
212
213 // The variable textOffset, defined below, is what Line::leftOffset
214 // will be for the next line; Line::textOffset itself cannot be
215 // calculated before the line is complete.
216 bool regardBorder =
217 textblock->mustBorderBeRegarded (textblock->lines->size ());
218 textOffset =
219 misc::max (regardBorder ? textblock->newLineLeftBorder : 0,
220 textblock->boxOffsetX () + textblock->leftInnerPadding
221 + (textblock->lines->size () == 0 ?
222 textblock->line1OffsetEff : 0));
223
225
226 lineBorderAscent = 0;
227 for (int i = firstWordOfLine; i < textblock->words->size (); i++) {
228 Word *w = textblock->words->getRef (i);
229 int borderAscent =
232 w->size.ascent;
233 lineBorderAscent = misc::max (lineBorderAscent, borderAscent);
234 }
235 }
236
237 allocation->x = textblock->allocation.x + textOffset;
238 for (int i = firstWordOfLine; i < index; i++) {
239 Word *w = textblock->words->getRef(i);
240 allocation->x += w->size.width + w->effSpace;
241 }
242 if (start > 0 && word->content.type == core::Content::TEXT) {
243 allocation->x += textblock->textWidth (word->content.text, 0, start,
244 word->style,
245 word->flags & Word::WORD_START,
246 (word->flags & Word::WORD_END)
247 && word->content.text[start]
248 == 0);
249 }
250 allocation->y = lineYOffsetCanvas + lineBorderAscent - word->size.ascent;
251
252 allocation->width = word->size.width;
253 if (word->content.type == core::Content::TEXT) {
254 int wordEnd = strlen(word->content.text);
255
256 if (start > 0 || end < wordEnd) {
257 end = misc::min(end, wordEnd); /* end could be INT_MAX */
259 textblock->textWidth (word->content.text, start, end - start,
260 word->style,
261 (word->flags & Word::WORD_START)
262 && start == 0,
263 (word->flags & Word::WORD_END)
264 && word->content.text[end] == 0);
265 }
266 }
267 allocation->ascent = word->size.ascent;
269 } else
270 getAllocationOOF (start, end, allocation);
271}
272
274{
275 return ((Textblock*)getWidget())->words->size ();
276}
277
279 core::Content *content)
280{
281 *content = ((Textblock*)getWidget())->words->getRef(index)->content;
282}
283
284} // 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
lout::misc::NotSoSimpleVector< Word > * words
Definition textblock.hh:611
struct dw::Textblock::@30 hlStart[core::HIGHLIGHT_NUM_LAYERS]
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::@30 hlEnd[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:183
style::Style * getStyle()
Definition widget.hh:448
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:566
const char * getChars()
Return a NUL-terminated strings containing all appended strings.
Definition misc.cc:92
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:19
T max(T a, T b)
Definition misc.hh:20
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