Commit 4ff8467e authored by twanvl's avatar twanvl

Tweaked cursor movement a bit

parent b0f85751
...@@ -868,22 +868,33 @@ void TextValueEditor::insert(const String& text, const String& action_name) { ...@@ -868,22 +868,33 @@ void TextValueEditor::insert(const String& text, const String& action_name) {
/// compare two cursor positions, determine how much the text matches before and after /// compare two cursor positions, determine how much the text matches before and after
size_t match_cursor_position(size_t pos1, const String& text1, size_t pos2, const String& text2) { size_t match_cursor_position(size_t pos1, const String& text1, size_t pos2, const String& text2) {
size_t penalty = 0; // penalty for case mismatches size_t score = 0; // total score
size_t before; // Match part before cursor
for (before = 0 ; before < min(pos1,pos2) ; ++before) { size_t before1, before2;
Char c1 = text1.GetChar(pos1-before-1), c2 = text2.GetChar(pos2-before-1); for (before1 = before2 = 0 ; before1 < pos1 && before2 < pos2 ; ++before1, ++before2) {
if (toLower(c1) != toLower(c2)) break; Char c1 = text1.GetChar(pos1-before1-1), c2 = text2.GetChar(pos2-before2-1);
else if (c1 != c2) ++penalty; if (c1 == c2) score += 10000;
else if (toLower(c1) == toLower(c2)) score += 9999;
else if (isPunct(c1) && isPunct(c2)) score += 1;
else if (c1 == UNTAG_ATOM_KWPPH) {score += 1; --before2;}
else break;
} }
if (pos1 == before && pos2 == before) ++before; // bonus points for matching start of string // bonus points for matching start of string
size_t after; if (pos1 == before1 && pos2 == before2) score += 10000;
for (after = 0 ; after < min(text1.size() - pos1, text2.size() - pos2) ; ++after) { // Match part after cursor
Char c1 = text1.GetChar(pos1+after), c2 = text2.GetChar(pos2+after); size_t after1, after2;
if (toLower(c1) != toLower(c2)) break; for (after1 = after2 = 0 ; pos1 + after1 < text1.size() && pos2 + after2 < text2.size() ; ++after1, ++after2) {
else if (c1 != c2) ++penalty; Char c1 = text1.GetChar(pos1+after1), c2 = text2.GetChar(pos2+after2);
if (c1 == c2) score += 10;
else if (toLower(c1) == toLower(c2)) score += 9;
else if (isPunct(c1) && isPunct(c2)) score += 1;
else if (c2 == UNTAG_ATOM_KWPPH) {score += 1; --after1;}
else break;
} }
if (pos1+after == text1.size() && pos2+after == text2.size()) ++after; // bonus points for matching end of string // bonus points for matching end of string
return 1000 * before + 2 * after - penalty; // matching 'before' is more important if (pos1+after1 == text1.size() && pos2+after2 == text2.size()) score += 2;
// final score: matching 'before' is more important
return score;
} }
void TextValueEditor::replaceSelection(const String& replacement, const String& name, bool allow_auto_replace, bool select_on_undo) { void TextValueEditor::replaceSelection(const String& replacement, const String& name, bool allow_auto_replace, bool select_on_undo) {
...@@ -924,17 +935,17 @@ void TextValueEditor::replaceSelection(const String& replacement, const String& ...@@ -924,17 +935,17 @@ void TextValueEditor::replaceSelection(const String& replacement, const String&
size_t best_cursor = expected_cursor; size_t best_cursor = expected_cursor;
if (real_value.size() < expected_value.size() if (real_value.size() < expected_value.size()
&& expected_cursor < expected_value.size() && expected_cursor < expected_value.size()
&& expected_value.GetChar(expected_cursor) == _('\3') // \3 == <sep> && expected_value.GetChar(expected_cursor) == UNTAG_SEP
&& real_value.GetChar(start) == _('\3') // \3 == <sep> && real_value.GetChar(start) == UNTAG_SEP
&& real_value.size() - end_min == start) { && real_value.size() - end_min == start) {
// exception for type-over separators // exception for type-over separators
best_cursor = start + 1; best_cursor = start + 1;
} else { } else {
// try to find the best match // try to find the best match to what text we expected to be around the cursor
size_t best_match = 0; size_t best_match = 0;
for (size_t i = min(start, expected_cursor) ; i <= real_value.size() - end_min ; ++i) { for (size_t i = min(start, expected_cursor) ; i <= max(real_value.size() - end_min, expected_cursor) ; ++i) {
size_t match = match_cursor_position(expected_cursor, expected_value, i, real_value); size_t match = match_cursor_position(expected_cursor, expected_value, i, real_value);
if (match > best_match) { if (match > best_match || (match == best_match && abs((int)expected_cursor - (int)i) < abs((int)expected_cursor - (int)best_cursor))) {
best_match = match; best_match = match;
best_cursor = i; best_cursor = i;
} }
......
...@@ -347,12 +347,15 @@ String untag_for_cursor(const String& str) { ...@@ -347,12 +347,15 @@ String untag_for_cursor(const String& str) {
for (size_t i = 0 ; i < str.size() ; ) { for (size_t i = 0 ; i < str.size() ; ) {
Char c = str.GetChar(i); Char c = str.GetChar(i);
if (c == _('<')) { if (c == _('<')) {
if (is_substr(str, i, _("<atom"))) { if (is_substr(str, i, _("<atom-kwpph"))) {
i = match_close_tag_end(str, i); i = match_close_tag_end(str, i);
ret += _('\2'); // use a random character here ret += UNTAG_ATOM_KWPPH;
} else if (is_substr(str, i, _("<atom"))) {
i = match_close_tag_end(str, i);
ret += UNTAG_ATOM;
} else if (is_substr(str, i, _("<sep"))) { } else if (is_substr(str, i, _("<sep"))) {
i = match_close_tag_end(str, i); i = match_close_tag_end(str, i);
ret += _('\3'); // use a random character here ret += UNTAG_SEP;
} else if (i == 0 && is_substr(str, i, _("<prefix"))) { } else if (i == 0 && is_substr(str, i, _("<prefix"))) {
// prefix at start of string, skip contents, index never before // prefix at start of string, skip contents, index never before
i = match_close_tag_end(str,i); i = match_close_tag_end(str,i);
......
...@@ -114,6 +114,11 @@ void cursor_to_index_range(const String& str, size_t cursor, size_t& begin, size ...@@ -114,6 +114,11 @@ void cursor_to_index_range(const String& str, size_t cursor, size_t& begin, size
/// Find the character index corresponding to the given cursor position /// Find the character index corresponding to the given cursor position
size_t cursor_to_index(const String& str, size_t cursor, Movement dir = MOVE_MID); size_t cursor_to_index(const String& str, size_t cursor, Movement dir = MOVE_MID);
const Char UNTAG_ATOM = _('\2');
const Char UNTAG_SEP = _('\3');
const Char UNTAG_ATOM_KWPPH = _('\4');
/// Untag a string for use with cursors, <atom>...</atom> becomes a single character. /// Untag a string for use with cursors, <atom>...</atom> becomes a single character.
/** This string should only be used for cursor position calculations. */ /** This string should only be used for cursor position calculations. */
String untag_for_cursor(const String& str); String untag_for_cursor(const String& str);
......
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