unit modul_conout;

{$mode objfpc}{$H+}

interface

uses

GlobalTypes,
GlobalConst,
GlobalConfig,
SysUtils,
Console,
Platform,
GraphicsConsole,
IniFiles,

RFreeType;



// the Standard mode is a lage Screen-Char-Matrix
// the fast-graphic-mode make some commands faster with
// the help of graphical operations
{$DEFINE fast_graphic_mode}


// the Standard Screen on CP/M was 80x24 Character
// is this not defined, is the maximum resolution for this monitor used
{$DEFINE cpm_standard_screen_80x24}


// use_invert_display_attributes -> only for WordStar 3 usefull
{$DEFINE use_invert_display_attributes}




const

  Matrix_Col_Max = 100;
  Matrix_Row_Max = 50;


  Dummy_Char = ' ';
  Dummy_FG_COLOR = COLOR_BLACK;
  Dummy_BG_COLOR = COLOR_WHITE;


{$I COLOR_256_DWord.INC}



{
   COLOR_BLACK   = 0;
   COLOR_RED     = 1;
   COLOR_GREEN   = 2;
   COLOR_YELLOW  = 3;
   COLOR_BLUE    = 4;
   COLOR_MAGENTA = 5;
   COLOR_CYAN    = 6;
   COLOR_WHITE   = 7;

}




type




  // Frame-Buffer-Matrix (Bildwiederholspeicher)
  T_FBM_Character = record
                    Character : Char;
                    F_COLOR, B_COLOR : LongWord;
                  end;

  T_FB_Matrix = Array [1..Matrix_Col_Max,1..Matrix_Row_Max] of T_FBM_Character;


  TTermMode = (Normal_TM, IBM_ESC_TM, IBM_CSI_TM, {IBM_CSI_TM_Par, IBM_CSI_TM_Par_Zeile,}
               IBM_CSI_TM_Par_1, IBM_CSI_TM_Par_2, IBM_CSI_TM_Par_3,
               PC1715_ESC_TM, PC1715_TM_Zeile, DCA_TM, DCA_TM_Zeile,
               ADM31_ESC_TM, ADM31_ESC_TM_R, ADM31_ESC_TM_C, ADM31_ESC_ESC,
               ADM31_ESC_ESC_ESC, ADM31_ESC_TM_G, CHANGE_MODE, CHANGE_MODE_EMULATION);

  TEmuMode = (Emu_VT100, EMU_ADM31, Emu_PC1715);






  Tmod_conout = class(TObject)

    constructor Create; overload;
    destructor Destroy; override;

  private

    enable_cursor : Boolean;
    Matrix_Col_Count, Matrix_Row_Count : LongWord;
    Monitor_Width, Monitor_Height : LongWord;
    FB_Matrix : T_FB_Matrix;
    CUR_X, CUR_Y : LongWord;
    TermMode : TTermMode;
    EmuMode : TEmuMode;
    CSI_Parameter1, CSI_Parameter2,
    CSI_Parameter3, ESC_Zeile : LongWord;
    FG_COLOR, BG_COLOR : LongWord;
    Escape_Sequenz : ARRAY [1..20] of Byte;
    Escape_Sequenz_Laenge : Integer;

    procedure switch_Cursor_off;
    procedure switch_Cursor_on;
    procedure Show_Line(Line_Nr : LongWord);
    procedure Show_Matrix;
    procedure Clear_Screen;
    procedure save_INI;

  public
    Cursor_is_on : Boolean;
    procedure Write_Char(B_Char : Byte);
    procedure Write_String(der_Text : String);
    procedure Kursor_umschalten;
    function open_FreeType(FreeType_name : String; FreeType_size : Integer) : Boolean;

  end; // Tmod_conout = class(TObject)



var
  mod_conout : Tmod_conout;
  RFonts : TRFonts;
  GraphicHandle : TWindowHandle;
  Graphics_pos_y : Integer;
  Cursor_to_on : Boolean;
  Cursor_counter : Integer;

  Thread1Handle : TThreadHandle;



  function Thread1Execute(Parameter:Pointer):PtrInt;


  procedure Graphics_Create;
  procedure Graphics_WriteLn(GRA_String : String);
  procedure Graphics_Write_Error(GRA_String : String);



implementation


uses
  modul_itp3;




// ****************************************************************




  function Thread1Execute(Parameter:Pointer):PtrInt;
  begin
    Thread1Execute:=0;

    Cursor_to_on:=false;
    Cursor_counter:=0;

    while true do begin

      sleep(10);

      inc(Cursor_counter);

      if Cursor_counter>28 then begin

        Cursor_counter:=0;
        Cursor_to_on:= not Cursor_to_on;

      end; { if Cursor_counter=30 then }

    end; { while true do }

  end; { function Thread1Execute }





// ****************************************************************






//
procedure Graphics_Create;
begin

  Graphics_pos_y:=10;
  GraphicHandle:=GraphicsWindowCreate(ConsoleDeviceGetDefault, CONSOLE_POSITION_FULLSCREEN);

end; { procedure Graphics_Create }




// ****************************************************************





// sendet einen Text an das Grafik-Fenster
procedure Graphics_WriteLn(GRA_String : String);
begin
  GraphicsWindowDrawText(GraphicHandle,GRA_String,10,Graphics_pos_y);
  Graphics_pos_y:=Graphics_pos_y+20;
end; { procedure Graphics_WiriteLn }





// ****************************************************************





//
procedure Graphics_Write_Error(GRA_String : String);
begin
  GraphicsWindowDrawText(GraphicHandle,'              ',10,10);
  GraphicsWindowDrawText(GraphicHandle,GRA_String,10,10);
end; { procedure Graphics_Write_Error }





// ****************************************************************




constructor Tmod_conout.Create;
var
  FIni : TMemIniFile;
  EmuMode_INT : Integer;

begin
  inherited Create;


  // Initializing


  FG_COLOR := Dummy_FG_COLOR;
  BG_COLOR := Dummy_BG_COLOR;

  Escape_Sequenz_Laenge:=0;

  enable_cursor:=false;

  FramebufferGetPhysical(Monitor_Width, Monitor_Height);



  // INI

  EmuMode := EMU_VT100;

  IF FileExists('C:\RPI_Terminal.ini') then begin
    FIni := TMemIniFile.Create('C:\RPI_Terminal.ini');
    EmuMode_INT := FIni.ReadInteger('Switches', 'EmuMode', 0);

    case EmuMode_INT of
      0 : EmuMode := EMU_VT100;
      1 : EmuMode := EMU_ADM31;
      2 : EmuMode := Emu_PC1715;
    end;

    FIni.Free;

  end { IF FileExists('C:\EMUZ80.ini') then }
  else
    save_INI;



  // Initializing CPM-Emulator

  CUR_X:=1;
  CUR_Y:=1;

  TermMode:=Normal_TM;

  Cursor_is_on:=false;


  Thread1Handle:=BeginThread(@Thread1Execute,nil,Thread1Handle,THREAD_STACK_DEFAULT_SIZE);

  Graphics_WriteLn('Prozess fuer den Kursor wurde gestartet ...');

end; { constructor Tmod_conout.Create }






