Vertauschter WideString mit X11

Antworten
Mathias
Beiträge: 6193
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Vertauschter WideString mit X11

Beitrag von Mathias »

Ich habe folgendes Besipiel, welches mir den String richtig ausgibt. Gibt es etwas anderes als UTF8ToUTF16(), so das ich die for-to-Schleife umgehen kann ?
Vielleicht mit Ländercoden oder was Ähnlichem.

Code: Alles auswählen

  const
    Hello = 'Hello World !, ich habe "äüö ÄÜÖ ÿŸäüö   ggg" !äöü';
  var
       Char2BArr: TXChar2BArray;
       ws: WideString;
  begin
    ws := UTF8ToUTF16(Hello);
    WriteLn(ws);  // geht richtig
    for i := 1 to Length(ws) do begin
      ws[i] := widechar(Swap(word(ws[i])));  // Bytes in WideChar vertauschen
    end;
    
    XDrawString16(dis, win, gc, Left, Top + ascent - descent, @ws[1], Length(ws));     
Normalerweise arbeit X11 mit "TXChar2BArray", welches auch funktioniert, aber nur mit einer selbst zusammgewurstelten Code von einem C-Programm, welchen UTF8-Code umwandelt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Vertauschter WideString mit X11

Beitrag von theo »

Willst du nicht lieber Xutf8DrawString nehmen?

Mathias
Beiträge: 6193
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Vertauschter WideString mit X11

Beitrag von Mathias »

Ich habe es hingekriegt.

Code: Alles auswählen

  type
    TChar2BString = type ansistring(CP_UTF16BE);
Sogar Writeln macht da mit.

Code: Alles auswählen

    Char2BArr := UTF8ToUTF16(Hello);
    WriteLn(Char2BArr);
    XDrawString16(dis, win, gc, Left, Top, @Char2BArr[1], Length(Char2BArr) shr 1);
Willst du nicht lieber Xutf8DrawString nehmen?
Ja dies habe ich auch probiert und dies geht.
Nur hat das 2 Nachteile.
  • Man muss sich mit Fontsets rumschlagen
  • Der Zugriff auf die einzelnen Zeichen ist nicht linear, bei den 2BChars ist jedes Zeichen 2Byte gross, egal ob Umlaut oder nicht,
Klar ich könnte der bequemste Weg nehmen, dann würde ich Canvas.TextOut() nehmen. Aber ich will verstehen, wie das mit X11 funktioniert.
Versuche mal ein einfaches Edit-Feld mit Cursor selbst zu programmieren, das ist ein bodenloses Fass mit UTF8.

Unter dem Strich ist schon recht spannend, was da alles für Stringformate verwendet sind/wurden.
Das heute verwendete UTF8 Format ist noch nicht so uralt.

Edit: Meine Lösung mit "CP_UTF16BE" hat den Nachteil, das die Package LCLBase eingebunden werden muss.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Vertauschter WideString mit X11

Beitrag von Socke »

Mathias hat geschrieben:
Mo 26. Dez 2022, 13:53
Willst du nicht lieber Xutf8DrawString nehmen?
Ja dies habe ich auch probiert und dies geht.
Nur hat das 2 Nachteile.
  • Man muss sich mit Fontsets rumschlagen
  • Der Zugriff auf die einzelnen Zeichen ist nicht linear, bei den 2BChars ist jedes Zeichen 2Byte gross, egal ob Umlaut oder nicht,
Aber dir ist schon klar, dass du auch in UTF-16 Zeichen hast, die nicht in 2 Bytes hineinpassen? Die Probleme von UTF-8 sind identisch bei UTF-16, sie sind nur mindestens 1 Byte länger ;-)
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6193
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Vertauschter WideString mit X11

Beitrag von Mathias »

