/* * Dillo Widget * * Copyright 2005-2007 Sebastian Geerken * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "textblock.hh" #include "../lout/msg.h" #include "../lout/misc.hh" #include #include using namespace lout; namespace dw { Textblock::TextblockIterator::TextblockIterator (Textblock *textblock, core::Content::Type mask, bool atEnd): core::Iterator (textblock, mask, atEnd) { index = atEnd ? textblock->words->size () : -1; content.type = atEnd ? core::Content::END : core::Content::START; } Textblock::TextblockIterator::TextblockIterator (Textblock *textblock, core::Content::Type mask, int index): core::Iterator (textblock, mask, false) { this->index = index; if (index < 0) content.type = core::Content::START; else if (index >= textblock->words->size ()) content.type = core::Content::END; else content = textblock->words->getRef(index)->content; } object::Object *Textblock::TextblockIterator::clone() { return new TextblockIterator ((Textblock*)getWidget(), getMask(), index); } int Textblock::TextblockIterator::compareTo(object::Comparable *other) { return index - ((TextblockIterator*)other)->index; } bool Textblock::TextblockIterator::next () { Textblock *textblock = (Textblock*)getWidget(); if (content.type == core::Content::END) return false; do { index++; if (index >= textblock->words->size ()) { content.type = core::Content::END; return false; } } while ((textblock->words->getRef(index)->content.type & getMask()) == 0); content = textblock->words->getRef(index)->content; return true; } bool Textblock::TextblockIterator::prev () { Textblock *textblock = (Textblock*)getWidget(); if (content.type == core::Content::START) return false; do { index--; if (index < 0) { content.type = core::Content::START; return false; } } while ((textblock->words->getRef(index)->content.type & getMask()) == 0); content = textblock->words->getRef(index)->content; return true; } void Textblock::TextblockIterator::highlight (int start, int end, core::HighlightLayer layer) { Textblock *textblock = (Textblock*)getWidget(); int index1 = index, index2 = index; int oldStartIndex = textblock->hlStart[layer].index; int oldStartChar = textblock->hlStart[layer].nChar; int oldEndIndex = textblock->hlEnd[layer].index; int oldEndChar = textblock->hlEnd[layer].nChar; if (textblock->hlStart[layer].index > textblock->hlEnd[layer].index) { /* nothing is highlighted */ textblock->hlStart[layer].index = index; textblock->hlEnd[layer].index = index; } if (textblock->hlStart[layer].index >= index) { index2 = textblock->hlStart[layer].index; textblock->hlStart[layer].index = index; textblock->hlStart[layer].nChar = start; } if (textblock->hlEnd[layer].index <= index) { index2 = textblock->hlEnd[layer].index; textblock->hlEnd[layer].index = index; textblock->hlEnd[layer].nChar = end; } if (oldStartIndex != textblock->hlStart[layer].index || oldStartChar != textblock->hlStart[layer].nChar || oldEndIndex != textblock->hlEnd[layer].index || oldEndChar != textblock->hlEnd[layer].nChar) textblock->queueDrawRange (index1, index2); } void Textblock::TextblockIterator::unhighlight (int direction, core::HighlightLayer layer) { Textblock *textblock = (Textblock*)getWidget(); int index1 = index, index2 = index; if (textblock->hlStart[layer].index > textblock->hlEnd[layer].index) return; int oldStartIndex = textblock->hlStart[layer].index; int oldStartChar = textblock->hlStart[layer].nChar; int oldEndIndex = textblock->hlEnd[layer].index; int oldEndChar = textblock->hlEnd[layer].nChar; if (direction == 0) { index1 = textblock->hlStart[layer].index; index2 = textblock->hlEnd[layer].index; textblock->hlStart[layer].index = 1; textblock->hlEnd[layer].index = 0; } else if (direction > 0 && textblock->hlStart[layer].index <= index) { index1 = textblock->hlStart[layer].index; textblock->hlStart[layer].index = index + 1; textblock->hlStart[layer].nChar = 0; } else if (direction < 0 && textblock->hlEnd[layer].index >= index) { index1 = textblock->hlEnd[layer].index; textblock->hlEnd[layer].index = index - 1; textblock->hlEnd[layer].nChar = INT_MAX; } if (oldStartIndex != textblock->hlStart[layer].index || oldStartChar != textblock->hlStart[layer].nChar || oldEndIndex != textblock->hlEnd[layer].index || oldEndChar != textblock->hlEnd[layer].nChar) textblock->queueDrawRange (index1, index2); } void Textblock::TextblockIterator::getAllocation (int start, int end, core::Allocation *allocation) { Textblock *textblock = (Textblock*)getWidget(); int lineIndex = textblock->findLineOfWord (index); Line *line = textblock->lines->getRef (lineIndex); Word *word = textblock->words->getRef (index); allocation->x = textblock->allocation.x + textblock->lineXOffsetWidget (line); for (int i = line->firstWord; i < index; i++) { Word *w = textblock->words->getRef(i); allocation->x += w->size.width + w->effSpace; } if (start > 0 && word->content.type == core::Content::TEXT) { allocation->x += textblock->textWidth (word->content.text, 0, start, word->style, word->flags & Word::WORD_START, (word->flags & Word::WORD_END) && word->content.text[start] == 0); } allocation->y = textblock->lineYOffsetCanvas (line) + line->boxAscent - word->size.ascent; allocation->width = word->size.width; if (word->content.type == core::Content::TEXT) { int wordEnd = strlen(word->content.text); if (start > 0 || end < wordEnd) { end = misc::min(end, wordEnd); /* end could be INT_MAX */ allocation->width = textblock->textWidth (word->content.text, start, end - start, word->style, (word->flags & Word::WORD_START) && start == 0, (word->flags & Word::WORD_END) && word->content.text[end] == 0); } } allocation->ascent = word->size.ascent; allocation->descent = word->size.descent; } } // namespace dw