{==============================================================================}
{==============================================================================}
{TConOut}
function Tmod_conout.open_FreeType(FreeType_name : String; FreeType_size : Integer) : Boolean;
var
  FileExists_FreeType : Boolean;
begin

  if FileExists(FreeType_name+'.ttf') then begin

    FileExists_FreeType:=true;

    Graphics_WriteLn('Font-Datei:'+FreeType_name+'.ttf wurde gefunden ...');

    RFonts := TRFonts.Create;

    RFonts.open_Font(GraphicHandle,FreeType_name, FreeType_size);

    RFonts.Margin_Left:=10;
    RFonts.Margin_Top:=10+RFonts.Font_Height;

    RFonts.System_Bar_Top := 0;

    Matrix_Col_Count:=80;
    Matrix_Row_Count:=24;

  end
  else begin

    FileExists_FreeType:=false;
    Graphics_WriteLn('*** Font-Datei:'+FreeType_name+'.ttf wurde nicht gefunden ...');
    Graphics_WriteLn('*** Terminal-Programm wird beendet ...');

  end; { if FileExists(FreeType_name+'.ttf') then }


  Result:=FileExists_FreeType;


end; { function Tmod_conout.open_FreeType }








{==============================================================================}
{==============================================================================}
{TConOut}
procedure Tmod_conout.switch_Cursor_on;
begin

  RFonts.FT_DrawChar('_', CUR_X, CUR_Y,
                      FB_Matrix[CUR_X,CUR_Y].F_COLOR,
                      FB_Matrix[CUR_X,CUR_Y].B_COLOR);

  Cursor_is_on:=true;

  enable_cursor:=true;

end; { procedure Tmod_conout.switch_Cursor_on }




{==============================================================================}
{==============================================================================}
{TConOut}
procedure Tmod_conout.switch_Cursor_off;
begin

  if enable_cursor then

    RFonts.FT_DrawChar(FB_Matrix[CUR_X,CUR_Y].Character,
                       CUR_X, CUR_Y,
                       FB_Matrix[CUR_X,CUR_Y].F_COLOR,
                       FB_Matrix[CUR_X,CUR_Y].B_COLOR);

  Cursor_is_on:=false;

end; { procedure Tmod_conout.switch_Cursor_off }









{==============================================================================}
{==============================================================================}
{Tmod_conout}
procedure Tmod_conout.Kursor_umschalten;
begin

  if Cursor_is_on then begin
    switch_Cursor_off;
  end
  else begin
    switch_Cursor_on;
  end; { if Cursor_is_on then }

end; { procedure Tmod_conout.Kursor_umschalten }








{==============================================================================}
{==============================================================================}
{Tmod_conout}
procedure Tmod_conout.Show_Line(Line_Nr : LongWord);
var
  counter_x : LongWord;
begin

  for counter_x:=1 to Matrix_Col_Count do begin

    RFonts.FT_DrawChar(
                       FB_Matrix[counter_x,Line_Nr].Character,
                       counter_x,
                       Line_Nr,
                       FB_Matrix[counter_x,Line_Nr].F_COLOR,
                       FB_Matrix[counter_x,Line_Nr].B_COLOR);

  end; { for counter_x:=1 to Matrix_width do }

end; { procedure Tmod_conout.Show_Line }





{==============================================================================}
{==============================================================================}
{Tmod_conout}
procedure Tmod_conout.Show_Matrix;
var
  counter_x, counter_y : LongWord;
begin

  // new !!!
 GraphicsWindowDrawBlock(GraphicHandle,0,RFonts.System_Bar_Top,Monitor_Width-1,
                          Monitor_Height-1,COLOR_White);


  for counter_y:=1 to Matrix_Row_Count do begin

    for counter_x:=1 to Matrix_Col_Count do begin

      RFonts.FT_DrawChar(FB_Matrix[counter_x,counter_y].Character,
                             counter_x, counter_y,
                             FB_Matrix[counter_x,counter_y].F_COLOR,
                             FB_Matrix[counter_x,counter_y].B_COLOR);

    end; { for counter_x:=1 to Matrix_Col_Count do }

  end; { for counter_y:=1 to Matrix_Row_Count do }

end; { procedure Tmod_conout.Show_Matrix }








{==============================================================================}
{==============================================================================}
{Tmod_conout}
// Erase all of the display -- all lines are erased,
// changed to single-width, and the cursor does not move.
procedure Tmod_conout.Clear_Screen;
var
  counter_x, counter_y : LongWord;
begin

  for counter_y:=1 to Matrix_Row_Count do begin

    for counter_x:=1 to Matrix_Col_Count do begin

      FB_Matrix[counter_x,counter_y].Character:=Dummy_Char;
      FB_Matrix[counter_x,counter_y].F_COLOR:=FG_COLOR;
      FB_Matrix[counter_x,counter_y].B_COLOR:=BG_COLOR;

    end; { for counter_x:=1 to Matrix_Col_Count do }

  end; { for counter_y:=1 to Matrix_height do }


  GraphicsWindowDrawBlock(GraphicHandle,0,RFonts.System_Bar_Top,Monitor_Width-1,
                          Monitor_Height-1,COLOR_White);

  // Show_Matrix;


  // cursor does not move ????????????????
  CUR_X:=1;
  CUR_Y:=1;

end; { procedure Tmod_conout.Clear_Screen }







{==============================================================================}
{==============================================================================}
{Tmod_conout}
procedure Tmod_conout.Write_Char(B_Char : Byte);







  function ColorByte_to_ColorLongWord(CtC_Byte : Byte) : LongWord;
  var
    CtC_LongWord : LongWord;
  begin

    // 8 bit Transparency
    CtC_LongWord:=COLOR_256_DWord[CtC_Byte];

    CtC_LongWord:=CtC_LongWord+$FF000000;

    Result:=CtC_LongWord;

  end;









  procedure SCROLL_UP;
  var
    SD_CUR_X, SD_CUR_Y : LongWord;

{$IFDEF fast_graphic_mode}
    lWidth, lHeight, lResult: LongWord; // OT 20170204
    lSource, lDest: TConsolePoint; // OT 20170204
{$ENDIF}

  begin

    for SD_CUR_Y:=1 to Matrix_Row_Count-1 do begin
      for SD_CUR_X:=1 to Matrix_Col_Count do begin
        FB_Matrix[SD_CUR_X,SD_CUR_Y]:=FB_Matrix[SD_CUR_X,SD_CUR_Y+1];
      end;
    end;

    for SD_CUR_X:=1 to Matrix_Col_Count do begin
      FB_Matrix[SD_CUR_X,Matrix_Row_Count].Character:=Dummy_Char;
      FB_Matrix[SD_CUR_X,Matrix_Row_Count].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[SD_CUR_X,Matrix_Row_Count].B_COLOR:=Dummy_BG_COLOR;
    end;

    CUR_X:=1;
    CUR_Y:=Matrix_Row_Count;


