Commit f47d6140 authored by twanvl's avatar twanvl

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.
parent a2fd7841
......@@ -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 <line>
// 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;
......
......@@ -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);
};
......
......@@ -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<Line> lines_before;
vector<CharInfo> 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<CharInfo>& 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<CharInfo>& 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) {
......
......@@ -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
......
......@@ -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
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment