23#include "../lout/msg.h"
24#include "../lout/misc.hh"
25#include "../lout/unicode.hh"
26#include "../lout/debug.hh"
67 this->xWordWidget = xWordWidget;
68 this->lineNo = lineNo;
77 && wordNo < textblock->words->size()
78 && lineNo < textblock->lines->size();
85 Line *line = textblock->lines->getRef (lineNo);
86 *x = textblock->allocation.x + this->xWordWidget;
87 *y = textblock->lineYOffsetCanvas (line);
88 *width = textblock->words->getRef(wordNo)->size.width;
93 int *widthRef,
int *heightRef)
96 textblock->getPaddingArea (xRef, yRef, widthRef, heightRef);
101 return textblock->words->getRef(wordNo)->style;
106 textblock->queueDrawArea (x - textblock->allocation.x,
107 y - textblock->allocation.y, width, height);
116 *width = textblock->words->getRef(wordNo)->effSpace;
121 return textblock->words->getRef(wordNo)->spaceStyle;
134 {
"\xe2\x80\x94",
false,
true,
false,
235 paragraphs =
new misc::SimpleVector <Paragraph> (1);
236 lines =
new misc::SimpleVector <Line> (1);
238 words =
new misc::NotSoSimpleVector <Word> (1);
239 anchors =
new misc::SimpleVector <Anchor> (1);
264 hlEnd[layer].index = 0;
265 hlEnd[layer].nChar = 0;
283 for (
int i = 0; i <
words->size(); i++)
286 for (
int i = 0; i <
anchors->size(); i++) {
310 Widget **references,
int *x,
int *y)
312 DBG_OBJ_ENTER (
"resize", 0,
"sizeRequestImpl",
"%d, ...", numPos);
350 if (
lines->size () > 0) {
351 Line *firstLine =
lines->getRef(0), *lastLine =
lines->getLastRef ();
372 lastLine->top - firstLine->
borderAscent + lastLine->borderAscent +
378 lastLine->borderDescent, lastLine->marginDescent);
387 "before considering lineBreakWidth (= %d): %d * (%d + %d)",
393 DBG_OBJ_MSG (
"resize", 1,
"lineBreakWidth needs no consideration");
395 DBG_OBJ_MSGF (
"resize", 1,
"before correction: %d * (%d + %d)",
434 int widgetMargin,
int lineBorderTotal,
437 DBG_OBJ_ENTER (
"resize", 0,
"calcVerticalBorder",
"%d, %d, %d, %d, %d",
438 widgetPadding, widgetBorder, widgetMargin, lineBorderTotal,
443 if (widgetPadding == 0 && widgetBorder == 0) {
444 if (lineMarginTotal - lineBorderTotal >= widgetMargin)
445 result = lineMarginTotal;
447 result = widgetMargin + lineBorderTotal;
449 result = lineMarginTotal + widgetPadding + widgetBorder + widgetMargin;
489 DBG_OBJ_MSGF (
"resize", 1,
"paragraphs[%d]->maxParMin = %d (%d)",
492 DBG_OBJ_MSGF (
"resize", 1,
"paragraphs[%d]->maxParMax = %d (%d)",
497 DBG_OBJ_MSGF (
"resize", 0,
"after considering paragraphs: %d (%d) / %d (%d)",
508 DBG_OBJ_MSGF (
"resize", 0,
"after adding diff: %d (%d) / %d (%d)",
516 DBG_OBJ_MSGF (
"resize", 0,
"after correction: %d (%d) / %d (%d)",
523 "finally, after considering OOFM: %d (%d) / %d (%d)",
541 OOFAwareWidget::notifySetAsTopLevel ();
549 OOFAwareWidget::notifySetParent ();
552 for (
int i = 0; i <
NUM_OOFM; i++) {
572 DBG_OBJ_ENTER (
"resize", 0,
"sizeAllocateImpl",
"%d, %d; %d * (%d + %d)",
580 int lineIndex, wordIndex;
596 for (lineIndex = 0; lineIndex <
lines->size (); lineIndex++) {
611 line =
lines->getRef (lineIndex);
614 DBG_OBJ_MSGF (
"resize", 1,
"xCursor = %d (initially)", xCursor);
618 word =
words->getRef (wordIndex);
627 "allocating widget in flow: line %d, word %d",
628 lineIndex, wordIndex);
651 if (childAllocation.
x != oldChildAllocation->
x ||
652 childAllocation.
y != oldChildAllocation->
y ||
653 childAllocation.
width != oldChildAllocation->
width) {
662 oldChildAllocation->
y - this->allocation.y);
666 }
else if (childAllocation.
ascent + childAllocation.
descent !=
688 oldChildAllocation->
y - this->allocation.y +
689 oldChildAllocation->
ascent +
704 DBG_OBJ_MSGF (
"resize", 1,
"xCursor = %d (after word %d)",
706 DBG_MSG_WORD (
"resize", 1,
"<i>that is:</i> ", wordIndex,
"");
716 for (
int i = 0; i <
anchors->size(); i++) {
722 lines->size () <= 0 ||
742 OOFAwareWidget::calcExtraSpaceImpl (numPos, references, x, y);
744 int clearPosition = 0;
758 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getAvailWidthOfChild",
"%p, %s",
759 child, forceValue ?
"true" :
"false");
780 int maxWidth = child->calcWidth (child->getStyle()->maxWidth,
781 -1,
this, -1,
false);
785 int minWidth = child->calcWidth (child->getStyle()->minWidth,
786 -1,
this, -1,
false);
795 width = Widget::getAvailWidthOfChild (child, forceValue);
797 if (forceValue &&
this == child->getContainer () &&
817 return Widget::getAvailHeightOfChild (child, forceValue);
824 for (
int i = 0; i <
words->size (); i++) {
838 "Textblock/affectsSizeChangeContainerChild",
"%p", child);
847 ret = Widget::affectsSizeChangeContainerChild (child);
863 if (
lines->size () > 0) {
914 DBG_OBJ_ENTER (
"resize", 1,
"markExtremesChange",
"%d", ref);
990 _MSG(
"MN tb=%p tooltipOld=%p hoverTooltip=%p\n",
1032 int charPos = 0, link = -1;
1035 if (
words->size () == 0) {
1042 if (event->
yCanvas < yFirst) {
1045 }
else if (event->
yCanvas >= yLast) {
1047 wordIndex =
words->size () - 1;
1069 int wordStartX = nextWordStartX;
1073 if (event->
xWidget >= wordStartX &&
1074 event->
xWidget < nextWordStartX) {
1081 if (wordIndex < line->lastWord &&
1082 (
words->getRef(wordIndex + 1)->content.type !=
1096 int glyphX = wordStartX;
1111 nextCharPos - charPos, word->
style,
1112 isStartWord && charPos == 0,
1115 if (event->
xWidget > glyphX + glyphWidth) {
1116 glyphX += glyphWidth;
1117 charPos = nextCharPos;
1119 }
else if (event->
xWidget >= glyphX + glyphWidth/2){
1122 charPos = nextCharPos;
1128 nextCharPos - charPos,
1130 isStartWord && charPos == 0,
1135 charPos = nextCharPos;
1143 if (event->
xWidget >= (wordStartX + nextWordStartX) /2)
1160 DBG_OBJ_MSGF (
"events", 1,
"wordIndex = %d", wordIndex);
1161 DBG_MSG_WORD (
"events", 1,
"<i>this is:</i> ", wordIndex,
"");
1187 int x,
int yBase,
int width)
1217 const char *text,
int start,
int len,
bool isStart,
1239 bool initial_seen =
false;
1241 for (
int i = 0; i < start; i++)
1243 initial_seen =
true;
1257 int newlen = strlen(initial) + len-after;
1258 str = (
char *)malloc(newlen + 1);
1259 strcpy(str, initial);
1260 strncpy(str + strlen(str), text+after, len-after);
1268 str ? str : text + start, str ? strlen(str) : len);
1284 int xWidget,
int yWidgetBase)
1287 bool drawHyphen = wordIndex2 == line->
lastWord
1292 for (
int i = wordIndex1; i <= wordIndex2; i++)
1293 w +=
words->getRef(i)->size.width;
1294 w +=
words->getRef(wordIndex2)->hyphenWidth;
1299 if (wordIndex1 == wordIndex2 && !drawHyphen) {
1301 Word *word =
words->getRef (wordIndex1);
1303 false,
style, view, area, xWidget, yWidgetBase);
1306 int l = 0, totalWidth = 0;
1307 for (
int i = wordIndex1; i <= wordIndex2; i++) {
1313 char *text =
new char[l + (drawHyphen ? strlen (
hyphenDrawChar) : 0) + 1];
1315 for (
int i = wordIndex1; i <= wordIndex2; i++) {
1316 const char * t =
words->getRef(i)->content.text;
1317 strcpy (text + p, t);
1327 drawWord0 (wordIndex1, wordIndex2, text, totalWidth, drawHyphen,
1328 style, view, area, xWidget, yWidgetBase);
1338 const char *text,
int totalWidth,
bool drawHyphen,
1356 yWorldBase, text, 0, strlen (text), isStartTotal, isEndTotal);
1360 yWorldBase, totalWidth);
1365 const int wordLen = strlen (text);
1377 for (
int i = wordIndex1; i <
hlStart[layer].index; i++)
1380 firstCharIdx += strlen (
words->getRef(i)->content.text);
1384 lastCharIdx = wordLen;
1388 (
int)strlen (
words->getRef(
hlEnd[layer].index)
1390 for (
int i = wordIndex1; i <
hlEnd[layer].index; i++)
1393 lastCharIdx += strlen (
words->getRef(i)->content.text);
1400 isEndTotal && text[firstCharIdx] == 0);
1403 if (!drawHyphen && firstCharIdx == 0 && lastCharIdx == wordLen)
1407 lastCharIdx - firstCharIdx,
style,
1408 isStartTotal && firstCharIdx == 0,
1409 isEndTotal && text[lastCharIdx] == 0);
1425 yWorldBase, text, firstCharIdx,
1426 lastCharIdx - firstCharIdx,
1427 isStartTotal && firstCharIdx == 0,
1428 isEndTotal && lastCharIdx == wordLen);
1432 xStart, yWorldBase, width);
1448 bool highlight =
false;
1494 DBG_OBJ_ENTER (
"draw", 0,
"drawLine",
"..., [%d, %d, %d * %d]",
1500 DBG_OBJ_MSGF (
"draw", 1,
"line from %d to %d (%d words), at (%d, %d)",
1502 xWidget, yWidgetBase);
1511 DBG_MSG_WORD (
"draw", 2,
"<i>drawing: </i>", wordIndex,
"");
1527 child->
draw (view, &childArea, context);
1529 int wordIndex2 = wordIndex;
1530 while (wordIndex2 < line->lastWord &&
1531 (
words->getRef(wordIndex2)->flags
1533 word->
style ==
words->getRef(wordIndex2 + 1)->style)
1536 drawWord(line, wordIndex, wordIndex2, view, area,
1537 xWidget, yWidgetBase);
1539 for (
int i = wordIndex; i <= wordIndex2; i++)
1540 wordSize +=
words->getRef(i)->size.width;
1542 wordIndex = wordIndex2;
1543 word =
words->getRef(wordIndex);
1547 if (word->
effSpace > 0 && wordIndex < line->lastWord &&
1548 words->getRef(wordIndex + 1)->content.type !=
1555 drawSpace (wordIndex, view, area, xWidget + wordSize,
1561 xWidget += wordSize + word->
effSpace;
1581 if (
lines->size() == 0)
1589 lines->getRef(0)->borderAscent,
1590 lines->getRef(0)->marginAscent));
1601 DBG_OBJ_ENTER (
"events", 0,
"findLineIndex",
"%d, %d", y, ascent);
1606 int maxIndex =
lines->size () - 1;
1607 int step,
index, low = 0;
1609 step = (
lines->size() + 1) >> 1;
1610 while ( step > 1 ) {
1614 step = (step + 1) >> 1;
1640 if (wordIndex < 0 || wordIndex >=
words->size () ||
1642 lines->size () <= 0 || wordIndex >
lines->getLastRef()->lastWord)
1645 int high =
lines->size () - 1,
index, low = 0;
1648 index = (low + high) / 2;
1649 if (wordIndex >=
lines->getRef(
index)->firstWord) {
1650 if (wordIndex <= lines->getRef(
index)->lastWord)
1666 if (wordIndex < 0 || wordIndex >=
words->size () ||
1670 wordIndex >
paragraphs->getLastRef()->lastWord))
1674 index = (low + high) / 2;
1676 if (wordIndex <= paragraphs->getRef(
index)->lastWord)
1690 int lineIndex, wordIndex;
1691 int xCursor, lastXCursor, yWidgetBase;
1699 line =
lines->getRef (lineIndex);
1706 word =
words->getRef (wordIndex);
1707 lastXCursor = xCursor;
1709 if (lastXCursor <= x && xCursor > x) {
1710 if (x >= xCursor - word->
effSpace) {
1711 if (wordIndex < line->lastWord &&
1712 (
words->getRef(wordIndex + 1)->content.type !=
1721 y <= yWidgetBase + word->size.descent)
1734 DBG_OBJ_ENTER (
"draw", 0,
"Textblock::drawLevel",
"(%d, %d, %d * %d), %s",
1741 lineIndex <
lines->size (); lineIndex++) {
1747 drawLine (line, view, area, context);
1754 for (
int oofmIndex = 0; oofmIndex <
NUM_OOFM; oofmIndex++) {
1755 for (
int wordIndex = 0; wordIndex <
words->size (); wordIndex++) {
1767 OOFAwareWidget::drawLevel (view, area, level, context);
1780 DBG_OBJ_ENTER (
"construct.word", 0,
"addWord",
"%d * (%d + %d), %d, %p",
1790 int wordNo =
words->size () - 1;
1795 return words->getRef (wordNo);
1932 bool initial_seen =
false;
1934 for (
int i = 0; i < start; i++)
1936 initial_seen =
true;
1984 int height, leading;
2005 size->
ascent += leading / 2;
2006 size->
descent += leading - (leading / 2);
2028 DBG_OBJ_ENTER (
"construct.word", 0,
"addText",
"..., %d, %p",
2034 for (
const char *s = text; s; s =
nextUtf8Char (s, text + len - s)) {
2038 if (s <= text + len - lDiv) {
2039 if (memcmp (s,
divChars[j].s, lDiv *
sizeof (
char)) == 0)
2044 if (foundDiv != -1) {
2045 if (
divChars[foundDiv].penaltyIndexLeft != -1)
2047 if (
divChars[foundDiv].penaltyIndexRight != -1)
2052 if (numParts == 1) {
2065 PRINTF (
"HYPHENATION: '");
2066 for (
size_t i = 0; i < len; i++)
2068 PRINTF (
"', with %d parts\n", numParts);
2071 int n = 0, totalLenCharRemoved = 0;
2072 int *partPenaltyIndex =
new int[numParts - 1];
2073 int *partStart =
new int[numParts];
2074 int *partEnd =
new int[numParts];
2075 bool *charRemoved =
new bool[numParts - 1];
2076 bool *canBeHyphenated =
new bool[numParts + 1];
2077 bool *permDivChar =
new bool[numParts - 1];
2078 bool *unbreakableForMinWidth =
new bool[numParts - 1];
2079 canBeHyphenated[0] = canBeHyphenated[numParts] =
true;
2081 partEnd[numParts - 1] = len;
2083 for (
const char *s = text; s; s =
nextUtf8Char (s, text + len - s)) {
2087 if (s <= text + len - lDiv) {
2088 if (memcmp (s,
divChars[j].s, lDiv *
sizeof (
char)) == 0)
2093 if (foundDiv != -1) {
2094 int lDiv = strlen (
divChars[foundDiv].s);
2096 if (
divChars[foundDiv].charRemoved) {
2097 assert (
divChars[foundDiv].penaltyIndexLeft != -1);
2098 assert (
divChars[foundDiv].penaltyIndexRight == -1);
2101 charRemoved[n] =
true;
2102 permDivChar[n] =
false;
2103 unbreakableForMinWidth[n] =
2106 partEnd[n] = s - text;
2107 partStart[n + 1] = s - text + lDiv;
2109 totalLenCharRemoved += lDiv;
2111 assert (
divChars[foundDiv].penaltyIndexLeft != -1 ||
2112 divChars[foundDiv].penaltyIndexRight != -1);
2114 if (
divChars[foundDiv].penaltyIndexLeft != -1) {
2116 charRemoved[n] =
false;
2117 permDivChar[n] =
false;
2118 unbreakableForMinWidth[n] =
2121 partEnd[n] = s - text;
2122 partStart[n + 1] = s - text;
2126 if (
divChars[foundDiv].penaltyIndexRight != -1) {
2128 charRemoved[n] =
false;
2129 permDivChar[n] =
true;
2130 unbreakableForMinWidth[n] =
2133 partEnd[n] = s - text + lDiv;
2134 partStart[n + 1] = s - text + lDiv;
2142 const char *textWithoutHyphens;
2143 char *textWithoutHyphensBuf =
new char[len - totalLenCharRemoved];
2144 int *breakPosWithoutHyphens;
2145 int *breakPosWithoutHyphensBuf =
new int[numParts - 1];
2147 if (totalLenCharRemoved == 0) {
2149 textWithoutHyphens = text;
2153 breakPosWithoutHyphens = partEnd;
2156 textWithoutHyphens = textWithoutHyphensBuf;
2157 breakPosWithoutHyphens = breakPosWithoutHyphensBuf;
2160 for (
int i = 0; i < numParts; i++) {
2161 memmove (textWithoutHyphensBuf + n, text + partStart[i],
2162 partEnd[i] - partStart[i]);
2163 n += partEnd[i] - partStart[i];
2164 if (i < numParts - 1)
2165 breakPosWithoutHyphensBuf[i] = n;
2169 PRINTF(
"H... without hyphens: '");
2170 for (
size_t i = 0; i < len - totalLenCharRemoved; i++)
2171 PUTCHAR(textWithoutHyphens[i]);
2176 numParts - 1, breakPosWithoutHyphens, wordSize);
2179 for (
int i = 0; i < numParts; i++) {
2185 if (canBeHyphenated[i] && canBeHyphenated[i + 1])
2188 if(i < numParts - 1) {
2194 if (unbreakableForMinWidth[i])
2202 if (i == numParts - 1)
2205 addText0 (text + partStart[i], partEnd[i] - partStart[i],
2217 if(i < numParts - 1) {
2221 penalties[partPenaltyIndex[i]][1],
false);
2239 delete[] partPenaltyIndex;
2242 delete[] charRemoved;
2243 delete[] canBeHyphenated;
2244 delete[] permDivChar;
2245 delete[] unbreakableForMinWidth;
2246 delete[] textWithoutHyphensBuf;
2247 delete[] breakPosWithoutHyphensBuf;
2256 int numBreaks,
int *breakPos,
2260 int lastStart = breakPos[numBreaks - 1];
2262 &wordSize[numBreaks],
true,
true);
2264 PRINTF(
"H... [%d] '", numBreaks);
2265 for (
size_t i = 0; i < textLen - lastStart; i++)
2267 PRINTF(
"' -> %d\n", wordSize[numBreaks].width);
2271 for (
int i = numBreaks - 1; i >= 0; i--) {
2272 int start = (i == 0) ? 0 : breakPos[i - 1];
2274 i == 0, i == numBreaks - 1);
2276 PRINTF(
"H... [%d] '", i);
2277 for (
size_t j = 0; j < textLen - start; j++)
2279 PRINTF(
"' -> %d\n", wordSize[i].width);
2281 for (
int j = i + 1; j < numBreaks + 1; j++) {
2283 PRINTF(
"H... - %d = %d\n", wordSize[j].width, wordSize[i].width);
2295 DBG_OBJ_ENTER (
"resize", 0,
"calcSizeOfWidgetInFlow",
"%d, %p, ...",
2298 bool result, firstWordOfLine;
2303 firstWordOfLine = wordIndex == 1 ||
2307 firstWordOfLine = wordIndex == 0 ||
2313 if (firstWordOfLine &&
2319 int lastWord =
lines->empty () ? -1 :
lines->getLastRef()->lastWord;
2320 assert (wordIndex > lastWord);
2341 int yRel = yLine -
min (lastMargin, widget->getStyle()->margin.top);
2344 "leftBorder = %d + %d + (%d == 0 ? %d : 0) = %d, "
2345 "rightBorder = %d, yRel = %d - min (%d, %d) = %d",
2348 widget->getStyle()->margin.top, yRel);
2353 int oldXRel = leftBorder;
2356 widget->sizeRequest (size, childParams.
getNumPos (),
2358 childParams.
getY ());
2367 switch(widget->getStyle()->textAlign) {
2386 if (xRel < leftBorder)
2389 DBG_OBJ_MSGF (
"resize", 2,
"xRel = %d, oldXRel = %d", xRel, oldXRel);
2393 if (xRel == oldXRel)
2397 widget->sizeRequest (size, childParams.
getNumPos (),
2399 childParams.
getY ());
2411 DBG_OBJ_MSG (
"resize", 1,
"do not pass position");
2412 widget->sizeRequest (size);
2423 if (reference ==
this) {
2440 "..., %d, %s:%s:%s:%s:%s:%s:%s:%s, %p, %d * (%d + %d)",
2498 DBG_OBJ_MSGF (
"construct.word", 1,
"ouf of flow: oofmIndex = %d (%s)",
2508 DBG_OBJ_MSGF (
"construct.word", 1,
"oofmSubRef = %d => parentRef = %d",
2574 if (
lines->size () == 0)
2578 copy = Widget::addAnchor (name, y);
2580 copy = Widget::addAnchor (name);
2593 anchor->
name = copy;
2610 int wordIndex =
words->size () - 1;
2611 if (wordIndex >= 0) {
2629 DBG_OBJ_ENTER (
"construct.word", 0,
"addBreakOption",
"%p, %s",
2630 style, forceBreak ?
"true" :
"false");
2632 int wordIndex =
words->size () - 1;
2633 if (wordIndex >= 0) {
2645 DBG_OBJ_ENTER (
"construct.word", 0,
"fillSpace",
"%d, ...", wordNo);
2647 DBG_OBJ_MSGF (
"construct.word", 1,
"style.white-space = %s",
2655 "pre-line" :
"???");
2676 !word->content.space &&
2681 word->content.space =
true;
2682 word->origSpace = word->effSpace =
2687 word->spaceStyle->unref ();
2688 word->spaceStyle =
style;
2703 int breakPenalty1,
int breakPenalty2,
2706 DBG_OBJ_ENTER (
"construct.word", 0,
"setBreakOption",
"..., %d, %d, %s",
2707 breakPenalty1, breakPenalty2, forceBreak ?
"true" :
"false");
2746 DBG_OBJ_ENTER (
"construct.word", 0,
"addParbreak",
"%d, %p",
2749 "<i>No nesting! Stack trace may be incomplete.</i>");
2757 if (
words->size () == 0 ||
2767 for (
Widget *widget =
this;
2768 widget->getParent() != NULL &&
2771 widget = widget->getParent ()) {
2774 bool isfirst = (textblock2->
words->getRef(
index)->content.type
2776 && textblock2->
words->getRef(
index)->content.widget
2786 ->getRef(lineno - 1)->firstWord)) &&
2806 if ((word =
words->getRef(
words->size () - 1)) &&
2840 if (
words->size () == 0 ||
2869 assert (
words->size () >= 1);
2870 assert (
words->getRef(
words->size () - 1)->content.type
2886 if (
words->size () >= 2)
2887 words->getRef(
words->size () - 2)->origSpace =
2888 words->getRef(
words->size () - 2)->effSpace = 0;
2895 DBG_OBJ_ENTER (
"events", 0,
"Textblock::getWidgetAtPointLevel",
"%d, %d, %s",
2898 Widget *widgetAtPoint = NULL;
2905 if (lineIndex >= 0 && lineIndex < lines->size ()) {
2908 for (
int wordIndex = line->
lastWord;
2909 widgetAtPoint == NULL && wordIndex >= line->
firstWord;
2925 for (
int oofmIndex =
NUM_OOFM; widgetAtPoint == NULL && oofmIndex >= 0;
2927 for (
int wordIndex =
words->size () - 1;
2928 widgetAtPoint == NULL && wordIndex >= 0; wordIndex--) {
2944 OOFAwareWidget::getWidgetAtPointLevel (x, y, level, context);
2949 return widgetAtPoint;
2958 if (
lines->size() > 0) {
2997 for (
int lineIndex = 0; lineIndex <
lines->size(); lineIndex++) {
2998 bool changed =
false;
3011 styleAttrs = *old_style;
3017 styleAttrs = *old_style;
3047 bool includeFirstSpace,
bool includeLastSpace)
3053 DBG_OBJ_ENTER (
"draw", 0,
"queueDrawRange",
"%d, %d", index1, index2);
3066 if (line1idx >= 0 && line2idx >= 0) {
3068 *line2 =
lines->getRef (line2idx);
3072 line2->contentDescent - y;
3095 if (lineNo >= 0 && lineNo < lines->size ())
3115 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getGeneratorX",
"%d", oofmIndex);
3132 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getGeneratorY",
"%d", oofmIndex);
3149 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getGeneratorRest",
"%d", oofmIndex);
3189 int firstWordAfterLastLine =
3190 lines->size() > 0 ?
lines->getLastRef()->lastWord + 1 : 0;
3191 for (
int i = firstWordAfterLastLine; i <
words->size(); i++) {
3206 int w0 =
lines->size () > 0 ?
lines->getLastRef()->maxLineWidth : 0;
3209 DBG_OBJ_MSGF (
"resize", 1,
"wThis = min(%d + %d + %d, %d) = %d",
3212 int w =
max(wThis, wChild);
3240 "toplevel: %s, block: %s, float: %s, abspos: %s, fixpos: %s",
3246 result = toplevel || (block && !(vloat || abspos || fixpos));
3271 int firstWord = lineNo == 0 ? 0 :
lines->getRef(lineNo - 1)->lastWord + 1;
3272 int lastWord = lineNo <
lines->size() ?
3273 lines->getRef(lineNo)->lastWord :
words->size() - 1;
3280 DBG_OBJ_ENTER (
"resize", 0,
"getWidgetRegardingBorderForLine",
"%d, %d",
3281 firstWord, lastWord);
3286 if (firstWord < words->size ()) {
3291 DBG_MSG_WORD (
"resize", 1,
"<i>first word:</i> ", firstWord,
"");
3304 return widgetRegardingBorder;
3329 if (
lines->size () == 0) {
3336 Line *firstLine =
lines->getRef (0), *lastLine =
lines->getLastRef ();
3342 - firstLine->
borderAscent + lastLine->top + lastLine->totalHeight (0);
3344 *lastMargin = lastLine->marginDescent - lastLine->borderDescent;
Base class (rather a tag interface) for those widgets regarding borders defined by floats,...
bool lineMustBeBroken(int penaltyIndex)
void setPenalty(int penalty)
void setPenalties(int penalty1, int penalty2)
Sets the penalty, multiplied by 100.
void getBgArea(int *x, int *y, int *width, int *height)
Return the area covered by the background image.
core::style::Style * getStyle()
Return the style this background image is part of.
static TextblockIterator * createWordIndexIterator(Textblock *textblock, core::Content::Type mask, int wordIndex)
Implementation used for words.
bool readyToDraw()
If this method returns false, nothing is done at all.
void draw(int x, int y, int width, int height)
Draw (or queue for drawing) an area, which is given in canvas coordinates.
void setData(int xWordWidget, int lineNo)
WordImgRenderer(Textblock *textblock, int wordNo)
void getBgArea(int *x, int *y, int *width, int *height)
Return the area covered by the background image.
void getRefArea(int *xRef, int *yRef, int *widthRef, int *heightRef)
Return the "reference area".
core::style::Style * getStyle()
Return the style this background image is part of.
A Widget for rendering text blocks, i.e.
void drawLine(Line *line, core::View *view, core::Rectangle *area, core::DrawingContext *context)
int findParagraphOfWord(int wordIndex)
Find the paragraph of word wordIndex.
void drawWord0(int wordIndex1, int wordIndex2, const char *text, int totalWidth, bool drawHyphen, core::style::Style *style, core::View *view, core::Rectangle *area, int xWidget, int yWidgetBase)
TODO Comment.
void calcTextSizes(const char *text, size_t textLen, core::style::Style *style, int numBreaks, int *breakPos, core::Requisition *wordSize)
void breakAdded()
Called directly after a (line or paragraph) break has been added.
void getExtremesSimpl(core::Extremes *extremes)
Simple variant, to be implemented by widgets with extremes not depending on positions.
struct dw::Textblock::@28 hlEnd[core::HIGHLIGHT_NUM_LAYERS]
void changeWordStyle(int from, int to, core::style::Style *style, bool includeFirstSpace, bool includeLastSpace)
void accumulateWordData(int wordIndex)
void addWidget(core::Widget *widget, core::style::Style *style)
Add a widget (word type) to the page.
void getWordExtremes(Word *word, core::Extremes *extremes)
Get the extremes of a word within a textblock.
void addSpace(core::style::Style *style)
?
lout::misc::NotSoSimpleVector< Word > * words
core::SizeParams sizeRequestParams
int yOffsetOfLineCreated(Line *line)
Includes margin, border, and padding.
void correctLastWordExtremes()
Called when something changed for the last word (space, hyphens etc.).
void setWordImgRenderer(int wordNo)
void enterNotifyImpl(core::EventCrossing *event)
void changeLinkColor(int link, int newColor)
void widgetRefSizeChanged(int externalIndex)
Called by an implementation of dw::oof::OutOfFlowMgr (actually only OOFPosRelMgr) for the generator o...
Widget * getExtremesReference(int index)
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
void handOverBreak(core::style::Style *style)
This function "hands" the last break of a page "over" to a parent page.
void processWord(int wordIndex)
void markSizeChange(int ref)
See Sizes of Dillo Widgets.
bool calcSizeOfWidgetInFlow(int wordIndex, Widget *widget, core::Requisition *size)
Calculate the size of a widget, and return whether it has to be positioned at the top of the line.
void oofSizeChanged(bool extremesChanged)
Called by an implementation of dw::oof::OutOfFlowMgr when the size of the container has changed,...
int numGetExtremesReferences()
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
int getGeneratorX(int oofmIndex)
Return position relative to container, not regarding margin/border/padding, Called by OOFFloatsMgr to...
void fillParagraphs()
Counter part to rewrap(), but for extremes, not size calculation.
static void setStretchabilityFactor(int stretchabilityFactor)
void rewrap()
Rewrap the page from the line from which this is necessary.
void drawSpace(int wordIndex, core::View *view, core::Rectangle *area, int xWidget, int yWidgetBase)
void sizeAllocateImpl(core::Allocation *allocation)
See Sizes of Dillo Widgets.
static const char * hyphenDrawChar
The character which is used to draw a hyphen at the end of a line, either caused by automatic hyphena...
core::Iterator * iterator(core::Content::Type mask, bool atEnd)
Return an iterator for this widget.
void calcExtraSpaceImpl(int numPos, Widget **references, int *x, int *y)
int findLineIndexWhenNotAllocated(int y)
int lineYOffsetWidget(Line *line, core::Allocation *allocation)
void cleanupWord(int wordNo)
void calcTextOffset(int lineIndex, int totalWidth)
Word * findWord(int x, int y, bool *inSpace)
Find the index of the word, or -1.
static void setPenaltyHyphen(int penaltyHyphen)
void calcTextSize(const char *text, size_t len, core::style::Style *style, core::Requisition *size, bool isStart, bool isEnd)
Calculate the size of a text word.
void notifySetParent()
This method is called after a widget has been added to a parent.
RegardingBorder * getWidgetRegardingBorderForLine(Line *line)
void setBreakOption(Word *word, core::style::Style *style, int breakPenalty1, int breakPenalty2, bool forceBreak)
Set a break option, if allowed by the style.
void drawWord(Line *line, int wordIndex1, int wordIndex2, core::View *view, core::Rectangle *area, int xWidget, int yWidgetBase)
Draw a word of text.
int numSizeRequestReferences()
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
static void setPenaltyEmDashLeft(int penaltyLeftEmDash)
int getAvailHeightOfChild(core::Widget *child, bool forceValue)
lout::misc::SimpleVector< Anchor > * anchors
bool affectsSizeChangeContainerChild(Widget *child)
int yOffsetOfLineToBeCreated(int *lastMargin=NULL)
Includes margin, border, and padding.
void setSpaceImgRenderer(int wordNo)
static int stretchabilityFactor
...
static void setPenaltyHyphen2(int penaltyHyphen2)
bool addAnchor(const char *name, core::style::Style *style)
Add an anchor to the page.
static void setPenaltyEmDashRight2(int penaltyRightEmDash2)
void addText(const char *text, size_t len, core::style::Style *style)
Add a word to the page structure.
int getGeneratorY(int oofmIndex)
Return position relative to container, not regarding margin/border/padding, Called by OOFFloatsMgr to...
bool findSizeRequestReference(Widget *reference, int *xRef=NULL, int *yRef=NULL)
void drawText(core::View *view, core::style::Style *style, core::style::Color::Shading shading, int x, int y, const char *text, int start, int len, bool isStart, bool isEnd)
void addBreakOption(core::style::Style *style, bool forceBreak)
Add a break option (see setBreakOption() for details).
int calcVerticalBorder(int widgetPadding, int widgetBorder, int widgetMargin, int lineBorderTotal, int lineMarginTotal)
int getMaxGeneratorWidth()
int getGeneratorRest(int oofmIndex)
static int penalties[PENALTY_NUM][2]
The penalties for hyphens and other, multiplied by 100.
void leaveNotifyImpl(core::EventCrossing *event)
void resizeDrawImpl()
Called after sizeAllocateImpl() to redraw necessary areas.
bool isBreakAllowed(core::style::Style *style)
static void setPenaltyEmDashRight(int penaltyRightEmDash)
bool usesAvailWidth()
Must be implemengted by a method returning true, when getAvailWidth() is called.
void addText0(const char *text, size_t len, short flags, core::style::Style *style, core::Requisition *size)
Add a word (without hyphens) to the page structure.
Widget * getWidgetAtPointLevel(int x, int y, int level, core::GettingWidgetAtPointContext *context)
int getGeneratorWidth()
Return width including margin/border/padding Called by OOFFloatsMgr to position floats.
struct dw::Textblock::@28 hlStart[core::HIGHLIGHT_NUM_LAYERS]
void decorateText(core::View *view, core::style::Style *style, core::style::Color::Shading shading, int x, int yBase, int width)
int findLineOfWord(int wordIndex)
Find the line of word wordIndex.
void removeChild(Widget *child)
int textWidth(const char *text, int start, int len, core::style::Style *style, bool isStart, bool isEnd)
void notifySetAsTopLevel()
This method is called after a widget has been set as the top of a widget tree.
void addParbreak(int space, core::style::Style *style)
Cause a paragraph break.
void fillSpace(int wordNo, core::style::Style *style)
Widget * sizeReferences[NUM_OOFM]
bool buttonPressImpl(core::EventButton *event)
void queueDrawRange(int index1, int index2)
Widget * sizeRequestReference(int index)
See Sizes of Dillo Widgets (or Size requisitions depending on positions).
bool isPossibleOOFContainer(int oofmIndex)
void containerSizeChangedForChildren()
void updateReference(int ref)
Update content in flow, down from ref.
bool usesMaxGeneratorWidth()
void fillWord(int wordNo, int width, int ascent, int descent, short flags, core::style::Style *style)
bool motionNotifyImpl(core::EventMotion *event)
bool sendSelectionEvent(core::SelectionState::EventType eventType, core::MousePositionEvent *event)
Send event to selection.
void addLinebreak(core::style::Style *style)
int findLineIndexWhenAllocated(int y)
void removeSpaceImgRenderer(int wordNo)
void initWord(int wordNo)
Basic initialization, which is necessary before fillWord.
void sizeRequestImpl(core::Requisition *requisition, int numPos, Widget **references, int *x, int *y)
The ascent of a textblock is the ascent of the first line, plus padding/border/margin.
bool buttonReleaseImpl(core::EventButton *event)
Textblock(bool limitTextWidth, bool treatAsInline=false)
Word * addWord(int width, int ascent, int descent, short flags, core::style::Style *style)
Add a new word (text, widget etc.) to a page.
int getAvailWidthOfChild(core::Widget *child, bool forceValue)
Computes the content width available of a child widget.
void removeWordImgRenderer(int wordNo)
static DivChar divChars[NUM_DIV_CHARS]
void markExtremesChange(int ref)
See Sizes of Dillo Widgets.
lout::misc::SimpleVector< Paragraph > * paragraphs
void drawLevel(core::View *view, core::Rectangle *area, int level, core::DrawingContext *context)
bool ignoreLine1OffsetSometimes
int lineYOffsetCanvas(Line *line, core::Allocation *allocation)
lout::misc::SimpleVector< Line > * lines
bool isPossibleOOFContainerParent(int oofmIndex)
int findLineIndex(int y)
Find the first line index that includes y, which is given in widget coordinates.
Set at the top when drawing.
Represents a enter or leave notify event.
Represents a mouse motion event.
Set at the top when getting the widget at the point.
Iterators are used to iterate through the contents of a widget.
virtual void unref()
Delete the iterator.
lout::misc::ZoneAllocator * textZone
int textWidth(style::Font *font, const char *text, int len)
int nextGlyph(const char *text, int idx)
bool emitLinkEnter(Widget *w, int link, int img, int x, int y)
char * textToUpper(const char *text, int len)
char * textToLower(const char *text, int len)
Base class for all mouse events related to a specific position.
dw::core::Shape implementation for simple rectangles.
Hold arguments passed to dw::core::Widget::sizeRequest and dw::core::Widget::getExtremes,...
void fill(int numPos, Widget **references, int *x, int *y)
void forChild(Widget *parent, Widget *child, int xRel, int yRel, SizeParams *childParams)
Widget ** getReferences()
bool findReference(Widget *reference, int *x, int *y)
static bool handledByStackingContextMgr(Widget *widget)
An interface to encapsulate platform dependent drawing.
virtual void drawText(style::Font *font, style::Color *color, style::Color::Shading shading, int x, int y, const char *text, int len)=0
virtual void drawRectangle(style::Color *color, style::Color::Shading shading, bool filled, int x, int y, int width, int height)=0
static Color * create(Layout *layout, int color)
TextTransform textTransform
StyleImage * backgroundImage
void setBorderColor(Color *val)
void putExternalImgRenderer(ImgRenderer *ir)
Add an additional ImgRenderer, especially used for drawing.
void removeExternalImgRenderer(ImgRenderer *ir)
Remove a previously added additional ImgRenderer.
static Style * create(StyleAttrs *attrs)
Represents additional data for OOF containers.
virtual void addWidgetInFlow(OOFAwareWidget *widget, OOFAwareWidget *parent, int externalIndex)=0
virtual int addWidgetOOF(core::Widget *widget, OOFAwareWidget *generator, int externalIndex)=0
virtual void calcWidgetRefSize(core::Widget *widget, core::Requisition *size)=0
virtual void markSizeChange(int ref)=0
virtual int getAvailHeightOfChild(core::Widget *child, bool forceValue)=0
virtual int getAvailWidthOfChild(core::Widget *child, bool forceValue)=0
virtual bool dealingWithSizeOfChild(core::Widget *child)=0
virtual void markExtremesChange(int ref)=0
bool instanceOf(int otherClassId)
Returns, whether this class is an instance of the class, given by otherClassId, or of a sub class of ...
void registerName(const char *className, int *classId)
This method must be called in the constructor for the sub class.
const char * strndup(const char *str, size_t t)
#define DBG_OBJ_ENTER0(aspect, prio, funname)
#define DBG_OBJ_SET_BOOL_O(obj, var, val)
#define DBG_OBJ_CREATE(klass)
#define DBG_OBJ_SET_BOOL(var, val)
#define DBG_OBJ_MSG_END()
#define DBG_OBJ_MSGF(aspect, prio, fmt,...)
#define DBG_OBJ_SET_NUM(var, val)
#define DBG_OBJ_MSG(aspect, prio, msg)
#define DBG_OBJ_ENTER(aspect, prio, funname, fmt,...)
#define DBG_OBJ_MSG_START()
#define DBG_OBJ_ASSOC_CHILD(child)
#define DBG_OBJ_ARRSET_PTR(var, ind, val)
#define DBG_OBJ_ARRATTRSET_NUM(var, ind, attr, val)
#define DBG_OBJ_SET_NUM_O(obj, var, val)
#define DBG_OBJ_LEAVE_VAL(fmt,...)
static int dIspunct(unsigned char c)
int multiplyWithPerLengthRounded(int x, Length l)
Like multiplyWithPerLength, but rounds to nearest integer instead of down.
@ TEXT_TRANSFORM_LOWERCASE
@ TEXT_TRANSFORM_UPPERCASE
@ TEXT_TRANSFORM_CAPITALIZE
@ TEXT_DECORATION_OVERLINE
@ TEXT_DECORATION_LINE_THROUGH
@ TEXT_DECORATION_UNDERLINE
bool isAbsLength(Length l)
Returns true if l is an absolute length.
int absLengthVal(Length l)
Returns the value of a length in pixels, as an integer.
@ LENGTH_AUTO
Represents "auto" lengths.
void splitHeightPreserveAscent(int height, int *ascent, int *descent)
Dw is in this namespace, or sub namespaces of this one.
Miscellaneous stuff, which does not fit anywhere else.
const char * boolToStr(bool b)
Stuff dealing with Unicode characters: UTF-8, character classes etc.
const char * nextUtf8Char(const char *s)
bool unbreakableForMinWidth
int maxParAdjustmentWidth
SpaceImgRenderer * spaceImgRenderer
core::style::Style * style
WordImgRenderer * wordImgRenderer
@ DIV_CHAR_AT_EOL
Must be drawn with a hyphen, when at the end of the line.
@ UNBREAKABLE_FOR_MIN_WIDTH
@ CAN_BE_HYPHENATED
Can be hyphenated automatically.
@ PERM_DIV_CHAR
Is or ends with a "division character", which is part of the word.
@ DRAW_AS_ONE_TEXT
This word must be drawn, together with the following word(s), by only one call of View::drawText(),...
BadnessAndPenalty badnessAndPenalty
core::style::Style * spaceStyle
Represents the allocation, i.e.
@ WIDGET_OOF_REF
reference to a widget out of flow (OOF); this widget (containing this content) is only the generator ...
@ WIDGET_IN_FLOW
widget in normal flow, so that this widget (containing this content) is both container (parent) and g...
static Content::Type maskForSelection(bool followReferences)
WidgetReference * widgetReference
static dw::core::style::Tooltip * hoverTooltip
#define DBG_MSG_WORD(aspect, prio, prefix, n, suffix)
#define DBG_SET_WORD_SIZE(n)