Exemplo n.º 1
0
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;
}
Exemplo n.º 3
0
bool ScrollToHomeAction::isEnabled() const {
	if (!isVisible()) {
		return false;
	}
	ZLTextWordCursor cursor = FBReader::Instance().bookTextView().textArea().startCursor();
	return cursor.isNull() || !cursor.isStartOfParagraph() || !cursor.paragraphCursor().isFirst();
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
std::vector<size_t>::const_iterator ZLTextView::nextBreakIterator() const {
    ZLTextWordCursor cursor = endCursor();
    if (cursor.isNull()) {
        cursor = startCursor();
    }
    if (cursor.isNull()) {
        return myTextBreaks.begin();
    }
    return std::lower_bound(myTextBreaks.begin(), myTextBreaks.end(), cursor.paragraphCursor().index());
}
Exemplo n.º 8
0
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);
		}
	}
}
Exemplo n.º 9
0
bool strongContains(const ZLTextSelectionModel::Range &range, const ZLTextWordCursor &cursor) {
	const int pn = cursor.paragraphCursor().index();
	const int wn = cursor.elementIndex();
	return
		((range.first.ParagraphIndex < pn) ||
		 ((range.first.ParagraphIndex == pn) &&
			(range.first.ElementIndex < wn))) &&
		((range.second.ParagraphIndex > pn) ||
		 ((range.second.ParagraphIndex == pn) &&
			(range.second.ElementIndex > wn)));
}
Exemplo n.º 10
0
size_t ZLTextView::PositionIndicator::sizeOfTextBeforeCursor(const ZLTextWordCursor &cursor) const {
	const size_t paragraphIndex = cursor.paragraphCursor().index();
	const size_t paragraphLength = cursor.paragraphCursor().paragraphLength();

	if (paragraphLength == 0) {
		return sizeOfTextBeforeParagraph(paragraphIndex);
	} else {
		return
			sizeOfTextBeforeParagraph(paragraphIndex) +
			muldiv(sizeOfParagraph(paragraphIndex), cursor.elementIndex(), paragraphLength);
	}
}
Exemplo n.º 11
0
void IfEmptyWordList()
{
	if (acwlistcount == 0)
	{
		ZLTextWordCursor cr = is_footnote_mode() ? footview->textArea().startCursor() : bookview->textArea().startCursor();
		int paragraph = !cr.isNull() ? cr.paragraphCursor().index() : 0;

		if (acwlistcount + 3 >= acwlistsize)
		{
			acwlistsize = acwlistsize + (acwlistsize >> 1) + 64;
			acwordlist = (SynWordList *)realloc(acwordlist, acwlistsize * sizeof(SynWordList));
		}
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;
}
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);
	}
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
void ZLTextView::PositionIndicator::draw() {
	ZLTextBaseStyle &baseStyle = ZLTextStyleCollection::instance().baseStyle();

	ZLPaintContext &context = this->context();

	ZLTextWordCursor endCursor = myTextView.endCursor();
	bool isEndOfText = false;
	if (endCursor.isEndOfParagraph()) {
		isEndOfText = !endCursor.nextParagraph();
	}

	myExtraWidth = 0;
	if (myInfo.isTimeShown()) {
		drawExtraText(timeString());
	}
	if (myInfo.isBatteryShown()) {
		drawExtraText(batteryString());
	}
	if (myInfo.isTextPositionShown()) {
		drawExtraText(textPositionString());
	}

	const long bottom = this->bottom();
	const long top = this->top();
	const long left = this->left();
	const long right = this->right();

	if (left >= right) {
		return;
	}

	size_t fillWidth = right - left - 1;

	if (!isEndOfText) {
		fillWidth =
			muldiv(fillWidth, sizeOfTextBeforeCursor(myTextView.endCursor()), sizeOfTextBeforeParagraph(endTextIndex()));
	}

	context.setColor(baseStyle.RegularTextColorOption.value());
	context.setFillColor(myInfo.color());
	context.fillRectangle(myTextView.visualX(left + 1), top + 1, myTextView.visualX(left + fillWidth + 1), bottom - 1);
	context.drawLine(myTextView.visualX(left), top, myTextView.visualX(right), top);
	context.drawLine(myTextView.visualX(left), bottom, myTextView.visualX(right), bottom);
	context.drawLine(myTextView.visualX(left), bottom, myTextView.visualX(left), top);
	context.drawLine(myTextView.visualX(right), bottom, myTextView.visualX(right), top);
}
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;
}
Exemplo n.º 17
0
size_t ZLTextView::PositionIndicator::sizeOfTextBeforeParagraph(size_t paragraphIndex) const {
	if (myTextView.myModel->kind() == ZLTextModel::TREE_MODEL) {
		ZLTextWordCursor cursor = myTextView.startCursor();
		if (cursor.isNull()) {
			cursor = myTextView.endCursor();
		}
		if (!cursor.isNull()) {
			const ZLTextTreeModel &treeModel = (const ZLTextTreeModel&)*myTextView.myModel;
			size_t sum = 0;
			for (size_t i = 0; i < paragraphIndex; ++i) {
				const ZLTextTreeParagraph *para = (const ZLTextTreeParagraph*)treeModel[i];
				if (para->parent()->isOpen()) {
					sum += sizeOfParagraph(i);
				}
			}
			return sum;
		}
	}
	return myTextView.myTextSize[paragraphIndex] - myTextView.myTextSize[startTextIndex()];
}
Exemplo n.º 18
0
void ZLTextSelectionModel::extendWordSelectionToParagraph() {
	clear();

	myFirstBound.Before.ElementIndex = 0;
	myFirstBound.Before.CharIndex = 0;
	myFirstBound.After = myFirstBound.Before;

	ZLTextWordCursor cursor = myView.startCursor();
	cursor.moveToParagraph(myFirstBound.Before.ParagraphIndex);
	cursor.moveToParagraphEnd();

	mySecondBound.Before.ElementIndex = cursor.elementIndex();
	mySecondBound.Before.CharIndex = 0;
	mySecondBound.After = mySecondBound.Before;

	myIsEmpty = false;
	myTextIsUpToDate = false;
	myRangeVectorIsUpToDate = false;
	myDoUpdate = false;
}
void ZLTextView::PositionIndicator::draw() {
	ZLPaintContext &context = this->context();

	ZLTextWordCursor endCursor = myTextView.textArea().endCursor();
	bool isEndOfText = false;
	if (endCursor.isEndOfParagraph()) {
		isEndOfText = !endCursor.nextParagraph();
	}

	myExtraWidth = 0;
	if (myInfo.isTimeShown()) {
		drawExtraText(timeString());
	}
	if (myInfo.isTextPositionShown()) {
		drawExtraText(textPositionString());
	}

	const long bottom = this->bottom();
	const long top = this->top();
	const long left = this->left();
	const long right = this->right();

	if (left >= right) {
		return;
	}

	size_t fillWidth = right - left - 1;

	if (!isEndOfText) {
		fillWidth =
			muldiv(fillWidth, sizeOfTextBeforeCursor(myTextView.textArea().endCursor()), sizeOfTextBeforeParagraph(endTextIndex()));
	}

	context.setColor(myTextView.color());
	context.setFillColor(myInfo.color());
	context.fillRectangle(left + 1, top + 1, left + fillWidth + 1, bottom - 1);
	context.drawLine(left, top, right, top);
	context.drawLine(left, bottom, right, bottom);
	context.drawLine(left, bottom, left, top);
	context.drawLine(right, bottom, right, top);
}
Exemplo n.º 20
0
void ZLTextSelectionModel::extendWordSelectionToParagraph() {
	clear();

	myFirstBound.Before.ElementIndex = 0;
	myFirstBound.Before.CharIndex = 0;
	myFirstBound.After = myFirstBound.Before;

	ZLTextWordCursor cursor = myArea.startCursor();
	cursor.moveToParagraph(myFirstBound.Before.ParagraphIndex);
	cursor.moveToParagraphEnd();

	mySecondBound.Before.ElementIndex = cursor.elementIndex();
	mySecondBound.Before.CharIndex = 0;
	mySecondBound.After = mySecondBound.Before;

	myIsEmpty = false;
	myTextIsUpToDate = false;
	myRangeVectorIsUpToDate = false;

	copySelectionToClipboard(ZLDialogManager::CLIPBOARD_SELECTION);
}
Exemplo n.º 21
0
int ZLTextSelectionModel::charIndex(const ZLTextElementArea &area, int x) {
	myView.myStyle.setTextStyle(area.Style, area.BidiLevel);
	ZLTextWordCursor cursor = myView.startCursor();
	cursor.moveToParagraph(area.ParagraphIndex);
	const ZLTextWord &word = (const ZLTextWord&)cursor.paragraphCursor()[area.ElementIndex];
	const bool mainDir =
		area.BidiLevel % 2 == myView.myStyle.baseBidiLevel() % 2;
	const int deltaX = mainDir ? x - area.XStart : area.XEnd - x;
	const int len = area.Length;
	const int start = area.StartCharIndex;
	int diff = deltaX;
	int previousDiff = diff;
	int index;
	for (index = 0; (index < len) && (diff > 0); ++index) {
		previousDiff = diff;
		diff = deltaX - myView.myStyle.wordWidth(word, start, index + 1);
	}
	if (previousDiff + diff < 0) {
		--index;
	}
	return start + index;
}
Exemplo n.º 22
0
int ZLTextSelectionModel::charIndex(const ZLTextElementRectangle &rectangle, int x) {
	int x1 = x - myArea.hOffset();
	ZLTextArea::Style style(myArea, rectangle.Style);
	style.setTextStyle(rectangle.Style, rectangle.BidiLevel);
	ZLTextWordCursor cursor = myArea.startCursor();
	cursor.moveToParagraph(rectangle.ParagraphIndex);
	const ZLTextWord &word = (const ZLTextWord&)cursor.paragraphCursor()[rectangle.ElementIndex];
	const bool mainDir =
		rectangle.BidiLevel % 2 == (myArea.isRtl() ? 1 : 0);
	const int deltaX = mainDir ? x1 - rectangle.XStart : rectangle.XEnd - x1;
	const int len = rectangle.Length;
	const int start = rectangle.StartCharIndex;
	int diff = deltaX;
	int previousDiff = diff;
	int index;
	for (index = 0; (index < len) && (diff > 0); ++index) {
		previousDiff = diff;
		diff = deltaX - style.wordWidth(word, start, index + 1);
	}
	if (previousDiff + diff < 0) {
		--index;
	}
	return start + index;
}
Exemplo n.º 23
0
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();
}
Exemplo n.º 24
0
BookTextView::Position BookTextView::cursorPosition(const ZLTextWordCursor &cursor) const {
	return Position(cursor.paragraphCursor().index(), cursor.elementIndex(), cursor.charIndex());
}
Exemplo n.º 25
0
BookTextView::Position BookTextView::cursorPosition(const ZLTextWordCursor &cursor) const {
	return Position(cursor.paragraphCursor().index(), cursor.wordNumber());
}
Exemplo n.º 26
0
bool ZLTextSelectionModel::selectWord(int x, int y) {
	clear();

	const ZLTextElementRectangle *rectangle = myArea.elementByCoordinates(x, y);
	if (rectangle == 0) {
		return false;
	}

	int startIndex = 0;
	int endIndex = 1;
	switch (rectangle->Kind) {
		default:
			return false;
		case ZLTextElement::IMAGE_ELEMENT:
			break;
		case ZLTextElement::WORD_ELEMENT:
		{
			ZLTextWordCursor cursor = myArea.startCursor();
			cursor.moveToParagraph(rectangle->ParagraphIndex);
			const ZLTextWord &word = (const ZLTextWord&)cursor.paragraphCursor()[rectangle->ElementIndex];
			ZLUnicodeUtil::Ucs4String ucs4string;
			ZLUnicodeUtil::utf8ToUcs4(ucs4string, word.Data, word.Size);
			startIndex = charIndex(*rectangle, x);
			if (startIndex == word.Length) {
				--startIndex;
			}
			endIndex = startIndex + 1;
			ZLUnicodeUtil::Ucs4Char ch = ucs4string[startIndex];
			if (ZLUnicodeUtil::isLetter(ch) || (('0' <= ch) && (ch <= '9'))) {
				while (--startIndex >= 0) {
					ch = ucs4string[startIndex];
					if (!ZLUnicodeUtil::isLetter(ch) && ((ch < '0') || (ch > '9'))) {
						break;
					}
				}
				++startIndex;
				while (++endIndex <= word.Length) {
					ch = ucs4string[endIndex - 1];
					if (!ZLUnicodeUtil::isLetter(ch) && ((ch < '0') || (ch > '9'))) {
						break;
					}
				}
				--endIndex;
			}
		}
	}

	myFirstBound.Before.Exists = true;
	myFirstBound.Before.ParagraphIndex = rectangle->ParagraphIndex;
	myFirstBound.Before.ElementIndex = rectangle->ElementIndex;
	myFirstBound.Before.CharIndex = startIndex;
	myFirstBound.After = myFirstBound.Before;

	mySecondBound.Before = myFirstBound.Before;
	mySecondBound.Before.CharIndex = endIndex;
	mySecondBound.After = mySecondBound.Before;

	myIsEmpty = false;
	myTextIsUpToDate = false;
	myRangeVectorIsUpToDate = false;

	copySelectionToClipboard(ZLDialogManager::CLIPBOARD_SELECTION);

	return true;
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
0
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;
	}
}
bool ZLTextAreaController::preparePaintInfo() {
	if ((myPaintState == NOTHING_TO_PAINT) || (myPaintState == READY)) {
		return false;
	}

            myArea.myLineInfoCache.insert(myArea.myLineInfos.begin(), myArea.myLineInfos.end());



	switch (myPaintState) {
		default:
			break;
		case TO_SCROLL_FORWARD:
			if (!myArea.myEndCursor.paragraphCursor().isLast() ||
					!myArea.myEndCursor.isEndOfParagraph()) {
				ZLTextWordCursor startCursor;
				switch (myScrollingMode) {
					case NO_OVERLAPPING:
						break;
					case KEEP_LINES:
						startCursor = findLineFromEnd(myOverlappingValue);
						break;
					case SCROLL_LINES:
						startCursor = findLineFromStart(myOverlappingValue);
						if (startCursor.isEndOfParagraph()) {
							startCursor.nextParagraph();
						}
						break;
					case SCROLL_PERCENTAGE:
						startCursor = findPercentFromStart(myOverlappingValue);
						break;
				}

				if (!startCursor.isNull() && (startCursor == myArea.myStartCursor)) {

					startCursor = findLineFromStart(1);

				}

				if (!startCursor.isNull()) {

					ZLTextWordCursor endCursor = buildInfos(startCursor);


					if (!visiblePageIsEmpty() && ((myScrollingMode != KEEP_LINES) || (endCursor != myArea.myEndCursor))) {

                                                    myArea.myStartCursor = startCursor;
                                                    myArea.myEndCursor = endCursor;

						break;
					}

				}

                                    myArea.myStartCursor = myArea.myEndCursor;
                                    myArea.myEndCursor = buildInfos(myArea.myStartCursor);

			}
			break;
		case TO_SCROLL_BACKWARD:
			if (!myArea.myStartCursor.paragraphCursor().isFirst() || !myArea.myStartCursor.isStartOfParagraph()) {
				switch (myScrollingMode) {
					case NO_OVERLAPPING:
						myArea.myStartCursor = findStart(myArea.myStartCursor, PIXEL_UNIT, myArea.height());
						break;
					case KEEP_LINES:
					{
						ZLTextWordCursor endCursor = findLineFromStart(myOverlappingValue);
						if (!endCursor.isNull() && (endCursor == myArea.myEndCursor)) {
							endCursor = findLineFromEnd(1);
						}
						if (!endCursor.isNull()) {
							ZLTextWordCursor startCursor = findStart(endCursor, PIXEL_UNIT, myArea.height());
							myArea.myStartCursor =
								(startCursor != myArea.myStartCursor) ?
									startCursor : findStart(myArea.myStartCursor, PIXEL_UNIT, myArea.height());
						} else {
							myArea.myStartCursor = findStart(myArea.myStartCursor, PIXEL_UNIT, myArea.height());
						}
						break;
					}
					case SCROLL_LINES:
						myArea.myStartCursor = findStart(myArea.myStartCursor, LINE_UNIT, myOverlappingValue);
						break;
					case SCROLL_PERCENTAGE:
						myArea.myStartCursor =
							findStart(myArea.myStartCursor, PIXEL_UNIT, myArea.height() * myOverlappingValue / 100);
						break;
				}
				myArea.myEndCursor = buildInfos(myArea.myStartCursor);
				if (visiblePageIsEmpty()) {
					myArea.myStartCursor = findStart(myArea.myStartCursor, LINE_UNIT, 1);
					myArea.myEndCursor = buildInfos(myArea.myStartCursor);
				}
			}
			break;
		case START_IS_KNOWN:
			myArea.myEndCursor = buildInfos(myArea.myStartCursor);
			if (visiblePageIsEmpty()) {
				ZLTextWordCursor startCursor = findLineFromStart(1);
				if (!startCursor.isNull()) {
					myArea.myStartCursor = startCursor;
					if (myArea.myStartCursor.isEndOfParagraph()) {
						myArea.myStartCursor.nextParagraph();
					}
					myArea.myEndCursor = buildInfos(myArea.myStartCursor);
				}
			}
			break;
		case END_IS_KNOWN:
			myArea.myStartCursor = findStart(myArea.myEndCursor, PIXEL_UNIT, myArea.height());
			myArea.myEndCursor = buildInfos(myArea.myStartCursor);
			break;
	}

        myPaintState = READY;
        myArea.myLineInfoCache.clear();
	return true;
}
Exemplo n.º 30
0
void ZLTextView::prepareTextLine(const ZLTextLineInfo &info, int y) {
	y = std::min(y + info.Height, topMargin() + textAreaHeight());

	myStyle.setTextStyle(info.StartStyle, info.StartBidiLevel);
	int spaceCounter = info.SpaceCounter;
	int fullCorrection = 0;
	const bool endOfParagraph = info.End.isEndOfParagraph();
	bool wordOccured = false;

	int x = lineStartMargin() + info.StartIndent;

	const int fontSize = myStyle.textStyle()->fontSize();
	// TODO: change metrics at font change
	const ZLTextStyleEntry::Metrics metrics(fontSize, fontSize / 2, viewWidth(), textAreaHeight());

	switch (myStyle.textStyle()->alignment()) {
		case ALIGN_RIGHT:
			if (!myStyle.baseIsRtl()) {
				x += metrics.FullWidth - myStyle.textStyle()->lineEndIndent(metrics, myStyle.baseIsRtl()) - info.Width;
			}
			break;
		case ALIGN_LEFT:
			if (myStyle.baseIsRtl()) {
				x += metrics.FullWidth - myStyle.textStyle()->lineEndIndent(metrics, myStyle.baseIsRtl()) - info.Width;
			}
			break;
		case ALIGN_LINESTART:
			break;
		case ALIGN_CENTER:
			x += (metrics.FullWidth - myStyle.textStyle()->lineEndIndent(metrics, myStyle.baseIsRtl()) - info.Width) / 2;
			break;
		case ALIGN_JUSTIFY:
			if (!endOfParagraph && (info.End.element().kind() != ZLTextElement::AFTER_PARAGRAPH_ELEMENT)) {
				fullCorrection = metrics.FullWidth - myStyle.textStyle()->lineEndIndent(metrics, myStyle.baseIsRtl()) - info.Width;
			}
			break;
		case ALIGN_UNDEFINED:
			break;
	}

	const ZLTextParagraphCursor &paragraph = info.RealStart.paragraphCursor();
	int paragraphIndex = paragraph.index();
	for (ZLTextWordCursor pos = info.RealStart; !pos.equalElementIndex(info.End); pos.nextWord()) {
		const ZLTextElement &element = paragraph[pos.elementIndex()];
		ZLTextElement::Kind kind = element.kind();
		int width = myStyle.elementWidth(element, pos.charIndex(), metrics);
	
		myStyle.applySingleControl(element);
		switch (kind) {
			case ZLTextElement::WORD_ELEMENT:
			case ZLTextElement::IMAGE_ELEMENT:
			{
				const int height = myStyle.elementHeight(element, metrics);
				const int descent = myStyle.elementDescent(element);
				const int length = (kind == ZLTextElement::WORD_ELEMENT) ? ((const ZLTextWord&)element).Length - pos.charIndex() : 0;
				addAreaToTextMap(
					ZLTextElementArea(
						paragraphIndex, pos.elementIndex(), pos.charIndex(), length, false,
						myStyle.textStyle(), kind,
						x, x + width - 1, y - height + 1, y + descent, myStyle.bidiLevel()
					)
				);
				wordOccured = true;
				break;
			}
			case ZLTextElement::CONTROL_ELEMENT:
			case ZLTextElement::FORCED_CONTROL_ELEMENT:
				break;
			case ZLTextElement::HSPACE_ELEMENT:
			case ZLTextElement::NB_HSPACE_ELEMENT:
				if (wordOccured && (spaceCounter > 0)) {
					int correction = fullCorrection / spaceCounter;
					x += context().spaceWidth() + correction;
					fullCorrection -= correction;
					wordOccured = false;
					--spaceCounter;
				}
				break;
			case ZLTextElement::INDENT_ELEMENT:
			case ZLTextElement::BEFORE_PARAGRAPH_ELEMENT:
			case ZLTextElement::AFTER_PARAGRAPH_ELEMENT:
			case ZLTextElement::EMPTY_LINE_ELEMENT:
			case ZLTextElement::FIXED_HSPACE_ELEMENT:
				break;
			case ZLTextElement::START_REVERSED_SEQUENCE_ELEMENT:
				//context().setColor(ZLColor(0, 255, 0));
				//context().drawLine(visualX(x), y, visualX(x), y - 20);
				break;
			case ZLTextElement::END_REVERSED_SEQUENCE_ELEMENT:
				flushRevertedElements(myStyle.bidiLevel());
				//context().setColor(ZLColor(255, 0, 0));
				//context().drawLine(visualX(x), y, visualX(x), y - 20);
				break;
		}

		x += width;
	}
	if (!endOfParagraph && (info.End.element().kind() == ZLTextElement::WORD_ELEMENT)) {
		int start = 0;
		if (info.End.equalElementIndex(info.RealStart)) {
			start = info.RealStart.charIndex();
		}
		const int len = info.End.charIndex() - start;
		if (len > 0) {
			const ZLTextWord &word = (const ZLTextWord&)info.End.element();
			ZLUnicodeUtil::Ucs4String ucs4string;
			ZLUnicodeUtil::utf8ToUcs4(ucs4string, word.Data, word.Size);
			const bool addHyphenationSign = ucs4string[start + len - 1] != '-';
			const int width = myStyle.wordWidth(word, start, len, addHyphenationSign);
			const int height = myStyle.elementHeight(word, metrics);
			const int descent = myStyle.elementDescent(word);
			addAreaToTextMap(
				ZLTextElementArea(
					paragraphIndex, info.End.elementIndex(), start, len, addHyphenationSign,
					myStyle.textStyle(), ZLTextElement::WORD_ELEMENT,
					x, x + width - 1, y - height + 1, y + descent, word.BidiLevel
				)
			);
		}
	}

	for (unsigned char i = myStyle.bidiLevel(); i > myStyle.baseBidiLevel(); --i) {
		flushRevertedElements(i - 1);
	}
}