{$IFDEF fast_graphic_mode}

    // OT 20170204: do not redraw the graphics screen but scroll it.

    lSource.X := 0;
    lSource.Y := RFonts.System_Bar_Top + RFonts.Margin_Top + RFonts.Font_Height;

    lDest.X := 0;
    lDest.Y := lSource.Y - RFonts.Font_Height;

    lWidth:=Monitor_Width-1;

    lHeight:=(RFonts.Font_Height*(Matrix_Row_Count));

    lResult := GraphicsWindowMoveImage(GraphicHandle, lSource, lDest,
                                       lWidth,lHeight, Dummy_BG_COLOR);

    // clear RFonts.System_Bar_Top + RFonts.Margin_Top
    GraphicsWindowDrawBlock(GraphicHandle,0,0,Monitor_Width-1,
               RFonts.System_Bar_Top+RFonts.Margin_Top+ RFonts.Font_Height-1,Dummy_BG_COLOR);



{$ELSE}

    Show_Matrix;

{$ENDIF}

  end; { procedure SCROLL_UP }





  procedure LINE_FEED;
  begin
    Inc(CUR_Y);
    if CUR_Y>Matrix_Row_Count then begin
      SCROLL_UP;
    end;
    TermMode:=Normal_TM;
  end; { procedure LINE_FEED }





  // Move the cursor to the home position.
  procedure CURSOR_HOME;
  begin
    CUR_X:=1;
    CUR_Y:=1;
    TermMode:=Normal_TM;
  end; { procedure CURSOR_HOME }





  // Move the active position upward one position without altering the horizontal position.
  // If an attempt is made to move the cursor above the top margin, the cursor stops at the top margin.
  procedure CURSOR_UP;
  begin
    DEC(CUR_Y);
    if CUR_Y<1 then begin
      CUR_Y:=1;
    end;
    TermMode:=Normal_TM;
  end; { procedure CURSOR_UP }






  procedure CURSOR_COUNTER_UP(counter : Integer);
  begin

    if CUR_Y>counter then
      CUR_Y:=CUR_Y-counter
    else
      CUR_Y:=1;

    TermMode:=Normal_TM;

  end; { procedure CURSOR_COUNTER_UP }






  // Move the active position downward one position without altering the horizontal position.
  // If an attempt is made to move the cursor below the bottom margin,
  // the cursor stops at the bottom margin.
  procedure CURSOR_DOWN;
  begin
    INC(CUR_Y);
    if CUR_Y>Matrix_Row_Count then begin
      CUR_Y:=Matrix_Row_Count;
    end;
    TermMode:=Normal_TM;
  end; { procedure CURSOR_DOWN }





  procedure CURSOR_COUNTER_DOWN(counter : Integer);
  begin

    if (CUR_Y+counter)<Matrix_Row_Count then
      CUR_Y:=CUR_Y+counter
    else
      CUR_Y:=Matrix_Row_Count;

    TermMode:=Normal_TM;

  end; { procedure CURSOR_COUNTER_DOWN }




  // Move the active position to the right.
  // If an attempt is made to move the cursor to the right of the right margin,
  // the cursor stops at the right margin.
  procedure CURSOR_RIGHT;
  begin

    INC(CUR_X);
    if CUR_X>Matrix_Col_Count then begin
      CUR_X:=Matrix_Col_Count;
    end;

    TermMode:=Normal_TM;

  end; { procedure CURSOR_RIGHT }




  // Move the active position one position to the left.
  // If an attempt is made to move the cursor to the left of the left margin,
  // the cursor stops at the left margin.
  procedure CURSOR_LEFT;
  begin

    DEC(CUR_X);
    if CUR_X<1 then begin
      CUR_X:=1;
    end;

    TermMode:=Normal_TM;

  end; { procedure CURSOR_LEFT }




  procedure CURSOR_TAB;
  begin
    CUR_X:=8 * ((CUR_X div 8) +1);
  end; { procedure CURSOR_TAB }




  procedure CURSOR_FORWARD;
  begin
    CURSOR_RIGHT;
  end; { procedure CURSOR_FORWARD }





  procedure CURSOR_COUNTER_FORWARD(counter : Integer);
  begin

    if (CUR_X+counter)<Matrix_Col_Count then
      CUR_X:=CUR_X+counter
    else
      CUR_X:=Matrix_Col_Count;

    TermMode:=Normal_TM;

  end; { CURSOR_COUNTER_FORWARD }





  procedure CURSOR_BACKWARD;
  begin
    CURSOR_LEFT;
  end; { procedure CURSOR_BACKWARD }






  procedure CURSOR_COUNTER_BACKWARD(counter : Integer);
  begin

    if CUR_X>counter then
      CUR_X:=CUR_X-counter
    else
      CUR_X:=1;

    TermMode:=Normal_TM;

  end; { procedure CURSOR_COUNTER_BACKWARD }





  { *** DELETE *** }



  // Clear line from cursor right
  // Erase all characters from the active position to the end of the current line.
  // The active position is not changed.
  procedure Erase_to_End_of_Line;
  var
    SD_CUR_X : LongWord;
  begin

    for SD_CUR_X:=CUR_X to Matrix_Col_Count do begin
      FB_Matrix[SD_CUR_X,CUR_Y].Character:=Dummy_Char;
      FB_Matrix[SD_CUR_X,CUR_Y].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[SD_CUR_X,CUR_Y].B_COLOR:=Dummy_BG_COLOR;
    end; { for SD_CUR_X:=CUR_X to Matrix_Col_Count do }

    TermMode:=Normal_TM;
    Show_Line(CUR_Y);

  end; { procedure Erase_to_End_of_Line }





  // Erase all characters from the active position to the end of the screen.
  // The active position is not changed.
  procedure Erase_to_End_of_Screen;
  var
    SD_CUR_X, SD_CUR_Y : LongWord;
  begin
    Erase_to_End_of_Line;

    if CUR_Y<Matrix_Row_Count then begin
      for SD_CUR_Y:=CUR_Y+1 to Matrix_Row_Count do begin
         for SD_CUR_X:=1 to Matrix_Col_Count do begin

           FB_Matrix[SD_CUR_X,SD_CUR_Y].Character:=Dummy_Char;
           FB_Matrix[SD_CUR_X,SD_CUR_Y].F_COLOR:=Dummy_FG_COLOR;
           FB_Matrix[SD_CUR_X,SD_CUR_Y].B_COLOR:=Dummy_BG_COLOR;

         end; { for SD_CUR_X:=1 to Matrix_Col_Count do }
      end; { for SD_CUR_Y:=CUR_Y+1 to Matrix_Row_Count do }
    end; { if CUR_Y<Matrix_Row_Count then }

    TermMode:=Normal_TM;
    Show_Matrix;

  end; { procedure Erase_to_End_of_Screen }




  procedure INSERT_CHARACTER;
  var
    SD_CUR_X : LongWord;
  begin

    if CUR_X<Matrix_Col_Count then begin

      for SD_CUR_X:=Matrix_Col_Count downto CUR_X+1 do begin
        FB_Matrix[SD_CUR_X,CUR_Y]:=FB_Matrix[SD_CUR_X-1,CUR_Y];
      end; { for SD_CUR_X:=CUR_X to Matrix_Col_Count do }

    end; { if SD_CUR_X<Matrix_width then }

    FB_Matrix[CUR_X,CUR_Y].Character:=Dummy_Char;
    FB_Matrix[CUR_X,CUR_Y].F_COLOR:=Dummy_FG_COLOR;
    FB_Matrix[CUR_X,CUR_Y].B_COLOR:=Dummy_BG_COLOR;

    TermMode:=Normal_TM;
    Show_Line(CUR_Y);

  end; { procedure INSERT_CHARACTER }




  procedure DELETE_CHARACTER;
  var
    SD_CUR_X : LongWord;
  begin

    for SD_CUR_X:=CUR_X to Matrix_Col_Count-1 do begin
      FB_Matrix[SD_CUR_X,CUR_Y]:=FB_Matrix[SD_CUR_X+1,CUR_Y];
    end; { for SD_CUR_X:=CUR_X to Matrix_Col_Count-1 do }

    TermMode:=Normal_TM;
    Show_Line(CUR_Y);

  end; { procedure DELETE_CHARACTER }




  procedure DELETE_LINE;
  var
    SD_CUR_X : LongWord;
  begin

    for SD_CUR_X:=1 to Matrix_Col_Count do begin
      FB_Matrix[SD_CUR_X,CUR_Y].Character:=Dummy_Char;
      FB_Matrix[SD_CUR_X,CUR_Y].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[SD_CUR_X,CUR_Y].B_COLOR:=Dummy_BG_COLOR;
    end; { for SD_CUR_X:=1 to Matrix_Col_Count do }

    CUR_X:=1;

    TermMode:=Normal_TM;
    Show_Line(CUR_Y);

  end; { procedure DELETE_LINE }






  procedure DELETE_BOL;
  var
    SD_CUR_X : LongWord;
  begin

    for SD_CUR_X:=1 to CUR_X do begin
      FB_Matrix[SD_CUR_X,CUR_Y].Character:=Dummy_Char;
      FB_Matrix[SD_CUR_X,CUR_Y].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[SD_CUR_X,CUR_Y].B_COLOR:=Dummy_BG_COLOR;
    end; { for SD_CUR_X:=1 to CUR_X-1 do }

    TermMode:=Normal_TM;
    Show_Line(CUR_Y);

  end; { procedure DELETE_BOL }



  // Erase from start of the screen to the active position, inclusive
  procedure Erase_from_start_of_the_screen;
  var
    SD_CUR_X, SD_CUR_Y : LongWord;
  begin
    DELETE_BOL;

    if CUR_Y>1 then begin
      for SD_CUR_Y:=1 to CUR_Y-1 do begin
         for SD_CUR_X:=1 to Matrix_Col_Count do begin
           FB_Matrix[SD_CUR_X,SD_CUR_Y].Character:=Dummy_Char;
           FB_Matrix[SD_CUR_X,SD_CUR_Y].F_COLOR:=Dummy_FG_COLOR;
           FB_Matrix[SD_CUR_X,SD_CUR_Y].B_COLOR:=Dummy_BG_COLOR;
         end; { for SD_CUR_X:=1 to Matrix_Col_Count do }
      end; { for SD_CUR_Y:=1 to CUR_Y-1 do }
    end; { if CUR_Y>1 then }

    TermMode:=Normal_TM;
    Show_Matrix;

  end; { procedure Erase_from_start_of_the_screen }





  procedure RUN_BELL;
  begin
    // dummy
  end; { procedure RUN_BELL }



  procedure RUN_DEL;
  begin

    if CUR_X>1 then begin
      Dec(CUR_X);
      FB_Matrix[CUR_X,CUR_Y].Character:=Dummy_Char;
      FB_Matrix[CUR_X,CUR_Y].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[CUR_X,CUR_Y].B_COLOR:=Dummy_BG_COLOR;
    end;

    TermMode:=Normal_TM;
    Show_Line(CUR_Y);

  end; { procedure RUN_DEL }







  procedure DELETE_LINE_SCR_ROLL;
  var
    SD_CUR_X, SD_CUR_Y : LongWord;

