فهرست منبع

* Copy keyboard and mouse units from trunk

git-svn-id: branches/fixes_2_0@3576 -
daniel 19 سال پیش
والد
کامیت
39b4d1f6d8
5فایلهای تغییر یافته به همراه443 افزوده شده و 161 حذف شده
  1. 1 0
      .gitattributes
  2. 32 0
      rtl/inc/video.inc
  3. 48 0
      rtl/unix/convert.inc
  4. 66 28
      rtl/unix/keyboard.pp
  5. 296 133
      rtl/unix/video.pp

+ 1 - 0
.gitattributes

@@ -4223,6 +4223,7 @@ rtl/unix/bunxh.inc svneol=native#text/plain
 rtl/unix/bunxovl.inc svneol=native#text/plain
 rtl/unix/bunxovlh.inc svneol=native#text/plain
 rtl/unix/classes.pp svneol=native#text/plain
+rtl/unix/convert.inc -text
 rtl/unix/crt.pp svneol=native#text/plain
 rtl/unix/cthreads.pp svneol=native#text/plain
 rtl/unix/ctypes.inc svneol=native#text/plain

+ 32 - 0
rtl/inc/video.inc

@@ -76,6 +76,7 @@ begin
     end;
 end;
 
+(*
 Procedure AssignVideoBuf (OldCols, OldRows : Word);
 
 Var NewVideoBuf,NewOldVideoBuf : PVideoBuf;
@@ -109,6 +110,37 @@ begin
   VideoBuf:=NewVideoBuf;
   OldVideoBuf:=NewOldVideoBuf;
 end;
+*)
+Procedure AssignVideoBuf (OldCols, OldRows : Word);
+
+var NewVideoBuf,NewOldVideoBuf:PVideoBuf;
+    old_rowstart,new_rowstart:word;
+
+begin
+  VideoBufSize:=ScreenWidth*ScreenHeight*sizeof(TVideoCell);
+  GetMem(NewVideoBuf,VideoBufSize);
+  GetMem(NewOldVideoBuf,VideoBufSize);
+  {Move contents of old videobuffers to new if there are any.}
+  if VideoBuf<>nil then
+    begin
+      if ScreenWidth<OldCols then
+        OldCols:=ScreenWidth;
+      if ScreenHeight<OldRows then
+        OldRows:=ScreenHeight;
+      old_rowstart:=0;
+      new_rowstart:=0;
+      repeat
+        move(VideoBuf^[old_rowstart],NewVideoBuf^[new_rowstart],OldCols*sizeof(TVideoCell));
+        move(OldVideoBuf^[old_rowstart],NewOldVideoBuf^[new_rowstart],OldCols*sizeof(TVideoCell));
+        inc(old_rowstart,OldCols);
+        inc(new_rowstart,ScreenWidth);
+        dec(OldRows);
+      until OldRows=0;
+    end;
+  FreeVideoBuf;
+  VideoBuf:=NewVideoBuf;
+  OldVideoBuf:=NewOldVideoBuf;
+end;
 
 Procedure InitVideo;
 

+ 48 - 0
rtl/unix/convert.inc

