Difference between revisions of "Lazarus with FPC3.0 without UTF-8 mode"

From Lazarus wiki
Jump to navigationJump to search
(file encoding + simple example added)
(→‎Simple Example: Console output)
Line 30: Line 30:
 
begin
 
begin
 
   test := 'ÄÖÜ';
 
   test := 'ÄÖÜ';
   writeln(test);
+
   WriteLn(test);
   readln;
+
   ReadLn;
 
end.     
 
end.     
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 37: Line 37:
 
Start your program.
 
Start your program.
  
 +
==Problem System encoding and Console encoding (Windows)==
 +
 +
If you start the simple example, you will maybe see a wrong content for that <code>writeln('ÄÖÜ')</code>. This is because you can have different codepages, for the console and the file system. To check, which codepage you have, you can make a simple test:
 +
<syntaxhighlight>
 +
  Writeln('Console output codepage: ', GetTextCodePage(Output));
 +
  Writeln('System codepage: ', DefaultSystemCodePage); 
 +
</syntaxhighlight>
 +
If your console codepage is a other one than your system codepage, you can change it in that way (original code from [http://forum.lazarus.freepascal.org/index.php/topic,30200.msg191843.html#msg191843 forum])
 +
<syntaxhighlight>
 +
unit setdefaultcodepages;
 +
 +
interface
 +
 +
uses
 +
  Windows;
 +
 +
implementation
 +
 +
Const
 +
  LF_FACESIZE = 32;
 +
 +
Type
 +
  CONSOLE_FONT_INFOEX = record
 +
    cbSize : ULONG;
 +
    nFont : DWORD;
 +
    dwFontSize : COORD;
 +
    FontFamily : UINT;
 +
    FontWeight : UINT;
 +
    FaceName : Array [0..LF_FACESIZE-1] Of WCHAR;
 +
  end;
 +
 +
{ Only supported in Vista and onwards!}
 +
 +
function GetCurrentConsoleFontEx(hConsoleOutput: HANDLE; bMaximumWindow: BOOL; var CONSOLE_FONT_INFOEX): BOOL; stdcall; external kernel32;
 +
function SetCurrentConsoleFontEx(hConsoleOutput: HANDLE; bMaximumWindow: BOOL; var CONSOLE_FONT_INFOEX): BOOL; stdcall; external kernel32;
 +
 +
var
 +
  New_CONSOLE_FONT_INFOEX : CONSOLE_FONT_INFOEX;
 +
 +
initialization
 +
  SetConsoleOutputCP(1252);
 +
  System.SetTextCodePage(Output, 1252);
 +
 +
  FillChar(New_CONSOLE_FONT_INFOEX, SizeOf(CONSOLE_FONT_INFOEX), 0);
 +
  New_CONSOLE_FONT_INFOEX.cbSize := SizeOf(CONSOLE_FONT_INFOEX);
 +
 +
  New_CONSOLE_FONT_INFOEX.FaceName := 'Lucida Console';
 +
  New_CONSOLE_FONT_INFOEX.FontWeight := 700;
 +
 +
  SetCurrentConsoleFontEx(StdOutputHandle, False, New_CONSOLE_FONT_INFOEX);
 +
end. 
 +
</syntaxhighlight>
 +
 +
If you now build a project and use that unit, all strings are correct shown (Strings also Shortstrings). For example:
 +
<syntaxhighlight>
 +
program project1;
 +
 +
{$mode objfpc}{$H+}
 +
{$codepage cp1252}
 +
 +
uses
 +
  setdefaultcodepages;
 +
 +
const
 +
  StrCP1252 = #$80#$C4#$D6#$8C#$A5;
 +
 +
var
 +
  AStr : String;
 +
  AShortString : ShortString;
 +
begin
 +
  AStr := StrCP1252;
 +
  AShortString := StrCP1252;
 +
  WriteLn(StrCP1252);
 +
  WriteLn('€ÄÖŒ¥');
 +
  WriteLn(AStr);
 +
  WriteLn(AShortString);
 +
  ReadLn;
 +
end.
 +
</syntaxhighlight>
  
 
[[Category:FPC 3.0+ stuff]]
 
[[Category:FPC 3.0+ stuff]]

Revision as of 15:18, 30 October 2015

This page explains the problems and their possible solutions when using Lazarus with FPC 3.0+ but without the new UTF-8 mode. It may be needed when big parts of program code depend on system codepage.

To disable the new UTF-8 mode, -dDisableUTF8RTL must be defined in project options, "Additions and Overrides" page. There is a button "Use system encoding" to help adding it with one click. This way it affects both the project and all its dependent packages, including LazUtils which contains the relevant code. If you use strings with codepoints > 127 in your project, you have to change the file encoding to the system encoding too.

Many of the problems are counter-intuitive. Bart has collected some reported issues under a meta-issue. It includes issues in FPC.

ToDo: Explain each problem and a solution for it ...

Simple Example

  • create a New Project -> Simple Program
  • activate the -dDisableUTF8RTL mode with Project Options ... -> Compiler Options -> Additions and Overrides -> click on Use system encoding
  • change the file encoding: Source Editor -> mouse rightclick -> File Settings -> Encoding -> take your system encoding (for that example take 1252) and confirm

Now you are able to build a project without UTF8 dependences.

Write something in your source editor:

program project1;

{$mode objfpc}{$H+}
{$codepage cp1252}

var
  test: String;

begin
  test := 'ÄÖÜ';
  WriteLn(test);
  ReadLn;
end.

Start your program.

Problem System encoding and Console encoding (Windows)

If you start the simple example, you will maybe see a wrong content for that writeln('ÄÖÜ'). This is because you can have different codepages, for the console and the file system. To check, which codepage you have, you can make a simple test:

  Writeln('Console output codepage: ', GetTextCodePage(Output));
  Writeln('System codepage: ', DefaultSystemCodePage);

If your console codepage is a other one than your system codepage, you can change it in that way (original code from forum)

unit setdefaultcodepages;

interface

uses
  Windows;

implementation

Const
  LF_FACESIZE = 32;

Type
  CONSOLE_FONT_INFOEX = record
    cbSize : ULONG;
    nFont : DWORD;
    dwFontSize : COORD;
    FontFamily : UINT;
    FontWeight : UINT;
    FaceName : Array [0..LF_FACESIZE-1] Of WCHAR;
  end;

{ Only supported in Vista and onwards!}

function GetCurrentConsoleFontEx(hConsoleOutput: HANDLE; bMaximumWindow: BOOL; var CONSOLE_FONT_INFOEX): BOOL; stdcall; external kernel32;
function SetCurrentConsoleFontEx(hConsoleOutput: HANDLE; bMaximumWindow: BOOL; var CONSOLE_FONT_INFOEX): BOOL; stdcall; external kernel32;

var
  New_CONSOLE_FONT_INFOEX : CONSOLE_FONT_INFOEX;

initialization
  SetConsoleOutputCP(1252);
  System.SetTextCodePage(Output, 1252);

  FillChar(New_CONSOLE_FONT_INFOEX, SizeOf(CONSOLE_FONT_INFOEX), 0);
  New_CONSOLE_FONT_INFOEX.cbSize := SizeOf(CONSOLE_FONT_INFOEX);

  New_CONSOLE_FONT_INFOEX.FaceName := 'Lucida Console';
  New_CONSOLE_FONT_INFOEX.FontWeight := 700;

  SetCurrentConsoleFontEx(StdOutputHandle, False, New_CONSOLE_FONT_INFOEX);
end.

If you now build a project and use that unit, all strings are correct shown (Strings also Shortstrings). For example:

program project1;

{$mode objfpc}{$H+}
{$codepage cp1252}

uses
  setdefaultcodepages;

const
  StrCP1252 = #$80#$C4#$D6#$8C#$A5;

var
  AStr : String;
  AShortString : ShortString;
begin
  AStr := StrCP1252;
  AShortString := StrCP1252;
  WriteLn(StrCP1252);
  WriteLn('€ÄÖŒ¥');
  WriteLn(AStr);
  WriteLn(AShortString);
  ReadLn;
end.