{$IFDEF fast_graphic_mode}

    lResult, lWidth, lHeight : LongWord;
    lSource, lDest: TConsolePoint;

{$ENDIF}

  begin

    for SD_CUR_Y:=CUR_Y to Matrix_Row_Count-1 do begin
      for SD_CUR_X:=1 to Matrix_Col_Count do begin
        FB_Matrix[SD_CUR_X,SD_CUR_Y]:=FB_Matrix[SD_CUR_X,SD_CUR_Y+1];
      end; { for SD_CUR_X:=1 to Matrix_Col_Count do }
    end; { for SD_CUR_Y:=CUR_Y to Matrix_height-1 do }

    for SD_CUR_X:=1 to Matrix_Col_Count do begin
      FB_Matrix[SD_CUR_X,Matrix_Row_Count].Character:=Dummy_Char;
      FB_Matrix[SD_CUR_X,Matrix_Row_Count].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[SD_CUR_X,Matrix_Row_Count].B_COLOR:=Dummy_BG_COLOR;
    end; { for SD_CUR_X:=1 to Matrix_Col_Count do }



{$IFDEF fast_graphic_mode}

    { OT 20170211 }


    lSource.X := 0;
    lSource.Y := RFonts.System_Bar_Top + RFonts.Margin_Top +
                 RFonts.Font_Height + (CUR_Y*RFonts.Font_Height);

    lDest.X := 0;
    lDest.Y := lSource.Y - RFonts.Font_Height;

    lWidth:=Monitor_Width-1;
    lHeight:=(RFonts.Font_Height*(Matrix_Row_Count-CUR_Y));

    lResult := GraphicsWindowMoveImage(GraphicHandle, lSource, lDest,
                                       lWidth, lHeight, COLOR_green);


{$ELSE}

    CUR_X:=1;
    Show_Matrix;