@@ -0,0 +1,48 @@
+const convert_linuxlowascii_to_vga:array[#0..#31] of word=(
+        $0020,$0001,$0002,$0003,$0004,$0005,$0006,$0007,
+        $00db,$0009,$00db,$000b,$006f,$0070,$006e,$002a,
+        $0010,$0011,$0012,$0013,$0014,$0015,$0016,$0017,
+        $0018,$0019,$001a,$0011,$001c,$001d,$001e,$001f
+      );
+      convert_lowascii_to_iso01:array[#0..#31] of word=(
+        $0020,$006f,$006f,$006f,$006f,$006f,$006f,$0020, { $00..$07 }
+        $f861,$006f,$f861,$0064,$006f,$0070,$006e,$002a, { $08..$0f }
+        $003e,$003c,$007c,$0021,$00b6,$00a7,$005f,$007c, { $10..$18 }
+        $0076,$005e,$003e,$003c,$f86d,$f86e,$005e,$0076  { $18..$1f }
+      );
+      convert_cp437_to_iso01:array[#128..#255] of word=(
+        $00c7,$00fc,$00e9,$00e2,$00e4,$00e0,$00e5,$00e7, { $80..$87 }
+        $00ea,$00eb,$00e8,$00ef,$00ee,$00ec,$00c4,$00c5, { $88..$8f }
+        $00c9,$00e6,$00c6,$00f4,$00f6,$00f2,$00fb,$00f9, { $90..$97 }
+        $00ff,$00d6,$00dc,$00a2,$00a3,$00a5,$0050,$0066, { $98..$9f }
+        $00e1,$00ed,$00f3,$00fa,$00f1,$00d1,$00aa,$00ba, { $a0..$a7 }
+        $00bf,$f86c,$00ac,$00bd,$00bc,$00a1,$00ab,$00bb, { $a8..$af }
+        $f861,$f861,$f861,$f878,$f875,$f875,$f875,$f86b, { $b0..$b7 }
+        $f86b,$f875,$f878,$f86b,$f86a,$f86a,$f86a,$f86b, { $b8..$bf }
+        $f86d,$f876,$f877,$f874,$f871,$f86e,$f874,$f874, { $c0..$c7 }
+        $f86d,$f86c,$f876,$f877,$f874,$f871,$f86e,$f876, { $c8..$cf }
+        $f876,$f877,$f877,$f86d,$f86d,$f86c,$f86c,$f86e, { $d0..$d7 }
+        $f86e,$f86a,$f86c,$f861,$f861,$f861,$f861,$f861, { $d8..$df }
+        $0061,$00df,$f86c,$f87b,$0053,$0073,$00b5,$0054, { $e0..$e7 }
+        $00d8,$0054,$004f,$0064,$0049,$00f8,$0065,$006e, { $e8..$ef }
+        $003d,$00b1,$f879,$f87a,$f878,$f878,$00f7,$00b1, { $f0..$f7 }
+        $00b0,$0078,$00b7,$0056,$006e,$00b2,$002a,$00a0  { $f8..$ff }
+      );
+      convert_cp850_to_iso01:array[#128..#255] of word=(
+        $00c7,$00fc,$00e9,$00e2,$00e4,$00e0,$00e5,$00e7, { $80..$87 }
+        $00ea,$00eb,$00e8,$00ef,$00ee,$00ec,$00c4,$00c5, { $88..$8f }
+        $00c9,$00e6,$00c6,$00f4,$00f6,$00f2,$00fb,$00f9, { $90..$97 }
+        $00ff,$00d6,$00dc,$00a2,$00a3,$00a5,$0050,$0066, { $98..$9f }
+        $00e1,$00ed,$00f3,$00fa,$00f1,$00d1,$00aa,$00ba, { $a0..$a7 }
+        $00bf,$f86c,$00ac,$00bd,$00bc,$00a1,$00ab,$00bb, { $a8..$af }
+        $f861,$f861,$f861,$f878,$f875,$00c1,$00c2,$00c0, { $b0..$b7 }
+        $00a9,$f875,$f878,$f86b,$f86a,$00a2,$00a5,$f86b, { $b8..$bf }
+        $f86d,$f876,$f877,$f874,$f871,$f86e,$00e3,$00c3, { $c0..$c7 }
+        $f86d,$f86c,$f876,$f877,$f874,$f871,$f86e,$00a4, { $c8..$cf }
+        $00f0,$00d0,$00ca,$00cb,$00c8,$0069,$00cd,$00ce, { $d0..$d7 }
+        $00cf,$f86a,$f86c,$f861,$f861,$00a6,$00cc,$f861, { $d8..$df }
+        $00d3,$00df,$00d4,$00d2,$00f5,$00d5,$00b5,$00fe, { $e0..$e7 }
+        $00de,$00da,$00db,$00d9,$00fd,$00dd,$00af,$00b4, { $e8..$ef }
+        $00ad,$00b1,$f879,$00be,$00b6,$00a7,$00f7,$00b8, { $f0..$f7 }
+        $00b0,$00a8,$00b7,$00b9,$00b3,$00b2,$002a,$00a0  { $f8..$ff }
+      );

+ 66 - 28
rtl/unix/keyboard.pp

@@ -81,6 +81,8 @@ const KbShiftUp    = $f0;
       KbShiftHome  = $f4;
       KbShiftEnd   = $f5;
 
+      double_esc_hack_enabled : boolean = false;
+
 {$ifdef Unused}
 type
    TKeyState = Record
@@ -679,17 +681,25 @@ end;
 function FindSequence(const St : String;var AChar,AScan :byte) : boolean;
 var
   NPT : PTreeElement;
-  i : byte;
+  i,p : byte;
 begin
   FindSequence:=false;
   AChar:=0;
   AScan:=0;
   if St='' then
     exit;
