[gelöst] TRichMemo und Umlaute

Rund um die LCL und andere Komponenten
Antworten
meister0815
Beiträge: 43
Registriert: Sa 26. Jun 2010, 17:10

[gelöst] TRichMemo und Umlaute

Beitrag von meister0815 »

Hallöchen,
hab noch ein Problem mit TRichMemo:

Und zwar zählen Umlaute als 2 Zeichen! D.h. wenn ich ein RichMemo habe, in dessen erster Zeile steht: "Über", dann liefert mir RichMemo.GetTextLen "5", während wenn nur "Uber" in der ersten Zeile steht, mir GetTextLen "4" liefert. Habe rumprobiert, und das ist mit allen Umlauten so.

Habe auch die Charsets Ansi und Unicode ausprobiert, ohne Effekt.

Gibt es eine Möglichkeit, diese Doppelzählung zu umgehen?

Falls nicht, wie zähle ich dann die Umlaute? Die folgende Funktion findet keinen einzigen Umlaut:

Code: Alles auswählen

function getUmlautZahl(strs: TStrings): Integer;
var i,j, zahl: Integer;
begin
  zahl:= 0;
  for i:= 0 to strs.Count-1 do
    for j:=0 to length(strs[i])-1 do
      if (copy(strs[i],j,1) = 'ä') or
         (copy(strs[i],j,1) = 'ö') or
         (copy(strs[i],j,1) = 'ü') or
         (copy(strs[i],j,1) = 'Ä') or
         (copy(strs[i],j,1) = 'Ö') or
         (copy(strs[i],j,1) = 'Ü') then
        inc(zahl);
  result:=zahl;
end;


Ich vermute es wird nichts gefunden, weil RichMemo die Umlaute eben nicht als Umlaute, sondern als 2-Zeichenkombination führt.

Bin für jede Hilfe wie immer dankbar!
Viele Grüße, Meister0815
Zuletzt geändert von meister0815 am Di 26. Okt 2010, 17:37, insgesamt 1-mal geändert.

KOBOLD Messring GmbH
Beiträge: 155
Registriert: Mi 22. Aug 2007, 14:52
OS, Lazarus, FPC: Mandriva Linux 2008 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 65719 Hofheim am Taunus
Kontaktdaten:

Re: TRichMemo und Umlaute

Beitrag von KOBOLD Messring GmbH »

Willkommen im Club... der Unicode-geschädigten.
Diese Thema hatten wir schon dutzende Male hier im Forum (und wahrscheinlich millionenfach weltweit).
Kurze Erklärung: Früher war die Welt noch in Ordnung :) denn da hatte jeder Buchstabe ein Byte oder Char und ein String war einfach ein Array Of Char. Nachteil: wir hatten nur 255 Zeichen, arme Leute aus Russland, China, Osteuropa, denn das langte nicht.
Jetzt haben wir Unicode, UTF-8, Multibyte-Zeichensätze. Wir nehmen mal 1 oder auch 2 oder 3 Byte für einen Buchstaben. Die ersten Bits sind jetzt Marker, die sagen ob wir 2 oder 3 Byte brauchen. Siehe das "kleine" Handbuch für Unicode, es hat über 1000 Seiten, denn da steckt mehr dahinter, als man sich träumen lässt.
Altbewährte Pascal-Funktionen, wie Copy, die wirklich Byte-weise arbeiten, funktionieren da natürlich nicht mehr.
Also: Entweder ganz streng Unicode-Buch studieren und die Byte-Marker für die Sonderzeichen raussuchen und Abfragen, oder - falls du wirklich auf die chinesischen etc. Zeichen verzichten willst - kannst Du mit ConvertEncoding aus der Unit LConvEncoding den "alten" Zustand wieder herstellen und den Zeichensatz wieder auf z.B. iso88591 setzen (unser westeuropäischer ANSI-Zeichensatz, so im wesentlichen), dann könnten die "1-Byte-Funktionen" wie Copy wieder greifen. Aber denk dran: sämtliche Lazarus-Komponenten arbeiten intern mit UTF-8 und Du schreibst es selbst im Quelltext-Editor (so jedenfalls der Standard, man kann das alles umstellen, tut sich damit aber keinen Gefallen).
Ich hoffe diese Erklärung hilft Dir und verwirrt nicht noch mehr, ich bin selbst noch immer am verzweifeln darüber und meine eigenen Anwendungen sind oft gespickt mit den ConvertEncodings...

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: TRichMemo und Umlaute

