(svn r25654) -Fix: Improve character and word deletion for CJK languages and complex scripts.

This commit is contained in:
michi_cc 2013-08-05 20:35:35 +00:00
parent 76367f6bf1
commit a31be4ce11
2 changed files with 49 additions and 83 deletions

View File

@ -42,58 +42,6 @@ bool Textbuf::CanDelChar(bool backspace)
return backspace ? this->caretpos != 0 : this->caretpos < this->bytes - 1; return backspace ? this->caretpos != 0 : this->caretpos < this->bytes - 1;
} }
/**
* Get the next character that will be removed by DelChar.
* @param backspace if set, delete the character before the caret,
* otherwise, delete the character after it.
* @return the next character that will be removed by DelChar.
* @warning You should ensure Textbuf::CanDelChar returns true before calling this function.
*/
WChar Textbuf::GetNextDelChar(bool backspace)
{
assert(this->CanDelChar(backspace));
const char *s;
if (backspace) {
s = Utf8PrevChar(this->buf + this->caretpos);
} else {
s = this->buf + this->caretpos;
}
WChar c;
Utf8Decode(&c, s);
return c;
}
/**
* Delete a character at the caret position in a text buf.
* @param backspace if set, delete the character before the caret,
* else delete the character after it.
* @warning You should ensure Textbuf::CanDelChar returns true before calling this function.
*/
void Textbuf::DelChar(bool backspace)
{
assert(this->CanDelChar(backspace));
WChar c;
char *s = this->buf + this->caretpos;
if (backspace) s = Utf8PrevChar(s);
uint16 len = (uint16)Utf8Decode(&c, s);
/* Move the remaining characters over the marker */
memmove(s, s + len, this->bytes - (s - this->buf) - len);
this->bytes -= len;
this->chars--;
if (backspace) this->caretpos -= len;
this->UpdateStringIter();
this->UpdateWidth();
this->UpdateCaretPosition();
}
/** /**
* Delete a character from a textbuffer, either with 'Delete' or 'Backspace' * Delete a character from a textbuffer, either with 'Delete' or 'Backspace'
* The character is delete from the position the caret is at * The character is delete from the position the caret is at
@ -102,41 +50,61 @@ void Textbuf::DelChar(bool backspace)
*/ */
bool Textbuf::DeleteChar(uint16 keycode) bool Textbuf::DeleteChar(uint16 keycode)
{ {
if (keycode == WKC_BACKSPACE || keycode == WKC_DELETE) { bool word = (keycode & WKC_CTRL) != 0;
bool backspace = keycode == WKC_BACKSPACE;
if (CanDelChar(backspace)) { keycode &= ~WKC_SPECIAL_KEYS;
this->DelChar(backspace); if (keycode != WKC_BACKSPACE && keycode != WKC_DELETE) return false;
return true;
bool backspace = keycode == WKC_BACKSPACE;
if (!CanDelChar(backspace)) return false;
char *s = this->buf + this->caretpos;
uint16 len = 0;
if (word) {
/* Delete a complete word. */
if (backspace) {
/* Delete whitespace and word in front of the caret. */
len = this->caretpos - (uint16)this->char_iter->Prev(StringIterator::ITER_WORD);
s -= len;
} else {
/* Delete word and following whitespace following the caret. */
len = (uint16)this->char_iter->Next(StringIterator::ITER_WORD) - this->caretpos;
}
/* Update character count. */
for (const char *ss = s; ss < s + len; Utf8Consume(&ss)) {
this->chars--;
}
} else {
/* Delete a single character. */
if (backspace) {
/* Delete the last code point in front of the caret. */
s = Utf8PrevChar(s);
WChar c;
len = (uint16)Utf8Decode(&c, s);
this->chars--;
} else {
/* Delete the complete character following the caret. */
len = (uint16)this->char_iter->Next(StringIterator::ITER_CHARACTER) - this->caretpos;
/* Update character count. */
for (const char *ss = s; ss < s + len; Utf8Consume(&ss)) {
this->chars--;
}
} }
return false;
} }
if (keycode == (WKC_CTRL | WKC_BACKSPACE) || keycode == (WKC_CTRL | WKC_DELETE)) { /* Move the remaining characters over the marker */
bool backspace = keycode == (WKC_CTRL | WKC_BACKSPACE); memmove(s, s + len, this->bytes - (s - this->buf) - len);
this->bytes -= len;
if (!CanDelChar(backspace)) return false; if (backspace) this->caretpos -= len;
WChar c = this->GetNextDelChar(backspace);
/* Backspace: Delete left whitespaces. this->UpdateStringIter();
* Delete: Delete right word. this->UpdateWidth();
*/ this->UpdateCaretPosition();
while (backspace ? IsWhitespace(c) : !IsWhitespace(c)) {
this->DelChar(backspace);
if (!this->CanDelChar(backspace)) return true;
c = this->GetNextDelChar(backspace);
}
/* Backspace: Delete left word.
* Delete: Delete right whitespaces.
*/
while (backspace ? !IsWhitespace(c) : IsWhitespace(c)) {
this->DelChar(backspace);
if (!this->CanDelChar(backspace)) return true;
c = this->GetNextDelChar(backspace);
}
return true;
}
return false; return true;
} }
/** /**

View File

@ -65,8 +65,6 @@ private:
StringIterator *char_iter; StringIterator *char_iter;
bool CanDelChar(bool backspace); bool CanDelChar(bool backspace);
WChar GetNextDelChar(bool backspace);
void DelChar(bool backspace);
void UpdateStringIter(); void UpdateStringIter();
void UpdateWidth(); void UpdateWidth();