Aber dir ist schon klar, dass du auch in UTF-16 Zeichen hast, die nicht in 2 Bytes hineinpassen?
Hast leider recht, Wikipedia hat er verraten. Somit gibt es noch mehr Durcheinander.
Was ich festgestellt habe, bei X11 das es sehr wenige Zeichen gibt welche im 2. Byte von UTF16 eine Zeichen grösser 0 hat. Eine 1 hat zB. "Ÿ", welches aber X11 nicht mal ausgeben kann. Somit habe ich das Gefühl, das mit CP_UTF16BE ziemlich alles abgedeckt wird, was ein normler PC verwendet.
Ich denke auch kaum, das X11 etwas grösseres als 16Bit verwendet. Das Hausformat von X11 sieht so aus:

Code: Alles auswählen

   PXChar2b = ^TXChar2b;
   TXChar2b = record
        byte1 : cuchar;
        byte2 : cuchar;
     end;
Ist in der Unit xlib enthalten.
Was ich vermute, OSs, welche UTF8 mit allen Sonderzeichen verwenden, machen dies auf einer höheren Ebene, so wie es GTK, QT, etc. machen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Vertauschter WideString mit X11

Beitrag von theo »

Nimm einfach Xutf8DrawString, das braucht kein komisches Zeug wie PXChar2b.

PascalDragon
Beiträge: 829
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Vertauschter WideString mit X11

Beitrag von PascalDragon »

Mathias hat geschrieben:
Mo 26. Dez 2022, 08:54
Ich habe folgendes Besipiel, welches mir den String richtig ausgibt. Gibt es etwas anderes als UTF8ToUTF16(), so das ich die for-to-Schleife umgehen kann ?
Vielleicht mit Ländercoden oder was Ähnlichem.

Code: Alles auswählen

  const
    Hello = 'Hello World !, ich habe "äüö ÄÜÖ ÿŸäüö   ggg" !äöü';
  var
       Char2BArr: TXChar2BArray;
       ws: WideString;
  begin
    ws := UTF8ToUTF16(Hello);
    WriteLn(ws);  // geht richtig
    for i := 1 to Length(ws) do begin
      ws[i] := widechar(Swap(word(ws[i])));  // Bytes in WideChar vertauschen
    end;
    
    XDrawString16(dis, win, gc, Left, Top + ascent - descent, @ws[1], Length(ws));     
Normalerweise arbeit X11 mit "TXChar2BArray", welches auch funktioniert, aber nur mit einer selbst zusammgewurstelten Code von einem C-Programm, welchen UTF8-Code umwandelt.
Bitte beachte XDrawString16 arbeitet nicht mit UTF-16. Das stammt aus einer Zeit als es UTF-16 als solches noch gar nicht gab. Du solltest also das von theo vorgeschlagene Xutf8DrawString verwenden.
Mathias hat geschrieben:
Mo 26. Dez 2022, 13:53
Ich habe es hingekriegt.

Code: Alles auswählen

  type
    TChar2BString = type ansistring(CP_UTF16BE);
Sogar Writeln macht da mit.

Code: Alles auswählen

    Char2BArr := UTF8ToUTF16(Hello);
    WriteLn(Char2BArr);
    XDrawString16(dis, win, gc, Left, Top, @Char2BArr[1], Length(Char2BArr) shr 1);
Ein 2 Byte Encoding wie CP_UTF16BE als CodePage für einen AnsiString zu verwenden ist undefiniertes Verhalten. Das kann gut gehen, kann dir aber genauso gut komplett um die Ohren fliegen.
Mathias hat geschrieben:
Mo 26. Dez 2022, 13:53
Willst du nicht lieber Xutf8DrawString nehmen?
Ja dies habe ich auch probiert und dies geht.
Nur hat das 2 Nachteile.
  • Man muss sich mit Fontsets rumschlagen
  • Der Zugriff auf die einzelnen Zeichen ist nicht linear, bei den 2BChars ist jedes Zeichen 2Byte gross, egal ob Umlaut oder nicht,
