BLF: Editing Text with Combining Characters
Corrections for caret insertion & movement and deletion for text strings that include non-precomposed diacritical marks (Unicode combining characters). See D15659 for more details and examples. Differential Revision: https://developer.blender.org/D15659 Reviewed by Campbell Barton
This commit is contained in:
parent
697e86a761
commit
12fdf9069a
|
@ -33,6 +33,7 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_cursor_utf8.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
|
@ -973,9 +974,16 @@ size_t blf_str_offset_from_cursor_position(struct FontBLF *font,
|
|||
.r_offset = (size_t)-1,
|
||||
};
|
||||
blf_font_boundbox_foreach_glyph(font, str, str_len, blf_cursor_position_foreach_glyph, &data);
|
||||
|
||||
if (data.r_offset == (size_t)-1) {
|
||||
/* We are to the right of the string, so return position of null terminator. */
|
||||
data.r_offset = BLI_strnlen(str, str_len);
|
||||
}
|
||||
else if (BLI_str_utf8_char_width(&str[data.r_offset]) < 1) {
|
||||
/* This is a combining character (or invalid), so move to previous visible valid char. */
|
||||
BLI_str_cursor_step_prev_utf8(str, str_len, (int *)&data.r_offset);
|
||||
}
|
||||
|
||||
return data.r_offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -896,8 +896,7 @@ void txt_move_left(Text *text, const bool sel)
|
|||
(*charp) -= tabsize;
|
||||
}
|
||||
else {
|
||||
const char *prev = BLI_str_find_prev_char_utf8((*linep)->line + *charp, (*linep)->line);
|
||||
*charp = prev - (*linep)->line;
|
||||
BLI_str_cursor_step_prev_utf8((*linep)->line, (*linep)->len, charp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -941,7 +940,7 @@ void txt_move_right(Text *text, const bool sel)
|
|||
(*charp) += tabsize;
|
||||
}
|
||||
else {
|
||||
(*charp) += BLI_str_utf8_size((*linep)->line + *charp);
|
||||
BLI_str_cursor_step_next_utf8((*linep)->line, (*linep)->len, charp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1757,8 +1756,6 @@ void txt_duplicate_line(Text *text)
|
|||
|
||||
void txt_delete_char(Text *text)
|
||||
{
|
||||
uint c = '\n';
|
||||
|
||||
if (!text->curl) {
|
||||
return;
|
||||
}
|
||||
|
@ -1778,10 +1775,9 @@ void txt_delete_char(Text *text)
|
|||
}
|
||||
}
|
||||
else { /* Just deleting a char */
|
||||
size_t c_len = text->curc;
|
||||
c = BLI_str_utf8_as_unicode_step(text->curl->line, text->curl->len, &c_len);
|
||||
c_len -= text->curc;
|
||||
UNUSED_VARS(c);
|
||||
int pos = text->curc;
|
||||
BLI_str_cursor_step_next_utf8(text->curl->line, text->curl->len, &pos);
|
||||
size_t c_len = pos - text->curc;
|
||||
|
||||
memmove(text->curl->line + text->curc,
|
||||
text->curl->line + text->curc + c_len,
|
||||
|
@ -1805,8 +1801,6 @@ void txt_delete_word(Text *text)
|
|||
|
||||
void txt_backspace_char(Text *text)
|
||||
{
|
||||
uint c = '\n';
|
||||
|
||||
if (!text->curl) {
|
||||
return;
|
||||
}
|
||||
|
@ -1828,13 +1822,9 @@ void txt_backspace_char(Text *text)
|
|||
txt_pop_sel(text);
|
||||
}
|
||||
else { /* Just backspacing a char */
|
||||
const char *prev = BLI_str_find_prev_char_utf8(text->curl->line + text->curc,
|
||||
text->curl->line);
|
||||
size_t c_len = prev - text->curl->line;
|
||||
c = BLI_str_utf8_as_unicode_step(text->curl->line, text->curl->len, &c_len);
|
||||
c_len -= prev - text->curl->line;
|
||||
|
||||
UNUSED_VARS(c);
|
||||
int pos = text->curc;
|
||||
BLI_str_cursor_step_prev_utf8(text->curl->line, text->curl->len, &pos);
|
||||
size_t c_len = text->curc - pos;
|
||||
|
||||
/* source and destination overlap, don't use memcpy() */
|
||||
memmove(text->curl->line + text->curc - c_len,
|
||||
|
|
|
@ -25,6 +25,9 @@ typedef enum eStrCursorJumpDirection {
|
|||
bool BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos);
|
||||
bool BLI_str_cursor_step_prev_utf8(const char *str, size_t maxlen, int *pos);
|
||||
|
||||
bool BLI_str_cursor_step_next_utf32(const char32_t *str, size_t maxlen, int *pos);
|
||||
bool BLI_str_cursor_step_prev_utf32(const char32_t *str, size_t maxlen, int *pos);
|
||||
|
||||
void BLI_str_cursor_step_utf8(const char *str,
|
||||
size_t maxlen,
|
||||
int *pos,
|
||||
|
|
|
@ -96,27 +96,35 @@ static eStrCursorDelimType cursor_delim_type_utf8(const char *ch_utf8,
|
|||
return cursor_delim_type_unicode(uch);
|
||||
}
|
||||
|
||||
/* Keep in sync with BLI_str_cursor_step_next_utf32. */
|
||||
bool BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos)
|
||||
{
|
||||
if ((*pos) >= (int)maxlen) {
|
||||
return false;
|
||||
}
|
||||
const char *str_end = str + (maxlen + 1);
|
||||
const char *str_pos = str + (*pos);
|
||||
const char *str_next = BLI_str_find_next_char_utf8(str_pos, str_end);
|
||||
if (str_next != str_end) {
|
||||
(*pos) += (str_next - str_pos);
|
||||
if ((*pos) > (int)maxlen) {
|
||||
(*pos) = (int)maxlen;
|
||||
}
|
||||
return true;
|
||||
const char *str_next = str_pos;
|
||||
do {
|
||||
str_next = BLI_str_find_next_char_utf8(str_next, str_end);
|
||||
} while (str_next < str_end && str_next[0] != 0 && BLI_str_utf8_char_width(str_next) < 1);
|
||||
(*pos) += (str_next - str_pos);
|
||||
if ((*pos) > (int)maxlen) {
|
||||
(*pos) = (int)maxlen;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BLI_str_cursor_step_prev_utf8(const char *str, size_t UNUSED(maxlen), int *pos)
|
||||
/* Keep in sync with BLI_str_cursor_step_prev_utf32. */
|
||||
bool BLI_str_cursor_step_prev_utf8(const char *str, size_t maxlen, int *pos)
|
||||
{
|
||||
if ((*pos) > 0) {
|
||||
if ((*pos) > 0 && (*pos) <= maxlen) {
|
||||
const char *str_pos = str + (*pos);
|
||||
const char *str_prev = BLI_str_find_prev_char_utf8(str_pos, str);
|
||||
const char *str_prev = str_pos;
|
||||
do {
|
||||
str_prev = BLI_str_find_prev_char_utf8(str_prev, str);
|
||||
} while (str_prev > str && BLI_str_utf8_char_width(str_prev) == 0);
|
||||
(*pos) -= (str_pos - str_prev);
|
||||
return true;
|
||||
}
|
||||
|
@ -202,26 +210,29 @@ void BLI_str_cursor_step_utf8(const char *str,
|
|||
}
|
||||
}
|
||||
|
||||
/* UTF32 version of BLI_str_cursor_step_utf8 (keep in sync!)
|
||||
* less complex since it doesn't need to do multi-byte stepping.
|
||||
*/
|
||||
|
||||
/* Helper functions so we can match #BLI_str_cursor_step_utf8. */
|
||||
static bool cursor_step_next_utf32(const char32_t *UNUSED(str), size_t maxlen, int *pos)
|
||||
/* Keep in sync with BLI_str_cursor_step_next_utf8. */
|
||||
bool BLI_str_cursor_step_next_utf32(const char32_t *str, size_t maxlen, int *pos)
|
||||
{
|
||||
if ((*pos) >= (int)maxlen) {
|
||||
return false;
|
||||
}
|
||||
(*pos)++;
|
||||
do {
|
||||
(*pos)++;
|
||||
} while (*pos < (int)maxlen && str[*pos] != 0 && BLI_wcwidth(str[*pos]) == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cursor_step_prev_utf32(const char32_t *UNUSED(str), size_t UNUSED(maxlen), int *pos)
|
||||
/* Keep in sync with BLI_str_cursor_step_prev_utf8. */
|
||||
bool BLI_str_cursor_step_prev_utf32(const char32_t *str, size_t UNUSED(maxlen), int *pos)
|
||||
{
|
||||
if ((*pos) <= 0) {
|
||||
return false;
|
||||
}
|
||||
(*pos)--;
|
||||
do {
|
||||
(*pos)--;
|
||||
} while (*pos > 0 && BLI_wcwidth(str[*pos]) == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -236,7 +247,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str,
|
|||
|
||||
if (direction == STRCUR_DIR_NEXT) {
|
||||
if (use_init_step) {
|
||||
cursor_step_next_utf32(str, maxlen, pos);
|
||||
BLI_str_cursor_step_next_utf32(str, maxlen, pos);
|
||||
}
|
||||
else {
|
||||
BLI_assert(jump == STRCUR_JUMP_DELIM);
|
||||
|
@ -250,7 +261,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str,
|
|||
* look at function cursor_delim_type_unicode() for complete
|
||||
* list of special character, ctr -> */
|
||||
while ((*pos) < maxlen) {
|
||||
if (cursor_step_next_utf32(str, maxlen, pos)) {
|
||||
if (BLI_str_cursor_step_next_utf32(str, maxlen, pos)) {
|
||||
if ((jump != STRCUR_JUMP_ALL) &&
|
||||
(delim_type != cursor_delim_type_unicode((uint)str[*pos]))) {
|
||||
break;
|
||||
|
@ -264,7 +275,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str,
|
|||
}
|
||||
else if (direction == STRCUR_DIR_PREV) {
|
||||
if (use_init_step) {
|
||||
cursor_step_prev_utf32(str, maxlen, pos);
|
||||
BLI_str_cursor_step_prev_utf32(str, maxlen, pos);
|
||||
}
|
||||
else {
|
||||
BLI_assert(jump == STRCUR_JUMP_DELIM);
|
||||
|
@ -279,7 +290,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str,
|
|||
* list of special character, ctr -> */
|
||||
while ((*pos) > 0) {
|
||||
const int pos_prev = *pos;
|
||||
if (cursor_step_prev_utf32(str, maxlen, pos)) {
|
||||
if (BLI_str_cursor_step_prev_utf32(str, maxlen, pos)) {
|
||||
if ((jump != STRCUR_JUMP_ALL) &&
|
||||
(delim_type != cursor_delim_type_unicode((uint)str[*pos]))) {
|
||||
/* left only: compensate for index/change in direction */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_cursor_utf8.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -393,3 +394,485 @@ TEST(string, Utf8AsUnicodeStep)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf32_empty
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf32Empty)
|
||||
{
|
||||
const char32_t empty[] = U"";
|
||||
const size_t len = 0;
|
||||
int pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(empty, len, &pos));
|
||||
pos = 1;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(empty, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf32_single
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf32Single)
|
||||
|
||||
{
|
||||
const char32_t single[] = U"0";
|
||||
const size_t len = 1;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(single, len, &pos) && pos == 1);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(single, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf32_simple
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf32Simple)
|
||||
{
|
||||
const char32_t simple[] = U"012";
|
||||
const size_t len = 3;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(simple, len, &pos) && pos == 1);
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(simple, len, &pos) && pos == 2);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(simple, len - 1, &pos));
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(simple, len, &pos) && pos == 3);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(simple, len, &pos));
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf32_allcombining
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf32AllCombining)
|
||||
{
|
||||
const char32_t allcombining[] = U"\u0300\u0300\u0300";
|
||||
const size_t len = 3;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos) && pos == 3);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos) && pos == 3);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos) && pos == 3);
|
||||
pos = 3;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf32_complex
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf32Complex)
|
||||
{
|
||||
/* Combining character, "A", two combining characters, "B".*/
|
||||
const char32_t complex[] = U"\u0300\u0041\u0300\u0320\u0042";
|
||||
const size_t len = 5;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 1);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 4);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 4);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 4);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 5);
|
||||
pos = 5;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(complex, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf32_invalid
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf32Invalid)
|
||||
{
|
||||
/* Latin1 "À", tab, carriage return, linefeed, separated by combining characters.*/
|
||||
const char32_t invalid[] = U"\u00C0\u0300\u0009\u0300\u000D\u0300\u000A\u0300";
|
||||
const size_t len = 8;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 2);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 2);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 4);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 4);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 6);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 6);
|
||||
pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 8);
|
||||
pos = 7;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 8);
|
||||
pos = 8;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf32(invalid, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf32_empty
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf32Empty)
|
||||
{
|
||||
const char32_t emtpy[] = U"";
|
||||
const size_t len = 0;
|
||||
int pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(emtpy, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf32_single
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf32Single)
|
||||
{
|
||||
const char32_t single[] = U"0";
|
||||
const size_t len = 1;
|
||||
int pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(single, len, &pos) && pos == 0);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(single, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf32_simple
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf32Simple)
|
||||
{
|
||||
const char32_t simple[] = U"012";
|
||||
const size_t len = 3;
|
||||
int pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(simple, len, &pos) && pos == 2);
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(simple, len, &pos) && pos == 1);
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(simple, len, &pos) && pos == 0);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(simple, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf32_allcombining
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf32AllCombining)
|
||||
{
|
||||
const char32_t allcombining[] = U"\u0300\u0300\u0300";
|
||||
const size_t len = 3;
|
||||
int pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos) && pos == 0);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos) && pos == 0);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos) && pos == 0);
|
||||
pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf32_complex
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf32Complex)
|
||||
{
|
||||
/* Combining character, "A", two combining characters, "B".*/
|
||||
const char32_t complex[] = U"\u0300\u0041\u0300\u0320\u0042";
|
||||
const size_t len = 5;
|
||||
int pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 4);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 1);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 1);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 1);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 0);
|
||||
pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(complex, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf32_invalid
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf32Invalid)
|
||||
{
|
||||
/* Latin1 "À", tab, carriage return, linefeed, separated by combining characters.*/
|
||||
const char32_t invalid[] = U"\u00C0\u0300\u0009\u0300\u000D\u0300\u000A\u0300";
|
||||
const size_t len = 8;
|
||||
int pos = 8;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 6);
|
||||
pos = 7;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 6);
|
||||
pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 4);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 4);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 2);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 2);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 0);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 0);
|
||||
pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf8_empty
|
||||
* \{ */
|
||||
TEST(string, StrCursorStepNextUtf8Empty)
|
||||
{
|
||||
const char empty[] = "";
|
||||
const size_t len = 0;
|
||||
int pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(empty, len, &pos));
|
||||
pos = 1;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(empty, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf8_single
|
||||
* \{ */
|
||||
TEST(string, StrCursorStepNextUtf8Single)
|
||||
{
|
||||
const char single[] = "0";
|
||||
const size_t len = 1;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(single, len, &pos) && pos == 1);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(single, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf8_simple
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf8Simple)
|
||||
{
|
||||
const char simple[] = "012";
|
||||
const size_t len = 3;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(simple, len, &pos) && pos == 1);
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(simple, len, &pos) && pos == 2);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(simple, len - 1, &pos));
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(simple, len, &pos) && pos == 3);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(simple, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf8_allcombining
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf8AllCombining)
|
||||
{
|
||||
const char allcombining[] = "\xCC\x80\xCC\x80\xCC\x80";
|
||||
const size_t len = 6;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6);
|
||||
pos = 6;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf8_complex
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf8AllComplex)
|
||||
{
|
||||
/* Combining character, "A", "©", two combining characters, "B".*/
|
||||
const char complex[] = "\xCC\x80\x41\xC2\xA9\xCC\x80\xCC\xA0\x42";
|
||||
const size_t len = 10;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 2);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 2);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 7;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 8;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 9;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 10);
|
||||
pos = 10;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(complex, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_next_utf8_invalid
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepNextUtf8Invalid)
|
||||
{
|
||||
/* Latin1 "À", combining, tab, carriage return, linefeed, combining.*/
|
||||
const char invalid[] = "\xC0\xCC\x80\x09\x0D\x0A\xCC\x80";
|
||||
const size_t len = 8;
|
||||
int pos = 0;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 7;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8);
|
||||
pos = 8;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_next_utf8(invalid, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf8_empty
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf8Empty)
|
||||
{
|
||||
const char empty[] = "";
|
||||
const size_t len = 0;
|
||||
int pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(empty, len, &pos));
|
||||
pos = 1;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(empty, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf8_single
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf8Single)
|
||||
{
|
||||
const char single[] = "0";
|
||||
const size_t len = 1;
|
||||
int pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(single, len, &pos) && pos == 0);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(single, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf8_single
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf8Simple)
|
||||
{
|
||||
const char simple[] = "012";
|
||||
const size_t len = 3;
|
||||
int pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(simple, len, &pos) && pos == 2);
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(simple, len, &pos) && pos == 1);
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(simple, len, &pos) && pos == 0);
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(simple, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf8_allcombining
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf8AllCombining)
|
||||
{
|
||||
const char allcombining[] = "\xCC\x80\xCC\x80\xCC\x80";
|
||||
const size_t len = 6;
|
||||
int pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0);
|
||||
pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf8_complex
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf8Complex)
|
||||
{
|
||||
/* Combining character, "A", "©", two combining characters, "B".*/
|
||||
const char complex[] = "\xCC\x80\x41\xC2\xA9\xCC\x80\xCC\xA0\x42";
|
||||
const size_t len = 10;
|
||||
int pos = 10;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 9);
|
||||
pos = 9;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 8;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 7;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 2);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 0);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 0);
|
||||
pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(complex, len, &pos));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Test #BLI_str_cursor_step_prev_utf8_invalid
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCursorStepPrevUtf8Invalid)
|
||||
{
|
||||
/* Latin1 "À", combining, tab, carriage return, linefeed, combining.*/
|
||||
const char invalid[] = "\xC0\xCC\x80\x09\x0D\x0A\xCC\x80";
|
||||
const size_t len = 8;
|
||||
int pos = 8;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 5);
|
||||
pos= 7;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 5);
|
||||
pos = 6;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 5);
|
||||
pos = 5;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 4);
|
||||
pos = 4;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 3);
|
||||
pos = 3;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 0);
|
||||
pos = 2;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 0);
|
||||
pos = 1;
|
||||
EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 0);
|
||||
pos = 0;
|
||||
EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1160,14 +1160,13 @@ static int move_cursor(bContext *C, int type, const bool select)
|
|||
}
|
||||
|
||||
case PREV_CHAR:
|
||||
ef->pos--;
|
||||
BLI_str_cursor_step_prev_utf32(ef->textbuf, ef->len, &ef->pos);
|
||||
cursmove = FO_CURS;
|
||||
break;
|
||||
|
||||
case NEXT_CHAR:
|
||||
ef->pos++;
|
||||
BLI_str_cursor_step_next_utf32(ef->textbuf, ef->len, &ef->pos);
|
||||
cursmove = FO_CURS;
|
||||
|
||||
break;
|
||||
|
||||
case PREV_LINE:
|
||||
|
@ -1506,10 +1505,9 @@ static int delete_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
range[0] = ef->pos - 1;
|
||||
range[1] = ef->pos;
|
||||
|
||||
ef->pos--;
|
||||
BLI_str_cursor_step_prev_utf32(ef->textbuf, ef->len, &ef->pos);
|
||||
range[0] = ef->pos;
|
||||
break;
|
||||
case DEL_NEXT_CHAR:
|
||||
if (ef->pos >= ef->len) {
|
||||
|
@ -1517,7 +1515,8 @@ static int delete_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
range[0] = ef->pos;
|
||||
range[1] = ef->pos + 1;
|
||||
range[1] = ef->pos;
|
||||
BLI_str_cursor_step_next_utf32(ef->textbuf, ef->len, &range[1]);
|
||||
break;
|
||||
case DEL_NEXT_WORD: {
|
||||
int pos = ef->pos;
|
||||
|
|
Loading…
Reference in New Issue