{$ENDIF}

    TermMode:=Normal_TM;

  end; { procedure DELETE_LINE_SCR_ROLL }








  procedure INSERT_LINE_SCR_ROLL;
  var
    SD_CUR_X, SD_CUR_Y : LongWord;
  begin

    if CUR_Y<Matrix_Row_Count then begin

      for SD_CUR_Y:=Matrix_Row_Count downto CUR_Y+1 do begin
        for SD_CUR_X:=1 to Matrix_Col_Count do begin
          FB_Matrix[SD_CUR_X,SD_CUR_Y]:=FB_Matrix[SD_CUR_X,SD_CUR_Y-1];
        end; { for SD_CUR_X:=1 to Matrix_Col_Count do }
      end; { for SD_CUR_Y:=Matrix_Row_Count downto CUR_Y+1 do }

    end; { if CUR_Y<Matrix_Row_Count then }

    for SD_CUR_X:=1 to Matrix_Col_Count do begin
      FB_Matrix[SD_CUR_X,CUR_Y].Character:=Dummy_Char;
      FB_Matrix[SD_CUR_X,CUR_Y].F_COLOR:=Dummy_FG_COLOR;
      FB_Matrix[SD_CUR_X,CUR_Y].B_COLOR:=Dummy_BG_COLOR;
    end; { for SD_CUR_X:=1 to Matrix_Col_Count do }

    TermMode:=Normal_TM;
    Show_Matrix;

  end; { procedure INSERT_LINE_SCR_ROLL }






  { ############################################################## }




  procedure Normal_Terminal_Mode;
  begin

    case B_Char of
      $01 : CURSOR_HOME;   // auf Pos 1,1
      $04 : CURSOR_RIGHT;  // rechts
      $05 : CURSOR_UP;     // oben
      $07 : RUN_BELL;      // BELL - Glocke
      $09 : CURSOR_TAB;    // TAB
      $0A : LINE_FEED;     // LF
      $0C : CLEAR_SCREEN;  // CLS - Clear Screen
      $0D : CUR_X:=1;      // CR
      $13 : CURSOR_LEFT;   // links
      $16 : Erase_to_End_of_Line; // ab Cursorposition bis Zeilenende loeschen
      $18 : CURSOR_DOWN;   // unten
      $1B : begin
              case EmuMode of
                Emu_VT100  : TermMode:=IBM_ESC_TM;
                EMU_ADM31  : TermMode:=ADM31_ESC_TM;
                Emu_PC1715 : TermMode:=PC1715_ESC_TM;

              else
                TermMode:= PC1715_ESC_TM;
              end;
            end; { $1B [ESC] }

      $20..$7E : begin

                   RFonts.FT_DrawChar(Char(B_Char), CUR_X,
                                      CUR_Y,FG_COLOR,BG_COLOR);

                   FB_Matrix[CUR_X,CUR_Y].Character:=Char(B_Char);
                   FB_Matrix[CUR_X,CUR_Y].F_COLOR:=FG_COLOR;
                   FB_Matrix[CUR_X,CUR_Y].B_COLOR:=BG_COLOR;

                   // Matrix_Col_Count:=80;
                   // Matrix_Row_Count:=24;
                   Inc(CUR_X);
                   if CUR_X>Matrix_Col_Count then begin
                     CUR_X:=1;
                     Inc(CUR_Y);
                     if CUR_Y>Matrix_Row_Count then begin
                       SCROLL_UP;
                     end;
                   end;

                 //  CURSOR_RIGHT;

                 end; { $20..$7E }

      $7F : RUN_DEL;

    else

    end;

  end; { procedure Normal_Terminal_Mode }






  procedure Escape_Reset;
  begin
    CSI_Parameter1:=0;
    CSI_Parameter2:=0;
    CSI_Parameter3:=0;
    Escape_Sequenz_Laenge:=0;
    TermMode:=Normal_TM;
  end; // Escape_Reset






  procedure Escape_Fehler;
  var
    ESC_Zaehler : Byte;
    ESC_Byte : Byte;
    CUR_X2, CUR_Y2 : LongWord;
  begin

    CSI_Parameter1:=0;
    CSI_Parameter2:=0;
    CSI_Parameter3:=0;
    TermMode:=Normal_TM;

    CUR_Y2:=CUR_Y;
    CUR_Y:=25;
    CUR_X2:=CUR_X;
    CUR_X:=1;


    for ESC_Zaehler:=1 to 20 do begin
      Write_Char($20);
    end;

    CUR_X:=1;

    Write_Char($45); // E
    Write_Char($53); // S
    Write_Char($43); // C

    if Escape_Sequenz_Laenge>0 then begin

      for ESC_Zaehler:=1 to Escape_Sequenz_Laenge do begin
        ESC_Byte:=Escape_Sequenz[ESC_Zaehler];
        Write_Char(ESC_Byte);
      end;

    end;

    Escape_Reset;

    CUR_Y:=CUR_Y2;
    CUR_X:=CUR_X2;

  end; // Escape_Fehler;







  procedure SET_CURSOR_POSITION(Zeile, Spalte : Integer); // bezogen auf 1,1 !!!
  begin


{$IFDEF use_invert_display_attributes}
    if Zeile<1 then
      Zeile:=1;

    if Spalte<1 then
      Spalte:=1;

    CUR_X:=Spalte;
    CUR_Y:=Zeile;
{$ELSE}
    CUR_X:=Spalte+1;
    CUR_Y:=Zeile+1;
{$ENDIF}

    if (CUR_Y>Matrix_Row_Count) then
      CUR_Y:=Matrix_Row_Count;

    if (CUR_X>Matrix_Col_Count) then
      CUR_X:=Matrix_Col_Count;

    TermMode:=Normal_TM;

  end; { procedure SET_CURSOR_POSITION }






  // **********************************
  // ADM31_ESC_Terminal_Mode
  // **********************************


  procedure ADM31_ESC_Terminal_Mode;
  begin
    if B_Char<>$1B then begin

      case B_Char of

        $1B : begin
                TermMode:=ADM31_ESC_ESC; // ESC ESC
              end; { $1B }

        $28 : begin
                // ESC ( = Half intensity off
                // derzeit nicht implementiert
              end; { $28 }

        $29 : begin
                // ESC ) = Half intensity on
                // derzeit nicht implementiert
              end; { $29 }

        $2A : begin
                Clear_Screen; // ESC * = home & clear screen
                TermMode:=Normal_TM;
              end; { $2A }

        $3A : begin
                Clear_Screen; // ESC : = home & clear screen
                TermMode:=Normal_TM;
              end; { $3A }

        $3D : begin
                TermMode:=ADM31_ESC_TM_R; // ESC = R C
              end; { $3D }

        $45 : begin
                LINE_FEED; // ESC E = Insert line
                TermMode:=Normal_TM;
              end; { $45 }

        $47 : begin
                TermMode:=ADM31_ESC_TM_G; // ESC G ...
              end; { $47 }

        $4D : begin
                TermMode:=CHANGE_MODE; // ESC M - Mode fuer EMUZ80
              end; { $4D }

        $51 : begin
                INSERT_CHARACTER; // ESC Q = Insert Character
                TermMode:=Normal_TM;
              end; { $51 }

        $52 : begin
                DELETE_LINE; // ESC R = Delete Line
                TermMode:=Normal_TM;
              end; { $52 }

        $54 : begin
                Erase_to_End_of_Line; // ESC T = Erase to End of Line
                TermMode:=Normal_TM;
              end; { $54 }

        $57 : begin
                DELETE_CHARACTER; // ESC W = Delete Character
                TermMode:=Normal_TM;
              end; { $57 }

        $59 : begin
                Erase_to_End_of_Screen; // ESC Y = Erase to End of Screen
                TermMode:=Normal_TM;
              end; { $59 }

        $74 : begin
                Erase_to_End_of_Line; // ESC t = Erase to End of Line
                TermMode:=Normal_TM;
              end; { $74 }

        $79 : begin
                Erase_to_End_of_Screen; // ESC y = Erase to End of Screen
                TermMode:=Normal_TM;
              end; { $79 }

        else
          TermMode:=Normal_TM;
          Normal_Terminal_Mode;
        end; { case Zeichen of }
      end;

    end; { procedure ADM31_ESC_Terminal_Mode }





    procedure ADM31_ESC_Par_Zeile_Terminal_Mode;
    begin
      if B_Char>=$20 then begin
       // ESC_Zeile:=B_Char-$20;
        TermMode:=ADM31_ESC_TM_C;
      end
      else begin
      //  ESC_SonderZeichen_in_Matrix('=');
        TermMode:=Normal_TM;
      end;
    end; { procedure ADM31_ESC_Par_Zeile_Terminal_Mode }



    procedure ADM31_ESC_Par_Spalte_Terminal_Mode;
    begin
      if B_Char>=$20 then begin
        SET_CURSOR_POSITION(ESC_Zeile, B_Char-$20);
      end
      else begin

      end;
      TermMode:=Normal_TM;
    end; { procedure ADM31_ESC_Par_Spalte_Terminal_Mode }




    procedure ADM31_ESC_ESC_Terminal_Mode;
    begin
      case B_Char of
        $1B : begin
                TermMode:=ADM31_ESC_ESC_ESC;
              end; { $1B }
        $3D : begin
                TermMode:=ADM31_ESC_TM_R; // ESC = R C
              end; { $3D }
        $29 : begin
                // Zeichen - nicht implementiert
              end; { $29 }
        $54 : begin
                // Zeichen - nicht implementiert
              end; { $54 }
      else

        TermMode:=Normal_TM;
      end;

    end; { procedure ADM31_ESC_ESC_Terminal_Mode }




    procedure ADM31_ESC_ESC_ESC_Terminal_Mode;
    begin
      if B_Char=$1B then begin
        // color = Zeichen - nicht implementiert
        TermMode:=Normal_TM;
      end
      else begin

        TermMode:=Normal_TM;
      end;
    end; { procedure ADM31_ESC_ESC_ESC_Terminal_Mode }







    procedure ADM31_ESC_G_Terminal_Mode;
    begin
       case B_Char of
         $00 : begin
                 // ESC G 0 = Rev. video and blinking off, restore normal 80 col char set
                 // nicht implementiert
               end; { $00 }
         $01 : begin
                 // ESC G 1 = select 80 col alternate character set
                 // nicht implementiert
               end; { $01 }
         $02 : begin
                 // ESC G 2 = Blinking on
                 // nicht implementiert
               end; { $02 }
         $04 : begin
                 // ESC G 4 = Reverse video on
                 // nicht implementiert
               end; { $04 }
        else

        end; { case Zeichen of }
       TermMode:=Normal_TM;
    end; { procedure ADM31_ESC_Terminal_Mode }






    // **********************************
    // IBM VT100 Terminal_Mode
    // **********************************


    procedure IBM_ESC_Terminal_Mode;
    begin
      case B_Char of

        $3C : begin // ESC <
                { Enter ANSI Mode    ESC <
                  All subsequent escape sequences will be interpreted
                  according to ANSI Standards X3.64-1977 and X3.41-1974.
                  The VT52 escape sequence designed in this section will
                  not be recognized.
                }
                EmuMode:=Emu_VT100;  // VT52 = ESC < - ENTER_ANSI_MODE
              end; { $3C }


        $3D : begin
                TermMode:=CHANGE_MODE; // ESC = - Mode fuer EMUZ80
              end; { $3D }


        $41 : begin
                 CURSOR_UP;  // VT52 = ESC A - CURSOR_UP
              end; { $41 }

        $42 : begin
                CURSOR_DOWN; // VT52 = ESC B - CURSOR_DOWN
              end; { $42 }

        $43 : begin
                CURSOR_RIGHT; // VT52 = ESC C - CURSOR_RIGHT
              end; { $43 }

        $44 : begin
                CURSOR_LEFT; // VT52 = ESC D - CURSOR_LEFT
              end; { $44 }


        $46 : begin
                // Enter_Graphics_Mode; // VT52 = ESC F - Enter Graphics Mode
              end; { $46 }


        $47 : begin
                // Exit_Graphics_Mode; // VT52 = ESC G - Exit Graphics Mode
              end; { $47 }



        $48 : begin
                CURSOR_HOME; // VT52 = ESC H - Cursor to Home
              end; { $48 }


        $4A : begin
                Erase_to_End_of_Screen; // VT52 = ESC J - Erase to End of Screen
              end; { $4A }


        $4B : begin
                Erase_to_End_of_Line; // VT52 = ESC K - Erase to End of Line
              end; { $4B }


        $59 : begin
                TermMode:=DCA_TM; // VT52 = ESC Y Zeile Spalte - DIRECT_CURSOR_ADRESS
              end; { $59 }

        $5B : begin
                TermMode:=IBM_CSI_TM; // Control Sequence Introducer (CSI) = ESC [
              end; { $5B }

        $63 : begin // VT52 = ESC c - RIS - Reset To Initial State
                CLEAR_SCREEN;
              end; { $63 }



      else

        TermMode:=Normal_TM;
      end; { case Zeichen of }
     end; { procedure ESC_Terminal_Mode }








    procedure Set_Display_Attribute(DispAttr : LongWord);
    begin


      case DispAttr of

        // *** Textattribute ***


        // ESC [ 0 m = Alle Attribute AUS (Reset all attributes)
        0 : begin

              FG_COLOR:=COLOR_BLACK;     // turn off attributes - normal video
              BG_COLOR:=COLOR_WHITE;

            end; { 0 }

        // ESC [ 1 m = Fett ein
        1 : begin
              FG_COLOR:=COLOR_GRAY;
              BG_COLOR:=COLOR_WHITE;
            end;

        // ESC [ 4 m = Unterstreichen
        4 : begin
              FG_COLOR:=COLOR_PURPLE;
              BG_COLOR:=COLOR_WHITE;
            end;

        // ESC [ 5 m = Blinken EIN
        5 : begin
              FG_COLOR:=COLOR_RED;
              BG_COLOR:=COLOR_WHITE;
            end;

        // ESC [ 7 m = Invertierte Darstellung
        7 : begin

{$IFDEF use_invert_display_attributes}
              FG_COLOR:=COLOR_WHITE;
              BG_COLOR:=COLOR_GRAY;
{$ELSE}
              FG_COLOR:=COLOR_BLACK;     // turn off attributes - normal video
              BG_COLOR:=COLOR_WHITE;
{$ENDIF}

            end;

        // ESC [ 8 m = Versteckt ein
        8 : begin
              FG_COLOR:=COLOR_WHITE;
              BG_COLOR:=COLOR_WHITE;
            end;




        // *** Vordergrundfarben ***

        // ESC [ 30 m = Vordergrundfarbe - 30 Schwarz
        30 : FG_COLOR:=COLOR_BLACK;

        // ESC [ 31 m = Vordergrundfarbe - 31 Rot
        31 : FG_COLOR:=COLOR_RED;

        // ESC [ 32 m = Vordergrundfarbe - 32 Gr³n
        32 : FG_COLOR:=COLOR_GREEN;

        // ESC [ 33 m = Vordergrundfarbe - 33 Gelb
        33 : FG_COLOR:=COLOR_YELLOW;

        // ESC [ 34 m = Vordergrundfarbe - 34 Blau
        34 : FG_COLOR:=COLOR_BLUE;

        // ESC [ 35 m = Vordergrundfarbe - 35 Magenta
        35 : FG_COLOR:=COLOR_MAGENTA;

        // ESC [ 36 m = Vordergrundfarbe - 36 Cyanblau
        36 : FG_COLOR:=COLOR_CYAN;

        // ESC [ 37 m = Vordergrundfarbe - 37 Wei▀
        37 : FG_COLOR:=COLOR_WHITE;




        // *** Hintergrundfarben ***

        // ESC [ 40 m = Hintergrundfarbe - 40 Schwarz
        40 : BG_COLOR:=COLOR_BLACK;

        // ESC [ 41 m = Hintergrundfarbe - 41 Rot
        41 : BG_COLOR:=COLOR_RED;

        // ESC [ 42 m = Hintergrundfarbe - 42 Gr³n
        42 : BG_COLOR:=COLOR_GREEN;

        // ESC [ 43 m = Hintergrundfarbe - 43 Gelb
        43 : BG_COLOR:=COLOR_YELLOW;

        // ESC [ 44 m = Hintergrundfarbe - 44 Blau
        44 : BG_COLOR:=COLOR_BLUE;

        // ESC [ 45 m = Hintergrundfarbe - 45 Magenta
        45 : BG_COLOR:=COLOR_MAGENTA;

        // ESC [ 46 m = Hintergrundfarbe - 46 Cyanblau
        46 : BG_COLOR:=COLOR_CYAN;

        // ESC [ 47 m = Hintergrundfarbe - 47 Wei▀
        47 : BG_COLOR:=COLOR_WHITE;

         else

        TermMode:=Normal_TM;
      end;

    end; { procedure Set_Display_Attribute }





    procedure Set_Display_Attribute2(DispAttr1, DispAttr2 : LongWord);
    begin

      Escape_Fehler;
                 {
      Set_Display_Attribute(DispAttr1);
      Set_Display_Attribute(DispAttr2);
                }
    end; { procedure Set_Display_Attribute2 }






    procedure IBM_CSI_Terminal_Mode;
    begin
      case B_Char of

        $30..$39 : begin
                    CSI_Parameter1:=B_Char-$30;
                    TermMode:=IBM_CSI_TM_Par_1;
                  end;

        $48 : begin // Character Attributes = ESC [ H
                 // Move the cursor to the home position.
                CURSOR_HOME;

                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $48 }

        $4A : begin // ESC [ J
                // erase to end of screen (inclusive)
                 Erase_to_End_of_Screen; // Erase to End of Screen

                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $4A }

        $4B : begin // ERASE LINE = ESC [ K
                // Clear line from cursor right
                Erase_to_End_of_Line; // Erase to End of Line
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $4B }

        $6D : begin // Character Attributes = ESC [ m
                Set_Display_Attribute(0);
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $6D }

        $66 : begin // Character Attributes = ESC [ f
                // Move cursor to upper left corner
                CURSOR_HOME;
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $66 }

      else

        Escape_Fehler;

      end;
    end; { procedure IBM_CSI_Terminal_Mode }





    procedure IBM_CSI_Par_1_Terminal_Mode;
    var
      x_counter : Integer;

    begin
      case B_Char of

        $30..$39 : begin
                     CSI_Parameter1:=(CSI_Parameter1*10)+B_Char-$30;
                     TermMode:=IBM_CSI_TM_Par_1;
                   end;

        $3B :      // ";"
    	       // ESC [ Pn1 ; PN2 H oder
    	       // ESC [ Pn1 ; PN2 f oder
                   // ESC [ Pn1 ; PN2 m oder
    	       // Xterm 256 colors - ESC[48;5;BCOLOR m oder
    	       // Xterm 256 colors - ESC[38;5;FCOLOR m
                   TermMode:=IBM_CSI_TM_Par_2;




        $41 : begin // CUU -- Cursor Up = ESC [ Pn A
                CURSOR_COUNTER_UP(CSI_Parameter1);
                TermMode:=Normal_TM;
                CSI_Parameter1:=0;
              end; { $41 }

        $42 : begin // CUD -- Cursor Down = ESC [ Pn B
                CURSOR_COUNTER_DOWN(CSI_Parameter1);
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $42 }

        $43 : begin // CUF -- Cursor Forward  = ESC [ Pn C
                CURSOR_COUNTER_FORWARD(CSI_Parameter1);
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $43 }

        $44 : begin // CUB -- Cursor Backward = ESC [ Pn D
                CURSOR_COUNTER_BACKWARD(CSI_Parameter1);
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $44 }


        $4B : begin // EL -- Erase In Line = ESC [ Pn K
                // Erases some or all characters in the active line according to the parameter.
                case CSI_Parameter1 of
                  0 : Erase_to_End_of_Line; // Erase to End of Line
                  1 : DELETE_BOL;
                  2 : DELETE_LINE;
                else

                end;
                  CSI_Parameter1:=0;
                  TermMode:=Normal_TM;
              end; { $4B }

        $4A : begin // ED -- Erase In Display = ESC [ Pn J
                // This sequence erases some or all of the characters in the
                // display according to the parameter. Any complete line
                // erased by this sequence will return that line to single
                // width mode.
                case CSI_Parameter1 of
                  0 : Erase_to_End_of_Screen;          // Erase to End of Screen
                  1 : Erase_from_start_of_the_screen;  // Erase from start of the screen
                                                       // to the active position, inclusive
                  2 : CLEAR_SCREEN; // erase entire screen (cursor doesn't move)
                else

                end;
                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $4A }


        $4C : begin // INSERT_LINE_SCR_ROLL = ESC [ Pn L
                for x_counter:=0 to CSI_Parameter1-1 do
                  INSERT_LINE_SCR_ROLL;

                CSI_Parameter1:=0;
                TermMode:=Normal_TM;
              end; { $4C }


        $4D : begin // "M" - DELETE_LINE_SCR_ROLL = ESC [ Pn M
                for x_counter:=0 to CSI_Parameter1-1 do
                  DELETE_LINE_SCR_ROLL;

                CSI_Parameter1:=0;
                TermMode:=Normal_TM;

              end; { $4D }


        $6D : begin// "m" Character Attributes = ESC [ Pn m
                Set_Display_Attribute(CSI_Parameter1);
                Escape_Reset;
              end;

      else

        Escape_Fehler;
      end;
    end; { procedure IBM_CSI_Par_1_Terminal_Mode }







    // IBM_CSI_TM_Par_2
    procedure IBM_CSI_Par_2_Terminal_Mode;
    begin

      case B_Char of

        $30..$39 : begin
                     CSI_Parameter2:=(CSI_Parameter2*10)+B_Char-$30;
                     TermMode:=IBM_CSI_TM_Par_2;
                   end;


        $3B : // ";"
              // Xterm 256 colors - ESC[48;5;BCOLOR m
              // Xterm 256 colors - ESC[38;5;FCOLOR m
              TermMode:=IBM_CSI_TM_Par_3;


        $48 : begin
                // "H" -- MOVE CURSOR = ESC [ Pn1 ; PN2 H
                SET_CURSOR_POSITION(CSI_Parameter1,CSI_Parameter2);
                Escape_Reset;
              end;


        $66 : begin
                // "f" -- MOVE CURSOR = ESC [ Pn1 ; PN2 f
                SET_CURSOR_POSITION(CSI_Parameter1,CSI_Parameter2);
                Escape_Reset;
              end;


        $6D : begin
                // "m" -- 2 mal Character Attribute = ESC [ Pn1 ; PN2 m
                Set_Display_Attribute2(CSI_Parameter1,CSI_Parameter2);
                Escape_Reset;
              end;


      else

        Escape_Fehler;

      end; { case Zeichen of }


    end; // IBM_CSI_Par_2_Terminal_Mode






    procedure IBM_CSI_Par_3_Terminal_Mode;
    begin


      case B_Char of

        $30..$39 : begin
                     CSI_Parameter3:=(CSI_Parameter3*10)+B_Char-$30;
                     TermMode:=IBM_CSI_TM_Par_3;
                   end;


        $6D : begin
                // "m"

                case CSI_Parameter1 of

                  48 : // Xterm 256 colors - ESC[48;5;BCOLOR m
                       if CSI_Parameter2=5 then begin
                         BG_COLOR:=ColorByte_to_ColorLongWord(Byte(CSI_Parameter3));
                       end;



                  38 : // Xterm 256 colors - ESC[38;5;FCOLOR m
                       if CSI_Parameter2=5 then begin
                         FG_COLOR:=ColorByte_to_ColorLongWord(Byte(CSI_Parameter3));
                       end;


                else
                  Escape_Fehler;
                end;

                Escape_Reset;

              end; // $6D


      else

        Escape_Fehler;

      end; { case Zeichen of }


    end; // IBM_CSI_Par_3_Terminal_Mode







    // ************
    //    PC1715
    // ************



    procedure PC1715_ESC_Terminal_Mode;
    begin

      case B_Char of
        $80..$89 : begin
                     ESC_Zeile:=B_Char-$80;
                     TermMode:=PC1715_TM_Zeile;
                   end;

        $4D : begin // ESC M - Mode fuer EMUZ80
                TermMode:=CHANGE_MODE;
              end; { $4D }

      else

        TermMode:=Normal_TM;

      end; { case B_Char of }


    end; { procedure PC1715_ESC_Terminal_Mode }




    procedure PC1715_ESC_Zeile_Terminal_Mode;
    begin
      if B_Char>=$80 then begin
        SET_CURSOR_POSITION(ESC_Zeile, B_Char-$80);
      end
      else begin

      end;

      TermMode:=Normal_TM;

    end; { procedure PC1715_ESC_Zeile_Terminal_Mode }





    procedure DCA_Terminal_Mode;
    begin
      if B_Char>=$20 then begin
        ESC_Zeile:=B_Char-$20;
        TermMode:=DCA_TM_Zeile;
      end
      else begin

        TermMode:=Normal_TM;
      end;
    end; { procedure DCA_Terminal_Mode }




    procedure DCA_Terminal_Mode_Zeile;
    begin
      if B_Char>=$20 then begin
        SET_CURSOR_POSITION(ESC_Zeile, B_Char-$20);
      end
      else begin

      end;
      TermMode:=Normal_TM;
    end; { procedure DCA_Terminal_Mode_Zeile }








    // ************************************
    //    CHANGE_MODE for all Emulations
    // ************************************




    procedure CHANGE_MODE_ESC_M_Terminal_Mode;
    begin
      case B_Char of

        $45 : begin // ESC M E ...
                TermMode:=CHANGE_MODE_EMULATION;
              end; { $48 }

      else
        TermMode:=Normal_TM;
      end;
    end; { procedure CHANGE_MODE_ESC_M_Terminal_Mode }



    procedure CHANGE_MODE_ESC_ME_Terminal_Mode;
    begin
      case B_Char of

        $30 : begin // ESC M E 0
                EmuMode:=Emu_VT100;
              end; { $30 }

        $31 : begin // ESC M E 1
                EmuMode:=EMU_ADM31;
              end; { $31 }

        $32 : begin // ESC M E 2
                EmuMode:=Emu_PC1715;
              end; { $32 }

      end; { case B_Char of }

      TermMode:=Normal_TM;

    end; { procedure CHANGE_MODE_ESC_ME_Terminal_Mode }





