23#include "../lout/msg.h"
24#include "../lout/misc.hh"
25#include "../lout/unicode.hh"
26#include "../lout/debug.hh"
66 this->xWordWidget = xWordWidget;
67 this->lineNo = lineNo;
76 && wordNo < textblock->words->size()
77 && lineNo < textblock->lines->size();
84 Line *line = textblock->lines->getRef (lineNo);
85 *x = textblock->allocation.x + this->xWordWidget;
86 *y = textblock->lineYOffsetCanvas (line);
87 *width = textblock->words->getRef(wordNo)->size.width;
92 int *widthRef,
int *heightRef)
95 textblock->getPaddingArea (xRef, yRef, widthRef, heightRef);
100 return textblock->words->getRef(wordNo)->style;
105 textblock->queueDrawArea (x - textblock->allocation.x,
106 y - textblock->allocation.y, width, height);
115 *width = textblock->words->getRef(wordNo)->effSpace;
120 return textblock->words->getRef(wordNo)->spaceStyle;
133 {
"\xe2\x80\x94",
false,
true,
false,
234 paragraphs =
new misc::SimpleVector <Paragraph> (1);
235 lines =
new misc::SimpleVector <Line> (1);
237 words =
new misc::NotSoSimpleVector <Word> (1);
238 anchors =
new misc::SimpleVector <Anchor> (1);
263 hlEnd[layer].index = 0;
264 hlEnd[layer].nChar = 0;
282 for (
int i = 0; i <
words->size(); i++)
285 for (
int i = 0; i <
anchors->size(); i++) {
309 Widget **references,
int *x,
int *y)
311 DBG_OBJ_ENTER (
"resize", 0,
"sizeRequestImpl",
"%d, ...", numPos);
349 if (
lines->size () > 0) {
350 Line *firstLine =
lines->getRef(0), *lastLine =
lines->getLastRef ();
371 lastLine->top - firstLine->
borderAscent + lastLine->borderAscent +
377 lastLine->borderDescent, lastLine->marginDescent);
386 "before considering lineBreakWidth (= %d): %d * (%d + %d)",
392 DBG_OBJ_MSG (
"resize", 1,
"lineBreakWidth needs no consideration");
394 DBG_OBJ_MSGF (
"resize", 1,
"before correction: %d * (%d + %d)",
433 int widgetMargin,
int lineBorderTotal,
436 DBG_OBJ_ENTER (
"resize", 0,
"calcVerticalBorder",
"%d, %d, %d, %d, %d",
437 widgetPadding, widgetBorder, widgetMargin, lineBorderTotal,
442 if (widgetPadding == 0 && widgetBorder == 0) {
443 if (lineMarginTotal - lineBorderTotal >= widgetMargin)
444 result = lineMarginTotal;
446 result = widgetMargin + lineBorderTotal;
448 result = lineMarginTotal + widgetPadding + widgetBorder + widgetMargin;
488 DBG_OBJ_MSGF (
"resize", 1,
"paragraphs[%d]->maxParMin = %d (%d)",
491 DBG_OBJ_MSGF (
"resize", 1,
"paragraphs[%d]->maxParMax = %d (%d)",
496 DBG_OBJ_MSGF (
"resize", 0,
"after considering paragraphs: %d (%d) / %d (%d)",
507 DBG_OBJ_MSGF (
"resize", 0,
"after adding diff: %d (%d) / %d (%d)",
515 DBG_OBJ_MSGF (
"resize", 0,
"after correction: %d (%d) / %d (%d)",
522 "finally, after considering OOFM: %d (%d) / %d (%d)",
540 OOFAwareWidget::notifySetAsTopLevel ();
548 OOFAwareWidget::notifySetParent ();
551 for (
int i = 0; i <
NUM_OOFM; i++) {
571 DBG_OBJ_ENTER (
"resize", 0,
"sizeAllocateImpl",
"%d, %d; %d * (%d + %d)",
579 int lineIndex, wordIndex;
595 for (lineIndex = 0; lineIndex <
lines->size (); lineIndex++) {
610 line =
lines->getRef (lineIndex);
613 DBG_OBJ_MSGF (
"resize", 1,
"xCursor = %d (initially)", xCursor);
617 word =
words->getRef (wordIndex);
626 "allocating widget in flow: line %d, word %d",
627 lineIndex, wordIndex);
650 if (childAllocation.
x != oldChildAllocation->
x ||
651 childAllocation.
y != oldChildAllocation->
y ||
652 childAllocation.
width != oldChildAllocation->
width) {
661 oldChildAllocation->
y - this->allocation.y);
665 }
else if (childAllocation.
ascent + childAllocation.
descent !=
687 oldChildAllocation->
y - this->allocation.y +
688 oldChildAllocation->
ascent +
703 DBG_OBJ_MSGF (
"resize", 1,
"xCursor = %d (after word %d)",
705 DBG_MSG_WORD (
"resize", 1,
"<i>that is:</i> ", wordIndex,
"");
715 for (
int i = 0; i <
anchors->size(); i++) {
721 lines->size () <= 0 ||
741 OOFAwareWidget::calcExtraSpaceImpl (numPos, references, x, y);
743 int clearPosition = 0;
757 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getAvailWidthOfChild",
"%p, %s",
758 child, forceValue ?
"true" :
"false");
779 int maxWidth = child->calcWidth (child->getStyle()->maxWidth,
780 -1,
this, -1,
false);
784 int minWidth = child->calcWidth (child->getStyle()->minWidth,
785 -1,
this, -1,
false);
794 width = Widget::getAvailWidthOfChild (child, forceValue);
796 if (forceValue &&
this == child->getContainer () &&
816 return Widget::getAvailHeightOfChild (child, forceValue);
823 for (
int i = 0; i <
words->size (); i++) {
837 "Textblock/affectsSizeChangeContainerChild",
"%p", child);
846 ret = Widget::affectsSizeChangeContainerChild (child);
862 if (
lines->size () > 0) {
913 DBG_OBJ_ENTER (
"resize", 1,
"markExtremesChange",
"%d", ref);
989 _MSG(
"MN tb=%p tooltipOld=%p hoverTooltip=%p\n",
1031 int charPos = 0, link = -1;
1034 if (
words->size () == 0) {
1041 if (event->
yCanvas < yFirst) {
1044 }
else if (event->
yCanvas >= yLast) {
1046 wordIndex =
words->size () - 1;
1068 int wordStartX = nextWordStartX;
1072 if (event->
xWidget >= wordStartX &&
1073 event->
xWidget < nextWordStartX) {
1080 if (wordIndex < line->lastWord &&
1081 (
words->getRef(wordIndex + 1)->content.type !=
1095 int glyphX = wordStartX;
1110 nextCharPos - charPos, word->
style,
1111 isStartWord && charPos == 0,
1114 if (event->
xWidget > glyphX + glyphWidth) {
1115 glyphX += glyphWidth;
1116 charPos = nextCharPos;
1118 }
else if (event->
xWidget >= glyphX + glyphWidth/2){
1121 charPos = nextCharPos;
1127 nextCharPos - charPos,
1129 isStartWord && charPos == 0,
1134 charPos = nextCharPos;
1142 if (event->
xWidget >= (wordStartX + nextWordStartX) /2)
1159 DBG_OBJ_MSGF (
"events", 1,
"wordIndex = %d", wordIndex);
1160 DBG_MSG_WORD (
"events", 1,
"<i>this is:</i> ", wordIndex,
"");
1186 int x,
int yBase,
int width)
1216 const char *text,
int start,
int len,
bool isStart,
1238 bool initial_seen =
false;
1240 for (
int i = 0; i < start; i++)
1241 if (!ispunct(text[i]))
1242 initial_seen =
true;
1248 while (ispunct(text[after]))
1256 int newlen = strlen(initial) + len-after;
1257 str = (
char *)malloc(newlen + 1);
1258 strcpy(str, initial);
1259 strncpy(str + strlen(str), text+after, len-after);
1267 str ? str : text + start, str ? strlen(str) : len);
1283 int xWidget,
int yWidgetBase)
1286 bool drawHyphen = wordIndex2 == line->
lastWord
1291 for (
int i = wordIndex1; i <= wordIndex2; i++)
1292 w +=
words->getRef(i)->size.width;
1293 w +=
words->getRef(wordIndex2)->hyphenWidth;
1298 if (wordIndex1 == wordIndex2 && !drawHyphen) {
1300 Word *word =
words->getRef (wordIndex1);
1302 false,
style, view, area, xWidget, yWidgetBase);
1305 int l = 0, totalWidth = 0;
1306 for (
int i = wordIndex1; i <= wordIndex2; i++) {
1312 char *text =
new char[l + (drawHyphen ? strlen (
hyphenDrawChar) : 0) + 1];
1314 for (
int i = wordIndex1; i <= wordIndex2; i++) {
1315 const char * t =
words->getRef(i)->content.text;
1316 strcpy (text + p, t);
1326 drawWord0 (wordIndex1, wordIndex2, text, totalWidth, drawHyphen,
1327 style, view, area, xWidget, yWidgetBase);
1337 const char *text,
int totalWidth,
bool drawHyphen,
1355 yWorldBase, text, 0, strlen (text), isStartTotal, isEndTotal);
1359 yWorldBase, totalWidth);
1364 const int wordLen = strlen (text);
1376 for (
int i = wordIndex1; i <
hlStart[layer].index; i++)
1379 firstCharIdx += strlen (
words->getRef(i)->content.text);
1383 lastCharIdx = wordLen;
1387 (
int)strlen (
words->getRef(
hlEnd[layer].index)
1389 for (
int i = wordIndex1; i <
hlEnd[layer].index; i++)
1392 lastCharIdx += strlen (
words->getRef(i)->content.text);
1399 isEndTotal && text[firstCharIdx] == 0);
1402 if (!drawHyphen && firstCharIdx == 0 && lastCharIdx == wordLen)
1406 lastCharIdx - firstCharIdx,
style,
1407 isStartTotal && firstCharIdx == 0,
1408 isEndTotal && text[lastCharIdx] == 0);
1424 yWorldBase, text, firstCharIdx,
1425 lastCharIdx - firstCharIdx,
1426 isStartTotal && firstCharIdx == 0,
1427 isEndTotal && lastCharIdx == wordLen);
1431 xStart, yWorldBase, width);
1447 bool highlight =
false;
1493 DBG_OBJ_ENTER (
"draw", 0,
"drawLine",
"..., [%d, %d, %d * %d]",
1499 DBG_OBJ_MSGF (
"draw", 1,
"line from %d to %d (%d words), at (%d, %d)",
1501 xWidget, yWidgetBase);
1510 DBG_MSG_WORD (
"draw", 2,
"<i>drawing: </i>", wordIndex,
"");
1526 child->
draw (view, &childArea, context);
1528 int wordIndex2 = wordIndex;
1529 while (wordIndex2 < line->lastWord &&
1530 (
words->getRef(wordIndex2)->flags
1532 word->
style ==
words->getRef(wordIndex2 + 1)->style)
1535 drawWord(line, wordIndex, wordIndex2, view, area,
1536 xWidget, yWidgetBase);
1538 for (
int i = wordIndex; i <= wordIndex2; i++)
1539 wordSize +=
words->getRef(i)->size.width;
1541 wordIndex = wordIndex2;
1542 word =
words->getRef(wordIndex);
1546 if (word->
effSpace > 0 && wordIndex < line->lastWord &&
1547 words->getRef(wordIndex + 1)->content.type !=
1554 drawSpace (wordIndex, view, area, xWidget + wordSize,
1560 xWidget += wordSize + word->
effSpace;
1580 if (
lines->size() == 0)
1588 lines->getRef(0)->borderAscent,
1589 lines->getRef(0)->marginAscent));
1600 DBG_OBJ_ENTER (
"events", 0,
"findLineIndex",
"%d, %d", y, ascent);
1605 int maxIndex =
lines->size () - 1;
1606 int step,
index, low = 0;
1608 step = (
lines->size() + 1) >> 1;
1609 while ( step > 1 ) {
1613 step = (step + 1) >> 1;
1639 if (wordIndex < 0 || wordIndex >=
words->size () ||
1641 lines->size () <= 0 || wordIndex >
lines->getLastRef()->lastWord)
1644 int high =
lines->size () - 1,
index, low = 0;
1647 index = (low + high) / 2;
1648 if (wordIndex >=
lines->getRef(
index)->firstWord) {
1649 if (wordIndex <= lines->getRef(
index)->lastWord)
1665 if (wordIndex < 0 || wordIndex >=
words->size () ||
1669 wordIndex >
paragraphs->getLastRef()->lastWord))
1673 index = (low + high) / 2;
1675 if (wordIndex <= paragraphs->getRef(
index)->lastWord)
1689 int lineIndex, wordIndex;
1690 int xCursor, lastXCursor, yWidgetBase;
1698 line =
lines->getRef (lineIndex);
1705 word =
words->getRef (wordIndex);
1706 lastXCursor = xCursor;
1708 if (lastXCursor <= x && xCursor > x) {
1709 if (x >= xCursor - word->
effSpace) {
1710 if (wordIndex < line->lastWord &&
1711 (
words->getRef(wordIndex + 1)->content.type !=
1720 y <= yWidgetBase + word->size.descent)
1733 DBG_OBJ_ENTER (
"draw", 0,
"Textblock::drawLevel",
"(%d, %d, %d * %d), %s",
1740 lineIndex <
lines->size (); lineIndex++) {
1746 drawLine (line, view, area, context);
1753 for (
int oofmIndex = 0; oofmIndex <
NUM_OOFM; oofmIndex++) {
1754 for (
int wordIndex = 0; wordIndex <
words->size (); wordIndex++) {
1766 OOFAwareWidget::drawLevel (view, area, level, context);
1779 DBG_OBJ_ENTER (
"construct.word", 0,
"addWord",
"%d * (%d + %d), %d, %p",
1789 int wordNo =
words->size () - 1;
1794 return words->getRef (wordNo);
1931 bool initial_seen =
false;
1933 for (
int i = 0; i < start; i++)
1934 if (!ispunct(text[i]))
1935 initial_seen =
true;
1942 while (ispunct(text[after]))
1983 int height, leading;
2004 size->
ascent += leading / 2;
2005 size->
descent += leading - (leading / 2);
2027 DBG_OBJ_ENTER (
"construct.word", 0,
"addText",
"..., %d, %p",
2033 for (
const char *s = text; s; s =
nextUtf8Char (s, text + len - s)) {
2037 if (s <= text + len - lDiv) {
2038 if (memcmp (s,
divChars[j].s, lDiv *
sizeof (
char)) == 0)
2043 if (foundDiv != -1) {
2044 if (
divChars[foundDiv].penaltyIndexLeft != -1)
2046 if (
divChars[foundDiv].penaltyIndexRight != -1)
2051 if (numParts == 1) {
2064 PRINTF (
"HYPHENATION: '");
2065 for (
size_t i = 0; i < len; i++)
2067 PRINTF (
"', with %d parts\n", numParts);
2070 int n = 0, totalLenCharRemoved = 0;
2071 int *partPenaltyIndex =
new int[numParts - 1];
2072 int *partStart =
new int[numParts];
2073 int *partEnd =
new int[numParts];
2074 bool *charRemoved =
new bool[numParts - 1];
2075 bool *canBeHyphenated =
new bool[numParts + 1];
2076 bool *permDivChar =
new bool[numParts - 1];
2077 bool *unbreakableForMinWidth =
new bool[numParts - 1];
2078 canBeHyphenated[0] = canBeHyphenated[numParts] =
true;
2080 partEnd[numParts - 1] = len;
2082 for (
const char *s = text; s; s =
nextUtf8Char (s, text + len - s)) {
2086 if (s <= text + len - lDiv) {
2087 if (memcmp (s,
divChars[j].s, lDiv *
sizeof (
char)) == 0)
2092 if (foundDiv != -1) {
2093 int lDiv = strlen (
divChars[foundDiv].s);
2095 if (
divChars[foundDiv].charRemoved) {
2096 assert (
divChars[foundDiv].penaltyIndexLeft != -1);
2097 assert (
divChars[foundDiv].penaltyIndexRight == -1);
2100 charRemoved[n] =
true;
2101 permDivChar[n] =
false;
2102 unbreakableForMinWidth[n] =
2105 partEnd[n] = s - text;
2106 partStart[n + 1] = s - text + lDiv;
2108 totalLenCharRemoved += lDiv;
2110 assert (
divChars[foundDiv].penaltyIndexLeft != -1 ||
2111 divChars[foundDiv].penaltyIndexRight != -1);
2113 if (
divChars[foundDiv].penaltyIndexLeft != -1) {
2115 charRemoved[n] =
false;
2116 permDivChar[n] =
false;
2117 unbreakableForMinWidth[n] =
2120 partEnd[n] = s - text;
2121 partStart[n + 1] = s - text;
2125 if (
divChars[foundDiv].penaltyIndexRight != -1) {
2127 charRemoved[n] =
false;
2128 permDivChar[n] =
true;
2129 unbreakableForMinWidth[n] =
2132 partEnd[n] = s - text + lDiv;
2133 partStart[n + 1] = s - text + lDiv;
2141 const char *textWithoutHyphens;
2142 char *textWithoutHyphensBuf =
new char[len - totalLenCharRemoved];
2143 int *breakPosWithoutHyphens;
2144 int *breakPosWithoutHyphensBuf =
new int[numParts - 1];
2146 if (totalLenCharRemoved == 0) {
2148 textWithoutHyphens = text;
2152 breakPosWithoutHyphens = partEnd;
2155 textWithoutHyphens = textWithoutHyphensBuf;
2156 breakPosWithoutHyphens = breakPosWithoutHyphensBuf;
2159 for (
int i = 0; i < numParts; i++) {
2160 memmove (textWithoutHyphensBuf + n, text + partStart[i],
2161 partEnd[i] - partStart[i]);
2162 n += partEnd[i] - partStart[i];
2163 if (i < numParts - 1)
2164 breakPosWithoutHyphensBuf[i] = n;
2168 PRINTF(
"H... without hyphens: '");
2169 for (
size_t i = 0; i < len - totalLenCharRemoved; i++)
2170 PUTCHAR(textWithoutHyphens[i]);
2175 numParts - 1, breakPosWithoutHyphens, wordSize);
2178 for (
int i = 0; i < numParts; i++) {
2184 if (canBeHyphenated[i] && canBeHyphenated[i + 1])
2187 if(i < numParts - 1) {
2193 if (unbreakableForMinWidth[i])
2201 if (i == numParts - 1)
2204 addText0 (text + partStart[i], partEnd[i] - partStart[i],
2216 if(i < numParts - 1) {
2220 penalties[partPenaltyIndex[i]][1],
false);
2238 delete[] partPenaltyIndex;
2241 delete[] charRemoved;
2242 delete[] canBeHyphenated;
2243 delete[] permDivChar;
2244 delete[] unbreakableForMinWidth;
2245 delete[] textWithoutHyphensBuf;
2246 delete[] breakPosWithoutHyphensBuf;
2255 int numBreaks,
int *breakPos,
2259 int lastStart = breakPos[numBreaks - 1];
2261 &wordSize[numBreaks],
true,
true);
2263 PRINTF(
"H... [%d] '", numBreaks);
2264 for (
size_t i = 0; i < textLen - lastStart; i++)
2266 PRINTF(
"' -> %d\n", wordSize[numBreaks].width);
2270 for (
int i = numBreaks - 1; i >= 0; i--) {
2271 int start = (i == 0) ? 0 : breakPos[i - 1];
2273 i == 0, i == numBreaks - 1);
2275 PRINTF(
"H... [%d] '", i);
2276 for (
size_t j = 0; j < textLen - start; j++)
2278 PRINTF(
"' -> %d\n", wordSize[i].width);
2280 for (
int j = i + 1; j < numBreaks + 1; j++) {
2282 PRINTF(
"H... - %d = %d\n", wordSize[j].width, wordSize[i].width);
2294 DBG_OBJ_ENTER (
"resize", 0,
"calcSizeOfWidgetInFlow",
"%d, %p, ...",
2297 bool result, firstWordOfLine;
2302 firstWordOfLine = wordIndex == 1 ||
2306 firstWordOfLine = wordIndex == 0 ||
2312 if (firstWordOfLine &&
2318 int lastWord =
lines->empty () ? -1 :
lines->getLastRef()->lastWord;
2319 assert (wordIndex > lastWord);
2340 int yRel = yLine -
min (lastMargin, widget->getStyle()->margin.top);
2343 "leftBorder = %d + %d + (%d == 0 ? %d : 0) = %d, "
2344 "rightBorder = %d, yRel = %d - min (%d, %d) = %d",
2347 widget->getStyle()->margin.top, yRel);
2352 int oldXRel = leftBorder;
2355 widget->sizeRequest (size, childParams.
getNumPos (),
2357 childParams.
getY ());
2366 switch(widget->getStyle()->textAlign) {
2385 if (xRel < leftBorder)
2388 DBG_OBJ_MSGF (
"resize", 2,
"xRel = %d, oldXRel = %d", xRel, oldXRel);
2392 if (xRel == oldXRel)
2396 widget->sizeRequest (size, childParams.
getNumPos (),
2398 childParams.
getY ());
2410 DBG_OBJ_MSG (
"resize", 1,
"do not pass position");
2411 widget->sizeRequest (size);
2422 if (reference ==
this) {
2439 "..., %d, %s:%s:%s:%s:%s:%s:%s:%s, %p, %d * (%d + %d)",
2497 DBG_OBJ_MSGF (
"construct.word", 1,
"ouf of flow: oofmIndex = %d (%s)",
2507 DBG_OBJ_MSGF (
"construct.word", 1,
"oofmSubRef = %d => parentRef = %d",
2573 if (
lines->size () == 0)
2577 copy = Widget::addAnchor (name, y);
2579 copy = Widget::addAnchor (name);
2592 anchor->
name = copy;
2609 int wordIndex =
words->size () - 1;
2610 if (wordIndex >= 0) {
2628 DBG_OBJ_ENTER (
"construct.word", 0,
"addBreakOption",
"%p, %s",
2629 style, forceBreak ?
"true" :
"false");
2631 int wordIndex =
words->size () - 1;
2632 if (wordIndex >= 0) {
2644 DBG_OBJ_ENTER (
"construct.word", 0,
"fillSpace",
"%d, ...", wordNo);
2646 DBG_OBJ_MSGF (
"construct.word", 1,
"style.white-space = %s",
2654 "pre-line" :
"???");
2675 !word->content.space &&
2680 word->content.space =
true;
2681 word->origSpace = word->effSpace =
2686 word->spaceStyle->unref ();
2687 word->spaceStyle =
style;
2702 int breakPenalty1,
int breakPenalty2,
2705 DBG_OBJ_ENTER (
"construct.word", 0,
"setBreakOption",
"..., %d, %d, %s",
2706 breakPenalty1, breakPenalty2, forceBreak ?
"true" :
"false");
2745 DBG_OBJ_ENTER (
"construct.word", 0,
"addParbreak",
"%d, %p",
2748 "<i>No nesting! Strack trace may be incomplete.</i>");
2756 if (
words->size () == 0 ||
2766 for (
Widget *widget =
this;
2767 widget->getParent() != NULL &&
2770 widget = widget->getParent ()) {
2773 bool isfirst = (textblock2->
words->getRef(
index)->content.type
2775 && textblock2->
words->getRef(
index)->content.widget
2785 ->getRef(lineno - 1)->firstWord)) &&
2805 if ((word =
words->getRef(
words->size () - 1)) &&
2839 if (
words->size () == 0 ||
2868 assert (
words->size () >= 1);
2869 assert (
words->getRef(
words->size () - 1)->content.type
2885 if (
words->size () >= 2)
2886 words->getRef(
words->size () - 2)->origSpace =
2887 words->getRef(
words->size () - 2)->effSpace = 0;
2894 DBG_OBJ_ENTER (
"events", 0,
"Textblock::getWidgetAtPointLevel",
"%d, %d, %s",
2897 Widget *widgetAtPoint = NULL;
2904 if (lineIndex >= 0 && lineIndex < lines->size ()) {
2907 for (
int wordIndex = line->
lastWord;
2908 widgetAtPoint == NULL && wordIndex >= line->
firstWord;
2924 for (
int oofmIndex =
NUM_OOFM; widgetAtPoint == NULL && oofmIndex >= 0;
2926 for (
int wordIndex =
words->size () - 1;
2927 widgetAtPoint == NULL && wordIndex >= 0; wordIndex--) {
2943 OOFAwareWidget::getWidgetAtPointLevel (x, y, level, context);
2948 return widgetAtPoint;
2957 if (
lines->size() > 0) {
2996 for (
int lineIndex = 0; lineIndex <
lines->size(); lineIndex++) {
2997 bool changed =
false;
3010 styleAttrs = *old_style;
3016 styleAttrs = *old_style;
3046 bool includeFirstSpace,
bool includeLastSpace)
3052 DBG_OBJ_ENTER (
"draw", 0,
"queueDrawRange",
"%d, %d", index1, index2);
3065 if (line1idx >= 0 && line2idx >= 0) {
3067 *line2 =
lines->getRef (line2idx);
3071 line2->contentDescent - y;
3094 if (lineNo >= 0 && lineNo < lines->size ())
3114 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getGeneratorX",
"%d", oofmIndex);
3131 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getGeneratorY",
"%d", oofmIndex);
3148 DBG_OBJ_ENTER (
"resize", 0,
"Textblock::getGeneratorRest",
"%d", oofmIndex);
3188 int firstWordAfterLastLine =
3189 lines->size() > 0 ?
lines->getLastRef()->lastWord + 1 : 0;
3190 for (
int i = firstWordAfterLastLine; i <
words->size(); i++) {
3205 int w0 =
lines->size () > 0 ?
lines->getLastRef()->maxLineWidth : 0;
3208 DBG_OBJ_MSGF (
"resize", 1,
"wThis = min(%d + %d + %d, %d) = %d",
3211 int w =
max(wThis, wChild);
3239 "toplevel: %s, block: %s, float: %s, abspos: %s, fixpos: %s",
3245 result = toplevel || (block && !(vloat || abspos || fixpos));
3270 int firstWord = lineNo == 0 ? 0 :
lines->getRef(lineNo - 1)->lastWord + 1;
3271 int lastWord = lineNo <
lines->size() ?
3272 lines->getRef(lineNo)->lastWord :
words->size() - 1;
3279 DBG_OBJ_ENTER (
"resize", 0,
"getWidgetRegardingBorderForLine",
"%d, %d",
3280 firstWord, lastWord);
3285 if (firstWord < words->size ()) {
3290 DBG_MSG_WORD (
"resize", 1,
"<i>first word:</i> ", firstWord,
"");
3303 return widgetRegardingBorder;
3328 if (
lines->size () == 0) {
3335 Line *firstLine =
lines->getRef (0), *lastLine =
lines->getLastRef ();
3341 - firstLine->
borderAscent + lastLine->top + lastLine->totalHeight (0);
3343 *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 neccessary 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 implemtation 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,...)
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)