Beitrag von mse »

KOBOLD Messring GmbH hat geschrieben:Willkommen im Club... der Unicode-geschädigten.
An alle "Unicode-geschädigte" die es vielleicht noch nicht wissen:
Eine andere Möglichkeit zur Lösung der meisten Unicode Probleme ist die Verwendung von 16Bit UnicodeString statt utf-8 codierter AnsiString. MSEide+MSEgui hat diesen Weg eingeschlagen.

Martin

meister0815
Beiträge: 43
Registriert: Sa 26. Jun 2010, 17:10

Re: TRichMemo und Umlaute

Beitrag von meister0815 »

Sorry, wenn ich nochmal genauer nachfrage: Ich möchte eigentlich nur einen bestimmten Bereich in dem TRichMemo formatieren. Also das RichMemo ist sowas wie:

Code: Alles auswählen

blablabla blab bla Ä bla 
ü bla blabla Ö bla
ANDERES FORMAT bla bla bla
Um zu formatieren, benötige ich die Methode

Code: Alles auswählen

procedure SetTextAttributes(TextStart, TextLen: Integer; const TextParams: TFontParams);
TextLen und TextParams habe ich, nur der TextStart fehlt mir. Wie finde ich den heraus? Wenn ich die Length der einzelnen Zeilen (1-2) zusammen zähle, komme ich eben je nach Umlaut zum falschen Ergebnis: TextStart ist dann um die Zahl der Umlaute größer, als ich es für SetTextAttributes brauche.

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

Re: TRichMemo und Umlaute

Beitrag von theo »

In Unit LCLProc gibt es die Funktion UTF8Length();
Diese gibt dir die Stringlänge, so wie du sie siehst (Anzahl "Buchstaben").

meister0815
Beiträge: 43
Registriert: Sa 26. Jun 2010, 17:10

Re: TRichMemo und Umlaute

Beitrag von meister0815 »

theo hat geschrieben:In Unit LCLProc gibt es die Funktion UTF8Length();
Diese gibt dir die Stringlänge, so wie du sie siehst (Anzahl "Buchstaben").
Vielen Dank, das hat mir fein geholfen. Damit habe ich die Längen vergleichen können, und so den Unterschied an Länge herausgefunden. :-)

Ist echt super, wie hier im Forum einem immer geholfen! Großes Lob an die aktiven Leutchen :!: :!: :!:

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

Re: TRichMemo und Umlaute

Beitrag von theo »

KOBOLD Messring GmbH hat geschrieben: Ich hoffe diese Erklärung hilft Dir und verwirrt nicht noch mehr, ich bin selbst noch immer am verzweifeln darüber und meine eigenen Anwendungen sind oft gespickt mit den ConvertEncodings...
Das Ganze ist auf dieser Ebene nicht so kompliziert, wie es oft aus Unwissenheit dargestellt wird.
ConvertEncodings sind eigentlich nur dann nötig, wenn man von/nach ANSI Dateien lesen/schreiben will.
Zur internen "Char-weisen" Verarbeitung wechselt man besser auf UCS-2 mit UTF8Decode/Encode. Dann arbeitet man mit WideString weiter.
Aber oft ist auch das nicht nötig, wenn man verstanden hat, wie UTF-8 arbeitet. Denn die alten if Char in Set etc. Methoden haben eigentlich oberhalb dem ASCII Range sowieso ausgedient.

Will sagen: imho ist die Verwirrung oft grösser als das eigentliche Problem. ;-)

Antworten