begin

  mod_itp3.LED_CONOUT_ein;

  Cursor_counter:=0;
  switch_Cursor_off;


  // Abspeichern der Escape-Steuerzeichen fuer die
  // Anzeige der nicht ausgewerteter Sequenzen im Fehlerfall
  if TermMode<>Normal_TM then begin
    INC(Escape_Sequenz_Laenge);
    Escape_Sequenz[Escape_Sequenz_Laenge]:=B_Char;
  end;


  case EmuMode of

    Emu_VT100 : begin

      case TermMode of
        Normal_TM             : Normal_Terminal_Mode;
        IBM_ESC_TM            : IBM_ESC_Terminal_Mode;
        IBM_CSI_TM            : IBM_CSI_Terminal_Mode;

        IBM_CSI_TM_Par_1      : IBM_CSI_Par_1_Terminal_Mode;
        IBM_CSI_TM_Par_2      : IBM_CSI_Par_2_Terminal_Mode;
        IBM_CSI_TM_Par_3      : IBM_CSI_Par_3_Terminal_Mode;

        CHANGE_MODE           : CHANGE_MODE_ESC_M_Terminal_Mode;
        CHANGE_MODE_EMULATION : CHANGE_MODE_ESC_ME_Terminal_Mode;

      end; { case TermMode of }

    end; { Emu_VT100 }



    EMU_ADM31 : begin

      case TermMode of
        Normal_TM            : Normal_Terminal_Mode;
        ADM31_ESC_TM         : ADM31_ESC_Terminal_Mode;
        ADM31_ESC_TM_R       : ADM31_ESC_Par_Zeile_Terminal_Mode;
        ADM31_ESC_TM_C       : ADM31_ESC_Par_Spalte_Terminal_Mode;
        ADM31_ESC_ESC        : ADM31_ESC_ESC_Terminal_Mode;
        ADM31_ESC_ESC_ESC    : ADM31_ESC_ESC_ESC_Terminal_Mode;
        ADM31_ESC_TM_G       : ADM31_ESC_G_Terminal_Mode;
      end; { case TermMode of }

    end; { Emu_PC1715 }



    Emu_PC1715 : begin

      case TermMode of
        Normal_TM            : Normal_Terminal_Mode;
        PC1715_ESC_TM        : PC1715_ESC_Terminal_Mode;
        PC1715_TM_Zeile      : PC1715_ESC_Zeile_Terminal_Mode;
      end; { case TermMode of }

    end; { Emu_PC1715 }



  end; { case EmuMode of }


