Crosscompiling: Problem mit Umlauten

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Crosscompiling: Problem mit Umlauten

Beitrag von Aliobaba »

Hallo,

folgende Funktion nutze ich, um aus einem Memo-Feld ein einzelnes Wort, auf dem der Cursor steht, zu gewinnen:

Code: Alles auswählen

Function TForm_keys.Keyword_in_Memo_suchen(keyw : TMemo  ) : string;
var
  i, z, x , k , posit : integer;
  txt, s, res: WideString;
begin
   res := '';
   txt := UTF8Decode(keyw.Text);
   i := keyw.SelStart;
   posit :=  keyw.SelStart;
   s := '';
   repeat
     res := s + res;
     s := Copy(txt, i, 1);
     Dec(i);
   until (s <= ' ') or (i < 0);
   i := keyw.SelStart + 1;
   s := '';
   repeat
     res := res + s;
     s := Copy(txt, i, 1);
     Inc(i);
   until (s <= ' ') or (s = '');
   result := (ansistring(res)) ;
   Edit1.Text:= result;
end;   

Die funktioniert auch sehr gut, allerdings gibt es Probleme mit Umlauten:
Unter Linux (Kubuntu) wird das gewünschte Wort ohne Probleme aus dem Memo-Text extrahiert; kompiliere ich den identischen Code mit einer Windows-Oberfläche, so wird z.B. aus „Schlagwörter“ „Schlagw?rter“ und aus "Kübel" wird "K?bel".

Was mache ich falsch?
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

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

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Michl »

Ich nehme an, du nutzt unter Windows noch ein Lazarus mit FPC 2.6.4? Mit FPC 3.0.0 sollte es so funktionieren, bei FPC 2.6.4 musst du noch von WideString auf UTF8 explizit umwandeln. Für beide unschädlich ist UTF8Encode. So könnte es gehen (ungetestet):

Code: Alles auswählen

//   result := (ansistring(res)) ;
   result := UTF8Encode(res);

Code: Alles auswählen

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

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

Re: Crosscompiling: Problem mit Umlauten

Beitrag von wp_xyz »

Es geht auch ohne das meiner Meinung nach hässliche Umcodieren von UTF8 nach Widestrings und zurück, denn Spaces sind unter UTF8 dasselbe wie unter ANSI. Man muss nur beachten, dass der SelIndex des Memo sich auf den Zeichenindex bezieht, der bei UTF8 nicht identsich mit dem Byteindex sein muss. Aber dafür hat die Unit LazUTF8 die Funktion UTF8CharToByteIndex:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  i, i0: Integer;
  txt, res: String;
begin
   res := '';
   txt := Memo1.Lines.Text;
   // aktuelle Cursorposition als Byte-Index im UTF8-codierten String txt
   i0 := UTF8CharToByteIndex(PChar(txt), Length(txt), Memo1.SelStart);
   // rückwärts laufen bis zum vorigen Leerzeichen
   i := i0;
   while (i > 1) and (txt[i] <> ' ') do begin
     res := txt[i] + res;
     dec(i);
   end;
   // vorwärts laufen bis zum nächsten Leerzeichen
   i := i0 + 1;
   while (i <= Length(txt)) and (txt[i] <> ' ') do begin
     res := res + txt[i];
     inc(i);
   end;
   Edit1.Text := res;
end;

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

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Michl »

Oder wenn man verschiedene Trennzeichen verwenden will könnte man auch sowas machen (wird wohl erst mit FPC 3.0.0 und Lazarus 1.6 aufwärts funktionieren):

Code: Alles auswählen

