diff options
-rw-r--r-- | source/blender/blenlib/BLI_string_utf8.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/string_utf8.c | 50 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 71 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 9 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/makesrna.c | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 1 |
8 files changed, 117 insertions, 22 deletions
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 47980d104fe..efb9ac552df 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -49,7 +49,9 @@ char *BLI_str_prev_char_utf8(const char *p); /* wchar_t functions, copied from blenders own font.c originally */ size_t BLI_wstrlen_utf8(const wchar_t *src); +size_t BLI_strlen_utf8_char(const char *strc); size_t BLI_strlen_utf8(const char *strc); +size_t BLI_strlen_range_utf8(const char *start, const char *end); size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy); size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy); diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index ac2334e7d8e..9c7829dbcb6 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -231,28 +231,42 @@ size_t BLI_wstrlen_utf8(const wchar_t *src) return len; } -// utf8slen +/* size of UTF-8 character in bytes */ +size_t BLI_strlen_utf8_char(const char *strc) +{ + if ((*strc & 0xe0) == 0xc0) { + if ((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) + return 2; + } + else if ((*strc & 0xf0) == 0xe0) { + if ((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) + return 3; + } + else if ((*strc & 0xf8) == 0xf0) { + if ((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) + return 4; + } + + return 1; +} + size_t BLI_strlen_utf8(const char *strc) { - int len = 0; + int len; - while (*strc) { - if ((*strc & 0xe0) == 0xc0) { - if ((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) - strc++; - } - else if ((*strc & 0xf0) == 0xe0) { - if ((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) - strc += 2; - } - else if ((*strc & 0xf8) == 0xf0) { - if ((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) - strc += 3; - } + for (len = 0; *strc; len++) + strc += BLI_strlen_utf8_char(strc); - strc++; - len++; - } + return len; +} + +size_t BLI_strlen_range_utf8(const char *start, const char *end) +{ + const char *strc = start; + int len; + + for (len = 0; strc < end; len++) + strc += BLI_strlen_utf8_char(strc); return len; } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b3d6eac9142..7d7cef21281 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1299,6 +1299,71 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, } } +/* ************************ password text ****************************** + * + * Functions to convert password strings that should not be displayed + * to asterisk representation (e.g. mysecretpasswd -> *************) + * + * It converts every UTF-8 character to an asterisk, and also remaps + * the cursor position and selection start/end. + * + * Note: remaping is used, because password could contain UTF-8 characters. + * + */ + +static int ui_text_position_from_hidden(uiBut *but, int pos) +{ + const char *strpos; + int i; + + for (i = 0, strpos = but->drawstr; i < pos; i++) + strpos = BLI_str_find_next_char_utf8(strpos, NULL); + + return (strpos - but->drawstr); +} + +static int ui_text_position_to_hidden(uiBut *but, int pos) +{ + return BLI_strlen_range_utf8(but->drawstr, but->drawstr + pos); +} + +void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore) +{ + if (!(but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) + return; + + if (restore) { + /* restore original string */ + BLI_strncpy(but->drawstr, password_str, UI_MAX_DRAW_STR); + + /* remap cursor positions */ + if(but->pos >= 0) { + but->pos = ui_text_position_from_hidden(but, but->pos); + but->selsta = ui_text_position_from_hidden(but, but->selsta); + but->selend = ui_text_position_from_hidden(but, but->selend); + } + } + else { + /* convert text to hidden test using asterisks (e.g. pass -> ****) */ + int i, len = BLI_strlen_utf8(but->drawstr); + + /* remap cursor positions */ + if(but->pos >= 0) { + but->pos = ui_text_position_to_hidden(but, but->pos); + but->selsta = ui_text_position_to_hidden(but, but->selsta); + but->selend = ui_text_position_to_hidden(but, but->selend); + } + + /* save original string */ + BLI_strncpy(password_str, but->drawstr, UI_MAX_DRAW_STR); + + for (i = 0; i < len; i++) + but->drawstr[i] = '*'; + but->drawstr[i] = '\0'; + } +} + + /* ************* in-button text selection/editing ************* */ @@ -1322,13 +1387,15 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho uiStyle *style = UI_GetStyle(); // XXX pass on as arg uiFontStyle *fstyle = &style->widget; int startx = but->rect.xmin; - char *origstr; + char *origstr, password_str[UI_MAX_DRAW_STR]; uiStyleFontSet(fstyle); if (fstyle->kerning == 1) /* for BLF_width */ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + ui_button_text_password_hide(password_str, but, FALSE); + origstr = MEM_callocN(sizeof(char) * data->maxlen, "ui_textedit origstr"); BLI_strncpy(origstr, but->drawstr, data->maxlen); @@ -1407,6 +1474,8 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho if (fstyle->kerning == 1) BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + ui_button_text_password_hide(password_str, but, TRUE); + MEM_freeN(origstr); } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index b4b0686d6fc..98b75060aa8 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -160,7 +160,8 @@ struct uiBut { int flag, drawflag; eButType type; eButPointerType pointype; - short bit, bitnr, retval, strwidth, ofs, pos, selsta, selend, alignnr; + short bit, bitnr, retval, strwidth, alignnr; + short ofs, pos, selsta, selend; char *str; char strdata[UI_MAX_NAME_STR]; @@ -484,6 +485,7 @@ extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut extern void ui_button_active_free(const struct bContext *C, uiBut *but); extern int ui_button_is_active(struct ARegion *ar); extern int ui_button_open_menu_direction(uiBut *but); +extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore); /* interface_widgets.c */ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 39d90de91d8..a0a51a724c0 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1276,9 +1276,12 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b /* draws text and icons for buttons */ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect) { - if (but == NULL) { + char password_str[UI_MAX_DRAW_STR]; + + if (but == NULL) return; - } + + ui_button_text_password_hide(password_str, but, FALSE); /* clip but->drawstr to fit in available space */ if (but->editstr && but->pos >= 0) { @@ -1337,6 +1340,8 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB widget_draw_text(fstyle, wcol, but, rect); } + + ui_button_text_password_hide(password_str, but, TRUE); } diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 511999dfa37..7d6e07baebd 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -113,6 +113,7 @@ typedef enum PropertySubType { PROP_BYTESTRING = 4, /* a string which should be represented as bytes * in python, still NULL terminated though. */ PROP_TRANSLATE = 5, /* a string which should be translated */ + PROP_PASSWORD = 6, /* a string which should not be displayed in UI */ /* numbers */ PROP_UNSIGNED = 13, diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index fbb7fe5a346..df51715a324 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2345,6 +2345,7 @@ static const char *rna_property_subtypename(PropertySubType type) case PROP_COORDS: return "PROP_COORDS"; case PROP_LAYER: return "PROP_LAYER"; case PROP_LAYER_MEMBER: return "PROP_LAYER_MEMBER"; + case PROP_PASSWORD: return "PROP_PASSWORD"; default: { /* in case we don't have a type preset that includes the subtype */ if (RNA_SUBTYPE_UNIT(type)) { diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 39a05389b63..164c9fec110 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -78,6 +78,7 @@ static EnumPropertyItem property_subtype_string_items[] = { {PROP_FILENAME, "FILENAME", 0, "Filename", ""}, {PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""}, {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, + {PROP_PASSWORD, "PASSWORD", 0, "Password", 0}, {PROP_NONE, "NONE", 0, "None", ""}, {0, NULL, 0, NULL, NULL}}; |