end; { procedure Tmod_conout.Write_Char  }




procedure Tmod_conout.Write_String(der_Text : String);
var
  Text_Zeiger : Integer;
  ein_Byte : Byte;
begin

  for Text_Zeiger:=1 to Length(der_Text) do begin

    ein_Byte:=Byte(der_Text[Text_Zeiger]);
    Write_Char(ein_Byte);

  end;

  Write_Char($0D);
  Write_Char($0A);

end; { procedure Tmod_conout.Write_String }




{==============================================================================}
{==============================================================================}


procedure Tmod_conout.save_INI;
var
  FIni : TMemIniFile;
  EmuMode_INT : Integer;
begin

  FIni := TMemIniFile.Create('C:\RPI_Terminal.ini');

  case EmuMode of
    EMU_VT100  : EmuMode_INT:=0;
    EMU_ADM31  : EmuMode_INT:=1;
    Emu_PC1715 : EmuMode_INT:=2;
  else
    EmuMode_INT:=0;
  end;

  FIni.WriteInteger('Switches','EmuMode', EmuMode_INT );

  FIni.UpdateFile;

  FIni.Free;

end; { procedure Tmod_conout.save_INI }







destructor Tmod_conout.Destroy;
begin

  inherited Destroy;
end; { destructor Tmod_conout.Destroy }





end.

