Руководство программиста в Photon (953920), страница 68
Текст из файла (страница 68)
Unicode сконструирован на наборе символов ASCII, но использует 32-битовое кодирование для поддержки полностью многоязычного текста. Он не требует эскейп-последовательностей или управляющих кодов при задании любого символа на любом языке. Заметьте, что кодировка Unicode пригодна для трактовки всех символов – будь то буквы алфавита, иероглифы или символы – совершенно одинаковым образом.
При проектировании драйвера клавиатуры и механизмов обработки символов мы опирались на расширение Х11 клавиатуры и стандарты ISO 9995 и 10646-1.
Широкие и многобайтовые символы
ANSI С включает в себя следующие понятия:
широкий символ | Символ, представленный как значение типа wchar_t, которое обычно больше чем char |
многобайтовый символ | Последовательность из одного или более байтов, представляющих символ, хранимый в массиве char. Количество байтов зависит от символа |
широкосимвольная строка | Массив типа wchar_t |
многобайтовый символ | Последовательность многобайтовых символов, хранящаяся в массиве char |
Unicode
Unicode является 32-битовой схемой кодирования:
Он упаковывает большинство международных символов в широкосимвольном представлении (два байта на символ)
Коды меньше 128 определяют те же символы, что и стандарт ANSII.
Коды между 128 и 255 определяют те же символы, что и в наборе символов ISO 8859-1.
Существует область для частного использования в диапазоне от 0хЕ000 до 0хF7FF; Photon отображает её следующим образом:
Глифы | Диапазон |
Неотображаемые клавиши | 0хF000 – 0xF0FF |
Курсорный шрифт | 0xE900 – 0xE9FF |
Значение символов Unicode см. в файле /usr/include/photon/PkKeyDef.h. Более подробно об Unicode см. на вебсайте консорциума Unicode по адресу www.unicode.org.
UTF-8 кодирование
Известный прежде как UTF-2, формат преобразования UTF-8 (для "8-битовой формы") спроектирован для использования данных в символах Unicode в 8-битовом окружении UNIX. Каждое значение Unicode кодируется как многобайтовая последовательность UTF-8.
Вот некоторые из основных особенностей UTF-8:
-
В UTF-8 представление кодов менее 128 такое же, как в стандарте ASCII, так что любая ASCII строка является также корректной строкой UTF-8 и представлена теми же символами.
-
Значения ASCII, напротив, не участвуют в UTF-8 преобразовании, обеспечивая тем самым полную совместимость с исторически сложившимися файловыми системами, в которых лексический анализ производится на уровне байтов ASCII кодировки.
-
UTF-8 кодирует набор символов стандарта ISO 8859-1 как двухбайтовые последовательности.
-
UTF-8 упрощает преобразование в и из текста в Unicode.
-
Первый байт указывает число следующих байтов в многобайтовой последовательности, позволяя эффективно заранее выполнять лексический анализ.
-
Эффективным является нахождение начала символа в произвольном месте побайтового потока, поскольку Вам надо чаще всего просмотреть четыре байта вперёд, чтобы найти легко распознаваемый инициирующий байт. Например,
isInitialByte = ((byte & 0xC0) !=0x80);
-
UTF-8 является довольно компактным в смысле количества байтов, использующихся при кодировке.
В настоящее время кодировка такова:
-
Для многобайтовых кодировок первый байт устанавливает 1 в числе битов высокого порядка, равным числу байтов, использованных в кодировании; бит после них устанавливается в 0. Например, двухбайтовая последовательность начинается с 110 в первом байте.
-
Для всех последующих байтов многобайтной кодировки первые два бита – это 10. Оставшееся значение байта в многобайтовом кодировании всегда больше или равно 0x80.
В следующей таблице показана бинарная форма каждого байта кодирования и минимальное и максимальное значения символов, представленных 1-, 2-, 3-, и 4-байтовым кодированием:
Длина | Первый байт | Следующие байты | Минимальное значение | Максимальное значение |
Один байт | 0xxxxxxx | нет | 0x0000 | 0x007F |
Два байта | 110xxxxx | 10xxxxxx | 0x0080 | 0x07FF |
Три байта | 1110xxxx | 10xxxxxx | 0x0800 | 0xFFFF |
Четыре байта | 11110xxx | 10xxxxxx | 0x10000 | 0x10FFFF |
-
Действительное содержание многобайтового кода (т.е. широкосимвольного кода) является соединением ХХ битов в коде. Двухбайтовый код с кодировкой 11011111 10000000 кодирует широкий символ 11111000000.
-
Там, где возможен более чем один способ кодирования значения (как, например, 0), законным является только наикратчайший. Нулевой символ всегда является одним байтом.
Функции преобразования
В наших библиотеках языка С предполагается, что "широкий символ" является Unicode, и "мультибайт" – это UTF-8 в принятой по умолчанию локализации. Тип wchar_t определён как беззнаковый 32-битовый тип, и функции wctomb() и mbtowc() осуществляют UTF-8 кодирование в принятой по умолчанию локализации.
Многобайтовые символы в библиотеке С являются UTF-8 в принимаемой по умолчанию локализации; в различных локализациях многобайтовые символы могут использовать различную кодировку.
Вы можете использовать следующие функции (описанные в "Справочнике библиотечных функций QNX") для преобразования между широкосимвольной и многобайтовой кодировками:
mblen() | Вычисляет длину многобайтовой строки в символах |
mbtowc() | Преобразует многобайтовый символ в широкий символ |
mbstowcs() | Преобразует многобайтовую строку в широкосимвольную строку |
Библиотеки Photon'а используют многобайтовые UTF-8 строки символов: любая функция, обрабатывающая строки, должна быть в состоянии обработать действительную строку UTF-8, и функции, возвращающие строку, могут возвращать строку многобайтовых символов. Это также применяется к ресурсам виджета. Графические драйверы и сервер шрифтов предполагают, что все строки используют UTF-8.
Главная библиотека Photon'а ph предлагает следующие не-ANSI функции (описанные в "Справочнике библиотечных функций Photon'а") для работы с многобайтовыми UTF-8 и широкими символами:
utf8len() | Подсчитывает байты в UTF-8 символе |
utf8strblen() | Находит количество UTF-8 символов во фрагменте строки |
utf8strchr() | Ищет UTF-8 символ в строке |
utf8strichr() | Ищет UTF-8 символ в строке, игнорируя регистр |
utf8strirchr() | Ищет в обратном направлении UTF-8 символ в строке, игнорируя регистр |
utf8strlen() | Находит длину строки UTF-8 символов |
utf8strnchr() | Ищет UTF-8 символ во фрагменте строки |
utf8strncmp() | Сравнивает фрагмент строки UTF-8 символов |
utf8strndup() | Создаёт копию фрагмента строки UTF-8 символов |
utf8strnichr() | Ищет UTF-8 символ во фрагменте строки, игнорируя регистр |
utf8strnlen() | Находит количество байт, использованных для строки UTF-8 символов |
utf8strrchr() | Ищет в обратном направлении UTF-8 символ в строке |
utf8towc() | Преобразует UTF-8 символ в широкосимвольный код |
wctolower() | Возвращает эквивалент широкого символа в нижнем регистре |
wctoutf8() | Преобразует широкосимвольный код в UTF-8 символ |
Эти функции определены в <utf8.h> (заметьте, это не <photon/utf8.h>) и используют UTF-8 кодировку, не принимая во внимание, каковой является текущая локализация. UTF8_CUR_MAX определяет максимальное число байтов в UTF-8 символе.
Другие кодировки
Если вашему приложению требуется работать с другими символьными кодировками, Вам надо преобразовать в и из UTF-8. Символьные наборы определены в файле /usr/photon/translations/charsets и включают:
-
Big5 (Chinese)
-
Cyrillic (KOI8-R)
-
Japanese (EUC)
-
Japanese (Shift – JIS)
-
Korean (EUC)
-
Western (ISO 8859-1)
Предлагаются следующие функции преобразования, описанные в "Справочнике библиотечных функций Photon'а":
PxTranslateFromUTF() | Преобразовывает символы из UTF-8 |
PxTranslateList() | Создаёт список всех поддерживаемых преобразований символов |
PxTranslateSet() | Устанавливает новый символьный набор для преобразования |
PxTranslateStateFromUTF() | Преобразует символы из UTF-8, используя внутренний буфер состояния |
PxTranslateStateToUTF() | Преобразует символы в UTF-8, используя внутренний буфер состояния |
PxTranslateToUTF() | Преобразует символы в UTF-8 |
PxTranslateUnknown() | Управляет тем, как обрабатывать неизвестные кодировки |
Эти функции поддерживаются только в статической форме в библиотеке phexlib Photon'а. Прототипы находятся в файле <photon/PxProto.h>.
Драйверы клавиатуры
Драйвер клавиатуры управляется таблично; он обрабатывает любую клавиатуру со 127 или немного меньшим количеством физических клавиш.
Нажатие клавиши сохраняется в структуре типа PhKeyEvent_t (описанной в "Справочнике библиотечных функций Photon'а").
Пример: текстовые виджеты
Текстовые виджеты используют область key_sym для отображаемых символов. Эти виджеты также проверяют её для обнаружения движения курсора. Например, если содержанием области является Pk_Left, курсор движется влево. key_sym имеет значение Pk_Left как для клавиши "курсор влево", так и для клавиши "курсор влево" на цифровой клавишной панели (предполагается, что NumLock выключено).
Слепые клавиши (dead keys) и скомпонованные последовательности
QNX поддерживает "слепые" клавиши и "скомпонованные" клавиатурные последовательности для генерации key_syms, которые отсутствуют на клавиатуре. Область key_sym применима только к нажатию клавиши, а не к её отпусканию, чтобы гарантировать, что Вы получите только один символ, а не два.
Например, если клавиатура имеет слепую клавишу ударения (например, ` ), и пользователь нажимает её следом за е, Key_sym принимает значение "е" со знаком ударения (è). Если клавиша "е" не отпущена, и затем была нажата другая группа клавиш (или продолжена последовательность, или последовательность слепой клавиши), key_syms будет сохранять это в стеке до завершающего отпускания.
Если в ходе скомпонованной последовательности нажата неверная клавиша, драйверы клавиатуры генерируют key_syms для всех промежуточных клавиш, а не для действительного нажатия или отпускания.
Скомпонованные последовательности Photon'а
В Photon'е задействованы стандартные скомпонованные последовательности. Если Ваша клавиатура не включает в себя символы из стандартной таблицы кодов ASCII, Вы можете генерировать символ, используя скомпонованные последовательности. Например, символ ó может быть сгенерирован нажатием клавиши <Alt>, следом – клавиша <´>, и следом клавиша <о>.
Это не сочетание клавиш; нажимайте и отпускайте каждую клавишу одна за другой.