Search code examples
delphidelphi-7delphi-2010

Delphi unicode porting : Incompatible types: 'Char' and 'AnsiChar' error with Win32 functions like CharToOEM?


I am trying to convert some old Delphi 7 code to Delphi 2010

function AnsiToDOS(S: String): String;
begin
  SetLength(Result, Length(S));
  if S <> '' then begin
     CharToOEM(PChar(S), PChar(Result));
  end;
end;

I get the "Incompatible types: 'Char' and 'AnsiChar' " error at the line:

CharToOEM (external User32 function) found in

Windows.pas unit

Can I rewrite this AnsiToDos function somehow, or do I need to write my own CharToOEM routine?


Solution

  • In Unicode Delphi, CharToOem maps to the Unicode version CharToOemW which has the following signature:

    function CharToOem(Source: PWideChar; Dest: PAnsiChar): BOOL; stdcall;
    

    So you need to supply an ANSI output buffer but your code provides a Unicode output buffer.

    The natural conversion is to switch to an AnsiString return value. At the same time renamed the function as StringToOem to better reflect what it does.

    function StringToOem(const S: String): AnsiString;
    begin
      SetLength(Result, Length(S));
      if S <> '' then begin
        CharToOem(PChar(S), PAnsiChar(Result));
      end;
    end;
    

    An alternative would be to convert to OEM in place, but for this you need to pass in an ANSI string and call the ANSI version of the API call explicitly.

    function AnsiStringToOem(const S: AnsiString): AnsiString;
    begin
      Result := S;
      UniqueString(Result);
      if S <> '' then begin
        CharToOemA(PAnsiChar(Result), PAnsiChar(Result));
      end;
    end;
    

    I do have to comment that I am surprised to see the OEM character set still being actively used in the modern day. I thought it had gone the way of the dinosaurs!