diff --git a/misc.h b/misc.h index a85b87ae..a78f8c8d 100644 --- a/misc.h +++ b/misc.h @@ -67,6 +67,10 @@ void strbuf_finalise_agent_query(strbuf *buf); * work around the rather deficient interface of mb_to_wc. */ wchar_t *dup_mb_to_wc_c(int codepage, int flags, const char *string, int len); wchar_t *dup_mb_to_wc(int codepage, int flags, const char *string); +char *dup_wc_to_mb_c(int codepage, int flags, const wchar_t *string, int len, + const char *defchr, struct unicode_data *ucsdata); +char *dup_wc_to_mb(int codepage, int flags, const wchar_t *string, + const char *defchr, struct unicode_data *ucsdata); static inline int toint(unsigned u) { diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 4a6a1fe8..8048f811 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -17,6 +17,7 @@ add_sources_from_current_dir(utils dupprintf.c dupstr.c dup_mb_to_wc.c + dup_wc_to_mb.c encode_utf8.c encode_wide_string_as_utf8.c fgetline.c diff --git a/utils/dup_wc_to_mb.c b/utils/dup_wc_to_mb.c new file mode 100644 index 00000000..e91a8916 --- /dev/null +++ b/utils/dup_wc_to_mb.c @@ -0,0 +1,39 @@ +/* + * dup_wc_to_mb: memory-allocating wrapper on wc_to_mb. + * + * Also dup_wc_to_mb_c: same but you already know the length of the + * string. + */ + +#include + +#include "putty.h" +#include "misc.h" + +char *dup_wc_to_mb_c(int codepage, int flags, const wchar_t *string, int len, + const char *defchr, struct unicode_data *ucsdata) +{ + size_t outsize = len+1; + char *out = snewn(outsize, char); + + while (true) { + size_t outlen = wc_to_mb(codepage, flags, string, len, out, outsize, + defchr, ucsdata); + /* We can only be sure we've consumed the whole input if the + * output is not within a multibyte-character-length of the + * end of the buffer! */ + if (outlen < outsize && outsize - outlen > MB_LEN_MAX) { + out[outlen] = '\0'; + return out; + } + + sgrowarray(out, outsize, outsize); + } +} + +char *dup_wc_to_mb(int codepage, int flags, const wchar_t *string, + const char *defchr, struct unicode_data *ucsdata) +{ + return dup_wc_to_mb_c(codepage, flags, string, wcslen(string), + defchr, ucsdata); +}