From 1580b8deaf1a1999916f906c294e8e104a9c2884 Mon Sep 17 00:00:00 2001 From: twanvl Date: Sat, 22 Sep 2007 13:10:51 +0000 Subject: [PATCH] Fixed bug in smart_less, strings ending in numbers were compared incorrectly; Text viewer now doesn't scale when there is a line break inside a word; Fixed: extra newline was inserted when there was a line break inside a word if there was padding. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@743 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/gui/value/text.cpp | 20 ++++++----------- src/gui/value/text.hpp | 2 +- src/render/text/viewer.cpp | 45 ++++++++++++++++++++++++++------------ src/render/text/viewer.hpp | 3 ++- src/util/string.cpp | 16 +++++++++++--- 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 821567be..20eec182 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -430,18 +430,12 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) { } break; case WXK_UP: - if (field().multi_line) { - moveSelection(TYPE_INDEX, v.moveLine(selection_end_i, -1), !ev.ShiftDown(), MOVE_LEFT_OPT); - } else { - wordListDropDown(findWordList(selection_end_i)); - } + if ( wordListDropDown(findWordList(selection_end_i)) ) break; + moveSelection(TYPE_INDEX, v.moveLine(selection_end_i, -1), !ev.ShiftDown(), MOVE_LEFT_OPT); break; case WXK_DOWN: - if (field().multi_line) { - moveSelection(TYPE_INDEX, v.moveLine(selection_end_i, +1), !ev.ShiftDown(), MOVE_RIGHT_OPT); - } else { - wordListDropDown(findWordList(selection_end_i)); - } + if ( wordListDropDown(findWordList(selection_end_i)) ) break; + moveSelection(TYPE_INDEX, v.moveLine(selection_end_i, +1), !ev.ShiftDown(), MOVE_RIGHT_OPT); break; case WXK_HOME: // move to begining of line / all (if control) @@ -805,7 +799,7 @@ void TextValueEditor::showCaret() { // The caret wxCaret* caret = editor().GetCaret(); // cursor rectangle - RealRect cursor = v.charRect(selection_end_i); + RealRect cursor = v.charRect(selection_end_i, selection_start_i <= selection_end_i); cursor.width = 0; // height may be 0 near a // it is not 0 for empty text, because TextRenderer handles that case @@ -1312,8 +1306,8 @@ void TextValueEditor::drawWordListIndicators(RotatedDC& dc, bool redrawing) { RealRect& r = wl->rect; if (r.height < 0) { // find the rectangle for this indicator - RealRect start = v.charRect(wl->start); - RealRect end = v.charRect(wl->end > wl->start ? wl->end - 1 : wl->start); + RealRect start = v.charRect(wl->start, true); + RealRect end = v.charRect(wl->end > wl->start ? wl->end - 1 : wl->start, false); r.x = start.x; r.y = start.y; r.width = end.right() - start.left() + 0.5; diff --git a/src/gui/value/text.hpp b/src/gui/value/text.hpp index a99cb368..884939c7 100644 --- a/src/gui/value/text.hpp +++ b/src/gui/value/text.hpp @@ -182,7 +182,7 @@ class TextValueEditor : public TextValueViewer, public ValueEditor { WordListPosP findWordListBody(const RealPoint& pos) const; /// Find a WordListPos for a index position WordListPosP findWordList(size_t index) const; - /// Show a word list drop down menu, if wl + /// Show a word list drop down menu, if wl. Returns true if a list is shown bool wordListDropDown(const WordListPosP& wl); }; diff --git a/src/render/text/viewer.cpp b/src/render/text/viewer.cpp index 9b8a92d5..b45cfed1 100644 --- a/src/render/text/viewer.cpp +++ b/src/render/text/viewer.cpp @@ -216,11 +216,18 @@ size_t TextViewer::indexAt(const RealPoint& pos) const { return l->posToIndex(pos.x); } -RealRect TextViewer::charRect(size_t index) const { +RealRect TextViewer::charRect(size_t index, bool first) const { if (lines.empty()) return RealRect(0,0,0,0); const Line& l = findLine(index); size_t pos = index - l.start; if (pos + 1 >= l.positions.size()) { + if (!first && &l < &lines.back()) { + // try the start of the next line + const Line& l2 = *(&l+1); + if (index == l2.start) { + return RealRect(l2.positions.front(), l2.top, 0, l2.line_height); + } + } return RealRect(l.positions.back(), l.top, 0, l.line_height); } else { return RealRect(l.positions[pos], l.top, l.positions[pos + 1] - l.positions[pos], l.line_height); @@ -420,7 +427,7 @@ void TextViewer::prepareLinesTryScales(RotatedDC& dc, const String& text, const // Try the layout at the previous scale, this could give a quick upper bound elements.getCharInfo(dc, scale, 0, text.size(), chars); - bool fits = prepareLinesScale(dc, chars, style, true, lines); + bool fits = prepareLinesScale(dc, chars, style, false, lines); if (fits) { min_scale = scale; max_scale = min(max_scale, bound_on_max_scale(dc,style,lines,scale)); @@ -431,7 +438,7 @@ void TextViewer::prepareLinesTryScales(RotatedDC& dc, const String& text, const vector lines_before; vector chars_before; elements.getCharInfo(dc, scale, 0, text.size(), chars_before); - fits = prepareLinesScale(dc, chars_before, style, true, lines_before); + fits = prepareLinesScale(dc, chars_before, style, false, lines_before); if (fits) { // too bad swap(lines, lines_before); @@ -542,21 +549,23 @@ bool TextViewer::prepareLinesScale(RotatedDC& dc, const vector& chars, // Did the word become too long? if (style.field().multi_line && !break_now) { double max_width = lineRight(dc, style, line.top); - if (word_start == line.start && word_size.width > max_width) { - // single word on this line; the word is too long - if (stop_if_too_long) { - return false; // just give up + if (line_size.width + word_size.width > max_width) { + if (word_start == line.start) { + // single word on this line; the word is too long + if (stop_if_too_long) { + return false; // just give up + } else { + // force a word break + break_now = true; + accept_word = true; + hide_breaker = false; + line.break_after = BREAK_SOFT; + } } else { - // force a word break + // line would become too long, break before the current word break_now = true; - accept_word = true; - hide_breaker = false; line.break_after = BREAK_SOFT; } - } else if (line_size.width + word_size.width > max_width) { - // line would become too long, break before the current word - break_now = true; - line.break_after = BREAK_SOFT; } } // Ending the current word @@ -572,6 +581,14 @@ bool TextViewer::prepareLinesScale(RotatedDC& dc, const vector& chars, word_start = i + 1; positions_word.clear(); word_end_or_soft = 0; + // move character that goes outside the box to the next line + if (!hide_breaker && line.positions.size() > 2) { + line.positions.pop_back(); + word_start = i; + word_size = add_horizontal(word_size, c.size); + positions_word.push_back(word_size.width); + if (!c.soft) word_end_or_soft = i + 1; + } } // Breaking (ending the current line) if (break_now) { diff --git a/src/render/text/viewer.hpp b/src/render/text/viewer.hpp index 0bac7d54..130f0478 100644 --- a/src/render/text/viewer.hpp +++ b/src/render/text/viewer.hpp @@ -84,7 +84,8 @@ class TextViewer { RealPoint posOf(size_t index) const; /// Return the rectangle around a single character - RealRect charRect(size_t index) const; + /** If 'first' prefers earlier lines */ + RealRect charRect(size_t index, bool first) const; /// Is the character at the given index visible? bool isVisible(size_t index) const; /// Find the first character index that is at/before/after the given index, and which has a nonzero width diff --git a/src/util/string.cpp b/src/util/string.cpp index f6cdb300..e61dd876 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -300,6 +300,8 @@ bool smart_less(const String& sa, const String& sb) { // two numbers of the same length, but not equal return lt; } else if (a != b) { + // not a number + eq = true; lt = false; if (a >= 0x20 && b >= 0x20) { // compare characters Char la = remove_accents(a), lb = remove_accents(b); @@ -333,10 +335,18 @@ bool smart_less(const String& sa, const String& sb) { // When we are at the end; shorter strings come first // This is true for normal string collation // and also when both end in a number and another digit follows - if (na - pa != nb - pb) { - return na - pa < nb - pb; + if (in_num) { + if (na - pa < nb - pb) { + // number b continues? + Char b = sb.GetChar(pb); + if (isDigit(b) || eq) return true; // b is longer + } else if (na - pa > nb - pb) { + Char a = sa.GetChar(pa); + if (isDigit(a) || eq) return false; // a is longer + } + return lt; // compare numbers } else { - return lt; + return na - pa < nb - pb; // outside number, shorter string comes first } }