Widechars in Shortstring? - mal wieder Probleme mit Strings

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Widechars in Shortstring? - mal wieder Probleme mit Strings

Beitrag von Timm Thaler »

Ich lese einen Text aus einer (editierbaren) Combobox ein:

Code: Alles auswählen

var
  txt : shortstring;
begin
  txt := cbx_send.Text;
  uart.Send(txt);


und gebe ihn byteweise an der Seriellen aus:

Code: Alles auswählen

procedure Tuart.Send(txt : shortstring);
var
  btx : byte;
...
      btx := Ord(txt[i]);
      SerWrite(uhnd, btx, 1);


Eigentlich würde ich erwarten, dass im shortstring nur Zeichen mit der Länge 1 Byte stehen. Für Zeichen unter $7F funktioniert das auch.

Steht in meinem Eingabefeld aber ä,ö,ü oder Ähnliches, würde ich im shortstring unter Windows sowas wie $E4, $F6, $FC erwarten. Es stehen aber, und das habe ich auch im Debugger so gesehen, an der Stelle Widechars drin, nämlich $C3$A4, $C3$B6, $C3$BC. Für normale Buchstaben stehen für a, b, c $61, $62, $63, wie es sein soll.

Jetzt habe ich mal mit verschiedenen Konvertierungen und Compilerswitches rumprobiert, ich hab auch schon verschiedene Charaktersets für das Eingabefeld probiert, aber ich bekomme die Zeichen einfach nicht einstellig in den String. Dabei sollte es nach dieser Tabelle (http://wiki.freepascal.org/Better_Unicode_Support_in_Lazarus#String_Literals_Overview) eigentlich möglich sein, den String als shortstring weiterzugeben.

Es ist bestimmt ganz einfach, aber ich hab da gerade eine Denkblockade.

Disclaimer: Ja, ich weiss, es ist unschön Zeichen > $7F direkt zu senden, weil die beim Empfänger je nach Zeichensatz anders ankommen können. Aber dafür gibt es im Programm die Möglichkeit, Hex-Codes zu senden und zu empfangen. Ich könnte auch alles über $7F unterdrücken, aber ich will einfach mal wissen, warum das nicht geht.

Unter Purebasic geht der gleiche Kram mit Unicode-Compilierung übrigens problemlos, unter C++ mit Qt geht es, wenn ich den String mit toLocal8Bit konvertiere.

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von marcov »

Code: Alles auswählen

 
txt:=bx_send.text
 


ist wirklich etwas wie

Code: Alles auswählen

 
txt:=to_std8bitencoding(bx_send.text);
 


Und lazarus setzt die standard 8-bit encoding auf utf8. Das kann man zurück setzen und wieder normaler Windows codepage default machen mit http://wiki.freepascal.org/Lazarus_with ... UTF-8_mode

Man verliert denn aber utf8 im gui. Es kann dann vernünftiger sein für shortstrings expliziter Konversionen einzublenden.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Timm Thaler »

marcov hat geschrieben:Man verliert denn aber utf8 im gui. Es kann dann vernünftiger sein für shortstrings expliziter Konversionen einzublenden.


Ein "txt := UTF8ToSys(cbx_send.Text);" wie hier http://wiki.freepascal.org/Lazarus_with_FPC3.0_without_UTF-8_mode#Problem_applications_with_ACP_strings_and_LCL_controls beschrieben geht anscheinend nicht. cbx_send ist hierbei eine editierbare TComboBox aus den StdCtrls.

Oder muss ich txt auch statt als shortstring als ansistring mit einer bestimmten Codepage definieren?

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Michl »

Das beste ist mMn immer, wenn man eine GUI-App entwickelt, normale Strings zu verwenden, intern mit UTF8 zu arbeiten und nach extern die gewünschen Konvertierungen vorzunehmen, z.B. sollte es so funktionieren (ungetestet):

Code: Alles auswählen

uses ..., LazUTF8;
...
var
  txt: string// normaler String, kein Shortstring!!!
begin
  txt := UTF8ToWinCP(cbx_send.Text);
  uart.Send(txt);

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von mschnell »

Michl hat geschrieben:Das beste ist mMn immer, wenn man eine GUI-App entwickelt, normale Strings zu verwenden, intern mit UTF8 zu arbeiten und nach extern die gewünschen Konvertierungen vorzunehmen, z.B. sollte es so funktionieren


Bin ganz Deiner Ansicht. Ich verstehe allerdings nicht was an UTFR8 "normal" sein soll. Das ist eine genau so spezielle Codierung wie jede andere.

Es ist einfach nur ein Riesen-Mist, dass Lazarus/FPC und auch Delphi eine bestimmte String-Codierung (altes Lazarus und altes Delphi: ANSI Windows-Code Page, Neues Lazarus: UTF-8, neues Delphi UTF-16) so tut, als wäre es normal und für alle Zwecke sinnvoll.

-Michael

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Michl »

@mschnell: Vielleicht war ich etwas ungenau. Mit "normal" meine ich die "per default verwendeten". Ob man die UTF8-Kodierung mag oder nicht, sei mal dahingestellt, da sie jetzt einfach da ist und in Lazarus schon immer da war...

PS: Aktuell machen die Strings keinerlei Probleme, weder hier, noch im englischen Forum, noch in der Mailinglist, man muss sich nur damit beschäftigen :twisted:

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von mschnell »

Michl hat geschrieben: in Lazarus schon immer da war...


Stimmt nicht. Vor gar nicht so langer Zeit verwendete Lazarus (die LCL) ANSI ein-Byte-Codierung, sowohl in Windows als auch in Linux.

Irgendwann wurde die LCL dann auf UTF-8 umgestellt (weil Embarcadero Delphi ja auf die - ebenfalls nicht ordentlich funktionierenden - Unicode-Strings umgestellt hat), ohne dass es dafür irgendwelche Unterstützung vom FPC Compiler oder der RTL gab. Ergebnis: Katastrophe !!!! Zum Glück brauchte ich Lazarus zu dieser Zeit nicht.

Dann kamen die Code-aware Strings in FPC. Ergebnis, die Katastrophe hat sich verkleinert. Aber als "ordentliche Funktion" würde ich das nicht bezeichnen, sondern als reichlich unlogisch und wenig ausgereift.

-Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von wp_xyz »

Ich fürchte, hier wird wieder eine dieser unsinnigen String-Diskussionen losgehen... Aber ich will diese Bemerkungen nicht unkommentiert stehen lassen. Seitdem ich mit Lazarus intensiv arbeite (ca 2010), hatte Lazarus immer UTF8, und FPC hatte ANSI-Strings. Zugegeben, es hat einige Zeit gedauert, bis ich das kapiert habe. Geschätze 95% meiner Arbeit mit Lazarus funktionieren jetzt ohne Probleme. In den restlichen 5% rufe ich explizit Konvertierungsfunktionen auf. Von Chaos und Katastrophe würde ich nicht reden.

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

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Mathias »

@Timm Thaler

Ich denke, du willst am liebsten, das die Zeichen so kommen, wie in dieser ASCII-Tabelle

http://www.thealmightyguru.com/Pointles ... /ASCII.gif
Bild

Unter Windows konnte man da einfach

Code: Alles auswählen

UTFToConsole('ö');
eingeben, aber wie das unter Linux geht weis ich leider auch nicht.

Dazu habe ich noch was komisches endeckt.

Code: Alles auswählen

var
  s: String;
begin
  s := UTF8ToString('ö');
  WriteLn(Length(s));
  WriteLn(Length(UTF8ToString('ö')));
 

Beim ersten Writeln kommt eine "2" und beim zweiten eine "1".
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Michl »

Mathias hat geschrieben:Ich denke, du willst am liebsten, das die Zeichen so kommen, wie in dieser ASCII-Tabelle
Das sieht nach Codepage 437 aus.
In Europa wird oft unter Windows die Codepage 850 für die Console genutzt (zumindest bei mir).
Ändern kann man diese übrigens auch, sogar zu UTF8!

Mathias hat geschrieben:aber wie das unter Linux geht weis ich leider auch nicht.
Das ist ebenfalls recht unkompliziert möglich. Entweder man nutzt SetCodepage oder Methoden der LazUtils. Z.B.:

Code: Alles auswählen

uses ..., LConvEncoding;
...
  s := UTF8Tocp437('äöüØ', True); // enthält jetzt einen Codepage 437 kodierten String
  WriteLn(s, ' - ', Byte(s[4]));
  s := UTF8Tocp850('äöüØ', True); // enthält jetzt einen Codepage 850 kodierten String
  WriteLn(s, ' - ', Byte(s[4]));
Schön zu sehen, was mit dem Ø passiert. Da es in Codepage 437 nicht enthalten ist, wird es durch ein O ersetzt.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Timm Thaler »

Michl hat geschrieben:z.B. sollte es so funktionieren (ungetestet):

Code: Alles auswählen

  txt := UTF8ToWinCP(cbx_send.Text);


Danke, das geht. Ich hab zwar noch nicht ganz verstanden, warum, aber das finde ich noch raus.

Für die einlaufenden Daten geht es andersrum: WinCPToUTF8(Chr(brx)).

Sorry, ich hab seit 20 Jahren nichts mit Pascal gemacht, und unter TP haben wir noch UserInterfaces mit ASCII-Zeichen gebastelt. ;-)

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

