Fix T71273: Bad encoding of utf-8 for Text objects
authormano-wii <germano.costa@ig.com.br>
Fri, 22 Nov 2019 15:26:54 +0000 (12:26 -0300)
committermano-wii <germano.costa@ig.com.br>
Fri, 22 Nov 2019 15:27:34 +0000 (12:27 -0300)
`BLI_strncpy_wchar_from_utf8` internally assumes `wchar_t` is 32 bits
which is not the case on windows.

The solution is to replace `wchar_t` with `char32_t`.

Thanks to @robbott for compatibility on macOS.

Differential Revision: https://developer.blender.org/D6198

16 files changed:
extern/wcwidth/README.blender
extern/wcwidth/wcwidth.c
extern/wcwidth/wcwidth.h
source/blender/blenfont/intern/blf_font.c
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/object_dupli.c
source/blender/blenkernel/intern/text.c
source/blender/blenlib/BLI_string_cursor_utf8.h
source/blender/blenlib/BLI_string_utf8.h
source/blender/blenlib/BLI_sys_types.h
source/blender/blenlib/intern/string_cursor_utf8.c
source/blender/blenlib/intern/string_utf8.c
source/blender/editors/curve/editfont.c
source/blender/editors/curve/editfont_undo.c
source/blender/makesrna/intern/rna_curve.c

index 27c8574d1d7b1e0842585a4711023e6b13869751..3b32ddc5bc9b5a1355e2c0dfab87cf84f5eba81d 100644 (file)
@@ -2,4 +2,6 @@ Project: WC Width
 URL: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
 License: ICS
 Upstream version: 2007-05-26
-Local modifications: None
+Local modifications:
+* Fix T33192
+  Bad encoding of utf-8 on windows systems.
index 8cab81e32cd4e1b6d44b7ede1d355d8382477a24..8922ffe084234de2ab1c39d1f9c3207aa5a352f8 100644 (file)
@@ -59,8 +59,6 @@
  * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
  */
 
