/** * Write a UTF-8 string to the Windows console in Unicode (UTF-16) * * @param utf8String UTF-8 input string * @param utf8StringSize Number of bytes in UTF-8 string, no NUL terminator assumed * @return true if all characters were displayed (including zero characters) */ bool writeUtf8ToWindowsConsole( const char* utf8String, unsigned int utf8StringSize ) { int bufferSize = MultiByteToWideChar( CP_UTF8, // Code page 0, // Flags utf8String, // Input string utf8StringSize, // Input string length NULL, // No output buffer 0 // Zero means "compute required size" ); if ( bufferSize == 0 ) { return true; } boost::scoped_array<wchar_t> utf16String( new wchar_t[ bufferSize ] ); MultiByteToWideChar( CP_UTF8, // Code page 0, // Flags utf8String, // Input string utf8StringSize, // Input string length utf16String.get(), // UTF-16 output buffer bufferSize // Buffer size in wide characters ); const wchar_t* utf16Pointer = utf16String.get(); size_t numberOfCharactersToWrite = bufferSize; HANDLE consoleHandle = GetStdHandle( STD_OUTPUT_HANDLE ); while ( numberOfCharactersToWrite > 0 ) { static const DWORD MAXIMUM_CHARACTERS_PER_PASS = 8 * 1024; DWORD numberOfCharactersThisPass = static_cast<DWORD>( numberOfCharactersToWrite ); if ( numberOfCharactersThisPass > MAXIMUM_CHARACTERS_PER_PASS ) { numberOfCharactersThisPass = MAXIMUM_CHARACTERS_PER_PASS; } DWORD numberOfCharactersWritten; BOOL success = WriteConsoleW( consoleHandle, utf16Pointer, numberOfCharactersThisPass, &numberOfCharactersWritten, NULL ); if ( 0 == success ) { DWORD dosError = GetLastError(); static bool errorMessageShown = false; if ( ERROR_GEN_FAILURE == dosError ) { if ( ! errorMessageShown ) { std::cout << "\n---\nUnicode text could not be correctly displayed.\n" "Please change your console font to a Unicode font " "(e.g. Lucida Console).\n---\n" << std::endl; errorMessageShown = true; } // we can't display the text properly using a raster font, // but we can display the bits that will display ... _write( 1, utf8String, utf8StringSize ); } return false; } numberOfCharactersToWrite -= numberOfCharactersWritten; utf16Pointer += numberOfCharactersWritten; } return true; }
nsresult nsBeckyFilters::GetFolderNameFromTarget(const nsCString &aTarget, nsAString &aName) { int32_t backslashPosition = aTarget.RFindChar('\\'); if (backslashPosition > 0) { NS_ConvertUTF8toUTF16 utf16String(Substring(aTarget, backslashPosition + 1)); nsBeckyUtils::TranslateFolderName(utf16String, aName); } return NS_OK; }
std::wstring ToUtf16String(const std::string& str) { int length = static_cast<int>(str.size()); if (length == 0) return std::wstring(); int utf16StringLength = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), length, NULL, 0); if (utf16StringLength == 0) throw std::runtime_error("ToUTF16String failed. Can't determine the length of the buffer needed."); std::wstring utf16String(utf16StringLength, L'\0'); MultiByteToWideChar(CP_UTF8, 0, str.c_str(), length, &utf16String[0], utf16StringLength); return utf16String; }
/** * Write a UTF-8 string to the Windows console in Unicode (UTF-16) * * @param utf8String UTF-8 input string * @param utf8StringSize Number of bytes in UTF-8 string, no NUL terminator assumed * @return true if all characters were displayed (including zero characters) */ bool writeUtf8ToWindowsConsole( const char* utf8String, unsigned int utf8StringSize ) { int bufferSize = MultiByteToWideChar( CP_UTF8, // Code page 0, // Flags utf8String, // Input string utf8StringSize, // Input string length NULL, // No output buffer 0 // Zero means "compute required size" ); if ( bufferSize == 0 ) { return true; } boost::scoped_array<wchar_t> utf16String( new wchar_t[ bufferSize ] ); MultiByteToWideChar( CP_UTF8, // Code page 0, // Flags utf8String, // Input string utf8StringSize, // Input string length utf16String.get(), // UTF-16 output buffer bufferSize // Buffer size in wide characters ); const wchar_t* utf16Pointer = utf16String.get(); size_t numberOfCharactersToWrite = bufferSize; HANDLE consoleHandle = GetStdHandle( STD_OUTPUT_HANDLE ); while ( numberOfCharactersToWrite > 0 ) { static const DWORD MAXIMUM_CHARACTERS_PER_PASS = 8 * 1024; DWORD numberOfCharactersThisPass = static_cast<DWORD>( numberOfCharactersToWrite ); if ( numberOfCharactersThisPass > MAXIMUM_CHARACTERS_PER_PASS ) { numberOfCharactersThisPass = MAXIMUM_CHARACTERS_PER_PASS; } DWORD numberOfCharactersWritten; BOOL success = WriteConsoleW( consoleHandle, utf16Pointer, numberOfCharactersThisPass, &numberOfCharactersWritten, NULL ); if ( 0 == success ) { return false; } numberOfCharactersToWrite -= numberOfCharactersWritten; utf16Pointer += numberOfCharactersWritten; } return true; }
bool WebPopupMenuProxyGtk::typeAheadFind(GdkEventKey* event) { // If we were given a non-printable character just skip it. gunichar unicodeCharacter = gdk_keyval_to_unicode(event->keyval); if (!g_unichar_isprint(unicodeCharacter)) { resetTypeAheadFindState(); return false; } glong charactersWritten; GUniquePtr<gunichar2> utf16String(g_ucs4_to_utf16(&unicodeCharacter, 1, nullptr, &charactersWritten, nullptr)); if (!utf16String) { resetTypeAheadFindState(); return false; } // If the character is the same as the last character, the user is probably trying to // cycle through the menulist entries. This matches the WebCore behavior for collapsed menulists. static const uint32_t searchTimeoutMs = 1000; bool repeatingCharacter = unicodeCharacter != m_previousKeyEventCharacter; if (event->time - m_previousKeyEventTimestamp > searchTimeoutMs) m_currentSearchString = String(reinterpret_cast<UChar*>(utf16String.get()), charactersWritten); else if (repeatingCharacter) m_currentSearchString.append(String(reinterpret_cast<UChar*>(utf16String.get()), charactersWritten)); m_previousKeyEventTimestamp = event->time; m_previousKeyEventCharacter = unicodeCharacter; GUniquePtr<GList> children(gtk_container_get_children(GTK_CONTAINER(m_popup))); if (!children) return true; // We case fold before searching, because strncmp does not handle non-ASCII characters. GUniquePtr<gchar> searchStringWithCaseFolded(g_utf8_casefold(m_currentSearchString.utf8().data(), -1)); size_t prefixLength = strlen(searchStringWithCaseFolded.get()); // If a menu item has already been selected, start searching from the current // item down the list. This will make multiple key presses of the same character // advance the selection. GList* currentChild = children.get(); if (m_currentlySelectedMenuItem) { currentChild = g_list_find(children.get(), m_currentlySelectedMenuItem); if (!currentChild) { m_currentlySelectedMenuItem = nullptr; currentChild = children.get(); } // Repeating characters should iterate. if (repeatingCharacter) { if (GList* nextChild = g_list_next(currentChild)) currentChild = nextChild; } } GList* firstChild = currentChild; do { currentChild = g_list_next(currentChild); if (!currentChild) currentChild = children.get(); GUniquePtr<gchar> itemText(g_utf8_casefold(gtk_menu_item_get_label(GTK_MENU_ITEM(currentChild->data)), -1)); if (!strncmp(searchStringWithCaseFolded.get(), itemText.get(), prefixLength)) { gtk_menu_shell_select_item(GTK_MENU_SHELL(m_popup), GTK_WIDGET(currentChild->data)); break; } } while (currentChild != firstChild); return true; }