Re: Widechars in Shortstring? - mal wieder Probleme mit Stri

Beitrag von Mathias »

Michl hat geschrieben:
Mathias hat geschrieben:Ich denke, du willst am liebsten, das die Zeichen so kommen, wie in dieser ASCII-Tabelle
Das sieht nach Codepage 437 aus.
In Europa wird oft unter Windows die Codepage 850 für die Console genutzt (zumindest bei mir).
Ändern kann man diese übrigens auch, sogar zu UTF8!

Mathias hat geschrieben:aber wie das unter Linux geht weis ich leider auch nicht.
Das ist ebenfalls recht unkompliziert möglich. Entweder man nutzt SetCodepage oder Methoden der LazUtils. Z.B.:

Code: Alles auswählen

uses ..., LConvEncoding;
...
  s := UTF8Tocp437('äöüØ', True); // enthält jetzt einen Codepage 437 kodierten String
  WriteLn(s, ' - ', Byte(s[4]));
  s := UTF8Tocp850('äöüØ', True); // enthält jetzt einen Codepage 850 kodierten String
  WriteLn(s, ' - ', Byte(s[4]));
Schön zu sehen, was mit dem Ø passiert. Da es in Codepage 437 nicht enthalten ist, wird es durch ein O ersetzt.

Danke, jetzt läuft meine OpenGL-Anwendung, welche eine Bitmap-Font verwendet, mit allen ASCII-Zeichen bis 255.
Man lernt immer wieder dazu. :wink:

Was mich aber verwundert, das das Durchmesser Zeichen #237 Mühe macht.

Ist die cp437 der Zeichensatz, welcher fest im BIOS verbaut ist ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten