Sign in Join
Wiki copytemporary

FPC Unicode support/ru: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Введение
22
33До FPC 2.6.x включительно, RTL базировалась на своих аналогах в Turbo Pascal и Delphi 7. Это значит, что её функциональность была в основном построена на обработке строковых типов *shortstring*, *ansistring* и *pchar*. Ни один из этих типов не несёт какой либо информации о кодировке, связанной с ним, но неявно подразумевается, что строки находятся в "кодировке системы по умолчанию" и могут быть переданы на вызовы API операционной системы без преобразований.
44
55В Delphi 2009, Embarcadero полностью переключил RTL на тип *UnicodeString*, использующий представление строк UTF-16. Дополнительно были введены типы AnsiString, содержащие маркировку кодовой страницы. Это означает, что строковые переменные AnsiStrings, относящиеся к таким типам, всегда содержат информацию о кодовой странице, указывающую, как данные должны быть интерпретированы.
66
77Поддержка на уровне языка в FPC для таких строковых типов на настоящий момент уже доступна в текущих версиях компилятора "для разработчиков" (FPC 2.7.1/trunk). Поддержка на уровне RTL на настоящий момент неполная. На данной странице представлен обзор поведения таких строковых типов в отношении кодовых страниц, текущий уровень поддержки в RTL, а также возможные будущие пути, которыми эта поддержка может быть улучшена.
88
99# Обратная совместимость
1010
1111Весь существующий код, работающий в рамках стандартного подхода (*), предназначенный для предыдущих версий FPC, изменений не потребует. Он должен продолжать работать без каких либо модификаций под новыми версиями FPC. Условия этого "стандартного" использования множества переменных с кодовой страницей по умолчанию и их значений описаны ниже.
1212
1313(*) это в первую очередь означает: вы никогда не сохраняете данные в ansistring-ах с маркировкой кодовой страницы, отличающейся от системной кодовой страницы по умолчанию, и последовательно передаете строку в неизменном виде процедуре из FPC RTL. Например, в текущем коде Lazarus обычно производится вызов UTF8ToAnsi() перед передачей его строк подпрограммам FPC RTL.
1414
1515# Кодовые страницы
1616
1717Кодовая страница определяет, как именно индивидуальные байты строки должны интерпретироваться, т.е. какая буква, символ или иной графический примитив соответствует каждому байту или последовательности байтов.
1818
1919## Идентификаторы кодовых страниц
2020
2121Идентификатор кодовой страницы всегда хранится как значение типа *TSystemCodePage*, являющимся псевдонимом (alias) для [[Word]]. Значение представляет собой соответствующую кодовую страницу, как это определено в \[<http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85>).aspx Microsoft Windows\]. Дополнительно используются следующие три специальных значения кодовых страниц:
2222
2323- CP_ACP: это значение представляет собой текущий набор "системной кодовой страницы по умолчанию". См. дополнительную информацию в разделе #Настройки кодовой страницы.
2424- CP_OEM: это значение представляет собой кодовую страницу OEM. На платформе Windows оно соответствует кодовой странице, используемой консолью (т.е. окном программы cmd.exe). На других платформах это значение интерпретируется точно так же, как CP_ACP.
2525- CP_NONE: это значение указывает, что никакая информация о кодовой странице не ассоциирована со строковыми данными. Результат любой прямой или косвенной операции по конвертированию этих данных в другую кодовую страницу не определён.
2626
2727Примечание: идентификаторы кодовых страниц отличаются от имён кодовых страниц, используемых в директивах *[{\$codepage xxx}](http://www.freepascal.org/docs-html/prog/progsu88.html)* (доступных и в текущем стабильном FPC). Имена кодовых страниц для директивы берутся из специального перечня, в котором представлены такие идентификаторы, как *cp866*, *cp1251* и *utf8*.
2828
2929## Настройки кодовой страницы
3030
3131Модуль system содержит глобальные переменные, указывающих кодовую страницу по умолчанию, использующуюся для некоторых операций.
3232
3333### DefaultSystemCodePage
3434
3535- **Назначение**: определяет, как интерпретируется CP_ACP
3636- **Начальное значение**:
3737 - Windows: результат системного вызова *GetACP*, который возвращает кодовую страницу Windows ANSI.
3838 - iOS: UTF-8
3939 - Unix (кроме iOS): Базируется на текущих установках переменных окружения *LANG* или *LC_CTYPE*. Обычно это UTF-8, но нет никаких гарантий этого.
4040 - Другие платформы: CP_ACP (эти платформы на настоящий момент не поддерживают несколько кодовых страниц, и жестко привязаны к использованию своих, специфичных для операционной системы кодовых страниц во всех случаях)
4141- **Модификация**: Можно изменить значение переменной вызовом *SetMultiByteConversionCodePage(CodePage: TSystemCodePage)*
4242- **Примечания**: Поскольку значение этой переменной может быть изменено, не стоит полагаться на неё для определения действительной "системной кодовой страницы по умолчанию" операционной системы (даже в случае, если вы делаете это непосредственно после запуска программы, вы не можете быть уверены, что какие либо модули (unit) не внесли изменения в эту переменную при выполнении своих блоков инициализации).
4343
4444### DefaultFileSystemCodePage
4545
4646- **Назначение**: определяет кодовую страницу, на которую переводятся имена файлов, каталогов и путей доступа перед вызовами API операционной системы, ***если*** RTL использует однобайтовый OS API для этих целей на текущей платформе. Эта кодовая страница также используется для промежуточных операций, касающих файловых путей внутри RTL перед тем, как сделать вызов OS API. Эта переменная отсутствует в Delphi и была введена в FPC для того, чтобы сделать возможным изменение значения *DefaultSystemCodePage* без разрушения интерфейсов RTL с вызовами функций API ОС, касающихся файловой системы.
4747- **Начальное значение**:
4848 - Windows: UTF-8, поскольку RTL использует вызовы API операционной системы в кодировке UTF-16 (при этом данные не теряются в операциях промежуточного преобразования).
4949 - macOS и iOS: UTF-8 (так определено Apple)
5050 - Unix (исключая macOS и iOS): DefaultSystemCodePage, поскольку кодировка имён файлов не определена на платформах Unix (имена файлов являются нетипизированным байтовым массивом, который может быть интерпретирован любым способом; не гарантируется, что это правильный UTF-8)
5151 - Другие платформы: то же самое, что в DefaultSystemCodePage
5252- **Модификация**: можно изменить это значение вызовом *SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage)*
5353- **Примечания**: настройки Unix/macOS/iOS учитываются только в случае, когда установлен менеджер широких строк *cwstring*, иначе DefaultFileSystemCodePage после запуска программы будет иметь то же значение, что и DefaultSystemCodePage.
5454
5555### DefaultRTLFileSystemCodePage
5656
5757- **Назначение**: определяет кодовую страницу, в кодировку которой транслируются имена файлов/путей перед тем, как они будут возвращены из процедур RTL, возвращающих строки формата RawByteString. Например, эта переменная используется для преобразования имён файлов/путей, возвращаемых RawbyteString-версиями функций *SysUtils.FindFirst* и *System.GetDir*. Основная причина их существования - обеспечение обратной совместимости с ранними версиями FPC, в которых всегда возвращались строки в кодировке, используемой для вызова функций API операционной системы, работающими с однобайтовой кодировкой (значение этой кодировки сейчас сохранено в *DefaultSystemCodePage*).
5858- **Начальное значение**
5959 - Windows: DefaultSystemCodePage, для совместимости с предыдущими версиями.
6060 - macOS и iOS: UTF-8, для совместимости с предыдущими версиями (на самом деле оно и раньше было UTF-8, результаты вызовов файлового API операционной системы не подвергались преобразованию).
6161 - Unix (кроме macOS и iOS): DefaultSystemCodePage, по той же причине, что обозначена для DefaultFileSystemCodePage. Установка значения, отличающегося от DefaultFileSystemCodePage - очень плохая идея для этих платформ, любое преобразование кодовых страниц может разрушить строки, поскольку их начальная кодировка неизвестна.
6262- **Модификация**: можно изменить значение этой переменной вызовом *SetMultiByteRTLFileSystemCodePage(CodePage: TSystemCodePage)*
6363- **Замечания**: те же, что и для DefaultFileSystemCodePage.
6464
6565# Строки
6666
6767## Строковые/символьные типы
6868
6969### Shortstring
7070
7171Кодовая страница данных типа shortstring неявно подразумевается как CP_ACP и, следовательно, будет равна текущему значению переменной DefaultSystemCodePage.
7272
7373### PAnsiChar/AnsiChar
7474
7575Эти типы - то же самое, что и старые типы PChar/Char. Во всех режимах компилятора, кроме *{\$mode delphiunicode}*, PChar/Char по-прежнему остаются псевдонимами для PAnsiChar/AnsiChar. Кодовая страница таких строк неявно подразумевается CP_ACP и, следовательно, будет равна текущему значению переменной DefaultSystemCodePage.
7676
7777### PWideChar/PUnicodeChar и WideChar/UnicodeChar
7878
7979Эти типы остались неизменными. WideChar/UnicodeChar могут содержать одиночную кодовую единицу UTF-16, в то время как PWideChar/PUnicodeChar указывают либо на одну кодовую единицу, либо на массив кодовых единиц UTF-16.
8080
8181В режиме *{\$mode delphiunicode}*, PChar будет псевдонимом для PWideChar/PUnicodeChar и Char будет псевдонимом для WideChar/UnicodeChar.
8282
8383### UnicodeString/WideString
8484
8585Эти типы остались такими же, как и в предыдущих версиях:
8686
8787- *Widestring* - то же самое что и "COM BSTR" под Windows, и алиас для UnicodeString для всех других платформ. Строковые данные этого типа представлены с использованием UTF-16.
8888- *UnicodeString* - строка со счётчиком ссылок и максимальной длиной high(SizeInt) кодовых единиц UTF-16.
8989
9090### Ansistring
9191
9292Семейство AnsiString - строковые типы со счетчиком ссылок и максимальной длиной high(SizeInt) байт. Кроме того, для каждой переменной такого типа сейчас сохраняется информация о кодовой странице, ассоциированной с данными.
9393
9494Важнее всего понять, новое для переменной типа AnsiString в том, что она одновременно может обладать декларированной/статической/основной/по умолчанию кодовой страницей (далее по тексту *статической кодовой страницей*) и динамической кодовой страницей. Статическая кодовая страница сообщает компилятору, что при присвоении какого либо значения переменной типа AnsiString, он должен сначала конвертировать данные в эту статическую кодовую страницу (кроме случая, когда она CP_NONE, см. ниже раздел #RawByteString). Динамическая кодовая страница является характеристикой каждого отдельного экземпляра переменной типа AnsiString, такой же, как длина и счетчик ссылок - она определяет действительную кодовую страницу строковых данных, в текущий момент содержащихся в переменной типа AnsiString.
9595
9696#### Статическая кодовая страница
9797
9898Статическая кодовая страница для AnsiString может быть назначена единственным способом - объявлением нового типа:
9999
100100``` pascal
101101type
102102 CP866String = type AnsiString(866); // обратите внимание на добавочное "type"
103103```
104104
105105Статическая кодовая страница переменной, объявленной просто как *AnsiString* (без указания кодовой страницы) - будет CP_ACP. По сути, тип AnsiString теперь семантически определён в unit System следующим образом:
106106
107107``` pascal
108108type
109109 AnsiString = type AnsiString(CP_ACP);
110110```
111111
112112Еще одним предопределённым типом для AnsiString(X) в unit System является UTF8String:
113113
114114``` pascal
115115type
116116 UTF8String = type AnsiString(CP_UTF8);
117117```
118118
119119После того, как вы объявили собственный тип AnsiString(X), вы можете использовать его наименование для объявления переменных, параметров, полей и т. д. как обычно.
120120
121121Обратите внимание, что CP_UTF16 и CP_UTF16BE не будут допустимыми кодовыми страницами для строк AnsiString. Результат объявления AnsiString с такими кодовыми страницами не определён.
122122
123123#### Динамическая кодовая страница
124124
125125Если строка со статической кодовой страницей X1 присваивается строке со статической кодовой страницей X2, и X1 не равно X2, строковые данные обычно сначала конвертируются в кодовую страницу X2 перед присвоением, и результирующая динамическая кодовая страница строки-результата будет X2. При присвоении строки переменной типа AnsiString с неуказанной кодовой страницей (= AnsiString(CP_ACP)) или ShortString, строковые данные будут конвертированы в DefaultSystemCodePage. Динамическая кодовая страница такой переменной типа AnsiString(CP_ACP) с момента присвоения поменяется на текущее значение DefaultSystemCodePage (например, 1251 для кодовой страницы Windows-1251), несмотря на то, что статическая кодовая страница такой переменной CP_ACP (Константа, обозначающая которую, не равна 1251). Это только один из примеров случая, когда статическая кодовая страница может отличаться от динамической кодовой страницы. В последующие разделах будет описано больше таких сценариев.
126126
127127Внимание: как объяснялось выше, произойдет или нет возможное преобразование кодовых страниц, зависит только от значения *статических кодовых страниц* строк, участвующих в операции. Это значит, что если вы присваиваете одну переменную типа AnsiString(X) другой переменной типа AnsiString(X) и динамическая кодовая страница присваиваемой строки отличается от X, строковые данные *не будут* конвертированы в кодовую страницу X перед присваиванием.
128128
129129#### RawByteString
130130
131131Тип RawByteString объявлен следующим образом:
132132
133133``` pascal
134134type
135135 RawByteString = type AnsiString(CP_NONE);
136136```
137137
138138Как объяснено ранее, результат конверсии из/в кодовую страницу CP_NONE не определён. Поскольку нет смысла объявлять в RTL тип, поведение которого не определено, поведение строк типа RawByteString несколько отличается от других типов семейства AnsiString(X).
139139
140140При первом приближении, *RawByteString* можно рассматривать как "нетипизированный AnsiString": присваивание переменной типа RawByteString строки типа AnsiString(X) будет выглядеть так же, как если переменной типа AnsiString(X) присвоить другую переменную AnsiString(X) с тем же самым значением X: никаких преобразований кодовых страниц или копирования не произойдёт, просто увеличится счетчик ссылок.
141141
142142Не так бросается в глаза, что в случае, когда переменная типа RawByteString присваивается переменной типа AnsiString(X), случится следующее: никакого копирования или преобразования кодовых страниц не происходит, лишь увеличится счётчик ссылок. Обратите внимание, это означает, что результаты функций, возвращающих RawByteString никогда не преобразуются в статическую кодовую страницу переменной-назначения. Это - еще один пример случая, когда динамическая кодовая страница AnsiString(X) принимает значение, не совпадающее с её статической кодовой страницей.
143143
144144Данный тип преимущественно используется, чтобы объявить *const*, *constref* и значения параметров, ожидающих любое значение типа AnsiString(X) без его преобразования в предопределённую статическую кодовую страницу. Обратите внимание, что если вы это сделаете, процедура, принимающая такие параметры, должна быть в состоянии обработать строки любой допустимой динамической кодовой страницы.
145145
146146Параметры *var* и *out* также могут быть объявлены как *RawByteString*, но в этом случае компилятор выдаст ошибку, если на эти параметры будет отображена переменная типа AnsiString(X), чья статическая кодовая страница отличается от CP_NONE. Такое поведение согласуется в целом с трактовкой параметров *var* и *out*: они требуют полного совпадения типов переменных, передаваемых им. Вы можете заключить аргумент в декларацию явного приведения типов RawByteString() для того, чтобы воспрепятствовать появлению сообщения об ошибке, но при этом должны быть готовы к тому, что возвращаемая строка может иметь любую динамическую кодовую страницу.
147147
148148------------------------------------------------------------------------
149149
150-Прим.перев.: Как можно так запутать такие простые вещи?! Весьма простое определение дается в небезызвестной статье на сайте Эмбаркадеро [Delphi в мире Юникода, часть II: новые возможности RTL и классы для поддержки Юникода](https://edn.embarcadero.com/article/38582#9%D0%94%D1%80%D1%83%D0%B3%D0%B8%D0%B5%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8RTL%D0%B4%D0%BB%D1%8F%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4%D0%B0):<i>"... в RTL введен тип RawByteString, который представляет собой строку, не связанную с какой-либо кодировкой... Назначение типа RawByteString – сделать возможной передачу строковых данных для любой кодовой страницы без каких-либо преобразований кодировки. Это очень полезно для подпрограмм, для которых кодировка не имеет значения, вроде побайтового поиска в строке."</i>
150+Прим.перев.: Как можно так запутать такие простые вещи?! Весьма простое определение дается в небезызвестной статье на сайте Эмбаркадеро [Delphi в мире Юникода, часть II: новые возможности RTL и классы для поддержки Юникода](https://edn.embarcadero.com/article/38582#9%D0%94%D1%80%D1%83%D0%B3%D0%B8%D0%B5%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8RTL%D0%B4%D0%BB%D1%8F%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4%D0%B0):"... в RTL введен тип RawByteString, который представляет собой строку, не связанную с какой-либо кодировкой... Назначение типа RawByteString – сделать возможной передачу строковых данных для любой кодовой страницы без каких-либо преобразований кодировки. Это очень полезно для подпрограмм, для которых кодировка не имеет значения, вроде побайтового поиска в строке."
151151
152152------------------------------------------------------------------------
153153
154154## Сцепление (конкантенации) строк
155155
156156Как правило, в Паскале тип результата выражения не зависит от того, как этот результат используется впоследствии. Так, умножение двух чисел longint на 32-битной платформе и присваивание результата переменной типа int64 означает выполнение умножения с использованием 32-битной арифметики, и лишь конечный результат конвертируется в 64 бита.
157157
158158Для строк с маркировкой кодовой страницы это правило не действует: сцепление двух или более строк всегда производится без каких либо потерь данных, и лишь после завершения операции строка-результат конвертируется в статическую кодовую страницу назначения (что может привести к потере данных).
159159
160160Присвоение результата конкантенации переменной типа RawByteString производится особым образом:
161161
162162- если все строки, участвующие в операции, имели одинаковую динамическую кодовую страницу, результат также будет иметь эту кодовую страницу
163163- в иных случаях результат будет преобразован в CP_ACP (возможно, в будущем такое поведение изменится, так как оно выглядит не очень практичным)
164164
165165## Строковые константы
166166
167167Строковые константы обрабатываются FPC следующим образом:
168168
169169- Если в файле есть директива *{\$codepage xxx}* (Например, `{$codepage UTF8}`), тогда строковые константы интерпретируются в соответствии с этой кодовой страницей, иначе:
170170- Если файл начинается с маркировки UTF-8 BOM, тогда строковые константы интерпретируются в качестве строк UTF-8, иначе:
171171- строковые константы копируются без каких либо преобразований во внутренний буфер и интерпретируются в виде символов с использованием следующих кодовых страниц:
172172 - *DefaultSystemCodePage* ***компьютера, на котором компилятор запущен***, когда директива *{\$modeswitch systemcodepage}* активна (то есть, компилирование одного и того же исходного кода на различных системах может приводить к тому, что строковые константы будут интерпретированы по разному; упомянутая директива введена для совместимости с Delphi и находится в состоянии «включено» по умолчанию в режиме *{\$mode delphiunicode}*)
173173 - CP_ACP в случае, когда директива *{\$modeswitch systemcodepage}* не активна (для совместимости с предыдущими версиями FPC)
174174
175175Во всех случаях, кроме последнего, действительная кодовая страница файла-исходника известна. Эта информация используется, когда компилятор вынужден конвертировать строковые константы в другую кодовую страницу. Для последнего же случая по умолчанию предполагается следующее: подразумевается, что строки принадлежат к кодовой странице 28591 (*ISO 8859-1 Latin 1; Western European*). Это предположение, или, в противоположность ему, фактическая кодовая страница и есть термин, обозначенный в тексте ниже как *кодовая страница исходника*.
176176
177177Когда строковая константа присваивается переменной типа AnsiString(X) в программном коде или как часть типизированной константы или при инициализации переменной, тогда
178178
179179- если X = CP_NONE (т. е. результат - переменная типа RawByteString), результат будет таким же, как если бы строковая константа была назначена переменной типа AnsiString(CP_ACP)
180180- если X = CP_ACP и кодовая страница строковой константы отличается от CP_ACP, строковая константа конвертируется во время компиляции в кодовую страницу исходника. Если кодовая страница исходника также CP_ACP, строка будет сохранена в программе в неизменной форме с маркёром кодовой страницы CP_ACP, и следовательно, ее значение и интерпретация будут зависеть от действующего значения глобальной переменной *DefaultSystemCodePage* во время исполнения. Это обеспечивает совместимость со старыми версиями FPC при присвоении строковых констант переменным типа AnsiString без использования директивы *{\$codepage xxx}* или маркировки UTF-8 BOM.
181181- при других значениях X строковая константа конвертируется во время компиляции в кодовую страницу X
182182
183183Аналогично, если строковая константа присваивается переменной типа UnicodeString, она конвертируется во время компиляции из кодовой страницы исходника в UTF-16.
184184
185185При присвоении переменным типов ShortString и PChar выполняются те же действия, что и для переменной типа AnsiString(CP_ACP).
186186
187187Обратите внимание, что именованные строковые константы будут подвержены конверсии во время компиляции при каждом присвоении переменным строковых типов, в зависимости от кодовой страницы, которую эти переменные используют. Что означает отсутствие выигрыша в скорости компиляции при использовании одной и той же строковой константы в различных кодовых страницах и строковых контекстах, экономия будет крайне незначительной.
188188
189189Из сказанного выше следует, что для обеспечения предсказуемой интерпретации строковых констант в исходном коде, лучше всего включить явную директиву *{\$codepage xxx}* (или использовать ее эквивалент в командной строке *-Fc*), или сохранять файлы с исходниками в UTF-8, с маркировкой BOM в начале файла.
190190
191191## Индексация строк
192192
193193Никаких изменений в индексацию строк не добавилось. Каждый элемент строки типа UnicodeString/WideString - это два байта, каждый элемент строки всех других строковых типов - один байт. Механизм индексации строк полностью игнорирует кодовые страницы и композиционные кодовые точки.
194194
195195# Изменения в RTL
196196
197197Для того, чтобы полностью гарантировать целостность данных в присутствии строк, маркированных кодовой страницей, все процедуры в RTL и пакетах, допускающие параметры типа *AnsiString*, должны быть адаптированы. Причина в том, что если их параметры останутся просто типа *AnsiString*, то любая строка с отличающейся статической кодовой страницей будет сконвертирована в *DefaultSystemCodePage* при передаче в эти параметры. Это может привести к искажению и потере данных.
198198
199199На настоящее время, основные процедуры, работающие с доступом к файловой системе, были обновлены с целью предотвращения искажения и потери данных. Ниже приведен полный список всех процедур, сохраняющих кодировку строк в FPC 2.7.1 и более поздних. Если иное не указано особо, все эти процедуры также имеют перегруженные (overload) версии, воспринимающие параметры типа 'UnicodeString''.
200200
201201- **System**: FExpand, LowerCase, UpperCase, GetDir, MKDir, ChDir, RMDir, Assign, Erase, Rename, процедуры стандартного ввода/вывода (Read/Write/Readln/Writeln/Readstr/Writestr), Insert, Copy, Delete, SetString
202202- **ObjPas** (автоматически подключается в режимах Delphi и ObjFPC): AssignFile
203203- **SysUtils**: FileCreate, FileOpen, FileExists, DirectoryExists, FileSetDate, FileGetAttr, FileSetAttr, DeleteFile, RenameFile, FileSearch, ExeSearch, FindFirst, FindNext, FindClose, FileIsReadOnly, GetCurrentDir, SetCurrentDir, ChangeFileExt, ExtractFilePath, ExtractFileDrive, ExtractFileName, ExtractFileExt, ExtractFileDir, ExtractShortPathName, ExpandFileName, ExpandFileNameCase, ExpandUNCFileName, ExtractRelativepath, IncludeTrailingPathDelimiter, IncludeTrailingBackslash, ExcludeTrailingBackslash, ExcludeTrailingPathDelimiter, IncludeLeadingPathDelimiter, ExcludeLeadingPathDelimiter, IsPathDelimiter, DoDirSeparators, SetDirSeparators, GetDirs, ConcatPaths, GetEnvironmentVariable
204204- **Unix**: процедуры fp*(), относящиеся к операциям с файловой системой (не имеют перегруженных экземпляров с параметрами типа *UnicodeString*), POpen
205205- **DynLibs**: все процедуры
206206
207207# Что необходимо сделать с RTL
208208
209209Поскольку приведённый выше перечень содержит все процедуры, подвергшиеся модификации, остальные процедуры RTL еще не поддерживают произвольные кодовые страницы. Этот раздел содержит перечень подводных камней, найденных отдельными людьми, и если это возможно, обходных путей. Обратите внимание, что процедуры, не попавшие ни в этот список, ни в список выше, использовать столь же опасно, как и перечисленные здесь.
210210
211211## TFormatSettings и DefaultFormatSettings
212212
213213Тип аргументов *ThousandSeparator* и *DecimalSeparator* - AnsiChar. Это означает, что если переменная *DefaultSystemCodePage* имеет значение UTF-8 и разделитель текущей локали более одного байта длиной в этой кодировке, такие поля недостаточны для его представления. В качестве примера можно привести символы неразрывных пробелов, используемые во французской и русской локали для отображения *ThousandSeparator*.
214214
215215# Старые/устаревшие разделы
216216
217217> **Warning:** Эти разделы сохранены в исторических целях - пожалуйста обновите разделы выше с этой информацией, если она до сих пор используется. Начиная с FPC 2.7 (текущая разрабатываемая версия), расширенная поддержка Unicode была реализована.
218218
219219## Изменения, видимые пользователям
220220
221221Полная поддержка строк, маркированных кодовой страницей невозможна без нарушения существующего кода. Ниже приведен список, который пытается обобщить наиболее важные изменения, видимые для пользователя.
222222
223223- Заголовок строки получил два новых поля: кодировка и размер элемента. На 32-битных платформах это увеличило размер заголовка на 4 байта, на 64-битных платформах - на 8 байт.
224224- WideCharLenToString, UnicodeCharLenToString, WideCharToString, UnicodeCharToString и OleStrToString теперь возвращают UnicodeString вместо Ansistring, как было ранее.
225225- тип параметра dest функций WideCharLenToString и UnicodeCharLenToString изменён с Ansistring на Unicodestring
226226- UTF8ToAnsi и AnsiToUTF8 теперь принимают RawByteString
227227
228228# См. также
229229
230230- [[Character and string types/ru|Символьные и строковые типы]]
231231- [[unicode use cases]]
232232- [[LCL Unicode Support/ru|Поддержка Юникода в Lazarus]]
233233- Предложение: [[not Delphi compatible enhancement for Unicode Support]]
234234
235235---
236236*From the Free Pascal wiki, page "FPC Unicode support/ru", as it stood on 2019-12-22 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
237237Category: FPC/ru
238238Category: Russian
239239Category: Unicode/ru

Back to history