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; }
std::string FBView::word(const ZLTextElementArea &area) const { std::string txt; if (area.Kind == ZLTextElement::WORD_ELEMENT) { ZLTextWordCursor cursor = startCursor(); cursor.moveToParagraph(area.ParagraphIndex); cursor.moveTo(area.ElementIndex, 0); const ZLTextWord &word = (ZLTextWord&)cursor.element(); ZLUnicodeUtil::Ucs4String ucs4; ZLUnicodeUtil::utf8ToUcs4(ucs4, word.Data, word.Size); ZLUnicodeUtil::Ucs4String::iterator it = ucs4.begin(); while ((it != ucs4.end()) && !ZLUnicodeUtil::isLetter(*it)) { ++it; } if (it != ucs4.end()) { ucs4.erase(ucs4.begin(), it); it = ucs4.end() - 1; while (!ZLUnicodeUtil::isLetter(*it)) { --it; } ucs4.erase(it + 1, ucs4.end()); ZLUnicodeUtil::ucs4ToUtf8(txt, ucs4); } } return txt; }
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; }
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; }
// Added by John to enable caller to get text from current visible page. void ZLTextSelectionModel::text(std::string & text, int max) { text.clear(); ZLTextWordCursor start = myView.startCursor(); ZLTextWordCursor end = myView.endCursor(); ZLTextWordCursor cursor = start; while (cursor < end) { if (cursor.isEndOfParagraph()) { cursor.nextParagraph(); continue; } const ZLTextElement &element = cursor.element(); switch (element.kind()) { case ZLTextElement::WORD_ELEMENT: { const ZLTextWord &word = (const ZLTextWord&)element; if (cursor.sameElementAs(end)) { if (start.sameElementAs(end)) { int skip = ZLUnicodeUtil::length(word.Data, start.charIndex()); int length = ZLUnicodeUtil::length(word.Data, end.charIndex()) - skip; text.append(word.Data + skip, length); } else { text.append(word.Data, ZLUnicodeUtil::length(word.Data, end.charIndex())); } } else if (cursor.charIndex() == 0) { text.append(word.Data, word.Size); } else /* cursor == start */ { int skip = ZLUnicodeUtil::length(word.Data, cursor.charIndex()); text.append(word.Data + skip, word.Size - skip); } } break; case ZLTextElement::HSPACE_ELEMENT: case ZLTextElement::NB_HSPACE_ELEMENT: { text += ' '; } break; } cursor.nextWord(); if (text.size() >= max) { return; } } }
void ZLTextView::ViewStyle::applyControls(const ZLTextWordCursor &begin, const ZLTextWordCursor &end) { for (ZLTextWordCursor cursor = begin; !cursor.equalWordNumber(end); cursor.nextWord()) { const ZLTextElement &element = cursor.element(); if (element.kind() == ZLTextElement::CONTROL_ELEMENT) { applyControl((ZLTextControlElement&)element); } else if (element.kind() == ZLTextElement::FORCED_CONTROL_ELEMENT) { applyControl((ZLTextForcedControlElement&)element); } } }
bool CollectionView::_onStylusPress(int x, int y) { fbreader().setHyperlinkCursor(false); const ZLTextElementArea *imageArea = elementByCoordinates(x, y); if ((imageArea != 0) && (imageArea->Kind == ZLTextElement::IMAGE_ELEMENT)) { ZLTextWordCursor cursor = startCursor(); cursor.moveToParagraph(imageArea->ParagraphIndex); cursor.moveTo(imageArea->ElementIndex, 0); const ZLTextElement &element = cursor.element(); if (element.kind() != ZLTextElement::IMAGE_ELEMENT) { return false; } const ZLTextImageElement &imageElement = (ZLTextImageElement&)element; const std::string &id = imageElement.id(); if (id == CollectionModel::BookInfoImageId) { editBookInfo(collectionModel().bookByParagraphIndex(imageArea->ParagraphIndex)); return true; } else if (id == CollectionModel::RemoveBookImageId) { removeBook(collectionModel().bookByParagraphIndex(imageArea->ParagraphIndex)); return true; } else if (id == CollectionModel::RemoveTagImageId) { removeTag(collectionModel().tagByParagraphIndex(imageArea->ParagraphIndex)); return true; } else if (id == CollectionModel::TagInfoImageId) { editTagInfo(collectionModel().tagByParagraphIndex(imageArea->ParagraphIndex)); return true; } else { return false; } } int index = paragraphIndexByCoordinates(x, y); if (index == -1) { return false; } BookDescriptionPtr book = collectionModel().bookByParagraphIndex(index); if (!book.isNull()) { fbreader().openBook(book); fbreader().showBookTextView(); return true; } return false; }
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(); }
bool NetLibraryView::_onStylusPress(int x, int y) { fbreader().setHyperlinkCursor(false); if (model().isNull()) { return false; } const ZLTextElementArea *imageArea = elementByCoordinates(x, y); if ((imageArea == 0) || (imageArea->Kind != ZLTextElement::IMAGE_ELEMENT)) { return false; } ZLTextWordCursor cursor = startCursor(); cursor.moveToParagraph(imageArea->ParagraphIndex); cursor.moveTo(imageArea->ElementIndex, 0); const ZLTextElement &element = cursor.element(); if (element.kind() != ZLTextElement::IMAGE_ELEMENT) { return false; } const ZLTextImageElement &imageElement = (ZLTextImageElement&)element; const std::string &id = imageElement.id(); shared_ptr<NetworkBookInfo> book = myParagraphToBookMap[imageArea->ParagraphIndex]; if (book.isNull()) { return false; } if ((id == DownloadEpub) || (id == DownloadMobi)) { if (!ZLNetworkManager::instance().connect()) { NetworkOperationRunnable::showErrorMessage( ZLResource::resource("dialog") ["networkError"] ["couldntConnectToNetworkMessage"].value() ); return false; } NetworkBookInfo::URLType format = (id == DownloadEpub) ? NetworkBookInfo::BOOK_EPUB : NetworkBookInfo::BOOK_MOBIPOCKET; DownloadBookRunnable downloader(*book, format); downloader.executeWithUI(); if (downloader.hasErrors()) { downloader.showErrorMessage(); } else { BookDescriptionPtr description = BookDescription::getDescription(downloader.fileName()); WritableBookDescription wDescription(*description); wDescription.clearAuthor(); wDescription.addAuthor(book->Author.DisplayName, book->Author.SortKey); wDescription.title() = book->Title; wDescription.language() = book->Language; for (std::vector<std::string>::const_iterator it = book->Tags.begin(); it != book->Tags.end(); ++it) { wDescription.addTag(*it); } wDescription.saveInfo(); fbreader().openBook(description); fbreader().setMode(FBReader::BOOK_TEXT_MODE); rebuildModel(); } return true; } else if ((id == ReadLocalEpub) || (id == ReadLocalMobi)) { NetworkBookInfo::URLType format = (id == DownloadEpub) ? NetworkBookInfo::BOOK_EPUB : NetworkBookInfo::BOOK_MOBIPOCKET; fbreader().openFile(NetworkLinkCollection::instance().bookFileName(book->URLByType[format])); fbreader().setMode(FBReader::BOOK_TEXT_MODE); return true; } else if (id == OpenInBrowser) { std::string url = book->URLByType[NetworkBookInfo::LINK_HTTP]; shared_ptr<ProgramCollection> collection = fbreader().webBrowserCollection(); if (!url.empty() && !collection.isNull()) { shared_ptr<Program> program = collection->currentProgram(); if (!program.isNull()) { program->run("openLink", url); } } return true; } return false; }
void ZLTextSelectionModel::createData() const { if (!myTextIsUpToDate && !isEmpty()) { Range r = internalRange(); ZLTextWordCursor start = myArea.startCursor(); start.moveToParagraph(r.first.ParagraphIndex); start.moveTo(r.first.ElementIndex, r.first.CharIndex); ZLTextWordCursor end = myArea.startCursor(); end.moveToParagraph(r.second.ParagraphIndex); end.moveTo(r.second.ElementIndex, r.second.CharIndex); std::set<ZLTextParagraphCursorPtr> pcursors; pcursors.insert(start.paragraphCursorPtr()); ZLTextWordCursor cursor = start; while (cursor < end) { if (cursor.isEndOfParagraph()) { cursor.nextParagraph(); pcursors.insert(cursor.paragraphCursorPtr()); myText.append(ZLibrary::EndOfLine); continue; } const ZLTextElement &element = cursor.element(); switch (element.kind()) { case ZLTextElement::WORD_ELEMENT: { const ZLTextWord &word = (const ZLTextWord&)element; if (cursor.sameElementAs(end)) { if (start.sameElementAs(end)) { int skip = ZLUnicodeUtil::length(word.Data, start.charIndex()); int length = ZLUnicodeUtil::length(word.Data, end.charIndex()) - skip; myText.append(word.Data + skip, length); } else { myText.append(word.Data, ZLUnicodeUtil::length(word.Data, end.charIndex())); } } else if (cursor.charIndex() == 0) { myText.append(word.Data, word.Size); } else /* cursor == start */ { int skip = ZLUnicodeUtil::length(word.Data, cursor.charIndex()); myText.append(word.Data + skip, word.Size - skip); } break; } case ZLTextElement::IMAGE_ELEMENT: if (myImage.isNull()) { myImage = ((const ZLTextImageElement&)element).image(); } break; case ZLTextElement::HSPACE_ELEMENT: case ZLTextElement::NB_HSPACE_ELEMENT: myText += ' '; break; default: break; } cursor.nextWord(); } if ((cursor == end) && !cursor.isEndOfParagraph() && myImage.isNull()) { const ZLTextElement &element = cursor.element(); if (element.kind() == ZLTextElement::IMAGE_ELEMENT) { myImage = ((const ZLTextImageElement&)element).image(); } } myCursors.swap(pcursors); myTextIsUpToDate = true; } }
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; }