Fix for 3d text ctrl+arrow keys failing for multi-byte characters.

This commit is contained in:
Campbell Barton 2013-12-29 16:54:43 +11:00
parent 07851dd8df
commit d0ec1b1caa
3 changed files with 119 additions and 38 deletions

View File

@ -48,4 +48,8 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
strCursorJumpType jump, bool use_init_step);
void BLI_str_cursor_step_wchar(const wchar_t *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
strCursorJumpType jump, bool use_init_step);
#endif /* __BLI_STRING_CURSOR_UTF8_H__ */

View File

@ -51,12 +51,8 @@ typedef enum strCursorDelimType {
STRCUR_DELIM_OTHER
} strCursorDelimType;
static strCursorDelimType cursor_delim_type(const char *ch_utf8)
static strCursorDelimType cursor_delim_type_unicode(const unsigned int uch)
{
/* for full unicode support we really need to have large lookup tables to figure
* out whats what in every possible char set - and python, glib both have these. */
unsigned int uch = BLI_str_utf8_as_unicode(ch_utf8);
switch (uch) {
case ',':
case '.':
@ -90,6 +86,7 @@ static strCursorDelimType cursor_delim_type(const char *ch_utf8)
case ' ':
case '\t':
case '\n':
return STRCUR_DELIM_WHITESPACE;
case '\\':
@ -111,6 +108,14 @@ static strCursorDelimType cursor_delim_type(const char *ch_utf8)
return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */
}
static strCursorDelimType cursor_delim_type_utf8(const char *ch_utf8)
{
/* for full unicode support we really need to have large lookup tables to figure
* out whats what in every possible char set - and python, glib both have these. */
unsigned int uch = BLI_str_utf8_as_unicode(ch_utf8);
return cursor_delim_type_unicode(uch);
}
int BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos)
{
const char *str_end = str + (maxlen + 1);
@ -156,13 +161,13 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
}
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type(&str[*pos]) : STRCUR_DELIM_NONE;
const strCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type_utf8(&str[*pos]) : STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function cursor_delim_type() for complete
* list of special character, ctr -> */
while ((*pos) < maxlen) {
if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type(&str[*pos]))) {
if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_utf8(&str[*pos]))) {
break;
}
}
@ -181,14 +186,14 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
}
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType delim_type = (*pos) > 0 ? cursor_delim_type(&str[(*pos) - 1]) : STRCUR_DELIM_NONE;
const strCursorDelimType delim_type = (*pos) > 0 ? cursor_delim_type_utf8(&str[(*pos) - 1]) : STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function cursor_delim_type() for complete
* list of special character, ctr -> */
while ((*pos) > 0) {
const int pos_prev = *pos;
if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type(&str[*pos]))) {
if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_utf8(&str[*pos]))) {
/* left only: compensate for index/change in direction */
if ((pos_orig - (*pos)) >= 1) {
*pos = pos_prev;
@ -206,3 +211,93 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
BLI_assert(0);
}
}
/* wchar_t version of BLI_str_cursor_step_utf8 (keep in sync!)
* less complex since it doesn't need to do multi-byte stepping.
*/
/* helper funcs so we can match BLI_str_cursor_step_utf8 */
static bool wchar_t_step_next(const wchar_t *UNUSED(str), size_t maxlen, int *pos)
{
if ((*pos) >= (int)maxlen) {
return false;
}
(*pos)++;
return true;
}
static bool wchar_t_step_prev(const wchar_t *UNUSED(str), size_t UNUSED(maxlen), int *pos)
{
if ((*pos) <= 0) {
return false;
}
(*pos)--;
return true;
}
void BLI_str_cursor_step_wchar(const wchar_t *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
strCursorJumpType jump, bool use_init_step)
{
const int pos_orig = *pos;
if (direction == STRCUR_DIR_NEXT) {
if (use_init_step) {
wchar_t_step_next(str, maxlen, pos);
}
else {
BLI_assert(jump == STRCUR_JUMP_DELIM);
}
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type_unicode((unsigned int)str[*pos]) : STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function cursor_delim_type_unicode() for complete
* list of special character, ctr -> */
while ((*pos) < maxlen) {
if (wchar_t_step_next(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_unicode((unsigned int)str[*pos]))) {
break;
}
}
else {
break; /* unlikely but just in case */
}
}
}
}
else if (direction == STRCUR_DIR_PREV) {
if (use_init_step) {
wchar_t_step_prev(str, maxlen, pos);
}
else {
BLI_assert(jump == STRCUR_JUMP_DELIM);
}
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType delim_type = (*pos) > 0 ? cursor_delim_type_unicode((unsigned int)str[(*pos) - 1]) : STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function cursor_delim_type() for complete
* list of special character, ctr -> */
while ((*pos) > 0) {
const int pos_prev = *pos;
if (wchar_t_step_prev(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_unicode((unsigned int)str[*pos]))) {
/* left only: compensate for index/change in direction */
if ((pos_orig - (*pos)) >= 1) {
*pos = pos_prev;
}
break;
}
}
else {
break;
}
}
}
}
else {
BLI_assert(0);
}
}

View File

@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_string_cursor_utf8.h"
#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
@ -545,33 +546,6 @@ void ED_text_to_object(bContext *C, Text *text, int split_lines)
}
/********************** utilities ***************************/
static short next_word(Curve *cu)
{
short s;
for (s = cu->pos; ((cu->str[s]) && (cu->str[s] != ' ') && (cu->str[s] != '\n') &&
(cu->str[s] != 1) && (cu->str[s] != '\r'));
s++)
{
/* pass */
}
return cu->str[s] ? (s + 1) : s;
}
static short prev_word(Curve *cu)
{
short s;
if (cu->pos == 0) return(0);
for (s = cu->pos - 2; ((cu->str[s]) && (cu->str[s] != ' ') && (cu->str[s] != '\n') &&
(cu->str[s] != 1) && (cu->str[s] != '\r'));
s--)
{
/* pass */
}
return cu->str[s] ? (s + 1) : s;
}
static int kill_selection(Object *obedit, int ins) /* 1 == new character */
{
@ -877,16 +851,24 @@ static int move_cursor(bContext *C, int type, int select)
break;
case PREV_WORD:
{
int pos = cu->pos;
if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
cu->pos = prev_word(cu);
BLI_str_cursor_step_wchar(ef->textbuf, cu->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
cu->pos = pos;
cursmove = FO_CURS;
break;
}
case NEXT_WORD:
{
int pos = cu->pos;
if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;
cu->pos = next_word(cu);
BLI_str_cursor_step_wchar(ef->textbuf, cu->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
cu->pos = pos;
cursmove = FO_CURS;
break;
}
case PREV_CHAR:
if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1;