lv_ta: full UTF-8 support

This commit is contained in:
Gabor Kiss-Vamosi
2017-09-22 13:58:01 +02:00
parent 6e3445c2d6
commit 1bbe6e1068
4 changed files with 74 additions and 93 deletions

View File

@@ -10,6 +10,7 @@
#if USE_LV_LABEL != 0
#include "misc/gfx/color.h"
#include "misc/gfx/text.h"
#include "misc/math/math_base.h"
#include "lv_label.h"
#include "../lv_obj/lv_obj.h"
@@ -165,22 +166,28 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
lv_label_ext_t * ext = lv_obj_get_ext(label);
/*If trying to set its own text or the text is NULL then refresh */
if(text == ext->txt || text == NULL) {
/*If text is NULL then refresh */
if(text == NULL) {
lv_label_refr_text(label);
return;
}
/*Allocate space for the new text*/
uint32_t len = strlen(text) + 1;
if(ext->txt != NULL && ext->static_txt == 0) {
dm_free(ext->txt);
ext->txt = NULL;
if(ext->txt == text) {
/*If set its own text then reallocate it (maybe its size changed)*/
ext->txt = dm_realloc(ext->txt, strlen(ext->txt) + 1);
} else {
/*Allocate space for the new text*/
uint32_t len = strlen(text) + 1;
if(ext->txt != NULL && ext->static_txt == 0) {
dm_free(ext->txt);
ext->txt = NULL;
}
ext->txt = dm_alloc(len);
strcpy(ext->txt, text);
ext->static_txt = 0; /*Now the text is dynamically allocated*/
}
ext->txt = dm_alloc(len);
strcpy(ext->txt, text);
ext->static_txt = 0; /*Now the text is dynamically allocated*/
lv_label_refr_text(label);
}
/**
@@ -243,11 +250,9 @@ void lv_label_set_text_static(lv_obj_t * label, const char * text)
* @param pos character index to insert
* 0: before first char.
* LV_LABEL_POS_LAST: after last char.
* < 0: count from the end
* -1: before the last char.
* @param txt pointer to the text to insert
*/
void lv_label_ins_text(lv_obj_t * label, int32_t pos, const char * txt)
void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
{
lv_label_ext_t * ext = lv_obj_get_ext(label);
@@ -262,17 +267,15 @@ void lv_label_ins_text(lv_obj_t * label, int32_t pos, const char * txt)
uint32_t new_len = ins_len + old_len;
ext->txt = dm_realloc(ext->txt, new_len + 1);
if(pos == LV_LABEL_POS_LAST) pos = old_len;
else if(pos < 0) pos = old_len + pos;
/*Copy the second part into the end to make place to text to insert*/
int32_t i;
for(i = new_len; i >= pos + ins_len; i--){
ext->txt[i] = ext->txt[i - ins_len];
if(pos == LV_LABEL_POS_LAST) {
#if TXT_UTF8 == 0
pos = old_len;
#else
pos = txt_len(ext->txt);
#endif
}
/* Copy the text into the new space*/
memcpy(ext->txt + pos, txt, ins_len);
txt_ins(ext->txt, pos, txt);
lv_label_refr_text(label);
}

View File

@@ -113,7 +113,7 @@ void lv_label_set_text_static(lv_obj_t * label, const char * text);
* -1: before the last char.
* @param txt pointer to the text to insert
*/
void lv_label_ins_text(lv_obj_t * label, int32_t pos, const char * txt);
void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt);
/**
* Set the behavior of the label with longer text then the object size

View File

@@ -211,44 +211,37 @@ bool lv_ta_signal(lv_obj_t * ta, lv_signal_t sign, void * param)
* @param ta pointer to a text area object
* @param c a character
*/
void lv_ta_add_char(lv_obj_t * ta, char c)
void lv_ta_add_char(lv_obj_t * ta, uint32_t c)
{
lv_ta_ext_t * ext = lv_obj_get_ext(ta);
const char * label_txt = lv_label_get_text(ext->label);
/*Test the new length: txt length + 1 (closing'\0') + 1 (c character)*/
if((strlen(label_txt) + 2) > LV_TA_MAX_LENGTH) return;
if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/
uint32_t cur_pos;
#if TXT_UTF8 == 0
cur_pos = ext->cursor_pos;
char letter_buf[2];
letter_buf[0] = c;
letter_buf[1] = '\0';
#else
cur_pos = txt_utf8_get_id(label_txt, ext->cursor_pos);
/*Swap because of UTF-8 is "big-endian-like" */
if(((c >> 8) & 0b11100000) == 0b11000000) {
c = (c & 0xFF) << 8 | ((c >> 8) & 0xFF);
}
if(((c >> 16) & 0b11110000) == 0b11100000) {
c = (c & 0xFF) << 16 | ((c >> 16) & 0xFF);
}
if(((c >> 24) & 0b11111000) == 0b11110000) {
c = ((c & 0xFF) << 24) | (((c >> 8) & 0xFF) >> 16) | (((c >> 16) & 0xFF) >> 8) | ((c >> 24) & 0xFF);
}
char letter_buf[8] = {0};
memcpy(letter_buf, &c, txt_utf8_size(c));
#endif
lv_label_ins_text(ext->label, ext->cursor_pos, letter_buf); /*Insert the character*/
char buf[LV_TA_MAX_LENGTH];
/*Insert the character*/
memcpy(buf, label_txt, cur_pos);
buf[cur_pos] = c;
memcpy(buf + cur_pos + 1, label_txt + cur_pos, strlen(label_txt) - cur_pos + 1);
if(ext->pwd_mode != 0) {
/*Refresh the label*/
lv_label_set_text(ext->label, buf);
if(ext->pwd_mode != 0) {
#if TXT_UTF8 != 0
cur_pos = txt_utf8_get_id(ext->pwd_tmp, ext->cursor_pos); /*Noral text contains '*', pwd_tmp normal UTF-8 letter, so the cursor points to a different byte*/
#endif
ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + 2); /*+2: the new char + \0 */
dm_assert(ext->pwd_tmp);
memcpy(buf, ext->pwd_tmp, cur_pos);
buf[cur_pos] = c;
memcpy(buf + cur_pos + 1, ext->pwd_tmp + cur_pos, strlen(ext->pwd_tmp) - cur_pos + 1);
strcpy(ext->pwd_tmp, buf);
ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + 2); /*+2: the new char + \0 */
dm_assert(ext->pwd_tmp);
txt_ins(ext->pwd_tmp, ext->cursor_pos, letter_buf);
anim_t a;
a.var = ta;
@@ -284,38 +277,19 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt)
lv_ta_ext_t * ext = lv_obj_get_ext(ta);
const char * label_txt = lv_label_get_text(ext->label);
uint16_t label_len = strlen(label_txt);
uint16_t txt_len = strlen(txt);
/*Test the new length (+ 1 for the closing '\0')*/
if((label_len + txt_len + 1) > LV_TA_MAX_LENGTH) return;
if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/
/*Insert the text*/
char buf[LV_TA_MAX_LENGTH];
uint32_t cur_pos;
#if TXT_UTF8 == 0
cur_pos = ext->cursor_pos;
#else
cur_pos = txt_utf8_get_id(label_txt, ext->cursor_pos);
#endif
memcpy(buf, label_txt, cur_pos);
memcpy(buf + cur_pos, txt, txt_len);
memcpy(buf + cur_pos + txt_len, label_txt+cur_pos, label_len - cur_pos + 1);
/*Refresh the label*/
lv_label_set_text(ext->label, buf);
lv_label_ins_text(ext->label, ext->cursor_pos, txt);
if(ext->pwd_mode != 0) {
ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + txt_len + 1);
dm_assert(ext->pwd_tmp);
memcpy(buf, ext->pwd_tmp, ext->cursor_pos);
memcpy(buf + cur_pos, txt, txt_len);
memcpy(buf + cur_pos + txt_len, ext->pwd_tmp+ext->cursor_pos, label_len - ext->cursor_pos + 1);
strcpy(ext->pwd_tmp, buf);
txt_ins(ext->pwd_tmp, ext->cursor_pos, txt);
anim_t a;
a.var = ta;
@@ -392,15 +366,17 @@ void lv_ta_del(lv_obj_t * ta)
if(cur_pos == 0) return;
char * label_txt = lv_label_get_text(ext->label);
/*Delete a character*/
char buf[LV_TA_MAX_LENGTH];
const char * label_txt = lv_label_get_text(ext->label);
uint16_t label_len = strlen(label_txt);
memcpy(buf, label_txt, cur_pos - 1);
memcpy(buf+cur_pos - 1, label_txt + cur_pos, label_len - cur_pos + 1);
#if TXT_UTF8 == 0
txt_cut(label_txt, ext->cursor_pos - 1, 1);
#else
uint32_t byte_pos = txt_utf8_get_id(label_txt, ext->cursor_pos - 1);
txt_cut(label_txt, ext->cursor_pos - 1, txt_utf8_size(label_txt[byte_pos]));
#endif
/*Refresh the label*/
lv_label_set_text(ext->label, buf);
lv_label_set_text(ext->label, label_txt);
/*Don't let 'width == 0' because cursor will not be visible*/
if(lv_obj_get_width(ext->label) == 0) {
lv_style_t * style = lv_obj_get_style(ext->label);
@@ -408,13 +384,18 @@ void lv_ta_del(lv_obj_t * ta)
}
if(ext->pwd_mode != 0) {
ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(buf));
#if TXT_UTF8 == 0
txt_cut(ext->pwd_tmp, ext->cursor_pos - 1, 1);
#else
uint32_t byte_pos = txt_utf8_get_id(ext->pwd_tmp, ext->cursor_pos - 1);
txt_cut(ext->pwd_tmp, ext->cursor_pos - 1, txt_utf8_size(label_txt[byte_pos]));
#endif
ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + 1);
dm_assert(ext->pwd_tmp);
strcpy(ext->pwd_tmp, buf);
}
/*Move the cursor to the place of the deleted character*/
lv_ta_set_cursor_pos(ta, lv_ta_get_cursor_pos(ta) - 1);
lv_ta_set_cursor_pos(ta, ext->cursor_pos - 1);
/*It is a valid x step so save it*/
lv_ta_save_valid_cursor_x(ta);
@@ -949,14 +930,11 @@ static void pwd_char_hider(lv_obj_t * ta)
int16_t len = txt_len(txt);
bool refr = false;
uint16_t i;
for(i = 0; i < len; i++) {
if(txt[i] != '*') {
txt[i] = '*';
refr = true;
}
}
for(i = 0; i < len; i++) txt[i] = '*';
if(refr != false) lv_label_set_text(ext->label, NULL);
txt[i] = '\0';
if(refr != false) lv_label_set_text(ext->label, txt);
}
}

View File

@@ -87,7 +87,7 @@ bool lv_ta_signal(lv_obj_t * ta, lv_signal_t sign, void * param);
* @param ta pointer to a text area object
* @param c a character
*/
void lv_ta_add_char(lv_obj_t * ta, char c);
void lv_ta_add_char(lv_obj_t * ta, uint32_t c);
/**
* Insert a text to the current cursor position