ZLTextWordCursor ZLTextAreaController::buildInfos(const ZLTextWordCursor &start) { myArea.myLineInfos.clear(); ZLTextWordCursor cursor = start; int textHeight = myArea.height(); int counter = 0; do { ZLTextWordCursor paragraphEnd = cursor; paragraphEnd.moveToParagraphEnd(); ZLTextWordCursor paragraphStart = cursor; paragraphStart.moveToParagraphStart(); ZLTextArea::Style style(myArea, myArea.myProperties.baseStyle()); style.applyControls(paragraphStart, cursor); ZLTextLineInfoPtr info = new ZLTextLineInfo(cursor, style.textStyle(), style.bidiLevel()); while (!info->End.isEndOfParagraph()) { info = myArea.processTextLine(style, info->End, paragraphEnd); textHeight -= info->Height + info->Descent; if ((textHeight < 0) && (counter > 0)) { break; } textHeight -= info->VSpaceAfter; cursor = info->End; myArea.myLineInfos.push_back(info); if (textHeight < 0) { break; } ++counter; } } while (cursor.isEndOfParagraph() && cursor.nextParagraph() && !cursor.paragraphCursor().isEndOfSection() && (textHeight >= 0)); return cursor; }
bool BookTextView::getHyperlinkInfo(const ZLTextElementRectangle &rectangle, std::string &id, ZLHyperlinkType &type) const { if ((rectangle.Kind != ZLTextElement::WORD_ELEMENT) && (rectangle.Kind != ZLTextElement::IMAGE_ELEMENT)) { return false; } ZLTextWordCursor cursor = textArea().startCursor(); cursor.moveToParagraph(rectangle.ParagraphIndex); cursor.moveToParagraphStart(); ZLTextKind hyperlinkKind = REGULAR; for (int i = 0; i < rectangle.ElementIndex; ++i) { const ZLTextElement &element = cursor.element(); if (element.kind() == ZLTextElement::CONTROL_ELEMENT) { const ZLTextControlEntry &control = ((const ZLTextControlElement&)element).entry(); if (control.isHyperlink()) { hyperlinkKind = control.kind(); id = ((const ZLTextHyperlinkControlEntry&)control).label(); type = ((const ZLTextHyperlinkControlEntry&)control).hyperlinkType(); } else if (!control.isStart() && (control.kind() == hyperlinkKind)) { hyperlinkKind = REGULAR; } } cursor.nextWord(); } return hyperlinkKind != REGULAR; }
bool ZLTextArea::_getHyperlinkInfo(const ZLTextElementRectangle &rectangle, std::string &id, std::string &type, ZLTextKind& hyperlinkKind, int& x1, int&y1, int& x2, int& y2) const { if ((rectangle.Kind != ZLTextElement::WORD_ELEMENT) && (rectangle.Kind != ZLTextElement::IMAGE_ELEMENT)) { return false; } ZLTextWordCursor cursor = startCursor(); cursor.moveToParagraph(rectangle.ParagraphIndex); cursor.moveToParagraphStart(); hyperlinkKind = REGULAR; for (int i = 0; i < rectangle.ElementIndex; ++i) { const ZLTextElement &element = cursor.element(); if (element.kind() == ZLTextElement::CONTROL_ELEMENT) { const ZLTextControlEntry &control = ((const ZLTextControlElement&)element).entry(); if (control.isHyperlink()) { hyperlinkKind = control.kind(); id = ((const ZLTextHyperlinkControlEntry&)control).label(); type = ((const ZLTextHyperlinkControlEntry&)control).hyperlinkType(); x1 = rectangle.XStart; y1 = rectangle.YStart; x2 = rectangle.XEnd; y2 = rectangle.YEnd; } else if (!control.isStart() && (control.kind() == hyperlinkKind)) { hyperlinkKind = REGULAR; } } cursor.nextWord(); } return hyperlinkKind != REGULAR; }
ZLTextWordCursor ZLTextAreaController::findStart(const ZLTextWordCursor &end, SizeUnit unit, int size) { ZLTextWordCursor start = end; size -= paragraphHeight(start, true, unit); bool positionChanged = !start.isStartOfParagraph(); start.moveToParagraphStart(); while (size > 0) { if (positionChanged && start.paragraphCursor().isEndOfSection()) { break; } if (!start.previousParagraph()) { break; } if (!start.paragraphCursor().isEndOfSection()) { positionChanged = true; } size -= paragraphHeight(start, false, unit); } skip(start, unit, -size); if (unit != LINE_UNIT) { bool sameStart = start == end; if (!sameStart && start.isEndOfParagraph() && end.isStartOfParagraph()) { ZLTextWordCursor startCopy = start; startCopy.nextParagraph(); sameStart = startCopy == end; } if (sameStart) { start = findStart(end, LINE_UNIT, 1); } } return start; }
bool BookTextView::getHyperlinkId(const ZLTextElementArea &area, std::string &id, bool &isExternal) const { if ((area.Kind != ZLTextElement::WORD_ELEMENT) && (area.Kind != ZLTextElement::IMAGE_ELEMENT)) { return false; } ZLTextWordCursor cursor = startCursor(); cursor.moveToParagraph(area.ParagraphNumber); cursor.moveToParagraphStart(); ZLTextKind hyperlinkKind = REGULAR; for (int i = 0; i < area.TextElementNumber; ++i) { const ZLTextElement &element = cursor.element(); if (element.kind() == ZLTextElement::CONTROL_ELEMENT) { const ZLTextControlEntry &control = ((const ZLTextControlElement&)element).entry(); if (control.isHyperlink()) { hyperlinkKind = control.kind(); id = ((const ZLTextHyperlinkControlEntry&)control).label(); } else if (!control.isStart() && (control.kind() == hyperlinkKind)) { hyperlinkKind = REGULAR; } } cursor.nextWord(); } isExternal = hyperlinkKind == EXTERNAL_HYPERLINK; return hyperlinkKind != REGULAR; }
void ZLTextAreaController::skip(ZLTextWordCursor &cursor, SizeUnit unit, int size) { ZLTextWordCursor paragraphStart = cursor; paragraphStart.moveToParagraphStart(); ZLTextWordCursor paragraphEnd = cursor; paragraphEnd.moveToParagraphEnd(); ZLTextArea::Style style(myArea, myArea.myProperties.baseStyle()); style.applyControls(paragraphStart, cursor); while (!cursor.isEndOfParagraph() && (size > 0)) { const ZLTextLineInfoPtr info = myArea.processTextLine(style, cursor, paragraphEnd); cursor = info->End; size -= infoHeight(*info, unit); } }
std::string BookTextView::getFirstInternalHyperlinkId(int x0, int y0, int x1, int y1) { std::string id; std::string type; const ZLTextElementArea * area = elementByCoordinates(x0, y0); const ZLTextElementArea * stop_area = elementByCoordinates(x1, y1); if ( !area || ((area->Kind != ZLTextElement::WORD_ELEMENT) && (area->Kind != ZLTextElement::IMAGE_ELEMENT))) { return id; } ZLTextWordCursor cursor = startCursor(); cursor.moveToParagraph(area->ParagraphIndex); int paragraphs = area->ParagraphIndex; int end_paragraphs = stop_area ? stop_area->ParagraphIndex : 0; do { cursor.moveToParagraphStart(); ZLTextKind hyperlinkKind = REGULAR; for ( ; !cursor.isEndOfParagraph();) { const ZLTextElement &element = cursor.element(); if (element.kind() == ZLTextElement::CONTROL_ELEMENT) { const ZLTextControlEntry &control = ((const ZLTextControlElement&)element).entry(); if (control.isHyperlink()) { hyperlinkKind = control.kind(); id = ((const ZLTextHyperlinkControlEntry&)control).label(); type = ((const ZLTextHyperlinkControlEntry&)control).hyperlinkType(); if (type == "internal") { return id; } } else if (!control.isStart() && (control.kind() == hyperlinkKind)) { hyperlinkKind = REGULAR; } } cursor.nextWord(); } } while( ++paragraphs <= end_paragraphs && cursor.nextParagraph()); return std::string(); }
int ZLTextAreaController::paragraphHeight(const ZLTextWordCursor &cursor, bool beforeCurrentPosition, SizeUnit unit) { ZLTextWordCursor word = cursor; word.moveToParagraphStart(); ZLTextWordCursor end = cursor; if (!beforeCurrentPosition) { end.moveToParagraphEnd(); } int size = 0; ZLTextArea::Style style(myArea, myArea.myProperties.baseStyle()); while (!word.equalElementIndex(end)) { const ZLTextLineInfoPtr info = myArea.processTextLine(style, word, end); word = info->End; size += infoHeight(*info, unit); } return size; }
const std::vector<ZLTextSelectionModel::Range> &ZLTextSelectionModel::ranges() const { if (!myRangeVectorIsUpToDate && !isEmpty()) { Range r = internalRange(); ZLTextWordCursor cursor = myArea.startCursor(); cursor.moveToParagraph(r.first.ParagraphIndex); cursor.moveToParagraphStart(); int startLevel = 0; for (int i = r.first.ElementIndex; i > 0; --i) { switch (cursor.element().kind()) { case ZLTextElement::START_REVERSED_SEQUENCE_ELEMENT: ++startLevel; break; case ZLTextElement::END_REVERSED_SEQUENCE_ELEMENT: --startLevel; break; default: break; } cursor.nextWord(); } cursor.moveToParagraph(r.second.ParagraphIndex); cursor.moveToParagraphEnd(); int endLevel = 0; for (int i = cursor.elementIndex() - r.second.ElementIndex; i > 0; --i) { cursor.previousWord(); switch (cursor.element().kind()) { case ZLTextElement::START_REVERSED_SEQUENCE_ELEMENT: --endLevel; break; case ZLTextElement::END_REVERSED_SEQUENCE_ELEMENT: ++endLevel; break; default: break; } } if ((startLevel == 0) && (endLevel == 0)) { myRanges.push_back(r); } else if (r.first.ParagraphIndex == r.second.ParagraphIndex) { BoundElement leftBound = r.first; BoundElement rightBound; rightBound.Exists = true; rightBound.ParagraphIndex = leftBound.ParagraphIndex; rightBound.CharIndex = 0; cursor.moveTo(r.first.ElementIndex, 0); for (int i = r.first.ElementIndex; i < r.second.ElementIndex; ++i) { ZLTextElement::Kind kind = cursor.element().kind(); if ((kind == ZLTextElement::START_REVERSED_SEQUENCE_ELEMENT) || (kind == ZLTextElement::END_REVERSED_SEQUENCE_ELEMENT)) { rightBound.ElementIndex = i; myRanges.push_back(Range(leftBound, rightBound)); leftBound = rightBound; } cursor.nextWord(); } myRanges.push_back(Range(leftBound, r.second)); } else { BoundElement leftBound = r.first; if (startLevel > 0) { BoundElement rightBound; rightBound.Exists = true; rightBound.ParagraphIndex = leftBound.ParagraphIndex; rightBound.ElementIndex = leftBound.ElementIndex; rightBound.CharIndex = 0; cursor.moveToParagraph(r.first.ParagraphIndex); cursor.moveTo(r.first.ElementIndex, 0); while (startLevel > 0) { switch(cursor.element().kind()) { case ZLTextElement::START_REVERSED_SEQUENCE_ELEMENT: ++startLevel; rightBound.ElementIndex = cursor.elementIndex(); myRanges.push_back(Range(leftBound, rightBound)); leftBound = rightBound; break; case ZLTextElement::END_REVERSED_SEQUENCE_ELEMENT: --startLevel; rightBound.ElementIndex = cursor.elementIndex(); myRanges.push_back(Range(leftBound, rightBound)); leftBound = rightBound; break; default: break; } cursor.nextWord(); } } BoundElement rightBound1 = r.second; if (endLevel > 0) { BoundElement leftBound1; leftBound1.Exists = true; leftBound1.ParagraphIndex = rightBound1.ParagraphIndex; leftBound1.ElementIndex = rightBound1.ElementIndex; leftBound1.CharIndex = 0; cursor.moveToParagraph(r.second.ParagraphIndex); cursor.moveTo(r.second.ElementIndex, 0); while (endLevel > 0) { switch(cursor.element().kind()) { case ZLTextElement::START_REVERSED_SEQUENCE_ELEMENT: --endLevel; leftBound1.ElementIndex = cursor.elementIndex(); myRanges.push_back(Range(leftBound1, rightBound1)); rightBound1 = leftBound1; break; case ZLTextElement::END_REVERSED_SEQUENCE_ELEMENT: ++endLevel; rightBound1.ElementIndex = cursor.elementIndex(); myRanges.push_back(Range(leftBound1, rightBound1)); rightBound1 = leftBound1; break; default: break; } cursor.previousWord(); } } myRanges.push_back(Range(leftBound, rightBound1)); } myRangeVectorIsUpToDate = true; } return myRanges; }