-#include <wchar.h>
-
 #include "wcwidth.h"
 
 struct interval {
@@ -69,7 +67,7 @@ struct interval {
 };
 
 /* auxiliary function for binary search in interval table */
-static int bisearch(wchar_t ucs, const struct interval *table, int max) {
+static int bisearch(char32_t ucs, const struct interval *table, int max) {
   int min = 0;
   int mid;
 
@@ -121,7 +119,7 @@ static int bisearch(wchar_t ucs, const struct interval *table, int max) {
  * in ISO 10646.
  */
 
-int mk_wcwidth(wchar_t ucs)
+int mk_wcwidth(char32_t ucs)
 {
   /* sorted list of non-overlapping intervals of non-spacing characters */
   /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
@@ -206,7 +204,7 @@ int mk_wcwidth(wchar_t ucs)
 }
 
 
-int mk_wcswidth(const wchar_t *pwcs, size_t n)
+int mk_wcswidth(const char32_t *pwcs, size_t n)
 {
   int w, width = 0;
 
@@ -229,7 +227,7 @@ int mk_wcswidth(const wchar_t *pwcs, size_t n)
  * the traditional terminal character-width behaviour. It is not
  * otherwise recommended for general use.
  */
-int mk_wcwidth_cjk(wchar_t ucs)
+int mk_wcwidth_cjk(char32_t ucs)
 {
   /* sorted list of non-overlapping intervals of East Asian Ambiguous
    * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
@@ -297,7 +295,7 @@ int mk_wcwidth_cjk(wchar_t ucs)
 }
 
 
-int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
+int mk_wcswidth_cjk(const char32_t *pwcs, size_t n)
 {
   int w, width = 0;
 
index 9ae6ec9ef143057d4a78c1ddd6add9d9c21bbb7c..d87eaf20695273448aa943737c905a9b4fa9def8 100644 (file)
 #ifndef __WCWIDTH_H__
 #define __WCWIDTH_H__
 
-#include <wchar.h>
+#ifndef __cplusplus
+#  if defined(__APPLE__)
+/* The <uchar.h> standard header is missing on macOS. */
+#include <stddef.h>
+typedef unsigned int char32_t;
+#  else
+#    include <uchar.h>
+#  endif
+#endif
 
-int mk_wcwidth(wchar_t ucs);
-int mk_wcswidth(const wchar_t *pwcs, size_t n);
-int mk_wcwidth_cjk(wchar_t ucs);
-int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n);
+int mk_wcwidth(char32_t ucs);
+int mk_wcswidth(const char32_t *pwcs, size_t n);
+int mk_wcwidth_cjk(char32_t ucs);
+int mk_wcswidth_cjk(const char32_t *pwcs, size_t n);
 
 #endif
index e0dfa6a22238ff6936f4e4f9a9366364d8017470..1c06dfd3f70611a6094881b23b01fa4b3ec8ad03 100644 (file)
@@ -504,7 +504,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
     /* do not return this loop if clipped, we want every character tested */
     blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
 
-    col = BLI_wcwidth((wchar_t)c);
+    col = BLI_wcwidth((char32_t)c);
     if (col < 0) {
       col = 1;
     }
index 3dd2a551a93e7f89c2473040e33627ff350b306f..1780ac9fc3eaa801e51cabfb30a8b4ad301b1910 100644 (file)
@@ -27,8 +27,6 @@
 extern "C" {
 #endif
 
-#include <wchar.h>
-
 struct CharInfo;
 struct Curve;
 struct Main;
@@ -48,7 +46,7 @@ typedef struct EditFontSelBox {
 } EditFontSelBox;
 
 typedef struct EditFont {
-  wchar_t *textbuf;
+  char32_t *textbuf;
   struct CharInfo *textbufinfo;
 
   /* array of rectangles & rotation */
@@ -90,7 +88,7 @@ bool BKE_vfont_to_curve_ex(struct Object *ob,
                            struct Curve *cu,
                            int mode,
                            struct ListBase *r_nubase,
-                           const wchar_t **r_text,
+                           const char32_t **r_text,
                            int *r_text_len,
                            bool *r_text_free,
                            struct CharTrans **r_chartransdata);
@@ -101,13 +99,13 @@ int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
 void BKE_vfont_select_clamp(struct Object *ob);
 
 void BKE_vfont_clipboard_free(void);
-void BKE_vfont_clipboard_set(const wchar_t *text_buf,
+void BKE_vfont_clipboard_set(const char32_t *text_buf,
                              const struct CharInfo *info_buf,
                              const size_t len);
-void BKE_vfont_clipboard_get(wchar_t **r_text_buf,
+void BKE_vfont_clipboard_get(char32_t **r_text_buf,
                              struct CharInfo **r_info_buf,
                              size_t *r_len_utf8,
-                             size_t *r_len_wchar);
+                             size_t *r_len_utf32);
 
 #ifdef __cplusplus
 }
index 250e6ff6a7bdc68f3891f5117f62f418c64d32f8..aac3e8cc7fc71f0022caff0c0762e227e94478c1 100644 (file)
@@ -25,7 +25,6 @@
 #include <string.h>
 #include <math.h>
 #include <stdlib.h>
-#include <wchar.h>
 #include <wctype.h>
 
 #include "CLG_log.h"
@@ -691,7 +690,7 @@ static bool vfont_to_curve(Object *ob,
                            int mode,
                            VFontToCurveIter *iter_data,
                            ListBase *r_nubase,
-                           const wchar_t **r_text,
+                           const char32_t **r_text,
                            int *r_text_len,
                            bool *r_text_free,
                            struct CharTrans **r_chartransdata)
@@ -712,8 +711,8 @@ static bool vfont_to_curve(Object *ob,
   int curbox;
   int selstart, selend;
   int cnr = 0, lnr = 0, wsnr = 0;
-  const wchar_t *mem = NULL;
-  wchar_t ascii;
+  const char32_t *mem = NULL;
+  char32_t ascii;
   bool ok = false;
   const float font_size = cu->fsize * iter_data->scale_to_fit;
   const float xof_scale = cu->xof / font_size;
@@ -759,16 +758,16 @@ static bool vfont_to_curve(Object *ob,
     custrinfo = ef->textbufinfo;
   }
   else {
-    wchar_t *mem_tmp;
+    char32_t *mem_tmp;
     slen = cu->len_wchar;
 
     /* Create unicode string */
-    mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(wchar_t), "convertedmem");
+    mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(*mem_tmp), "convertedmem");
     if (!mem_tmp) {
       return ok;
     }
 
-    BLI_strncpy_wchar_from_utf8(mem_tmp, cu->str, slen + 1);
+    BLI_str_utf8_as_utf32(mem_tmp, cu->str, slen + 1);
 
     if (cu->strinfo == NULL) { /* old file */
       cu->strinfo = MEM_calloc_arrayN((slen + 4), sizeof(CharInfo), "strinfo compat");
@@ -1605,7 +1604,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
                            Curve *cu,
                            int mode,
                            ListBase *r_nubase,
-                           const wchar_t **r_text,
+                           const char32_t **r_text,
                            int *r_text_len,
                            bool *r_text_free,
                            struct CharTrans **r_chartransdata)
@@ -1649,9 +1648,9 @@ bool BKE_vfont_to_curve(Object *ob, int mode)
  * \{ */
 
 static struct {
-  wchar_t *text_buffer;
+  char32_t *text_buffer;
   CharInfo *info_buffer;
-  size_t len_wchar;
+  size_t len_utf32;
   size_t len_utf8;
 } g_vfont_clipboard = {NULL};
 
@@ -1659,19 +1658,19 @@ void BKE_vfont_clipboard_free(void)
 {
   MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
   MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
-  g_vfont_clipboard.len_wchar = 0;
+  g_vfont_clipboard.len_utf32 = 0;
   g_vfont_clipboard.len_utf8 = 0;
 }
 
-void BKE_vfont_clipboard_set(const wchar_t *text_buf, const CharInfo *info_buf, const size_t len)
+void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, const size_t len)
 {
-  wchar_t *text;
+  char32_t *text;
   CharInfo *info;
 
   /* clean previous buffers*/
   BKE_vfont_clipboard_free();
 
-  text = MEM_malloc_arrayN((len + 1), sizeof(wchar_t), __func__);
+  text = MEM_malloc_arrayN((len + 1), sizeof(*text), __func__);
   if (text == NULL) {
     return;
   }
@@ -1682,21 +1681,21 @@ void BKE_vfont_clipboard_set(const wchar_t *text_buf, const CharInfo *info_buf,
     return;
   }
 
-  memcpy(text, text_buf, len * sizeof(wchar_t));
+  memcpy(text, text_buf, len * sizeof(*text));
   text[len] = '\0';
   memcpy(info, info_buf, len * sizeof(CharInfo));
 
   /* store new buffers */
   g_vfont_clipboard.text_buffer = text;
   g_vfont_clipboard.info_buffer = info;
-  g_vfont_clipboard.len_utf8 = BLI_wstrlen_utf8(text);
-  g_vfont_clipboard.len_wchar = len;
+  g_vfont_clipboard.len_utf8 = BLI_str_utf32_as_utf8_len(text);
+  g_vfont_clipboard.len_utf32 = len;
 }
 
-void BKE_vfont_clipboard_get(wchar_t **r_text_buf,
+void BKE_vfont_clipboard_get(char32_t **r_text_buf,
                              CharInfo **r_info_buf,
                              size_t *r_len_utf8,
-                             size_t *r_len_wchar)
+                             size_t *r_len_utf32)
 {
   if (r_text_buf) {
     *r_text_buf = g_vfont_clipboard.text_buffer;
@@ -1706,8 +1705,8 @@ void BKE_vfont_clipboard_get(wchar_t **r_text_buf,
     *r_info_buf = g_vfont_clipboard.info_buffer;
   }
 
-  if (r_len_wchar) {
-    *r_len_wchar = g_vfont_clipboard.len_wchar;
+  if (r_len_utf32) {
+    *r_len_utf32 = g_vfont_clipboard.len_utf32;
   }
 
   if (r_len_utf8) {
index 6b6c68b197ec237fcfdffd76ac5279f296985fe1..eceeb2312854195490e9cc5a4ae61329bf1359c9 100644 (file)
@@ -491,7 +491,7 @@ static void make_duplis_font(const DupliContext *ctx)
   float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
   int text_len, a;
   size_t family_len;
-  const wchar_t *text = NULL;
+  const char32_t *text = NULL;
   bool text_free = false;
 
   /* font dupliverts not supported inside collections */
index 5c050dde99014a525a4e2c230d9550a0b0f99ebd..163792984ad56468076c1c8d7c93a2fddcba61a8 100644 (file)
@@ -25,7 +25,6 @@
 #include <string.h> /* strstr */
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <wchar.h>
 #include <wctype.h>
 
 #include "MEM_guardedalloc.h"
index 2d0acabc9dee3b0abc8db64ed6dd3bca6fcc8ae9..a54089ad8d641680e4e25e8ae2b655d2e36a0cfa 100644 (file)
@@ -45,7 +45,7 @@ void BLI_str_cursor_step_utf8(const char *str,
                               eStrCursorJumpType jump,
                               bool use_init_step);
 
-void BLI_str_cursor_step_wchar(const wchar_t *str,
+void BLI_str_cursor_step_utf32(const char32_t *str,
                                size_t maxlen,
                                int *pos,
                                eStrCursorJumpDirection direction,
index 0cdd6e94610bc26cd041829ed8d4f7d9fff54547..1db4cdfecd6decfc00a05bf7c4a8c07e79b68cbd 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
 #endif
 
 #include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
 
 char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy)
     ATTR_NONNULL();
@@ -48,6 +49,13 @@ unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p,
 unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index)
     ATTR_NONNULL();
 size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf);
+size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
+                             const char *__restrict src_c,
+                             const size_t maxncpy) ATTR_NONNULL();
+size_t BLI_str_utf32_as_utf8(char *__restrict dst,
+                             const char32_t *__restrict src,
+                             const size_t maxncpy) ATTR_NONNULL();
+size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_NONNULL();
 
 char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONNULL();
 char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONNULL(1);
@@ -68,8 +76,8 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst,
                                    const size_t maxcpy) ATTR_NONNULL();
 
 /* count columns that character/string occupies, based on wcwidth.c */
-int BLI_wcwidth(wchar_t ucs);
-int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONNULL();
+int BLI_wcwidth(char32_t ucs);
+int BLI_wcswidth(const char32_t *pwcs, size_t n) ATTR_NONNULL();
 /* warning, can return -1 on bad chars */
 int BLI_str_utf8_char_width(const char *p) ATTR_NONNULL();
 int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONNULL();
index a82e6a562e072b0198d5e60dbdc6a2eefa04339a..354d27385a217ed877b8dc9cde34c0c5cfbad9f1 100644 (file)
@@ -72,6 +72,15 @@ typedef uint64_t u_int64_t;
 #include <stddef.h> /* size_t define */
 #include <stdbool.h>
 
+#ifndef __cplusplus
+#  if defined(__APPLE__)
+/* The <uchar.h> standard header is missing on macOS. */
+typedef unsigned int char32_t;
+#  else
+#    include <uchar.h>
+#  endif
+#endif
+
 typedef unsigned int uint;
 typedef unsigned short ushort;
 typedef unsigned long ulong;
index f0113a7028a39249d0ced23fdb08626ece3306a2..ee4c11b1c046176bcda85c976e5d2a1e7a6f0186 100644 (file)
@@ -211,12 +211,12 @@ void BLI_str_cursor_step_utf8(const char *str,
   }
 }
 
-/* wchar_t version of BLI_str_cursor_step_utf8 (keep in sync!)
+/* UTF32 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)
+static bool cursor_step_next_utf32(const char32_t *UNUSED(str), size_t maxlen, int *pos)
 {
   if ((*pos) >= (int)maxlen) {
     return false;
@@ -225,7 +225,7 @@ static bool wchar_t_step_next(const wchar_t *UNUSED(str), size_t maxlen, int *po
   return true;
 }
 
-static bool wchar_t_step_prev(const wchar_t *UNUSED(str), size_t UNUSED(maxlen), int *pos)
+static bool cursor_step_prev_utf32(const char32_t *UNUSED(str), size_t UNUSED(maxlen), int *pos)
 {
   if ((*pos) <= 0) {
     return false;
@@ -234,7 +234,7 @@ static bool wchar_t_step_prev(const wchar_t *UNUSED(str), size_t UNUSED(maxlen),
   return true;
 }
 
-void BLI_str_cursor_step_wchar(const wchar_t *str,
+void BLI_str_cursor_step_utf32(const char32_t *str,
                                size_t maxlen,
                                int *pos,
                                eStrCursorJumpDirection direction,
@@ -245,7 +245,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
 
   if (direction == STRCUR_DIR_NEXT) {
     if (use_init_step) {
-      wchar_t_step_next(str, maxlen, pos);
+      cursor_step_next_utf32(str, maxlen, pos);
     }
     else {
       BLI_assert(jump == STRCUR_JUMP_DELIM);
@@ -259,7 +259,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
        * 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 (cursor_step_next_utf32(str, maxlen, pos)) {
           if ((jump != STRCUR_JUMP_ALL) &&
               (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) {
             break;
@@ -273,7 +273,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
   }
   else if (direction == STRCUR_DIR_PREV) {
     if (use_init_step) {
-      wchar_t_step_prev(str, maxlen, pos);
+      cursor_step_prev_utf32(str, maxlen, pos);
     }
     else {
       BLI_assert(jump == STRCUR_JUMP_DELIM);
@@ -288,7 +288,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
        * list of special character, ctr -> */
       while ((*pos) > 0) {
         const int pos_prev = *pos;
-        if (wchar_t_step_prev(str, maxlen, pos)) {
+        if (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 */
index 92c4ec73768ed117e9bb4d60b773767ba3127d30..63657f33bbaa2b6b494ad2ebc571358892ade85c 100644 (file)
@@ -430,6 +430,11 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w,
     size_t step = 0;
     uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step);
     if (unicode != BLI_UTF8_ERR) {
+      /* TODO: `wchar_t` type is an implementation-defined and may represent
+       * 16-bit or 32-bit depending on operating system.
+       * So the ideal would be to do the corresponding encoding.
+       * But for now just assert that it has no conflicting use. */
+      BLI_assert(step <= sizeof(wchar_t));
       *dst_w = (wchar_t)unicode;
       src_c += step;
     }
@@ -451,12 +456,12 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w,
 
 /* count columns that character/string occupies, based on wcwidth.c */
 
-int BLI_wcwidth(wchar_t ucs)
+int BLI_wcwidth(char32_t ucs)
 {
   return mk_wcwidth(ucs);
 }
 
-int BLI_wcswidth(const wchar_t *pwcs, size_t n)
+int BLI_wcswidth(const char32_t *pwcs, size_t n)
 {
   return mk_wcswidth(pwcs, n);
 }
@@ -468,7 +473,7 @@ int BLI_str_utf8_char_width(const char *p)
     return -1;
   }
 
-  return BLI_wcwidth((wchar_t)unicode);
+  return BLI_wcwidth((char32_t)unicode);
 }
 
 int BLI_str_utf8_char_width_safe(const char *p)
@@ -480,7 +485,7 @@ int BLI_str_utf8_char_width_safe(const char *p)
     return 1;
   }
 
-  columns = BLI_wcwidth((wchar_t)unicode);
+  columns = BLI_wcwidth((char32_t)unicode);
 
   return (columns < 0) ? 1 : columns;
 }
@@ -726,6 +731,88 @@ size_t BLI_str_utf8_from_unicode(uint c, char *outbuf)
   return len;
 }
 
+size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
+                             const char *__restrict src_c,
+                             const size_t maxncpy)
+{
+  const size_t maxlen = maxncpy - 1;
+  size_t len = 0;
+
+  BLI_assert(maxncpy != 0);
+
+#ifdef DEBUG_STRSIZE
+  memset(dst_w, 0xff, sizeof(*dst_w) * maxncpy);
+#endif
+
+  while (*src_c && len != maxlen) {
+    size_t step = 0;
+    uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step);
+    if (unicode != BLI_UTF8_ERR) {
+      *dst_w = unicode;
+      src_c += step;
+    }
+    else {
+      *dst_w = '?';
+      src_c = BLI_str_find_next_char_utf8(src_c, NULL);
+    }
+    dst_w++;
+    len++;
+  }
+
+  *dst_w = 0;
+
+  return len;
+}
+
+size_t BLI_str_utf32_as_utf8(char *__restrict dst,
+                             const char32_t *__restrict src,
+                             const size_t maxncpy)
+{
+  const size_t maxlen = maxncpy - 1;
+  /* 6 is max utf8 length of an unicode char. */
+  const int64_t maxlen_secured = (int64_t)maxlen - 6;
+  size_t len = 0;
+
+  BLI_assert(maxncpy != 0);
+
+#ifdef DEBUG_STRSIZE
+  memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+  while (*src && len <= maxlen_secured) {
+    len += BLI_str_utf8_from_unicode((uint)*src++, dst + len);
+  }
+
+  /* We have to be more careful for the last six bytes,
+   * to avoid buffer overflow in case utf8-encoded char would be too long for our dst buffer. */
+  while (*src) {
+    char t[6];
+    size_t l = BLI_str_utf8_from_unicode((uint)*src++, t);
+    BLI_assert(l <= 6);
+    if (len + l > maxlen) {
+      break;
+    }
+    memcpy(dst + len, t, l);
+    len += l;
+  }
+
+  dst[len] = '\0';
+
+  return len;
+}
+
+/* utf32 len in utf8 */
+size_t BLI_str_utf32_as_utf8_len(const char32_t *src)
+{
+  size_t len = 0;
+
+  while (*src) {
+    len += BLI_str_utf8_from_unicode((uint)*src++, NULL);
+  }
+
+  return len;
+}
+
 /* was g_utf8_find_prev_char */
 /**
  * BLI_str_find_prev_char_utf8:
index e11807d818ffddd0629173c1457f94ab9af7e9cf..92957c51c08b54166206041bf926bee40e10a2a6 100644 (file)
@@ -468,7 +468,8 @@ static int kill_selection(Object *obedit, int ins) /* 1 == new character */
     if (ins == 0) {
       getfrom++;
     }
-    size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
+    size = (ef->len * sizeof(*ef->textbuf)) - (selstart * sizeof(*ef->textbuf)) +
+           (offset * sizeof(*ef->textbuf));
     memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
     memmove(ef->textbufinfo + selstart,
             ef->textbufinfo + getfrom,
@@ -488,7 +489,7 @@ static int kill_selection(Object *obedit, int ins) /* 1 == new character */
 
 /* text_update_edited(C, scene, obedit, 1, FO_EDIT); */
 static bool font_paste_wchar(Object *obedit,
-                             const wchar_t *str,
+                             const char32_t *str,
                              const size_t str_len,
                              /* optional */
                              struct CharInfo *str_info)
@@ -507,9 +508,10 @@ static bool font_paste_wchar(Object *obedit,
     kill_selection(obedit, 0);
 
     if (str_len) {
-      int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t);
+      int size = (ef->len * sizeof(*ef->textbuf)) - (ef->pos * sizeof(*ef->textbuf)) +
+                 sizeof(*ef->textbuf);
       memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
-      memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(wchar_t));
+      memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(*ef->textbuf));
 
       memmove(ef->textbufinfo + ef->pos + str_len,
               ef->textbufinfo + ef->pos,
@@ -538,9 +540,9 @@ static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
 
   int tmplen;
 
-  wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * (str_len + 1)), __func__);
+  char32_t *mem = MEM_mallocN((sizeof(*mem) * (str_len + 1)), __func__);
 
-  tmplen = BLI_strncpy_wchar_from_utf8(mem, str, str_len + 1);
+  tmplen = BLI_str_utf8_as_utf32(mem, str, str_len + 1);
 
   retval = font_paste_wchar(obedit, mem, tmplen, NULL);
 
@@ -919,7 +921,7 @@ static void copy_selection(Object *obedit)
     Curve *cu = obedit->data;
     EditFont *ef = cu->editfont;
     char *buf = NULL;
-    wchar_t *text_buf;
+    char32_t *text_buf;
     size_t len_utf8;
 
     /* internal clipboard (for style) */
@@ -930,7 +932,7 @@ static void copy_selection(Object *obedit)
     /* system clipboard */
     buf = MEM_mallocN(len_utf8 + 1, __func__);
     if (buf) {
-      BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1);
+      BLI_str_utf32_as_utf8(buf, text_buf, len_utf8 + 1);
       WM_clipboard_text_set(buf, false);
       MEM_freeN(buf);
     }
