int from_utf16(const wchar_t *utf16, TCHAR **buffer, unsigned long *buflen) { #ifdef UNICODE return to_utf16(utf16, buffer, buflen); #else return to_utf8(utf16, buffer, buflen); #endif }
std::wstring to_windows_path(const std::string &src) { std::wstring dst = to_utf16(src); std::replace(dst.begin(), dst.end(), L'/', L'\\'); return dst; }
void display_number_t::measure_vertical(extents_t& calculated_horizontal, const place_data_t& placed_horizontal) { assert(window_m); place_data_t save_bounds; implementation::get_control_bounds(window_m, save_bounds); place_data_t static_bounds; top(static_bounds) = top(placed_horizontal); left(static_bounds) = left(placed_horizontal); width(static_bounds) = width(placed_horizontal); height(static_bounds) = 10000; // bottomless implementation::set_control_bounds(window_m, static_bounds); HDC hdc(::GetWindowDC(window_m)); std::string title(implementation::get_window_title(window_m)); std::wstring wtitle; to_utf16(title.begin(), title.end(), std::back_inserter(wtitle)); place_data_liukahr_t out_extent; // metrics::set_theme_name(L"Edit"); // // If we don't have the type of this widget, then we should return a // zero sized rectangle. This is usually correct, and a good assumption // anyway. // int uxtheme_type = EP_EDITTEXT; // // Get the text metrics (and calculate the baseline of this widget) // TEXTMETRIC widget_tm; bool have_tm = metrics::get_font_metrics(uxtheme_type, widget_tm); assert(have_tm); const place_data_liukahr_t in_extents = static_bounds; bool have_extents = metrics::get_text_extents(uxtheme_type, wtitle.c_str(), out_extent, &in_extents); assert(have_extents); extents_t::slice_t& vert = calculated_horizontal.vertical(); vert.length_m = height(out_extent); // set the baseline for the text metrics::set_window(window_m); if (have_tm) // distance from top to baseline vert.guide_set_m.push_back(widget_tm.tmHeight - widget_tm.tmDescent); implementation::set_control_bounds(window_m, save_bounds); }
/* * call-seq: * string.transliterate(transform_string) -> string * * Transliterates string using transform. * */ static VALUE unicode_transliterate(int argc, VALUE *argv, VALUE string) { UChar str[BUF_SIZE]; int32_t slen = 0; UErrorCode status = U_ZERO_ERROR; UTransliterator *trans; VALUE transform; rb_scan_args(argc, argv, "01", &transform); if (NIL_P(transform)) transform = rb_str_new2("Latin; Lower; NFD; [^[:letter:] [:space:] [0-9] [:punctuation:]] Remove; NFC"); to_utf16(string, str, &slen); trans = get_trans(transform); utrans_transUChars(trans, str, &slen, BUF_SIZE, 0, &slen, &status); to_utf8(str, slen); }
// Write characters to output buffer. // We compensate for character-splitting. This is necessary because // MSVC does not support a UTF8 locale and as such streams interpret // narrow characters in the default locale. This implementation // assumes the stream will treat each byte of a multibyte narrow // chracter as an individual single byte character. std::streambuf::int_type unicode_streambuf::overflow( std::streambuf::int_type character) { // Add a single explicitly read byte to the buffer. // The narrow buffer is underexposed by 1 byte to accomodate this. if (character != traits_type::eof()) { *pptr() = static_cast<char>(character); pbump(sizeof(char)); } // This will be in the range 0..4, indicating the number of bytes that were // not written in the conversion. A nonzero value results when the buffer // terminates within a utf8 multiple byte character. uint8_t unwritten = 0; // Get the number of bytes in the buffer to convert. const auto write = pptr() - pbase(); if (write > 0) { // Convert utf8 to utf16, returning chars written and bytes unread. const auto chars = to_utf16(wide_, narrow_size_, narrow_, write, unwritten); // Write to the wide output buffer. const auto written = wide_buffer_->sputn(wide_, chars); // Handle write failure as an EOF. if (written != chars) return traits_type::eof(); } // Copy the fractional character to the beginning of the buffer. memcpy(narrow_, &narrow_[write - unwritten], unwritten); // Reset the pptr to the buffer start, leave pbase and epptr. // We could use just pbump for this if it wasn't limited to 'int' width. setp(narrow_, &narrow_[narrow_size_ - 1]); // Reset pptr just after the fractional character. pbump(unwritten); // Return the overflow byte or EOF sentinel. return character; };
/* * call-seq: * string.unicode_sort_key -> string * * Returns a string that will sort according to the Unicode collation algorithm. * */ static VALUE unicode_sort_key(VALUE string) { char str[BUF_SIZE]; UChar ustr[BUF_SIZE]; int32_t len = 0; int32_t ulen = 0; UErrorCode status = U_ZERO_ERROR; UCollator *col; to_utf16(string, ustr, &ulen); col = ucol_open("en_US", &status); if (U_SUCCESS(status)) { len = ucol_getSortKey(col, ustr, ulen, (uint8_t*)str, BUF_SIZE); ucol_close(col); } return rb_str_new(str, len - 1); }
//------------------------------------------------------------------------------ void win_screen_buffer::write(const char* data, int length) { str_iter iter(data, length); while (length > 0) { wchar_t wbuf[384]; int n = min<int>(sizeof_array(wbuf), length + 1); n = to_utf16(wbuf, n, iter); for (int i = 0; i < n; ++i) if (wbuf[i] == '\r') __debugbreak(); DWORD written; WriteConsoleW(m_handle, wbuf, n, &written, nullptr); n = int(iter.get_pointer() - data); length -= n; data += n; } }
static UTransliterator* get_trans(VALUE transform) { UChar str[BUF_SIZE]; int32_t len = 0; UTransliterator *trans; UErrorCode status = U_ZERO_ERROR; VALUE obj; obj = rb_hash_aref(trans_hash, transform); if (NIL_P(obj)) { to_utf16(transform, str, &len); trans = utrans_openU(str, len, UTRANS_FORWARD, NULL, 0, NULL, &status); if (trans) { obj = Data_Wrap_Struct(rb_cObject, 0, trans_free, trans); rb_hash_aset(trans_hash, transform, obj); } else { rb_raise(rb_eArgError, "invalid transform: %s", RSTRING_PTR(transform)); } } Data_Get_Struct(obj, UTransliterator, trans); return trans; }
std::u16string to_utf16(const std::u32string &s) { return to_utf16(to_utf8(s)); }