-  NPT:=RootTree[St[1]];
+  p:=1;
+  {This is a distusting hack for certain even more disgusting xterms: Some of
+   them send two escapes for an alt-key. If we wouldn't do this, we would need
+   to put a lot of entries twice in the table.}
+  if double_esc_hack_enabled and (st[1]=#27) and (st[2]='#27') and
+     (st[3] in ['a'..'z','A'..'Z','0'..'9','-','+','_','=']) then
+    inc(p);
+  NPT:=RootTree[St[p]];
+
   if npt<>nil then
     begin
-      for i:=2 to Length(St) do
+      for i:=p+1 to Length(St) do
         begin
           NPT:=FindChild(ord(St[i]),NPT);
           if NPT=nil then
@@ -1037,8 +1047,12 @@ var
   store    : array [0..8] of char;
   arrayind : byte;
   NPT,NNPT : PTreeElement;
+
+
   procedure GenMouseEvent;
+
   var MouseEvent: TMouseEvent;
+
   begin
     Fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
     case ch of
@@ -1105,41 +1119,62 @@ begin
     PushKey(ch)
   else
     begin
-     fpFD_ZERO(fdsin);
-     fpFD_SET(StdInputHandle,fdsin);
-     store[0]:=ch;
-     arrayind:=1;
+      fpFD_ZERO(fdsin);
+      fpFD_SET(StdInputHandle,fdsin);
+      store[0]:=ch;
+      arrayind:=1;
       while assigned(NPT) and syskeypressed do
         begin
           if inhead=intail then
             fpSelect(StdInputHandle+1,@fdsin,nil,nil,10);
           ch:=ttyRecvChar;
-          NNPT:=FindChild(ord(ch),NPT);
-          if assigned(NNPT) then
-            begin
-              NPT:=NNPT;
-              if NPT^.CanBeTerminal and
-                 assigned(NPT^.SpecialHandler) then
-                break;
-            End;
-          if ch<>#0 then
-            begin
-              store[arrayind]:=ch;
-              inc(arrayind);
-            end;
-          if not assigned(NNPT) then
+          if (ch=#27) and double_esc_hack_enabled then
             begin
-              if ch<>#0 then
+              {This is the same hack as in findsequence; see findsequence for
+               explanation.}
+              ch:=ttyrecvchar;
+              {Alt+O cannot be used in this situation, it can be a function key.} 
+              if not(ch in ['a'..'z','A'..'N','P'..'Z','0'..'9','-','+','_','=']) then
                 begin
-                  { Put that unused char back into InBuf }
-                  If InTail=0 then
-                    InTail:=InSize-1
+                  if intail=0 then
+                    intail:=insize
                   else
-                    Dec(InTail);
-                  InBuf[InTail]:=ch;
+                    dec(intail);
+                  inbuf[intail]:=ch;
+                  ch:=#27;
+                end
+              else
+                begin
+                  write(#27'[?1036l');
+                  double_esc_hack_enabled:=false;
                 end;
-              break;
             end;
+           NNPT:=FindChild(ord(ch),NPT);
+           if assigned(NNPT) then
+             begin
+               NPT:=NNPT;
+               if NPT^.CanBeTerminal and
+                  assigned(NPT^.SpecialHandler) then
+                 break;
+             End;
+           if ch<>#0 then
+             begin
+               store[arrayind]:=ch;
+               inc(arrayind);
+             end;
+           if not assigned(NNPT) then
+             begin
+               if ch<>#0 then
+                 begin
+                   { Put that unused char back into InBuf }
+                   If InTail=0 then
+                     InTail:=InSize-1
+                   else
+                     Dec(InTail);
+                   InBuf[InTail]:=ch;
+                 end;
+               break;
+             end;
         end;
       if assigned(NPT) and NPT^.CanBeTerminal then
         begin
@@ -1250,7 +1285,10 @@ begin
       if copy(fpgetenv('TERM'),1,5)='xterm' then
           {The alt key should generate an escape prefix. Save the old setting
            make make it send that escape prefix.}
+        begin
           write(#27'[?1036s'#27'[?1036h');
+          double_esc_hack_enabled:=true;
+        end;
 {$ifdef linux}
     end;
 {$endif}

+ 296 - 133
rtl/unix/video.pp

@@ -13,7 +13,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
  **********************************************************************}
-unit Video;
+unit video;
 
 {$I-}
 {$GOTO on}
@@ -24,6 +24,35 @@ unit Video;
 
 {$i videoh.inc}
 
+type  Tencoding=(cp437,         {Codepage 437}
+                 cp850,         {Codepage 850}
+                 cp852,         {Codepage 852}
+                 cp866,         {Codepage 866}
+                 koi8r,         {KOI8-R codepage}
+                 iso01,         {ISO 8859-1}
+                 iso02,         {ISO 8859-2}
+                 iso03,         {ISO 8859-3}
+                 iso04,         {ISO 8859-4}
+                 iso05,         {ISO 8859-5}
+                 iso06,         {ISO 8859-6}
+                 iso07,         {ISO 8859-7}
+                 iso08,         {ISO 8859-8}
+                 iso09,         {ISO 8859-9}
+                 iso10,         {ISO 8859-10}
+                 iso13,         {ISO 8859-13}
+                 iso14,         {ISO 8859-14}
+                 iso15);        {ISO 8859-15}
+
+const  {Contains all code pages that can be considered a normal vga font.
+        Note: KOI8-R has line drawing characters in wrong place. Support
+              can perhaps be added, for now we'll let it rest.}
+       vga_codepages=[cp437,cp850,cp852,cp866];
+       iso_codepages=[iso01,iso02,iso03,iso04,iso05,iso06,iso07,iso08,
+                      iso09,iso10,iso13,iso14,iso15];
+
+var internal_codepage,external_codepage:Tencoding;
+
+
 {*****************************************************************************}
                                 implementation
 {*****************************************************************************}
@@ -32,7 +61,7 @@ uses  baseunix,termio,strings
      {$ifdef linux},linuxvcs{$endif};
 
 {$i video.inc}
-
+{$i convert.inc}
 
 type  Tconsole_type=(ttyNetwork
                      {$ifdef linux},ttyLinux{$endif}
@@ -40,7 +69,9 @@ type  Tconsole_type=(ttyNetwork
                      ,ttyNetBSD);
 
       Tconversion=(cv_none,
-                   cv_vga_to_acs);
+                   cv_cp437_to_iso01,
+                   cv_cp850_to_iso01,
+                   cv_linuxlowascii_to_vga);
 
       Ttermcode=(
         enter_alt_charset_mode,
@@ -48,7 +79,8 @@ type  Tconsole_type=(ttyNetwork
         clear_screen,
         cursor_home,
         cursor_normal,
-        cursor_visible,
+        cursor_visible_underline,
+        cursor_visible_block,
         cursor_invisible,
         enter_ca_mode,
         exit_ca_mode,
@@ -64,7 +96,8 @@ const term_codes_ansi:Ttermcodes=
          #$1B#$5B#$48#$1B#$5B#$4A,                          {clear_screen}
          #$1B#$5B#$48,                                      {cursor_home}
          nil,                                               {cursor_normal}
-         nil,                                               {cursor_visible}
+         nil,                                               {cursor visible, underline}
+         nil,                                               {cursor visible, block}
          nil,                                               {cursor_invisible}
          nil,                                               {enter_ca_mode}
          nil,                                               {exit_ca_mode}
@@ -77,7 +110,8 @@ const term_codes_ansi:Ttermcodes=
          #$1B#$5B#$48#$1B#$5B#$4A,                          {clear_screen}
          #$1B#$5B#$48,                                      {cursor_home}
          #$1B#$5B#$3D#$30#$43,                              {cursor_normal}
-         #$1B#$5B#$3D#$31#$43,                              {cursor_visible}
+         #$1B#$5B#$3D#$31#$43,                              {cursor visible, underline}
+         #$1B#$5B#$3D#$31#$43,                              {cursor visible, block}
          nil,                                               {cursor_invisible}
          nil,                                               {enter_ca_mode}
          nil,                                               {exit_ca_mode}
@@ -89,9 +123,10 @@ const term_codes_ansi:Ttermcodes=
          #$1B#$5B#$31#$30#$6D,                              {exit_alt_charset_mode}
          #$1B#$5B#$48#$1B#$5B#$4A,                          {clear_screen}
          #$1B#$5B#$48,                                      {cursor_home}
-         #$1B#$5B#$3F#$32#$35#$68#$1B#$5B#$3F#$30#$63,      {cursor_normal}
-         #$1B#$5B#$3F#$32#$35#$68#$1B#$5B#$3F#$30#$63,      {cursor_visible}
-         #$1B#$5B#$3F#$32#$35#$6C,                          {cursor_invisible}
+         #$1B'[?25h'#$1B'[?0c',                             {cursor_normal}
+         #$1B'[?0c',                                        {cursor visible, underline}
+         #$1B'[?17;0;127c',                                 {cursor visible, block}
+         #$1B'[?1c',                                        {cursor_invisible}
          nil,                                               {enter_ca_mode}
          nil,                                               {exit_ca_mode}
          nil,                                               {exit_am_mode}
@@ -103,7 +138,8 @@ const term_codes_ansi:Ttermcodes=
          #$1B#$5B#$48#$1B#$5B#$4A{#$24#$3C#$35#$30#$3E},    {clear_screen}
          #$1B#$5B#$48,                                      {cursor_home}
          nil,                                               {cursor_normal}
-         nil,                                               {cursor_visible}
+         nil,                                               {cursor visible, underline}
+         nil,                                               {cursor visible, block}
          nil,                                               {cursor_invisible}
          nil,                                               {enter_ca_mode}
          nil,                                               {exit_ca_mode}
@@ -116,7 +152,8 @@ const term_codes_ansi:Ttermcodes=
          #$1B#$5B#$48#$1B#$5B#$4A,                          {clear_screen}
          #$1B#$5B#$48,                                      {cursor_home}
          nil,                                               {cursor_normal}
-         nil,                                               {cursor_visible}
+         nil,                                               {cursor visible, underline}
+         nil,                                               {cursor visible, block}
          nil,                                               {cursor_invisible}
          nil,                                               {enter_ca_mode}
          nil,                                               {exit_ca_mode}
@@ -129,7 +166,8 @@ const term_codes_ansi:Ttermcodes=
          #$1B#$5B#$48#$1B#$5B#$32#$4A,                      {clear_screen}
          #$1B#$5B#$48,                                      {cursor_home}
          #$1B#$5B#$3F#$31#$32#$6C#$1B#$5B#$3F#$32#$35#$68,  {cursor_normal}
-         #$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68,              {cursor_visible}
+         #$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68,              {cursor visible, underline}
+         #$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68,              {cursor visible, block}
          #$1B#$5B#$3F#$32#$35#$6C,                          {cursor_invisible}
          #$1B#$5B#$3F#$31#$30#$34#$39#$68,                  {enter_ca_mode}
          #$1B#$5B#$3F#$31#$30#$34#$39#$6C,                  {exit_ca_mode}
@@ -242,24 +280,17 @@ begin
 end;
 
 
-function SendEscapeSeqNdx(Ndx:Ttermcode) : boolean;
-var
-  P{,pdelay}:PChar;
+procedure SendEscapeSeqNdx(ndx:Ttermcode);
+
+var p:PChar;
+
 begin
-  SendEscapeSeqNdx:=false;
+{ Always true because of vt100 default.
   if not assigned(cur_term_Strings) then
-    exit{RunError(219)};
-  P:=cur_term_Strings^[Ndx];
-  if assigned(p) then
-   begin { Do not transmit the delays }
-{     pdelay:=strpos(p,'$<');
-     if assigned(pdelay) then
-       pdelay^:=#0;}
-     fpWrite(stdoutputhandle, P^, StrLen(P));
-     SendEscapeSeqNdx:=true;
-{     if assigned(pdelay) then
-       pdelay^:='$';}
-   end;
+    exit}{RunError(219)};
+  p:=cur_term_strings^[ndx];
+  if p<>nil then
+    fpwrite(stdoutputhandle,p^,strlen(p));
 end;
 
 
@@ -325,18 +356,17 @@ begin
   xy2ansi:=#27'['+movement+direction;
 end;
 
-
-
 const  ansitbl:array[0..7] of char='04261537';
 
-Function Attr2Ansi(Attr,OAttr:longint):string;
+{$ifdef disabled}
+Function Attr2Ansi(Attr,OAttr:byte):string;
 {
   Convert Attr to an Ansi String, the Optimal code is calculate
   with use of the old OAttr
 }
 var
   hstr : string[16];
-  OFg,OBg,Fg,Bg : longint;
+  OFg,OBg,Fg,Bg:byte;
 
   procedure AddSep(ch:char);
   begin
@@ -356,12 +386,16 @@ begin
   Bg:=Attr shr 4;
   OFg:=OAttr and $f;
   OBg:=OAttr shr 4;
+{  This resets colours to their defaults, the problem is we don't know what
+  the default is, i.e. it can either be white on black or back on white or
+  even something totally different. This causes undesired colour schemes
+  in the IDE on some terminals.
   if (OFg<>7) or (Fg=7) or ((OFg>7) and (Fg<8)) or ((OBg>7) and (Bg<8)) then
    begin
      hstr:='0';
      OFg:=7;
      OBg:=0;
-   end;
+   end;}
   if (Fg>7) and (OFg<8) then
    begin
      AddSep('1');
@@ -386,6 +420,50 @@ begin
    hstr:='';
   Attr2Ansi:=#27'['+hstr+'m';
 end;
+{$endif}
+
+function attr2ansi(attr,oattr:byte):string;
+
+var OFg,OBg,Fg,Bg:byte;
+
+begin
+  Fg:=Attr and $f;
+  Bg:=Attr shr 4;
+  OFg:=OAttr and $f;
+  OBg:=OAttr shr 4;
+  attr2ansi:=#27'[';
+  if fg and 8<>0 then
+    begin
+      {Enable bold if not yet on.}
+      if ofg and 8=0 then
+        attr2ansi:=attr2ansi+'1;';
+    end
+  else
+    {Disable bold if on.}
+    if ofg and 8<>0 then
+      attr2ansi:=attr2ansi+'22;';
+  if bg and 8<>0 then
+    begin
+      {Enable bold if not yet on.}
+      if obg and 8=0 then
+        attr2ansi:=attr2ansi+'5;';
+    end
+  else
+    {Disable bold if on.}
+    if obg and 8<>0 then
+      attr2ansi:=attr2ansi+'25;';
+
+  if fg and 7<>ofg and 7 then
+     attr2ansi:=attr2ansi+'3'+ansitbl[fg and 7]+';';
+  if bg and 7<>obg and 7 then
+     attr2ansi:=attr2ansi+'4'+ansitbl[bg and 7]+';';
+
+  if attr2ansi[length(attr2ansi)]=';' then
+    attr2ansi[length(attr2ansi)]:='m'
+  else
+   attr2ansi:='';
+end;
+
 
 procedure UpdateTTY(Force:boolean);
 type
@@ -412,24 +490,30 @@ var
   p,pold   : pvideocell;
   LastLineWidth : Longint;
 
-  procedure transform_using_acs(var st:string);
+  function transform_cp437_to_iso01(const st:string):string;
 
-  var res:string;
-      i:byte;
+  var i:byte;
       c:char;
       converted:word;
 
   begin
-    res:='';
+    transform_cp437_to_iso01:='';
     for i:=1 to length(st) do
       begin
         c:=st[i];
-        converted:=convert_vga_to_acs(c);
+        case c of
+          #0..#31:
+            converted:=convert_lowascii_to_iso01[c];
+          #128..#255:
+            converted:=convert_cp437_to_iso01[c];
+          else
+            converted:=byte(c);
+        end;
         if converted and $ff00=$f800 then
           begin
             if not in_ACS then
               begin
-                res:=res+ACSIn;
+                transform_cp437_to_iso01:=transform_cp437_to_iso01+ACSIn;
                 in_ACS:=true;
               end;
             c:=char(converted and $ff);
@@ -437,17 +521,92 @@ var
         else
           if in_ACS then
             begin
-              res:=res+ACSOut+Attr2Ansi(LastAttr,0);
+              transform_cp437_to_iso01:=transform_cp437_to_iso01+ACSOut+
+                                        Attr2Ansi(LastAttr,0);
+              in_ACS:=false;
+            end;
+        transform_cp437_to_iso01:=transform_cp437_to_iso01+c;
+      end;
+  end;
+
+  function transform_cp850_to_iso01(const st:string):string;
+
+  var i:byte;
+      c:char;
+      converted:word;
+
+  begin
+    transform_cp850_to_iso01:='';
+    for i:=1 to length(st) do
+      begin
+        c:=st[i];
+        case c of
+          #0..#31:
+            converted:=convert_lowascii_to_iso01[c];
+          #128..#255:
+            converted:=convert_cp850_to_iso01[c];
+          else
+            converted:=byte(c);
+        end;
+        if converted and $ff00=$f800 then
+          begin
+            if not in_ACS then
+              begin
+                transform_cp850_to_iso01:=transform_cp850_to_iso01+ACSIn;
+                in_ACS:=true;
+              end;
+          end
+        else
+          if in_ACS then
+            begin
+              transform_cp850_to_iso01:=transform_cp850_to_iso01+ACSOut+
+                                        Attr2Ansi(LastAttr,0);
               in_ACS:=false;
             end;
-        res:=res+c;
+        c:=char(converted and $ff);
+        transform_cp850_to_iso01:=transform_cp850_to_iso01+c;
       end;
-    st:=res;
   end;
 
+  function transform_linuxlowascii_to_vga(const st:string):string;
 
+  var i:byte;
+      c:char;
+      converted:word;
+
+  begin
+    transform_linuxlowascii_to_vga:='';
+    for i:=1 to length(st) do
+      begin
+        c:=st[i];
+        case c of
+          #0..#31:
+            converted:=convert_linuxlowascii_to_vga[c];
+          else
+            converted:=byte(c);
+        end;
+        c:=char(converted and $ff);
+        transform_linuxlowascii_to_vga:=transform_linuxlowascii_to_vga+c;
+      end;
+  end;
+
+  function transform(const hstr:string):string;
+
+  begin
+    case convert of
+      cv_linuxlowascii_to_vga:
+        transform:=transform_linuxlowascii_to_vga(hstr);
+      cv_cp437_to_iso01:
+        transform:=transform_cp437_to_iso01(hstr);
+      cv_cp850_to_iso01:
+        transform:=transform_cp850_to_iso01(hstr);
+      else
+        transform:=hstr;
+    end;
+  end;
 
   procedure outdata(hstr:string);
+
   begin
    If Length(HStr)>0 Then
    Begin
@@ -456,8 +615,8 @@ var
        hstr:=#13#10+hstr;
        dec(eol);
      end;
-    if (convert=cv_vga_to_acs) and (ACSIn<>'') and (ACSOut<>'') then
-      transform_using_acs(Hstr);
+{    if (convert=cv_vga_to_acs) and (ACSIn<>'') and (ACSOut<>'') then
+      transform_using_acs(Hstr);}
     move(hstr[1],outbuf[outptr],length(hstr));
     inc(outptr,length(hstr));
     if outptr>=1024 then
@@ -523,7 +682,7 @@ begin
   p:=PVideoCell(VideoBuf);
   pold:=PVideoCell(OldVideoBuf);
 { init Attr, X,Y and set autowrap off }
-  SendEscapeSeq(#27'[m'#27'[?7l'{#27'[H'} );
+  SendEscapeSeq(#27'[0;40;37m'#27'[?7l'{#27'[H'} );
 //  1.0.x: SendEscapeSeq(#27'[m'{#27'[H'});
   LastAttr:=7;
   LastX:=-1;
@@ -553,8 +712,8 @@ begin
               skipped:=false;
             end;
            chattr:=tchattr(p^);
-           if chattr.ch in [#0,#255] then
-            chattr.ch:=' ';
+{           if chattr.ch in [#0,#255] then
+            chattr.ch:=' ';}
            if chattr.ch=' ' then
             begin
               if Spaces=0 then
@@ -572,14 +731,14 @@ begin
             begin
               if (Spaces>0) then
                OutSpaces;
-              if ord(chattr.ch)<32 then
+{              if ord(chattr.ch)<32 then
                 begin
                   Chattr.Attr:= $ff xor Chattr.Attr;
-                  ChAttr.ch:= chr(ord(chattr.ch)+ord('A')-1);
-                end;
+                  ChAttr.ch:=chr(ord(chattr.ch)+ord('A')-1);
+                end;}
               if LastAttr<>chattr.Attr then
                OutClr(chattr.Attr);
-              OutData(chattr.ch);
+              OutData(transform(chattr.ch));
               LastX:=x+1;
               LastY:=y;
             end;
@@ -597,15 +756,15 @@ begin
    end;
   eol:=0;
  {if am in capabilities? Then}
-  If (Console=ttyFreeBSD) and (Plongint(p)^<>plongint(pold)^) Then
-   Begin
+  if (Console=ttyFreeBSD) and (Plongint(p)^<>plongint(pold)^) Then
+   begin
     OutData(XY2Ansi(ScreenWidth,ScreenHeight,LastX,LastY));
     OutData(#8);
     {Output last char}
     chattr:=tchattr(p[1]);
     if LastAttr<>chattr.Attr then
      OutClr(chattr.Attr);
-    OutData(chattr.ch);
+    OutData(transform(chattr.ch));
     inc(LastX);
 //    OutData(XY2Ansi(ScreenWidth-1,ScreenHeight,LastX,LastY));
 //   OutData(GetTermString(Insert_character));
@@ -614,10 +773,20 @@ begin
     chattr:=tchattr(p^);
     if LastAttr<>chattr.Attr then
      OutClr(chattr.Attr);
-    OutData(chattr.ch);
+    OutData(transform(chattr.ch));
     inc(LastX);
    end;
   OutData(XY2Ansi(CursorX+1,CursorY+1,LastX,LastY));
+  if in_ACS then
+    begin
+      {If the program crashes and the ACS is still enabled, the user's
+       keyboard will output strange characters. Therefore we disable the
+       acs after each screen update, so the risk that it happens is greatly
+       reduced.}
+{      SendEscapeSeqNdx(exit_alt_charset_mode);}
+      outdata(acsout);
+      in_acs:=false;
+    end;
 {$ifdef logging}
   blockwrite(f,logstart[1],length(logstart));
   blockwrite(f,nl,1);
@@ -627,8 +796,6 @@ begin
   blockwrite(f,nl,1);
 {$endif logging}
   fpWrite(stdoutputhandle,outbuf,outptr);
-  if in_ACS then
-    SendEscapeSeqNdx(exit_alt_charset_mode);
  {turn autowrap on}
 //  SendEscapeSeq(#27'[?7h');
 end;
@@ -689,7 +856,8 @@ var
   inputRaw, outputRaw: boolean;
 
 procedure saveRawSettings(const tio: termio.termios);
-Begin
+
+begin
   with tio do
    begin
      inputRaw :=
@@ -725,6 +893,44 @@ begin
   TCSetAttr(1,TCSANOW,tio);
 end;
 
+procedure decide_codepages;
+
+var s:string;
+
+begin
+  if external_codepage in vga_codepages then
+    begin
+      {Possible override...}
+      s:=upcase(fpgetenv('CONSOLEFONT_CP'));
+      if s='CP437' then
+        external_codepage:=cp437
+      else if s='CP850' then
+        external_codepage:=cp850;
+    end;
+  {A non-vcsa Linux console can display most control characters, but not all.}
+  if {$ifdef linux}(console<>ttyLinux) and{$endif}
+     (cur_term_strings=@term_codes_linux) then
+    convert:=cv_linuxlowascii_to_vga;
+  case external_codepage of
+    iso01:               {West Europe}
+      begin
+        internal_codepage:=cp850;
+        convert:=cv_cp850_to_iso01;
+      end;
+    iso02:               {East Europe}
+      internal_codepage:=cp852;
+    iso05:               {Cyrillic}
+      internal_codepage:=cp866;
+    else
+      if internal_codepage in vga_codepages then
+        internal_codepage:=external_codepage
+      else
+        {We don't know how to convert to the external codepage. Use codepage
+         437 in the hope that the actual font has similarity to codepage 437.}
+        internal_codepage:=cp437;
+  end;
+end;
+
 
 procedure prepareInitVideo;
 begin
@@ -769,7 +975,7 @@ var
   ThisTTY: String[30];
 {$endif}
 
-const font_vga:array[0..6] of char=#15#27'%@'#27'(U';
+const font_vga:array[0..11] of char=#15#27'%@'#27'(U'#27'[3h';
       font_custom:array[0..2] of char=#27'(K';
 
 begin
@@ -782,6 +988,7 @@ begin
      TTyfd:=-1;
      Console:=TTyNetwork;                 {Default: Network or other vtxxx tty}
      cur_term_strings:=@term_codes_vt100; {Default: vt100}
+     external_codepage:=iso01;            {Default: ISO-8859-1}
    {$ifdef linux}
      if vcs_device>=0 then
        begin
@@ -790,13 +997,19 @@ begin
          { open console, $1b6=rw-rw-rw- }
          ttyfd:=fpopen(fname,$1b6,O_RDWR);
          if ttyfd<>-1 then
-           console:=ttylinux
+           begin
+             console:=ttylinux;
+             external_codepage:=cp437;  {VCSA defaults to codepage 437.}
+           end
          else
            if try_grab_vcsa then
              begin
                ttyfd:=fpopen(fname,$1b6,O_RDWR);
                if ttyfd<>-1 then
-                 console:=ttylinux;
+                 begin
+                   console:=ttylinux;
+                   external_codepage:=cp437;  {VCSA defaults to codepage 437.}
+                 end;
              end;
        end;
    {$endif}
@@ -824,11 +1037,12 @@ begin
             {Executed in case ttylinux is false (i.e. no vcsa), but
              TERM=linux.}
             {Enable the VGA character set (codepage 437,850,....)}
-            fpwrite(stdoutputhandle,font_vga,7);
+            fpwrite(stdoutputhandle,font_vga,sizeof(font_vga));
+            external_codepage:=cp437;  {Now default to codepage 437.}
           end
         else
           {No VGA font :( }
-          fpwrite(stdoutputhandle,font_custom,3);
+          fpwrite(stdoutputhandle,font_custom,sizeof(font_vga));
         { running on a remote terminal, no error with /dev/vcsa }
    {$ifdef linux}
       end;
@@ -855,7 +1069,7 @@ begin
    {$endif}
         SendEscapeSeqNdx(cursor_home);
         SendEscapeSeqNdx(cursor_normal);
-        SendEscapeSeqNdx(cursor_visible);
+        SendEscapeSeqNdx(cursor_visible_underline);
         SendEscapeSeqNdx(enter_ca_mode);
         SetCursorType(crUnderLine);
         If Console=ttyFreeBSD Then
@@ -863,24 +1077,21 @@ begin
    {$ifdef linux}
       end;
    {$endif}
-     if assigned(cur_term_Strings) then
-       begin
+{   Always true because of vt100 default...
+      if assigned(cur_term_Strings) then
+       begin}
          ACSIn:=StrPas(cur_term_strings^[enter_alt_charset_mode]);
          ACSOut:=StrPas(cur_term_strings^[exit_alt_charset_mode]);
          if (ACSIn<>'') and (ACSOut<>'') then
            SendEscapeSeqNdx(ena_acs);
-{         if pos('$<',ACSIn)>0 then
-           ACSIn:=Copy(ACSIn,1,Pos('$<',ACSIn)-1);
-         if pos('$<',ACSOut)>0 then
-           ACSOut:=Copy(ACSOut,1,Pos('$<',ACSOut)-1);}
-         If fpGetEnv('TERM')='xterm' then
-           convert:=cv_vga_to_acs;  {use of acs for xterm is ok}
-       end
+(*         If fpGetEnv('TERM')='xterm' then
+           convert:=cv_vga_to_acs;  {use of acs for xterm is ok}*)
+{       end
      else
        begin
          ACSIn:='';
          ACSOut:='';
-       end;
+       end;}
 {$ifdef logging}
      assign(f,'video.log');
      rewrite(f,1);
@@ -890,6 +1101,8 @@ begin
    end
   else
    ErrorCode:=errVioInit; { not a TTY }
+
+  decide_codepages;
 end;
 
 procedure SysDoneVideo;
@@ -908,7 +1121,7 @@ begin
      SendEscapeSeqNdx(exit_ca_mode);
      SendEscapeSeqNdx(cursor_home);
      SendEscapeSeqNdx(cursor_normal);
-     SendEscapeSeqNdx(cursor_visible);
+     SendEscapeSeqNdx(cursor_visible_underline);
      SendEscapeSeq(#27'[H');
      if cur_term_strings=@term_codes_linux then
        begin
@@ -951,51 +1164,13 @@ var
   i : longint;
   p1,p2 : plongint;
 begin
-(*
-  if not force then
-   begin
-{$ifdef cpui386}
-     asm
-          pushl   %esi
-          pushl   %edi
-          movl    VideoBuf,%esi
-          movl    OldVideoBuf,%edi
-          movl    VideoBufSize,%ecx
-          shrl    $2,%ecx
-          repe
-          cmpsl
-          setne   DoUpdate
-          popl    %edi
-          popl    %esi
-     end;
-{$else not cpui386}
-     p1:=plongint(VideoBuf);
-     p2:=plongint(OldVideoBuf);
-     for i:=0 to VideoBufSize div 2 do
-       if (p1^<>p2^) then
-         begin
-           DoUpdate:=true;
-           break;
-         end
-       else
-         begin
-           { Inc does add sizeof(longint) to both pointer values }
-           inc(p1);
-           inc(p2);
-         end;
-{$endif not cpui386}
-   end
-  else
-   DoUpdate:=true;
-  if not DoUpdate then
-   exit;*)
 {$ifdef linux}
-  if Console=ttylinux then
+  if console=ttylinux then
     update_vcsa(force)
   else
 {$endif}
-    UpdateTTY(force);
-  Move(VideoBuf^, OldVideoBuf^, VideoBufSize);
+    updateTTY(force);
+  move(VideoBuf^,OldVideoBuf^,VideoBufSize);
 end;
 
 
@@ -1040,24 +1215,12 @@ begin
    exit;
   LastCursorType:=NewType;
   case NewType of
-   crBlock :
-     Begin
-       If not SendEscapeSeqNdx(cursor_visible) then
-        If Console<>ttyFreeBSD Then     // should be done only for linux?
-         SendEscapeSeq(#27'[?17;0;64c');
-     End;
-   crHidden :
-     Begin
-       If not SendEscapeSeqNdx(cursor_invisible) then
-        If Console<>ttyFreeBSD Then
-         SendEscapeSeq(#27'[?1c');
-     End;
+    crBlock:
+      SendEscapeSeqNdx(cursor_visible_block);
+    crHidden:
+      SendEscapeSeqNdx(cursor_invisible);
   else
-    begin
-      If not SendEscapeSeqNdx(cursor_normal) then
-        If Console<>ttyFreeBSD Then
-         SendEscapeSeq(#27'[?2c');
-    end;
+    SendEscapeSeqNdx(cursor_normal);
   end;
 end;