@@ -1004,7 +1006,7 @@ void FONT_OT_text_cut(wmOperatorType *ot)
 
 static bool paste_selection(Object *obedit, ReportList *reports)
 {
-  wchar_t *text_buf;
+  char32_t *text_buf;
   CharInfo *info_buf;
   size_t len;
 
@@ -1024,7 +1026,7 @@ static int paste_text_exec(bContext *C, wmOperator *op)
   Object *obedit = CTX_data_edit_object(C);
   int retval;
   size_t len_utf8;
-  wchar_t *text_buf;
+  char32_t *text_buf;
 
   /* Store both clipboards as utf8 for comparison,
    * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles
@@ -1050,7 +1052,7 @@ static int paste_text_exec(bContext *C, wmOperator *op)
       return OPERATOR_CANCELLED;
     }
 
-    BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
+    BLI_str_utf32_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
   }
 
   if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
@@ -1164,7 +1166,7 @@ static int move_cursor(bContext *C, int type, const bool select)
 
     case PREV_WORD: {
       int pos = ef->pos;
-      BLI_str_cursor_step_wchar(
+      BLI_str_cursor_step_utf32(
           ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
       ef->pos = pos;
       cursmove = FO_CURS;
@@ -1173,7 +1175,7 @@ static int move_cursor(bContext *C, int type, const bool select)
 
     case NEXT_WORD: {
       int pos = ef->pos;
-      BLI_str_cursor_step_wchar(
+      BLI_str_cursor_step_utf32(
           ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
       ef->pos = pos;
       cursmove = FO_CURS;
@@ -1528,7 +1530,7 @@ static int delete_exec(bContext *C, wmOperator *op)
       break;
     case DEL_NEXT_WORD: {
       int pos = ef->pos;
-      BLI_str_cursor_step_wchar(
+      BLI_str_cursor_step_utf32(
           ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
       range[0] = ef->pos;
       range[1] = pos;
@@ -1537,7 +1539,7 @@ static int delete_exec(bContext *C, wmOperator *op)
 
     case DEL_PREV_WORD: {
       int pos = ef->pos;
-      BLI_str_cursor_step_wchar(
+      BLI_str_cursor_step_utf32(
           ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
       range[0] = pos;
       range[1] = ef->pos;
@@ -1864,12 +1866,12 @@ void ED_curve_editfont_make(Object *obedit)
   if (ef == NULL) {
     ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont");
 
-    ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf");
+    ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(*ef->textbuf), "texteditbuf");
     ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo");
   }
 
   /* Convert the original text to wchar_t */
-  len_wchar = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4);
+  len_wchar = BLI_str_utf8_as_utf32(ef->textbuf, cu->str, MAXTEXT + 4);
   BLI_assert(len_wchar == cu->len_wchar);
   ef->len = len_wchar;
   BLI_assert(ef->len >= 0);
