Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2009-09

Case error with cirilyc

20 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ригел Rigel

Hello, I am trying to use cirilyc in case operator but error occured: Unit1.pas(45,11) Error: Constant and CASE types do not match (I was write an example but restruction of mail can't allow me to send it) In Delphi 7 everything is ok. When I change cirilyc to latin symbol everything is ok. Will be a fix for this problem in new versions of Lazarus or how can I can fix the problem? I am using Lazarus 0.9.29, FPC 2.3.1, SVN 21708 on Windows Vista 32bit (latest versions and updates).

Reply by email

dmitry boyarintsev
to Ригел Rigel

Rigel, do you mean?

var
  ch : char;
begin
  ch := 'Q';
  case ch of
    'Q': writeln('Q');
    'Z': writeln('Z');
    '?': writelh('?');    // cyrillic character gives the error
  end;
end.

If your unit is new one (created by Lazarus, rather than Delphi), then cyrillic characters are encoded as UTF8 character, that's 2 character strings.

You can achieve the same effect as Delphi, by changing file's encoding to the proper Ansi encoding:
Right Click on the editor -> File Settings -> Encoding -> select the required encoding (current Windows Ansi encoding)
(for example cp1251 for Russian charset)

Changing the encoding should fix the problem, but you might have a side effect on other (non Windows) systems.

thanks,
dmitry

Reply by email

Vincent Snijders
to dmitry boyarintsev
dmitry boyarintsev wrote 23 lines
Rigel, do you mean? var ch : char; begin ch := 'Q'; case ch of 'Q': writeln('Q'); 'Z': writeln('Z'); '?': writelh('?'); // cyrillic character gives the error end; end. If your unit is new one (created by Lazarus, rather than Delphi), then cyrillic characters are encoded as UTF8 character, that's 2 character strings. You can achieve the same effect as Delphi, by changing file's encoding to the proper Ansi encoding: Right Click on the editor -> File Settings -> Encoding -> select the required encoding (current Windows Ansi encoding) (for example cp1251 for Russian charset)

But this does not work if the ch is from a LCL component.

E.g
ch := Label.Caption[1];
Because the caption will be UTF8 encoded.

Vincent

Reply by email

Alexander Klenin
to dmitry boyarintsev
dmitry boyarintsev wrote 9 lines
> But this does not work if the ch is from a LCL component. > > E.g > ch := Label.Caption[1]; > Because the caption will be UTF8 encoded. well, it would work for: ?ch := UTF8Decode(Label.Caption)[1];

It should also work in FPC trunk, since "case of string" is implemented there.

Alexander S. Klenin

Reply by email

Vincent Snijders
to dmitry boyarintsev: well, it would work for: ch := UTF8Decode(Label.Caption)[1]; dmitry
dmitry boyarintsev wrote 8 lines
> But this does not work if the ch is from a LCL component. > > E.g > ch := Label.Caption[1]; > Because the caption will be UTF8 encoded. well, it would work for: ch := UTF8Decode(Label.Caption)[1];

And hope that the widechar to char conversion uses the encoding you thought it would use.

Conclusion, yes it is possible, but you must know what you are doing.

Vincent

Reply by email

Rigel Rigel

Dmitry,

I follow your instruction and now project compiles. But CASE don't effect on cirilyc symbol. In example output is without symbol. Lat symbols are ok.

Vincent, attachment without .exe, .o, .ppu is too big to and again restruction of mail can't allow me to send it.

Example with memo1, memo2, button1:
procedure TForm1.Button1Click(Sender: TObject);
var
  stInp: String;
  stOut: String;
  i: integer;
begin
  stOut := '';
  stInp := Memo1.Lines.Text;
  for i := 1 to length(stInp) do
  Begin
     // Cirilyc case
    case stInp[i] of
      '?': stOut := stOut + 'a'; //Cir
      '?': stOut := stOut + 'b';
      '?': stOut := stOut + 'v';
      '?': stOut := stOut + 'g';
      '?': stOut := stOut + 'd';
      'a': stOut := stOut + 'a'; //Lat
      'b': stOut := stOut + 'b';
      'v': stOut := stOut + 'v';
      'g': stOut := stOut + 'g';
      'd': stOut := stOut + 'd';
    End;
  end;
  stOut := stOut + stInp[i];
  Memo2.Lines.Text := stOut;
end;

Thanks,
Rigel

Show quoted text 41 lines
-------- ?????????? ????? -------- ??: dmitry boyarintsev ???????: Re: [Lazarus] Case error with cirilyc ??: Lazarus mailing list ????????? ??: ?????????, 2009, ????????? 17 08:57:41 EEST Rigel, do you mean? var ch : char; begin ch := 'Q'; case ch of 'Q': writeln('Q'); 'Z': writeln('Z'); '?': writelh('?'); // cyrillic character gives the error end; end. If your unit is new one (created by Lazarus, rather than Delphi), then cyrillic characters are encoded as UTF8 character, that's 2 character strings. You can achieve the same effect as Delphi, by changing file's encoding to the proper Ansi encoding: Right Click on the editor -> File Settings -> Encoding -> select the required encoding (current Windows Ansi encoding) (for example cp1251 for Russian charset) Changing the encoding should fix the problem, but you might have a side effect on other (non Windows) systems. thanks, dmitry -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Rigel Rigel

Dmitry,

I follow your instruction and now project compiles. But CASE don't effect on cirilyc symbol. In example output is without symbol. Lat symbols are ok.

Vincent, attachment without .exe, .o, .ppu is too big to and again restruction of mail can't allow me to send it.

Example with memo1, memo2, button1:
procedure TForm1.Button1Click(Sender: TObject);
var
stInp: String;
stOut: String;
i: integer;
begin
stOut := '';
stInp := Memo1.Lines.Text;
for i := 1 to length(stInp) do
Begin
// Cirilyc case
case stInp[i] of
'?': stOut := stOut + 'a'; //Cir
'?': stOut := stOut + 'b';
'?': stOut := stOut + 'v';
'?': stOut := stOut + 'g';
'?': stOut := stOut + 'd';
'a': stOut := stOut + 'a'; //Lat
'b': stOut := stOut + 'b';
'v': stOut := stOut + 'v';
'g': stOut := stOut + 'g';
'd': stOut := stOut + 'd';
End;
end;
stOut := stOut + stInp[i];
Memo2.Lines.Text := stOut;
end;

Thanks,
Rigel

Show quoted text 9 lines
-------- ?????????? ????? -------- ??: dmitry boyarintsev ???????: Re: [Lazarus] Case error with cirilyc ??: Lazarus mailing list ????????? ??: ?????????, 2009, ????????? 17 08:57:41 EEST Rigel, do you mean?...

Reply by email

dmitry boyarintsev
to Rigel Rigel: I follow your instruction and now project compiles. But CASE don't effect on cirilyc…

As Vincent mentioned earlier, LCL works with UTF8 Encoded strings.

You need to convert Memo.Text to ansi string first:

procedure TForm1.Button1Click(Sender: TObject);
var
?stInp: String;
?stOut: String;
?i: integer;
begin
?stOut := '';
?stInp := UTF8Decode(Memo1.Lines.Text); // convert the string
 ?for i := 1 to length(stInp) do
?Begin
....

thanks,
dmitry

Reply by email

Felipe Monteiro de Carvalho
to dmitry boyarintsev
dmitry boyarintsev wrote
You need to convert Memo.Text to ansi string first:

Maybe you ment convert to widestring, or wanted to use the routine UTF8ToAnsi. UTF8Decode returns a widestring.

If you wanted to use UTF8ToAnsi, then the application won't work in most computers. It may work in the majority of Windows computers in Russia, just like the Delphi solution, but I recommend using a more universal solution.

Felipe Monteiro de Carvalho

Reply by email

theo
to Rigel Rigel: I follow your instruction and now project compiles. But CASE don't effect on cirilyc…

You might try utf8scanner http://wiki.lazarus.freepascal.org/Theodp This should do what you need:

procedure TForm1.Button1Click(Sender: TObject);
var s :TUTF8Scanner;
begin
s := TUTF8Scanner.Create(Memo1.text);
s.FindChars :='?????abvgd';
//Memo1.text:=s.GenerateCaseStatement(); //Writes the case block for you
repeat
case s.FindIndex(s.Next) of
{?} 0: s.Replace('a');
{?} 1: s.Replace('b');
{?} 2: s.Replace('v');
{?} 3: s.Replace('g');
{?} 4: s.Replace('d');
{a} 5: s.Replace('a');
{b} 6: s.Replace('b');
{v} 7: s.Replace('v');
{g} 8: s.Replace('g');
{d} 9: s.Replace('d');
end;
until s.Done;
Memo2.Text := s.UTF8String;
s.free;
end;

Reply by email

Rigel Rigel

It works with lat symbol on the right but if on the right of CASE is cyrillic symbol in Memo2.text shows '?' instead correct symbol.

procedure TForm1.Button1Click(Sender: TObject);
  var
stInp: String;
stOut: String;
i: integer;
begin
stOut := '';
stInp := UTF8Decode(Memo1.Lines.Text); // convert the string
for i := 1 to length(stInp) do
case stInp[i] of
'?': stOut := stOut + '?'; //Cir --> in Memo2 shows '?'
'?': stOut := stOut + '?'; // --> in Memo2 shows '?'
'a': stOut := stOut + 'a'; //Lat --> ok
'b': stOut := stOut + 'b'; // --> ok
End;
stOut := stOut + stInp[i];
// stOut := UTF8Decode(stOut);
// Memo2.Lines.Text := UTF8Decode(stOut);
Memo2.Lines.Text := stOut;
end;
Show quoted text 11 lines
-------- ?????????? ????? -------- ??: dmitry boyarintsev ???????: Re: [Lazarus] Case error with cirilyc ??: Lazarus mailing list ????????? ??: ?????????, 2009, ????????? 17 16:09:03 EEST As Vincent mentioned earlier, LCL works with UTF8 Encoded strings. You need to convert Memo.Text to ansi string first:...

Reply by email

Rigel Rigel

I try it but don't work with cyrillic:
memo1 - ?????; output memo2 - ?????

procedure TForm1.Button1Click(Sender: TObject);
var s :TUTF8Scanner;
begin
s := TUTF8Scanner.Create(Memo1.Text);
s.FindChars :='?????';
// Memo1.text:=s.GenerateCaseStatement(); //Writes the case block for you
repeat
case s.FindIndex(s.Next) of
{?} 0: s.Replace('k');
{?} 1: s.Replace('?');
{?} 2: s.Replace('???');
{?} 3: s.Replace('g');
{?} 4: s.Replace('d');
end;
until s.Done;
Memo2.Text := s.UTF8String;
s.free;
end;
Show quoted text 7 lines
-------- ?????????? ????? -------- ??: theo ???????: Re: [Lazarus] Case error with cirilyc ??: ????????? ??: ?????????, 2009, ????????? 17 22:38:41 EEST You might try utf8scanner http://wiki.lazarus.freepascal.org/Theodp

...

Reply by email

theo
to Rigel Rigel

You should not replace multiple characters with this method like

s.Replace('???');
It works for me, if I write
s.Replace('?');

It outputs: k??gd then

Make sure your file encoding is UTF-8 (standard)

If you really need to replace with ??? then write the output in a second string like you did before.

Reply by email

dmitry boyarintsev
to Rigel Rigel: It works with lat symbol on the right but if on the right of CASE is cyrillic symbol in…

--- with UTF8Scanner ----

If you're using UTF8Scanner, then you should use UTF8 encoded files. You can enable UTF8 encoding the same way, you've enabled Ansi encoding.

But, since you're in Windows, FPC compiler treats all your sources as Ansi, (even if they're UTF8Encoded).
You should add {$codepage UTF8} before 'interface' section, so the compiler knows that UTF8 is used.

--- without UTF8Scanner ----

Rigel Rigel wrote
?It works with lat symbol on the right but if on the right of CASE is cyrillic symbol in Memo2.text shows '?' instead correct symbol.

You're getting '?' character, because LCL is expecting UTF8 Encoded string, while, you're filling stOut with ANSI characters. The code should be the following

procedure TForm1.Button1Click(Sender: TObject);
var
  stInp: String;
  stOut: String;
  i: integer;
begin
 stOut := '';
 stInp := UTF8ToAnsi(Memo1.Lines.Text); { convert the string UTF8
string to Ansi for Case processing }
 for i := 1 to length(stInp) do
 case stInp[i] of // ANSI case processing
 '?': stOut := stOut + '?'; //Cir --> in Memo2 shows '?'
 '?': stOut := stOut + '?'; // --> in Memo2 shows '?'
 'a': stOut := stOut + 'a'; //Lat --> ok
 'b': stOut := stOut + 'b'; // --> ok
 End;
 {stOut is ANSI encoded, LCL expects UTF8Strings, so you need to encode it}
 Memo2.Lines.Text := UTF8Encode(stOut);
end;

There's no explicit difference between Ansi and UTF8 strings. It's up to you, to know, about strings encoding.
Keep in mind, that standard LCL component are ALWAYS using UTF8 encoded strings. For the delphi compatibility you might need to convert them to Ansi strings, but you must convert ansi strings back to UTF8 if you want assign an ANSI string to LCL component.

Also, if you're using Ansi encoded file, you need to convert string constants to the UTF8 as well, for example

Label1.Caption := UTF8Encode('???? ???');
because Label1 as standard LCL component, expects UTF8 string.

The whole "mess" with UTF8/Ansi strings, is about code portability, between platforms.

thanks,
dmitry

Reply by email

Rigel Rigel

Thank you very much, Dmitry! It works.

Best regards,
Rigel

Show quoted text 7 lines
-------- ?????????? ????? -------- ??: dmitry boyarintsev ???????: Re: [Lazarus] Case error with cirilyc ??: Lazarus mailing list ????????? ??: ?????, 2009, ????????? 18 07:22:52 EEST --- with UTF8Scanner ----

.........

Reply by email