/* Convert a string from the current locale's character set to UTF-8. * Unfortunately, "current locale" can mean a few different things on * Windows -- we use the default ANSI code page, which does the right * thing for command-line arguments (like "-sPDFPassword=foo") and * for strings typed as input to gswin32.exe. It doesn't work for * strings typed as input to gswin32c.exe, which are normally in the * default OEM code page instead. * <string> .locale_to_utf8 <string> */ static int zlocale_to_utf8(i_ctx_t *i_ctx_p) { #define LOCALE_TO_UTF8_BUFFER_SIZE 1024 os_ptr op = osp; char *input; WCHAR wide_buffer[LOCALE_TO_UTF8_BUFFER_SIZE]; char utf8_buffer[LOCALE_TO_UTF8_BUFFER_SIZE]; int success; int code; check_read_type(*op, t_string); input = ref_to_string(op, imemory, "locale_to_utf8 input"); if (input == 0) return_error(gs_error_VMerror); success = MultiByteToWideChar(CP_ACP, 0, input, -1, wide_buffer, LOCALE_TO_UTF8_BUFFER_SIZE); ifree_string((byte *)input, r_size(op) + 1, "locale_to_utf8 input"); if (success == 0) return_error(gs_error_ioerror); success = WideCharToMultiByte(CP_UTF8, 0, wide_buffer, -1, utf8_buffer, LOCALE_TO_UTF8_BUFFER_SIZE, NULL, NULL); if (success == 0) return_error(gs_error_ioerror); code = string_to_ref(utf8_buffer, op, iimemory, "locale_to_utf8 output"); if (code < 0) return code; return 0; #undef LOCALE_TO_UTF8_BUFFER_SIZE }
/* <int> .oserrorstring false */ static int zoserrorstring(i_ctx_t *i_ctx_p) { os_ptr op = osp; const char *str; int code; uint len; byte ch; check_type(*op, t_integer); str = gp_strerror((int)op->value.intval); if (str == 0 || (len = strlen(str)) == 0) { make_false(op); return 0; } check_ostack(1); code = string_to_ref(str, op, iimemory, ".oserrorstring"); if (code < 0) return code; /* Strip trailing end-of-line characters. */ while ((len = r_size(op)) != 0 && ((ch = op->value.bytes[--len]) == '\r' || ch == '\n') ) r_dec_size(op, 1); push(1); make_true(op); return 0; }
/* Convert a string from the current locale's character set to UTF-8. * <string> .locale_to_utf8 <string> */ static int zlocale_to_utf8(i_ctx_t *i_ctx_p) { os_ptr op = osp; char *input; char *output; int code; check_read_type(*op, t_string); input = ref_to_string(op, imemory, "locale_to_utf8 input"); if (input == 0) return_error(gs_error_VMerror); output = stringprep_locale_to_utf8(input); ifree_string((byte *)input, r_size(op) + 1, "locale_to_utf8 input"); if (output == 0) { /* This function is intended to be used on strings whose * character set is unknown, so it's not an error if the * input contains invalid characters. Just return the input * string unchanged. * * Sadly, EINVAL from stringprep_locale_to_utf8 can mean * either an invalid character set conversion (which we care * about), or an incomplete input string (which we don't). * For now, we ignore EINVAL; the right solution is probably * to not use stringprep_locale_to_utf8, and just call iconv * by hand. */ if (errno == EILSEQ || errno == EINVAL) return 0; /* Other errors (like ENFILE) are real errors, which we * want to return to the user. */ return_error(gs_error_ioerror); } code = string_to_ref(output, op, iimemory, "locale_to_utf8 output"); free(output); if (code < 0) return code; return 0; }