Подтвердить что ты не робот

Как я могу проверить приложение Windows для правильной обработки Unicode?

Я не могу использовать предварительно упакованные строковые библиотеки Unicode, такие как ICU, потому что они взорвали размер двоичного файла до безумной степени (это программа 200k, ICU - 16 МБ +!).

Я использую встроенный тип строки wchar_t для всех уже, но я хочу, чтобы я не делал ничего глупого с точки зрения выполнения итераций в строках или таких вещей.

Существуют ли такие инструменты, как Fuzzers, для безопасности, но для Unicode? То есть, выкидывайте символы вне базовой многоязычной плоскости в свой код и гарантируйте, что все будет правильно обрабатываться как UTF-16?

(О, и, очевидно, кросс-платформенное решение работает, хотя большинство кросс-платформенных вещей должны поддерживать как UTF-8, так и UTF-16)

EDIT. Также обратите внимание на вещи, которые менее очевидны, чем суррогатные пары UTF-16 - такие вещи, как знаки акцента!

4b9b3361

Ответ 1

Некоторые вещи для проверки:

  • Убедитесь, что вместо передачи WM_CHAR вы обрабатываете WM_UNICHAR:

    Сообщение WM_UNICHAR совпадает с WM_CHAR, за исключением того, что использует UTF-32. Он предназначен для отправки или отправки символов Unicode в ANSI-окна, а - для обработки символов Unicode Additional Plane.

  • Do not предположим, что символ я th находится в индексе i. Очевидно, это не так, и если вам случится использовать этот факт, скажем, сломав строку пополам, тогда вы можете испортить ее.

  • Не указывайте пользователю (в строке состояния или что-то еще), что пользователь имеет N символов только потому, что массив символов имеет длину N.

Ответ 2

Неверный ответ

Используйте WM_UNICHAR, он обрабатывает UTF-32 и может обрабатывать символы дополнительной плоскости Unicode.

Пока это почти так, но полная правда выглядит так:

  • WM_UNICHAR - это взлом, предназначенный для ANSI Windows для получения символов Unicode. Создайте окно Unicode, и вы его никогда не получите.
  • Создайте окно ANSI, и вы будете удивлены, что он по-прежнему не работает должным образом. Уловка заключается в том, что при создании окна вы получаете WM_UNICHAR с 0xffff, с которым вы должны реагировать, возвращая 1 (по умолчанию процедура окна возвращает 0). Не получится, и вы больше никогда не увидите WM_UNICHAR. Хорошая работа, о которой не говорится в официальной документации.
  • Запустите программу в системе, которая по таинственным причинам не поддерживает WM_UNICHAR (например, мою систему Windows 7 64), и она все равно не будет работать, даже если вы все сделаете правильно.

Теоретически правильный ответ

Нет ничего, на что нужно обратить внимание или обратить внимание.

Скомпилируйте с помощью UNICODE или явным образом создайте свой оконный класс, а также свое окно, используя функцию "W", и используйте WM_CHAR, как если бы это было наиболее естественным делом. Это. Это действительно самая естественная вещь.

WM_CHAR использует UTF-16 (за исключением случаев, когда он отсутствует, например, в Windows 2000). Конечно, один символ UTF-16 не может представлять кодовые точки вне BMP, но это не проблема, потому что вы просто получаете два сообщения WM_CHAR, содержащие суррогатную пару. Он полностью прозрачен для вашего приложения, вам не нужно ничего делать особо. Любая функция Windows API, которая принимает широкую строку символов, тоже с удовольствием примет эти суррогаты.
Единственное, о чем нужно знать, это то, что теперь длина символа строки (очевидно) больше не просто число 16-битных слов. Но это было неправильное предположение, во всяком случае.

Печальная правда

В действительности, во многих (большинство? все?) системах вы получаете только одно сообщение WM_CHAR с wParam, содержащим младшие 16 бит key code. Что является могучим штрафом для чего-либо в BMP, но отстой в противном случае.

Я проверил это как с помощью кодов клавиш Alt-keypad, так и с созданием пользовательской раскладки клавиатуры, которая генерирует кодовые точки вне BMP. В любом случае принимается только один WM_CHAR, содержащий младшие 16 бит символа. Верхние 16 бит просто выбрасываются.

Чтобы ваша программа правильно работала с Unicode на 100%, вы, очевидно, должны использовать диспетчер методов ввода (ImmGetCompositionStringW), что является неприятным и плохо документированным. Для меня лично это просто означает: "ОК, винт". Но если вы заинтересованы в том, чтобы быть на 100% правильным, посмотрите исходный код любого редактора, используя Scintilla (ссылка на строку), которая делает именно это и работает отлично.