Sign in Join
Wiki copytemporary

LCL Unicode Support/de: what changed

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

OldNewLine
11## Einleitung
22
33Mit der Version 0.9.25 unterstützt Lazarus Unicode auf allen Plattformen außer auf Gtk 1. Diese Seite liefert Informationen für Anwender, die Strategie der Entwickler und eine Beschreibung der Konzepte und deren Anwendungsdetails.
44
55## Anweisungen für Benutzer
66
77In Unicode-Interfaces - das anzumerken ist wichtig - ist nicht alles in Unicode. Die Free Pascal Laufzeitbibliothek (RTL) und die Free Pascal FCL-Bibliothek sind ANSI. Es liegt in der Verantwortung des Entwicklers zu wissen, welche Kodierung die Zeichenketten verwenden, und eine saubere Umwandlung durchzuführen zwischen Bibliotheken mit unterschiedlichen Kodierungen.
88
99Normalerweise erfolgt eine Kodierung pro Bibliothek (d. h. eine dynamische Bibliothek 'dll' oder ein Lazarus-Package). Jede Bibliothek erwartet 1 einheitliche Art von Kodierung, also üblicherweise entweder Unicode (UTF-8 für Lazarus) oder ANSI (das bedeutet die Systemkodierung, und kann utf-8 sein oder nicht). Die RTL und die FCL von FPC 2.4 erwarten ANSI-Zeichenketten. FPC 2.5.x derzeit auch.
1010
1111Sie können zwischen Unicode und ANSI konvertieren mittels der Funktionen **UTF8ToAnsi** und **AnsiToUTF8** aus der Unit 'System' oder mittels **UTF8ToSys** und **SysToUTF8** aus der Unit 'FileUtil'. Die beiden letzteren sind eleganter, stellen aber mehr Code in Ihr Programm.
1212
1313Beispiele:
1414
1515Angenommen Sie haben eine Zeichenkette aus einem TEdit und wollen diese an eine Routine aus der RTL übergeben:
1616
1717``` pascal
1818var
1919 MyString: string; // utf-8 encoded
2020begin
2121 MyString := MyTEdit.Text;
2222 SomeRTLRoutine(UTF8ToAnsi(MyString));
2323end;
2424```
2525
2626Und in der umgekehrten Richtung:
2727
2828``` pascal
2929var
3030 MyString: string; // ansi encoded
3131begin
3232 MyString := SomeRTLRoutine;
3333 MyTEdit.Text := AnsiToUTF8(MyString);
3434end;
3535```
3636
3737**Wichtig**: UTF8ToAnsi gibt eine leere Zeichenkette zurück, wenn der UTF8-String ungültige Zeichen enthält.
3838
3939**Wichtig**: AnsiToUTF8 und UTF8ToAnsi brauchen einen Widestring-Manager unter Linux, BSD und Mac OS X. Sie können die Funktionen SysToUTF8 und UTF8ToSys (aus der Unit FileUtil) einsetzen oder einen Widestring-Manager, indem Sie 'cwstring' als eine der ersten Units zum uses-Abschnitt in Ihrem Programm hinzufügen.
4040
4141### Der Umgang mit UTF8 Zeichenketten und Zeichen
4242
4343Wenn Sie die Zeichen einer UTF8-Zeichenkette durchlaufen wollen, gibt es dafür zwei unterschiedliche Arten:
4444
4545- durchlaufen Sie die Bytes - ist nützlich zum Suchen eines Teilstrings oder wenn Sie nur die ASCII-Zeichen eines UTF8-Strings betrachten wollen. Zum Beispiel beim Parsen einer xml-Datei.
4646- durchlaufen Sie die Zeichen - ist nützlich für graphische Komponenten wie Synedit. Zum Beispiel wenn Sie wissen wollen, welches das dritte am Bildschirm dargestellte Zeichen ist.
4747
4848#### Suchen eines Teilstrings
4949
5050Wegen der besonderen Natur von UTF8 können Sie einfach die normalen Stringfunktionen verwenden:
5151
5252``` pascal
5353procedure Where(SearchFor, aText: string);
5454var
5555 BytePos: LongInt;
5656 CharacterPos: LongInt;
5757begin
5858 BytePos:=Pos(SearchFor,aText);
5959 CharacterPos:=UTF8Length(PChar(aText),BytePos-1);
6060 writeln('The substring "',SearchFor,'" is in the text "',aText,'"',
6161 ' at byte position ',BytePos,' and at character position ',CharacterPos);
6262end;
6363```
6464
6565#### Zugriff auf einen UTF8-String als Array
6666
6767Ein Array besteht aus aus Elementen gleicher Größe. Ein UTF8-Zeichen kann aber 1 bis 4 Bytes haben. Deshalb müssen Sie den UTF8-String konvertieren, entweder in ein Array aus Unicode-Werten (longwords) oder in ein Array aus PChar mit einem Zeiger auf jedes Zeichen.
6868
6969#### Durchlaufen von Zeichen mittels UTF8CharacterToUnicode
7070
7171Das Folgende demonstriert wie Sie die 32bit Unicode-Werte von Zeichen in einem UTF8-String durchlaufen:
7272
7373``` pascal
7474uses LCLProc;
7575...
7676procedure IterateUTF8Characters(const AnUTF8String: string);
7777var
7878 p: PChar;
7979 unicode: Cardinal;
8080 CharLen: integer;
8181begin
8282 p:=PChar(AnUTF8String);
8383 repeat
8484 unicode:=UTF8CharacterToUnicode(p,CharLen);
8585 writeln('Unicode=',unicode);
8686 inc(p,CharLen);
8787 until (CharLen=0) or (unicode=0);
8888end;
8989```
9090
9191### Der Umgang mit Verzeichnis- und Dateinamen
9292
9393Die Steuerelemente und Funktionen in Lazarus erwarten Dateinamen und Verzeichnisnamen in UTF-8 Kodierung, aber die RTL benutzt ANSI-Strings für Verzeichnisse und Dateinamen.
9494
9595Betrachten Sie beispielsweise eine Schaltfläche, die die Eigenschaft 'Directory' einer TFileListBox auf das aktuelle Verzeichnis setzt. Die RTL-Funktion [[doc:rtl/sysutils/getcurrentdir.html|GetCurrentDir]] ist ANSI, und nicht Unicode, deswegen muss man konvertieren:
9696
9797``` pascal
9898procedure TForm1.Button1Click(Sender: TObject);
9999begin
100100 FileListBox1.Directory:=SysToUTF8(GetCurrentDir);
101101 // or use the functions from the FileUtil unit
102102 FileListBox1.Directory:=GetCurrentDirUTF8;
103103end;
104104```
105105
106106Die Unit 'FileUtil' definiert allgemeine Dateifunktionen mit UTF-8 Strings:
107107
108108``` pascal
109109// Basisfunktionen ähnlich zur RTL, aber arbeiten mit UTF-8 anstelle der
110110// Systemkodierung
111111
112112// AnsiToUTF8 und UTF8ToAnsi brauchen einen Widestring-Manager unter Linux, BSD, Mac OS X,
113113// aber normalerweise nehmen diese Betriebssysteme UTF-8 als Systemkodierung, dann ist
114114// ein Widestring-Manager nicht nötig.
115115function NeedRTLAnsi: boolean;// wahr, wenn die Systemkodierung nicht UTF-8 ist
116116procedure SetNeedRTLAnsi(NewValue: boolean);
117117function UTF8ToSys(const s: string): string;// wie UTF8ToAnsi, aber unabhängig von einem Widestring-Manager
118118function SysToUTF8(const s: string): string;// wie AnsiToUTF8, aber unabhängig von einem Widestring-Manager
119119
120120// Dateioperationen
121121function FileExistsUTF8(const Filename: string): boolean;
122122function FileAgeUTF8(const FileName: string): Longint;
123123function DirectoryExistsUTF8(const Directory: string): Boolean;
124124function ExpandFileNameUTF8(const FileName: string): string;
125125function ExpandUNCFileNameUTF8(const FileName: string): string;
126126{$IFNDEF VER2_2_0}
127127function ExtractShortPathNameUTF8(Const FileName : String) : String;
128128{$ENDIF}
129129function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec): Longint;
130130function FindNextUTF8(var Rslt: TSearchRec): Longint;
131131procedure FindCloseUTF8(var F: TSearchrec);
132132function FileSetDateUTF8(const FileName: String; Age: Longint): Longint;
133133function FileGetAttrUTF8(const FileName: String): Longint;
134134function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
135135function DeleteFileUTF8(const FileName: String): Boolean;
136136function RenameFileUTF8(const OldName, NewName: String): Boolean;
137137function FileSearchUTF8(const Name, DirList : String): String;
138138function FileIsReadOnlyUTF8(const FileName: String): Boolean;
139139function GetCurrentDirUTF8: String;
140140function SetCurrentDirUTF8(const NewDir: String): Boolean;
141141function CreateDirUTF8(const NewDir: String): Boolean;
142142function RemoveDirUTF8(const Dir: String): Boolean;
143143function ForceDirectoriesUTF8(const Dir: string): Boolean;
144144
145145// Umgebung
146146function ParamStrUTF8(Param: Integer): string;
147147function GetEnvironmentStringUTF8(Index : Integer): String;
148148function GetEnvironmentVariableUTF8(const EnvVar: String): String;
149149function GetAppConfigDirUTF8(Global: Boolean): string;
150150```
151151
152152#### Mac OS X
153153
154154Die Dateifunktionen der Unit 'FileUtil' berücksichtigen eine Besonderheit von Mac OS X: OS X normalisiert Dateiname. Zum Beispiel kann der Dateiname 'ä.txt' in Unicode mit zwei unterschiedlichen Sequenzen (#\$C3#\$A4 und 'a'#\$CC#\$88) kodiert werden. Unter Linux und BSD können Sie einen Dateinamen mit beiden Kodierungen erzeugen. OS X konvertiert automatisch den a-Umlaut in die drei Byte Sequenz. Das bedeutet:
155155
156156``` pascal
157157if Filename1=Filename2 then ... // reicht nicht aus unter OS X
158158if AnsiCompareFileName(Filename1,Filename2)=0 then ... // reicht nicht aus unter fpc 2.2.2, nicht einmal mit 'cwstring'
159159if CompareFilenames(Filename1,Filename2)=0 then ... // dies funktioniert immer (Unit FileUtil oder FileProcs)
160160```
161161
162162## UTF8 und Quelltextdateien - die fehlende BOM
163163
164164Wenn Sie mit Lazarus Quelltextdateien erzeugen und einige Nicht-ASCII-Zeichen eintippen, dann wird diese Datei mit UTF8 gespeichert. Es **verwendet keine BOM** (Byte-Ordnungs-Markierung). Sie können die Kodierung ändern mittels eines Rechtsklicks im Quelltexteditor / Dateieinstellungen / Zeichenkodierung. Der Grund für die fehlende BOM ist die Art, wie FPC ANSI-Strings behandelt. Für die Kompatibilität benutzt die LCL ANSI-Strings und für die Portabilität benutzt die LCL UTF8.
165165
166166Anmerkung: Einige MS Windows Texteditoren verarbeiten diese Dateien mit der System-Codepage und zeigen dann ungültige Zeichen an. Fügen Sie **keine** BOM hinzu. Wenn Sie eine BOM einfügen, müssen Sie alle Stringzuweisungen ändern.
167167
168168Zum Beispiel:
169169
170170``` pascal
171171Button1.Caption := 'Über';
172172```
173173
174174Wenn keine BOM vorliegt (und kein Codepage-Parameter übergeben wurde), dann behandelt der Compiler die Zeichenkette wie systemkodiert und kopiert jedes Byte unkonvertiert in die Zeichenkette. Genau so erwartet die LCL die Zeichenketten.
175175
176176``` pascal
177177// Quelltextdatei gespeichert als UTF ohne BOM
178178if FileExists('Über.txt') then ; // falsch, weil 'FileExists' Systemkodierung erwartet
179179if FileExistsUTF8('Über.txt') then ; // richtig
180180```
181181
182182## Widestrings und Ansistrings
183183
184184Wenn Sie Ansistrings an Widestrings übergeben, müssen Sie die Kodierung konvertieren.
185185
186186``` pascal
187187var
188188 w: widestring;
189189begin
190190 w:='Über'; // falsch, weil der FPC die System-Codepage zu UTF16 konvertiert
191191 w:=UTF8ToUTF16('Über'); // richtig
192192 Button1.Caption:=UTF16ToUTF8(w);
193193end;
194194```
195195
196196## Quelltextdatei mit UTF8 BOM
197197
198198Wenn Sie in einer Unit zahlreiche Konvertierungen von Widestrings durchführen, könnte der Code dadurch lesbarer werden, dass Sie den Quelltext als UTF8 mit BOM abspeichern. Der Compiler erlaubt pro Unit eine Kodierung.
199199
200200### Ostasiatische Sprachen unter Windows
201201
202202Die Vorgabeschriftart (Tahoma) für Benutzerinterface-Steuerelemente unter Windows XP kann verschiedene Sprachen korrekt anzeigen, darunter Arabisch, Russisch und westliche Sprachen, aber nicht ostasiatische Sprachen, wie Chinesisch, Japanisch oder Koreanisch. Gehen Sie zur Systemsteuerung, wählen Sie 'Region und Sprache' aus, klicken Sie auf die Sprachformate und installieren Sie das East Asia Language Pack. Dadurch wird die Vorgabeschriftart ab jetzt diese Sprachen korrekt anzeigen. Natürlich haben Windows XP Versionen, die für diese Sprachen lokalisiert wurden, dieses Sprachpaket bereits installiert. Genauere Instruktionen gibt es [hier](http://newton.uor.edu/Departments&Programs/AsianStudiesDept/Language/asianlanguageinstallation_XP.html).
203203
204204## Implementierungsrichtlinien
205205
206206### Voraussetzungen
207207
208208Die Vision von Lazarus ist: "Write once, compile everywhere." Das bedeutet im Idealfall, eine Applikation, die Unicode eingeschaltet hat, hat nur einen Source-Code, der für alle Plattformen gültig ist, ohne irgendwelche konditionalen Definitionen.
209209
210210Der "Interface" Teil der LCL sollte Unicode für die Zielplattform bereitstellen, die Zielplattform sollte Unicode selber unterstützen, ohne den Anwendungsprogrammierer mit Details zu belästigen.
211211
212212Was Lazarus betrifft, ist die interne String-Kommunikation an den Schnittstellen "Anwendungscode \<--\> LCL" und "LCL \<--\> Widgetsets". Beide basieren nämlich auf den klassischen byte-orientierten Strings. Logisch sollten diese String konvertiert werden zu dem Code [[UTF-8]].
213213
214214### Migration zu Unicode
215215
216216Die meisten existierenden Versionen von Lazarus benutzen die ANSI-Kodierung, weil dies der Standard war für die Gtk1 und win32 Interfaces bis zur Version 0.9.24. Ab 0.9.25 verwenden alle Interfaces [[UTF-8]] als Standard (mit Ausnahme von gtk1, das [[UTF-8]] nur dann unterstützt, wenn auch die Systemkodierung [[UTF-8]] ist, und selbst damit gibt es Einschränkungen). Deshalb müssen alle Anwendungen, die Zeichenketten direkt an das Interface übergeben (sei es geschrieben im Code oder im Objektinspektor) diese Zeichenketten zu UTF-8 konvertieren.
217217
218218Derzeit haben wir verschiedene Gruppen von Interfaces, je nach Kodierung:
219219
220220- Interfaces die die ANSI-Kodierung verwenden: gtk (1) auf ANSI Systemen.
221221
222222- Interfaces die die [[UTF-8]]-Kodierung verwenden: gtk (1) auf UTF-8 Systemen, gtk2, qt, [[fpGUI]], carbon, win32, wince, alle anderen
223223
224224Beachten Sie, dass gtk (1) sowohl in den Gruppen ANSI als auch UTF-8 aufscheint. Das ist, weil die Kodierung von einer Umgebungsvariablen unter Gtk 1 kontrolliert wird.
225225
226226Die IDE wurde erweitert für das Laden/Speichern/Bearbeiten von Dateien mit unterschiedlichen Kodierungen (1 Kodierung pro Datei). Sie hat eine eingebaute Heuristik um die Kodierung zu ermitteln und Sie können die Kodierung einer Datei zu jedem Zeitpunkt ändern (Quelltexteditor / Popup-Menü / Dateieinstellungen / Kodierung). So kann die IDE alte Dateien und Projekte öffnen und auch zum Konvertieren der Kodierung benutzt werden.
227227
228228## Roadmap
229229
230230Da wir nunmehr Richtlinien haben, ist es an der Zeit eine "Roadmap" auszuarbeiten und diese Realität werden zu lassen. Vor diesem Hintergrund wurde der nachfolgend dargestellte Plan aufgestellt. Dieser Plan teilt die Aufgaben in zwei Gruppen ein. Eine Gruppe für primäre, eine für sekundäre Aufgaben.
231231
232232Alle primären Aufgaben müssen vollständig umgesetzt sein, bevor wir davon sprechen können, dass Lazarus Unicode-fähig ist. Diesen primären Aufgaben gilt daher unser Hauptaugenmerk. An ihnen werden wir bevorzugt arbeiten.
233233
234234Sekundäre Aufgaben sind zwar wünschenswert, werden aber erst umgesetzt, wenn sich für die Aufgabe jemand findet, der sie umsetzt.
235235
236236### Primäre Aufgaben
237237
238238**Ziel: Win32 Widgetset unterstützt UTF-8**
239239
240240Anmerkungen: On this step we will target all 32-bits Windows versions at the same time. All code produced on this effort will be isolated from the current win32 interface by IFDEFs, to avoid introducing bugs on this primary interface. After the transition time, the IFDEFs will be removed and only the Unicode code will remain.
241241
242242Status: vollständig implementiert
243243
244244**Aktualisieren der GTK2 Tastaturfunktionen, damit sie mit UTF-8 funktionieren**
245245
246246Anmerkungen:
247247
248248Status: fast vollendet. Some pre-editing features of the gtk2 are not yet supported in custom controls. I don't know, which language needs them.
249249
250250**Make sure the Lazarus IDE runs correctly with Win32 Unicode widgetset and supports UTF-8**
251251
252252Anmerkungen:
253253
254254Status: vollendet. Mit Ausnahme der Zeichentabelle ("Character-Map"), sie zeigt weiterhin lediglich 255 Zeichen. Aber alle modernen Betriebssysteme bieten ohnehin schöne Unicode-Zeichentabellen.
255255
256256**Make sure the Lazarus IDE runs correctly with Gtk 2 widgetset and supports UTF-8**
257257
258258Anmerkungen:
259259
260260Status: vollendet. Es gibt noch GTK2 intf bugs, aber diese haben nichts mit UTF-8 zu tun.
261261
262262### Sekundäre Aufgaben
263263
264264**Aktualisieren des Windows CE Interfaces, damit es UTF-8 benutzt**
265265
266266Anmerkungen: String-Umwandlungsroutinen konzentrieren sich auf die winceproc.pp file. Hier sind noch viele Tests notwendig.
267267
268268Status: vollendet
269269
270270**Aktualisieren der GTK1 Tastaturfunktionen, damit sie mit UTF-8 funktionieren**
271271
272272Anmerkungen:
273273
274274Status: nicht implementiert.
275275
276276**RTL in synedit vervollständigen**
277277
278278Anmerkungen: RTL meint von rechts nach links (right to left) wie es z.B. im Arabischen verwendet wird
279279
280280Status: nicht implementiert.
281281
282282## Grundlagen von Unicode
283283
284284Der Unicode-Standard weist den Integerzahlen von 0 bis 10FFFF(h) Zeichen zu. Jede solche Zuweisung wird auch "Codepoint" genannt. Mit anderen Worten, die Unicode-Zeichen sind im Prinzip definiert für die Codepoints von U+000000 bis U+10FFFF (0 to 1 114 111).
285285
286286Es gibt drei Schemata, um Unicode-Codepoints als eindeutige Bytesequenzen abzubilden. Diese Schemata nennt man Unicode-Transformationsformate: UTF-8, UTF-16 und UTF-32. Die Umwandlung untereinander ist möglich. Hier sind ihre grundlegenden Eigenschaften:
287287
288-`                              UTF-8 UTF-16 UTF-32`\
289-`Kleinster Codepoint    [hex] 000000 000000 000000`\
290-`Größter Codepoint      [hex] 10FFFF 10FFFF 10FFFF`\
291-`Größe der Codeeinheit [Bits]      8     16     32`\
292-`Minimale Bytes/Zeichen            1      2      4`\
293-`Maximale Bytes/Zeichen            4      4      4`
288+```text
289+ UTF-8 UTF-16 UTF-32
290+Kleinster Codepoint [hex] 000000 000000 000000
291+Größter Codepoint [hex] 10FFFF 10FFFF 10FFFF
292+Größe der Codeeinheit [Bits] 8 16 32
293+Minimale Bytes/Zeichen 1 2 4
294+Maximale Bytes/Zeichen 4 4 4
295+```
294296
295297**UTF-8** hat einige wichtige und nützliche Eigenschaften: Es wird interpretiert als Sequenz von Bytes, darum existiert das Konzept von nieder- und hochwertigem (lo- and hi-order) Byte nicht. Die Unicode- Zeichen U+0000 bis U+007F (ASCII) sind einfach als Bytes 00h bis 7Fh kodiert (ASCII Kompatibilität). Dies bedeutet, dass Dateien und Zeichenketten die nur 7-Bit ASCII-Zeichen enthalten die gleiche Kodierung sowohl unter ASCII als auch unter UTF-8 haben. Alle Zeichen \> U+007F sind kodiert als Sequenz mehrerer Bytes, deren zwei höchste Bits gesetzt sind. Nie ist eine Bytesequenz eines Zeichens in einer längeren Bytesequenz eines anderen Zeichens enthalten. Dies erlaubt eine Suche nach Teilstrings. Das erste Byte einer Multibyte-Sequenz, die ein nicht-ASCII-Zeichen darstellt ist immer im Bereic C0h bis FDh und es zeigt, wie viele Bytes für dieses Zeichen noch folgen. Alle weiteren Bytes in einer Multibyte-Sequenz sind im Bereich 80h bis BFh. Dadurch werden leichte Resynchronisation und Robustheit möglich.
296298
297299**UTF-16** hat die folgenden wichtigen Eigenschaften: Es benutzt ein einzelnes 16-Bit Wort zum Kodieren der Zeichen von U+0000 bis U+d7ff, und ein Paar von 16-Bit Worten, um jedes der restlichen Unicode-Zeichen zu kodieren.
298300
299301Zuletzt kann jedes Unicode-Zeichen auch als einzelne 32-Bit Einheit in **UTF-32** dargestellt werden.
300302
301303Für weitere Informationen siehe: [Unicode FAQ - Basic questions](http://www.unicode.org/faq/basic_q.html), [Unicode FAQ - UTF-8, UTF-16, UTF-32 & BOM](http://www.unicode.org/faq/utf_bom.html), [Wikipedia: UTF-8](http://en.wikipedia.org/wiki/UTF-8) [1](http://en.wikipedia.org/wiki/ISO-8859)
302304
303305## Grundlagen der Lazarus-Komponentenbibliotheks-Architektur
304306
305307Die LCL besteht aus zwei Teilen:
306308
3073091. Einem von der Zielplattform unabhängigen Teil, der eine Klassenhierarchie analog zur Delphi VCL implementiert;
3083102. "Interfaces" - einem Teil der das Interface zu den APIs einer jeden Zielplattform implementiert.
309311
310312Die Kommunikation zwischen den beiden Teilen erfolgt durch eine abstrakte Klasse 'TWidgetset'. Jedes Interface ist implementiert durch seine eigene, von TWidgetset abgeleitete Klasse.
311313
312314Das GTK 1 Interface ist das älteste. In diesem Widgetset ist die Zeichenkettenkodierung bestimmt durch die Umgebungsvariable 'LANG' (???--- , which is usually a iso The ISO-8859-n group of single byte encodings---???). Zuletzt (zum Beispiel bei Mandriva 2007), haben viele Distributionen ein Gtk 1 ausgeliefert, das für UTF-8 konfiguriert war. Unserem Gtk 1 Interface fehlt die vollständige Unterstützung für UTF-8 in den Tastaturverarbeitungsroutinen. Dieses große Problem zeigt, wie wichtig es für Lazarus ist, eine plattformübergreifende Unicodeunterstützung zu implementieren.
313315
314316Das Gtk2 Interface arbeitet nur mit UTF-8 Kodierung und unterstützt UTF-8 vollständig.
315317
316318Ab Lazarus 0.9.28 unterstützen das Windows und Windows CE Interface Unicode vollständig.
317319
318320Das Qt Interface ist für UTF-8 vorbereitet. Qt selbst benutzt UTF-16 als eingebaute Kodierung, aber das Lazarus Interface für Qt konvertiert von UTF-8 zu UTF-16.
319321
320322Für weitere Informationen siehe: [[LCL Internals|Internals of the LCL]]
321323
322324## Vorbereitung des Win32-Interfaces für Unicode
323325
324326### Richtlinien
325327
326328Als erstes, und auch wichtigstes, müssen alle Unicode-Patches für das Win32-Interface in Anweisungen für bedingte Kompilierung (IFDEF WindowsUnicodeSupport) eingeschlossen sein, um zu verhindern, dass das existierende ANSI-Interface zerbricht. Nachdem sich dies stabilisiert hat, werden alle IFDEFs entfernt und nur der Unicodeteil bleibt bestehen. Zu diesem Zeitpunkt brauchen alle Programme die ANSI-Zeichen verwenden eine Migration hin zu Unicode.
327329
328330Windows-Plattformen \<= Win9x basieren auf den Standards der ISO Codeseiten und unterstützen Unicode nur teilweise. Die Windows-Plattformen beginnend mit WinNT und Windows CE unterstützen Unicode vollständig. Win 9x und NT bieten deshalb zwei parallele Mengen von API-Funktionen: die alten ANSI-fähigen *A und die neuen Unicode-fähigen *W. *W Funktionen akzeptieren Widestrings, d.h. UTF-16 kodierte Strings, als Parameter. Windows CE verwendet nur die Wide API Funktionen.
329331
330332#### Wide-Funktionen, die es unter Windows 9x gibt
331333
332334Einzelne Wide API Funktionen gibt es unter Windows 9x. Hier ist eine Liste solcher Funktionen: <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mslu/winprog/other_existing_unicode_support.asp>
333335
334336Konvertierungsbeispiel:
335337
336338 GetTextExtentPoint32(hdcNewBitmap, LPSTR(ButtonCaption),
337339 Length(ButtonCaption), TextSize);
338340
339341wird zu:
340342
341343``` pascal
342344{$ifdef WindowsUnicodeSupport}
343345 GetTextExtentPoint32W(hdcNewBitmap, PWideChar(Utf8Decode(ButtonCaption)), Length(WideCaption), TextSize);
344346{$else}
345347 GetTextExtentPoint32(hdcNewBitmap, LPSTR(ButtonCaption), Length(ButtonCaption), TextSize);
346348{$endif}
347349```
348350
349351#### Funktionen die ANSI- und Wide- Versionen benötigen
350352
351353Erstes Konvertierungsbeispiel:
352354
353355``` pascal
354356function TGDIWindow.GetTitle: String;
355357var
356358 l: Integer;
357359begin
358360 l := Windows.GetWindowTextLength(Handle);
359361 SetLength(Result, l);
360362 Windows.GetWindowText(Handle, @Result[1], l);
361363end;
362364```
363365
364366wird zu:
365367
366368``` pascal
367369function TGDIWindow.GetTitle: String;
368370var
369371 l: Integer;
370372 AnsiBuffer: string;
371373 WideBuffer: WideString;
372374begin
373375
374376{$ifdef WindowsUnicodeSupport}
375377
376378 if UnicodeEnabledOS then
377379 begin
378380 l := Windows.GetWindowTextLengthW(Handle);
379381 SetLength(WideBuffer, l);
380382 l := Windows.GetWindowTextW(Handle, @WideBuffer[1], l);
381383 SetLength(WideBuffer, l);
382384 Result := Utf8Encode(WideBuffer);
383385 end
384386 else
385387 begin
386388 l := Windows.GetWindowTextLength(Handle);
387389 SetLength(AnsiBuffer, l);
388390 l := Windows.GetWindowText(Handle, @AnsiBuffer[1], l);
389391 SetLength(AnsiBuffer, l);
390392 Result := AnsiToUtf8(AnsiBuffer);
391393 end;
392394
393395{$else}
394396
395397 l := Windows.GetWindowTextLength(Handle);
396398 SetLength(Result, l);
397399 Windows.GetWindowText(Handle, @Result[1], l);
398400
399401{$endif}
400402
401403end;
402404```
403405
404406### Roadmap
405407
406408#### Was bereits mit Unicode funktionieren sollte:
407409
408410- TForm, TButton, TLabel
409411- die meisten Controls
410412- Menüs
411413- LCLIntf.ExtTextOut und die meisten anderen textbezogenen WinAPIs
412414- TStrings-basierte Steuerelemente. Beispiele: TComboBox, TListBox, etc...
413415- SynEdit kann UTF-8 Zeichen korrekt anzeigen und als Eingabe entgegennehmen
414416- Unicode-Zeichenketten zur/von der Zwischenablage schicken/empfangen
415417- Den Anwendungstitel in den Projekteinstellungen setzen. Zum Beispiel auf: 'Minha Aplicação'.
416418- Doppelklick im Editor auf Wörter mit nicht-ASCII Zeichen wählt diese Wörter aus
417419
418420#### Bekannte Probleme bei der Unicode-Unterstützung:
419421
420422- Viele Komponenten unterstützen RTL nicht oder nur fehlerhaft
421423- SynEdit unterstützt nicht RTL (right to left, von rechts nach links)
422424- Is OpenFileDialogCallBack tested with selection large numbers of files?
423425 - Is this problem unicode specific? I think it's a generic problem. --Sekelsenmat 13:40, 14 February 2008 (CET)
424426 - Maybe. I know I tested it with large number of files before the Unicode version was added. If it is a generic problem, then the the non-Unicode version got broken, when the Unicode version was added. Vincent 21:45, 15 February 2008 (CET)
425427 - Associated bugtracker item: <http://bugs.freepascal.org/view.php?id=10918> Fixed and implemented.
426428- class function TWin32WSSelectDirectoryDialog.CreateHandle: Title, FileName and InitialDir should be made Unicode aware.
427429 - Associated bugtracker item: <http://bugs.freepascal.org/view.php?id=10919> Implemented.
428430
429431**Mögliche Probleme bei der Unicode-Unterstützung**
430432
431433Basierend auf einer Durchsicht des Codes, sollten folgende Punkte getestet werden, weil der dortige Code nicht Unicode-fähig zu sein scheint:
432434
433435- class procedure TWin32WSCustomComboBox.SetText
434436- TWin32WSCustomTrayIcon.Show: ATrayIcon.Hint is not Unicode aware
435437- TWin32WidgetSet.MessageBox doesn't call MessageBoxW.
436438- TWin32WidgetSet.TextOut: Is Windows.TextOut supported on windows 9X?
437439 - Yes, please see [[LCL Unicode Support|LCL_Unicode_Support#Wide_functions_present_on_Windows_9x]]. Althought I never tested this.
438440- MessageBox buttons don't show unicode correctly when they are translated. Tested on the IDE. Could be a problem on the IDE however.
439441 - Note: I couldn't reproduce using the portuguese translation --Sekelsenmat 22:20, 12 January 2008 (CET)
440442- (list of unconfirmed problems, if confirmed can be moved to the list above)
441443
442444### Screenshots
443445
444446![](/wiki-images/4/49/Lazarus_Unicode_Test.png)
445447
446448## Siehe auch
447449
448450- [[UTF-8]] - Beschreibung von UTF-8 Zeichenketten
449451
450452---
451453*From the Free Pascal wiki, page "LCL Unicode Support/de", as it stood on 2020-02-19 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).*

Back to history