Wie schon oben erwähnt ist 2BChar eben nicht UTF-16, das heißt dein Code ist aktuell einfach falsch und funktioniert einfach nur weil du entsprechende Texte hast, mit denen dein Fehler nicht auffällt. Außerdem hat auch UTF-16 Multi-WideChar Sequenzen, nämlich die Surrogate Pairs, welche aus zwei WideChar-Elementen bestehen. Mal ganz davon abgesehen, dass in allen Unicode Encodings ein einzelnes visuelles Zeichen aus mehreren Codepoints zusammen gesetzt sein kann (zum Beispiel „ä” gibt es als solches, aber auch als „a¨”; von den ganzen komplexeren Emoji mal ganz zu schweigen)
FPC Compiler Entwickler

Mathias
Beiträge: 6193
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Vertauschter WideString mit X11

Beitrag von Mathias »

So wie es scheint, ist das ganze ein bodenloses Fass. Somit denke ich, das es keinen Sinn mehr macht, sich mit dieser Materie tiefer zu befassen.
Es wäre trotzdem interessant gewesen, zu verstehen, wie sich X11 entwickelt hat.
Zum Glück hat man heutzutage die LCL, was das einem alles im Hintergrund erledigt.
Was ich mit X11 feststellen konnte, die heutige GUI von Linux hat damit nicht mehr viel zu tun, ausser das erzeugen eines Fensters. Aber das wird wohl auch eine Frage der Zeit sein, dann läuft dies alles über Wayland. Wobei ich bis jetzt dafür keine Unterstützung von Lazarus gesehen habe. Nur ein kleines C-Demo, welche nicht mal den Display öffnen konnte.
Auch GTK und QT scheint nicht mehr viel mit X11 zu tun haben.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6193
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Vertauschter WideString mit X11

Beitrag von Mathias »

Ich habe dazu ein lustiges Programm geschrieben, welches den ganze WideString Zeichensatz bis 65536 ausgibt. Was dabei extrem ist, die vielen asiatischen Zeichen. Smilies hat es recht wenige, im Vergleich mit Whatsapp oder Telegram. Die vielen Smilies werden in UTF8 sein oder in den 4 Bit WideChars.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
const
  start = 32;
var
  ws: WideString;
  i: integer;
begin
  for i := start to 65000 do begin
    ws := ws + widechar(i);
  end;
  Memo1.Clear;
  memo1.Lines.Add(ws);
end;  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Vertauschter WideString mit X11

Beitrag von theo »

Ich hatte vor Urzeiten für die Lazarus IDE so ein Feature gebastelt:

Bearbeiten -> Aus der Zeichentabelle einfügen...

Dort sind die Zeichen nach Bereichen gruppiert und es geht auch für höhere Zeichen als nur bis $FFFF.
Es wird natürlich nur das angezeigt, wofür es einen Font gibt.

lazcharmap.png
lazcharmap.png (41.12 KiB) 2423 mal betrachtet

Mathias
Beiträge: 6193
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Vertauschter WideString mit X11

Beitrag von Mathias »

Ich hatte vor Urzeiten für die Lazarus IDE so ein Feature gebastelt:
Das habe ich gar nicht gewusst. das diese Tabelle von dir ist. Supi !
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 829
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Vertauschter WideString mit X11

Beitrag von PascalDragon »

Mathias hat geschrieben:
Mi 28. Dez 2022, 09:05
Ich habe dazu ein lustiges Programm geschrieben, welches den ganze WideString Zeichensatz bis 65536 ausgibt.
Seufz. Nochmal: Auch UTF-16 (was das Encoding von WideString bzw. UnicodeString ist) ist ein Multi-„Byte” Encoding: alle Zeichen jenseits der BMP (also Zeichen $10000 bis $10ffff) sind mittels zwei WideChar als sogennantes Surrogate Pair kodiert.
FPC Compiler Entwickler

Antworten