function WordAtCursor(aMemo: TMemo): string;
 
  function SeparationCodepoint(c: Char): Boolean;
  const
    Separators = '.,;!?/\()''"[]{}-';
  begin
    Result := (c < #33) or (Pos(c, Separators) > 0);
  end;
 
var
  StartOffset: Integer;
  EndOffset: Integer;
  aText: String;
begin
  aText := aMemo.Lines.Text;
  StartOffset := UTF8CharToByteIndex(PChar(aText), Length(aText), aMemo.SelStart);
  EndOffset := StartOffset + 1;
 
  while (StartOffset > 0) and not SeparationCodepoint(aText[StartOffset]) do
    Dec(StartOffset);
 
  while (EndOffset <= Length(aText)) and not SeparationCodepoint(aText[EndOffset]) do
    Inc(EndOffset);
 
  Result := Copy(aText, StartOffset + 1, EndOffset - StartOffset - 1);
end;

Code: Alles auswählen

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

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Aliobaba »

...ich danke Euch sehr für die Hilfe!
Kanns aber grad nicht testen, weil nun plötzlich mein Programm unter Linux startet, unter Windows nicht :(
ich melde mich, wenn ich weiß, woran das liegt. Jedenfalls wird's nicht langweilig, wenn man sich mit nur Halbwissen mit dem Programmieren beschäftigt.

Es ist schon eigenartig: Ich habe ein Startfenster, das dann das "eigentliche Programm" startet.
Alles funktioniert unter Linux einwandfrei; Kompiliert unter Windows sehe ich nach korrekter Anzeige des "Startfensters" von diesem "eigentlichen Programm" nur zwei "ShowMessage-Meldungen", aber sonst nichts.
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

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

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Mathias »

Müsste es diese Funktion nicht schon im Memo fest eingebaut sein ?

Wen man einen Doppelklick auf ein Wort macht, wird diese von Anfang, bis Ende markiert.

Ansonsten, wie wp_xyz schon schreibt, sollte dies ohne Kodierung gehen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Bitschubser
Beiträge: 61
Registriert: Mo 27. Aug 2012, 15:43

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Bitschubser »

wp_xyz hat geschrieben:... denn Spaces sind unter UTF8 dasselbe wie unter ANSI.


Obacht! Das gilt zwar für das Standard-Leerzeichen (ASCII $20), aber wenn das Progamm wirklich international verwendet wird kommen schnell mal andere Spaces vor.
In Japanischen und Chinesischen Unicode-Texten ist z.B. das ideographische Leerzeichen der Standard.

Meine Liste sieht z.Zt. so aus (ohne Anspruch auf Vollständigkeit):

Code: Alles auswählen

type
  TCharElement = record
    Chr  : char;
    Name : string;
  end;
 
const
  Spaces : array [0..17] of TCharElement =
    ((Chr : #$0020; Name : 'U+0020 SPACE'),
     (Chr : #$00A0; Name : 'U+00A0 NO-BREAK SPACE '),
     (Chr : #$1680; Name : 'U+1680 OGHAM SPACE MARK '),
     (Chr : #$2000; Name : 'U+2000 EN QUAD '),
     (Chr : #$2001; Name : 'U+2001 EM QUAD '),
     (Chr : #$2002; Name : 'U+2002 EN SPACE '),
     (Chr : #$2003; Name : 'U+2003 EM SPACE '),
     (Chr : #$2004; Name : 'U+2004 THREE-PER-EM SPACE '),
     (Chr : #$2005; Name : 'U+2005 FOUR-PER-EM SPACE '),
     (Chr : #$2006; Name : 'U+2006 SIX-PER-EM SPACE '),
     (Chr : #$2007; Name : 'U+2007 FIGURE SPACE '),
     (Chr : #$2008; Name : 'U+2008 PUNCTUATION SPACE '),
     (Chr : #$2009; Name : 'U+2009 THIN SPACE '),
     (Chr : #$200A; Name : 'U+200A HAIR SPACE '),
     (Chr : #$200B; Name : 'U+200B ZERO WIDTH SPACE '),
     (Chr : #$202F; Name : 'U+202F NARROW NO-BREAK SPACE '),
     (Chr : #$205F; Name : 'U+205F MEDIUM MATHEMATICAL SPACE '),
     (Chr : #$3000; Name : 'U+3000 IDEOGRAPHIC SPACE '));

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

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Mathias »

Wie funktioniert dies, ein char hat nur 1 Byte ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Bitschubser
Beiträge: 61
Registriert: Mo 27. Aug 2012, 15:43

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Bitschubser »

Mathias hat geschrieben:Wie funktioniert dies, ein char hat nur 1 Byte ?


Ah, sorry, hätte ich dranschreiben sollen:
Das ist Delphi-Code (2010, char = WideChar), unter Lazarus müsste man den Typ entsprechend anpassen.

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Aliobaba »

Hallo,

die Zeile:

Code: Alles auswählen

result := (UTF8Encode(res)) ; 

brachte die Lösung!
Herzlichen Dank an Euch Alle!
Und wenn mal ein Chinese oder ein Japaner sich beschwert, weil's trotzdem nur zu 99,9% funktioniert, dann melde ich mich wieder.
Umlaute sind wirklich "schwere Kost" - aber zu meinem Trost: Es geht offenbar nicht nur mir so.

Noch ein schönes Wochenende!
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

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

Re: Crosscompiling: Problem mit Umlauten

Beitrag von Mathias »

Das ist Delphi-Code (2010, char = WideChar),

Das ist auch wieder ein Stolper falle.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten