Question

I am migrating my Delphi 5 application to Delphi XE3. I am getting some erros while compiling it. Can someone please help me to resolve these. Thanks for help in advance.

  1. I am not able to find defination of function OemToChar in XE3. When I Ctrl+Click on that function it shows message Unable to locate 'WinAPI.Windows.pas'. I am not able to open any delphi component file. What is the location of windows.pas located on the system ? or How to resolve it ?

  2. Incompatiable Types: 'PAnsiChar' and 'PWideChar' in below function on line with OemToChar(p1, p2).

function OemToAnsi(const Str: string): string;
var
  p1,
  p2: PChar;
begin
  p1 := PChar(Str);
  p2 := StrNew(p1);
  OemToChar(p1, p2);
  Result := StrPas(p2);
  StrDispose(p2);
end;
  1. Getting error 'Low Bound Exceeds High Bound' in following code.

function StrToRichText(const Str: string): string;
var
  i: integer;
begin
  Result := '';
  for i := 1 to Length(Str) do
  begin
    case Str[i] of
      #128 .. #255 :
        Result := Result + '\''' + LowerCase(IntToHex(Ord(Str[i]), 2));
      '\','{','}':
        Result := Result + '\' + Str[i];
    else
      Result := Result + Str[i];
    end;
  end;
end;
Était-ce utile?

La solution

Your OemToAnsi function should look like this:

function OemToAnsi(const Str: AnsiString): AnsiString;
begin
  SetLength(Result, Length(Str));
  OemToCharA(PAnsiChar(Str), PAnsiChar(Result));
end;

But perhaps you'd be better with

function OemToWide(const Str: AnsiString): string;
begin
  SetLength(Result, Length(Str));
  OemToChar(PAnsiChar(Str), PChar(Result));
end;

As for your StrToRichText, that looks more difficult. It clearly only accepts ANSI input. If you want to stick with ANSI then just change the declaration to

function StrToRichText(const Str: AnsiString): AnsiString;

RTF is encoded with 7 bit ASCII. To make that function work with Unicode input you'd need to escape any characters with ordinal >= 128. The escaping is described, for example, on the Wikipedia Rich Text Format page. I'll leave that as an exercise for you!


Before you go much further you need to read Marco Cantù's white paper: Delphi and Unicode.

Autres conseils

  1. 'OemToChar()' is declared in 'Winapi.Windows.pas', just like the IDE says. Make sure your uses clause includes Winapi.Windows, or that Winapi is inluded in your Project's "Unit Scope Names" field in the Project Options if the uses clause includes 'Windows' instead (which it likely does since you are migrating).

  2. In D2009+, OemToChar() maps to OemToCharW() now, not to OemToCharA() anymore. The first parameter of both functions is a PAnsiChar. In D2009+, PChar maps to PWideChar now, not to PAnsiChar anymore, so you need to re-write your code accordingly, eg:

    function OemToAnsi(const Str: AnsiString): string;
    var
      S: String;
    begin
      SetLength(S, Length(Str));
      OemToChar(PAnsiChar(Str), PChar(S));
      Result := PChar(S);
    end;
    

    However, you should re-think why you still need to deal with OEM strings in the first place. They don't make as much sense in a Unicode world, and they are rarely even used in an Ansi world.

  3. Another case where you need to re-write the code to account for Char=WideChar now, since character ranges are much larger than Ansi character ranges. You I would use ordinals instead (you should also take UTF-16 surrogates into account properly, but I will leave that as an exercise for you), eg:

    function StrToRichText(const Str: string): string;
    var
      i: integer;
    begin
      Result := '';
      for i := 1 to Length(Str) do
      begin            
        case Ord(Str[i]) of
          128..255:
            Result := Result + '\''' + LowerCase(IntToHex(Ord(Str[i]), 2));
          Ord('\'), Ord('{'), Ord('}'):
            Result := Result + '\' + Str[i];
        else
          Result := Result + Str[i];
        end;
      end;
    end;
    

About Unicode you're already been addressed. There is also a lot of articles in google.


I also suggest you to read about class helpers and record helpers - that might help you with re-introducing some obsoleted functions in libraries, and delaying re-working of the codebase.

That also might help you to override errors like

var r: TRect;
 ....
  with r do begin
 ....
     B := IntersetRect( A1, A2 );
 ....
  end;

Regarding OemToChar - i guest t you'd better use convenient wrappers, that were given in RxLib in Delphi 5 times, then you'd migrate to Jedi Code Library and your code would just not have that problem.

However now you're at XEn - you can perfectly live without that.
http://docwiki.embarcadero.com/Libraries/XE2/en/System.SetCodePage

 var sa, so: RawByteString;
 ....
     sa := source; SetCodePage(sa, GetACP(), true);
     so := sa;     SetCodePage(so, GetOEMCP(), true);

Similar code works in my project, where i parse legacy binary data.

If you only care about one single locale, then you probably can hardcode this.

 var sa: AnsiString[1251]; so: AnsiString[866]; su: UnicodeString;
 ....
     sa := source; 
 ....
     su := sa; // Win32: MultiByteToWideCharBuf - official Microsoft way
     so := su; // Win32: WideCharToMultiByteBuf - official Microsoft way
 ....
     so := sa;  // double conversion in one step
     // did not tested, but should work accorrding to doc.   
     // looks like obsolete Win16 OemToChar
     // and like codepage-to-codepage direct transcoding
     //     routines from JCL.SF.NET
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top