diff options
author | Sebastian Geerken <devnull@localhost> | 2012-10-07 23:22:23 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2012-10-07 23:22:23 +0200 |
commit | d1179582ee86f08fbc23d2363df7a794324095e8 (patch) | |
tree | b923faa58dc565fe199b485039f712b4a80d8862 /dw/textblock_iterator.cc | |
parent | d5e75bd44a43d8ef3bfdc9ac98ab4dfc3f6a4f94 (diff) |
TextblockIterator in own source file.
Diffstat (limited to 'dw/textblock_iterator.cc')
-rw-r--r-- | dw/textblock_iterator.cc | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/dw/textblock_iterator.cc b/dw/textblock_iterator.cc new file mode 100644 index 00000000..63720ffb --- /dev/null +++ b/dw/textblock_iterator.cc @@ -0,0 +1,219 @@ +/* + * Dillo Widget + * + * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "textblock.hh" +#include "../lout/msg.h" +#include "../lout/misc.hh" + +#include <stdio.h> +#include <math.h> + +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(misc::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; + + 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; + } + + 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; + + 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; + } + + textblock->queueDrawRange (index1, index2); +} + +void Textblock::queueDrawRange (int index1, int index2) +{ + int from = misc::min (index1, index2); + int to = misc::max (index1, index2); + + from = misc::min (from, words->size () - 1); + from = misc::max (from, 0); + to = misc::min (to, words->size () - 1); + to = misc::max (to, 0); + + int line1idx = findLineOfWord (from); + int line2idx = findLineOfWord (to); + + if (line1idx >= 0 && line2idx >= 0) { + Line *line1 = lines->getRef (line1idx), + *line2 = lines->getRef (line2idx); + int y = lineYOffsetWidget (line1) + line1->boxAscent - + line1->contentAscent; + int h = lineYOffsetWidget (line2) + line2->boxAscent + + line2->contentDescent - y; + + queueDrawArea (0, y, allocation.width, h); + } +} + +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); + } + 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); + } + } + allocation->ascent = word->size.ascent; + allocation->descent = word->size.descent; +} + +} // namespace dw |