@@ -1901,13 +1903,13 @@ void ED_curve_editfont_load(Object *obedit)
 
   /* Calculate the actual string length in UTF-8 variable characters */
   cu->len_wchar = ef->len;
-  cu->len = BLI_wstrlen_utf8(ef->textbuf);
+  cu->len = BLI_str_utf32_as_utf8_len(ef->textbuf);
 
   /* Alloc memory for UTF-8 variable char length string */
-  cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str");
+  cu->str = MEM_mallocN(cu->len + sizeof(char32_t), "str");
 
   /* Copy the wchar to UTF-8 */
-  BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1);
+  BLI_str_utf32_as_utf8(cu->str, ef->textbuf, cu->len + 1);
 
   if (cu->strinfo) {
     MEM_freeN(cu->strinfo);
@@ -1943,7 +1945,7 @@ static int set_case(bContext *C, int ccase)
   Object *obedit = CTX_data_edit_object(C);
   Curve *cu = obedit->data;
   EditFont *ef = cu->editfont;
-  wchar_t *str;
+  char32_t *str;
   int len;
   int selstart, selend;
 
@@ -2010,18 +2012,16 @@ static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
   Object *obedit = CTX_data_edit_object(C);
   Curve *cu = obedit->data;
   EditFont *ef = cu->editfont;
-  wchar_t *str;
-  int len, ccase = CASE_UPPER;
+  char32_t *str;
+  int ccase = CASE_UPPER;
 
-  len = wcslen(ef->textbuf);
   str = ef->textbuf;
-  while (len) {
+  while (*str) {
     if (*str >= 'a' && *str <= 'z') {
       ccase = CASE_LOWER;
       break;
     }
 
-    len--;
     str++;
   }
 
index 26c0e5cf6c993b9074a83191391fe685bef4f728..f00c4731b0f565f04d40ebf4c4a5e2ddf6af9928 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <wchar.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -58,7 +57,7 @@
  * \{ */
 
 typedef struct UndoFont {
-  wchar_t *textbuf;
+  char32_t *textbuf;
   struct CharInfo *textbufinfo;
 
   int len, pos, selstart, selend;
@@ -233,7 +232,7 @@ static void undofont_to_editfont(UndoFont *uf, Curve *cu)
   uf_arraystore_expand(uf);
 #endif
 
-  final_size = sizeof(wchar_t) * (uf->len + 1);
+  final_size = sizeof(*ef->textbuf) * (uf->len + 1);
   memcpy(ef->textbuf, uf->textbuf, final_size);
 
   final_size = sizeof(CharInfo) * (uf->len + 1);
@@ -259,7 +258,8 @@ static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
 
   size_t final_size;
 
-  final_size = sizeof(wchar_t) * (ef->len + 1);
+  BLI_assert(sizeof(*uf->textbuf) == sizeof(*ef->textbuf));
+  final_size = sizeof(*uf->textbuf) * (ef->len + 1);
   uf->textbuf = MEM_mallocN(final_size, __func__);
   memcpy(uf->textbuf, ef->textbuf, final_size);
 
index 6a3ab632fd45a7178df742532502bebc92703e38..d7deccef355a65a15ebae8680c5b025fd538c5f0 100644 (file)
@@ -585,7 +585,7 @@ static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
     MEM_freeN(cu->strinfo);
   }
 
-  cu->str = MEM_mallocN(len_bytes + sizeof(wchar_t), "str");
+  cu->str = MEM_mallocN(len_bytes + sizeof(char32_t), "str");
   cu->strinfo = MEM_callocN((len_chars + 4) * sizeof(CharInfo), "strinfo");
 
   BLI_strncpy(cu->str, value, len_bytes + 1);