{ 
    SemTel version 1.0.0 ... comfortable telnet client
    Copyright (C) 1995-2000 Jan Tomasek <jan@tomasek.cz>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}

{-------------------------------------------------------------------------------
Version  : 0.918
Date     : 13.06.1999
Dialog   : Main window
History  :
  10.05.98 Opraveno "podivne" chovani pri zmene velokosti fontu podle okna
  16.05.98 Upraveno pro FTP server od F.P.
  24.06.98 Oprava kodovani cestiny
  07.07.98 Editace horkych klaves pro line mode
  21.07.98 Dalsi oprav pro FTP server od F.P
  22.07.98 kurzor se už chová normálně
  26.08.98 Opraveny problemy se ztratami pameti
  28.08.98 Pro tisk se pouziva TMemoryStream
  18.09.98 Opraveny chyby zanesene pri tisku pres stream
  24.01.99 Pridany dotazy pri ukoncovani.
  14.06.99 Opraven kod OTP kalkulacky aby varovala pred vyprsenim hesla kdyz je
           Count<CFG.OTPMinimum a aby odmitla pracovat kdyz je =0.
           Upraven zpusob zachytavani OTP vyzvy.
TODO     :
  * Zlikvidovat všechny komentáře kde se vyskytuje !!!
  * Utridit procedury
  * Kdyz je zamknuto tak se neukonci cela aplikace
  * Kdyz zamknout tak vsechny konzole a co LED
  * Zobrazovat IP klienta ktery je pripojen k FTP serveru
-------------------------------------------------------------------------------}

Unit
  Main;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages,
  Graphics, Forms,    INIFiles, Printers,
  Classes,  Controls, Dialogs,  Menus,
  ExtCtrls, StdCtrls, MSGlib,   PanClock,
  RoundLed, Console,  Chronog,  OneLine,
  xTerm,    Keygrab,  xForms,   RXCtrls,
  SelectC,  OTPCalc,  shellapi, ConnPar,
  PromtKey, STConfig, FtpSrv,   FTPSrvC,
  C3216,    SSLTnCnx, ComCtrls;

Type
  TPrnBuffRec = Record
    BuffLength : Word;
    Buffer     : Array [0..2047] of Char;
  end;

  TfMain = class(TxForm)
    MainMenu              : TMainMenu;
    mnFile                : TMenuItem;
    mnFile_Open           : TMenuItem;
    mnFile_Save           : TMenuItem;
    mnFile_N1             : TMenuItem;
    mnFile_Language       : TMenuItem;
    mnFile_Lock           : TMenuItem;
    mnFile_Log            : TMenuItem;
    mnFile_N2             : TMenuItem;
    mnFile_PrinterSetup   : TMenuItem;
    mnFile_ScreenCopy     : TMenuItem;
    mnFile_N4             : TMenuItem;
    mnFile_LocalIP        : TMenuItem;
    mnFile_FTPPassword    : TMenuItem;
    mnFile_FTPStartStop   : TMenuItem;
    mnFile_N3             : TMenuItem;
    mnFile_Exit           : TMenuItem;
    mnEdit                : TMenuItem;
    mnEdit_Paste          : TMenuItem;
    mnEdit_N1             : TMenuItem;
    mnEdit_HotKeys        : TMenuItem;
    mnEdit_Refresh        : TMenuItem;
    mnEdit_N2             : TMenuItem;
    mnEdit_LineMode       : TMenuItem;
    mnConnection          : TMenuItem;
    mnConnection_Select   : TMenuItem;
    mnConnection_Close    : TMenuItem;
    mnConnection_N1       : TMenuItem;
    mnConnection_Parametry: TMenuItem;
    mnConnection_N2       : TMenuItem;
    mnConnection_OTP      : TMenuItem;
    mnWindow              : TMenuItem;
    mnHelp                : TMenuItem;
    mnHelp_About          : TMenuItem;

    pmConnection          : TPopupMenu;
    pmConnection_Select   : TMenuItem;
    pmConnection_Close    : TMenuItem;

    pmFTP                 : TPopupMenu;
    pmFTP_Password        : TMenuItem;
    pmFTP_StartStop       : TMenuItem;
    pmFTP_LocalIP         : TMenuItem;
    pmFTP_N1              : TMenuItem;
    pmFTP_Param           : TMenuItem;

    pmLog                 : TPopupMenu;
    pmFile_Log            : TMenuItem;

    StatusPanel           : TPanel;
    CursorPos             : TPanel;
    PanelClock            : TPanelClock;
    LedStatusPanel        : TPanel;
    ConnStatus            : TRoundLed;
    SSLStatus             : TRoundLed;
    FTPRunning            : TRoundLed;
    Logging               : TRoundLed;
    FConsole              : TxTermConsole;
    Telnet                : TSSLTnCnx;


    ResizeTimer           : TTimer;
    Chrono                : TChrono;
    SaveAs: TSaveDialog;
    StatusTimer: TTimer;
    PrinterTimer: TTimer;
    ProgresBar: TPanel;
    mnFileFTPLocalSession: TMenuItem;
    mnFTP_LocalSession: TMenuItem;
    mnHelp_N1: TMenuItem;
    mnHelp_PublicKey: TMenuItem;
    mnHelp_N2: TMenuItem;
    mnHelp_www: TMenuItem;
    mnConnection_N3: TMenuItem;
    mnConnection_QuickConnect: TMenuItem;
    mnConnection_Duplicate: TMenuItem;
    pnRedirectedToPrinter: TPanel;
    pnRedirectedToPrinter_Title: TPanel;
    Bevel1: TBevel;
    pnRedirectedToPrinter_Gauge: TPanel;
    RedirectedToPrinter_Gauge: TProgressBar;
    pnRedirectedToPrinter_Action: TPanel;

    {-- Menu stuff ------------------------------------------------------------}
    procedure mnFile_LogClick(Sender: TObject);
    procedure mnFile_OpenClick(Sender: TObject);
    procedure mnFile_Language_czClick(Sender: TObject);
    procedure mnFile_Language_enClick(Sender: TObject);
    procedure mnFile_LockClick(Sender: TObject);
    procedure mnFile_ExitClick(Sender: TObject);
    procedure mnEdit_RefreshClick(Sender: TObject);
    procedure mnFile_PrinterSetupClick(Sender: TObject);
    procedure mnFile_ScreenCopyClick(Sender: TObject);
    procedure mnEdit_HotKeysClick(Sender: TObject);
    procedure mnEdit_PasteClick(Sender: TObject);
    procedure mnConnection_SelectClick(Sender: TObject);
    procedure mnConnection_OTPClick(Sender: TObject);
    procedure mnConnection_CloseClick(Sender: TObject);
    procedure mnConnection_ParametryClick(Sender: TObject);
    procedure mnHelp_AboutClick(Sender: TObject);
    {-- Telnet stuff ----------------------------------------------------------}
    procedure TelnetDataAvailable(Sender: TSSLTnCnx; Buffer: PChar; Len: Integer);
    procedure TelnetSessionConnected(Sender: TSSLTnCnx; Error: Word);
    procedure TelnetSessionClosed(Sender: TSSLTnCnx; Error: Word);
    {--Cliboard stuff----------------------------------------------------------}
    Procedure DrawMouseRect(X,Y,XX,YY:Integer);
    Procedure CheckMouseRect(Var X,Y:integer);
    Procedure CopyText(X,Y,XX,YY:Integer);
    Procedure FConsoleMouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);
    Procedure FConsoleMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    Procedure FConsoleMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    {-- KeyBoard stuff --------------------------------------------------------}
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    {-- Other stuff -----------------------------------------------------------}
    procedure ResizeTimerTimer(Sender: TObject);
    procedure mnFile_SaveClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure mnHelp_ContentsClick(Sender: TObject);
    procedure mnFile_FTPPasswordClick(Sender: TObject);
    procedure mnFile_FTPStartStopClick(Sender: TObject);
    procedure StatusTimerTimer(Sender: TObject);
    procedure PrinterTimerTimer(Sender: TObject);
    procedure pmFTP_ParamClick(Sender: TObject);
    procedure mnFile_LocalIPClick(Sender: TObject);
    procedure mnEdit_LineModeClick(Sender: TObject);
    procedure TelnetDisplay(Sender: TSSLTnCnx; Str: String);
    procedure TelnetDebug(Sender: TSSLTnCnx; Str: String);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure TelnetError(Sender: TSSLTnCnx; Error: Word);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure mnFile_FTPLocalSession(Sender: TObject);
    procedure mnFTP_LocalSessionClick(Sender: TObject);
    procedure mnHelp_PublicKeyClick(Sender: TObject);
    procedure mnHelp_wwwClick(Sender: TObject);
    procedure mnConnection_QuickConnectClick(Sender: TObject);
    procedure mnFile_LanguageClick(Sender: TObject);
    procedure mnConnection_DuplicateClick(Sender: TObject);
  private
    { Private declarations }
    InResize           : Boolean;
    InUpdate           : Boolean;
    TerminalEmulator   : TTerminalEmulator;
    OTPCStr            : PChar;
    FData              : PdConnectionParameters;
    MouseIsDown        : Boolean;
    MouseStartPoint,
    MouseLastPoint     : TPoint;
    IsLocked           : Boolean;
    Password           : String;
    HCArray            : TCPArray;
    HSArray            : TCPArray;
    CHArray            : TCPArray;
    HasFTPServer       : Boolean;
    HasFTPServerLocal  : Boolean;
    FLocalIP           : String;
    FIgnoreKeyPress    : Boolean;
    ConnParamModRes    : Integer;

    PRN                : PdPrinter;
    PRNbuffer          : TMemoryStream;
    PRNbuffer_tmp1     : Array[0..8*4096-1] of Byte;
    PRNbuffer_tmp1_cnt : Integer;
    PRNPrinting        : Boolean;
    PRNLF              : Boolean;
    PRNCR              : Boolean;
    PRNCPArray         : TCPArray;
    PRNCPSArray        : TCPArray;
    PRNTF              : TextFile;
    R2Prn_Counter      : Integer;
    PRNDirect          : THandle;
    PRNReceivedData    : File;
    PRNPrintedData     : File;

    Line               : String;

    FontData           : TSortedList;

    OTPMode            : Boolean;
    OTPChallenge       : String;
    OTPPosition        : TPoint;

    UserNameUsed       : Boolean;       

    {--Window stuff -----------------------------------------------------------}
    procedure SetConsoleParam;
    Procedure Resize; override;
    procedure CreateParams(VAR Params: TCreateParams); override;
    {--Telnet stuff -----------------------------------------------------------}
    Procedure Receive(P:PChar; Len: Integer);
    Procedure Transmit(P:PChar);
    Procedure SetTerminalWindowSize;
    Procedure PrintStr(S:ShortString);
    {--Other stuff ------------------------------------------------------------}
    Procedure UnLock;
    Procedure WProgress(P : Integer);
    procedure DefineSrtCt(Sender: TObject);
    Procedure PrinterOn(Sender:TObject);
    Procedure PrinterRealOn;
    Procedure PrinterOff(Sender:TObject);
    Procedure PrinterPrint(Sender:TObject;Buf:PChar;Len:Integer);
    Procedure OnOTP(Sender:TObject; Challenge:String);
    Procedure OTPChallengeAdd(Add:String);
    Function  OTPChallengeOk:Boolean;
    Procedure OnOTPCount(Sender:TObject; Count:Integer);
    Procedure FTPServerClientConnect(Sender: TObject; Client: TFtpCtrlSocket; Error: Word);
    Procedure FTPServerClientDisconnect(Sender: TObject; Client: TFtpCtrlSocket; Error: Word);
    Procedure FTPServerOnStart(Sender: TObject);

    Procedure SetFTPParameters;

    {!@#}
    {--KeyBoard stuff ---------------------------------------------------------}
    procedure CMDialogKey(Var msg:TCMDialogKey); message CM_DIALOGKEY;

    {-- FTP server support ----------------------------------------------------}
    Function  RandomPassword:String;

    {-- Opennin, saving ANSI files --------------------------------------------}
    Procedure OpenANSIFile;
    Procedure SaveANSIFile;

    {-- Window manament -------------------------------------------------------}
    {$IFDEF WIN32}Procedure WMSIZING(Var msg:tmessage); message WM_SIZING;{$ENDIF}
    procedure CheckLng;
    procedure CheckCursorPos;
    procedure CheckMenu;
    procedure CheckStatus;
    procedure CheckWindowSize;
    function  GetMaxFontHeight(X,Y:Integer):Integer;

    {-- Other stuff -----------------------------------------------------------}
    function GetLocalIP:String;

    {-- Printing stuff --------------------------------------------------------}
    procedure R2Prn_HidePanel;
    procedure R2Prn_ShowPanel;
    procedure R2Prn_SetTransferedBytes(B:Integer);
    procedure R2Prn_SetPrintedBytes;
  public
    OldEditsWindowProc : Pointer;
    HasCaret           : Boolean;

    {--Init/Destroy stuff -----------------------------------------------------}
    Constructor Create(aOwner : TComponent); override;
    Destructor Destroy; override;
    Function WriteINI:Boolean; override;
    Function ReadINI:Boolean; override;
    Function ReadMSG:Boolean; override;
    Procedure Connect(HostName, Port:String);
    Procedure SetCaption;
    Procedure SetParameters;
    Procedure ConnectionSelect;
    Procedure ConnectTo(ConnName:String; HostName, Port:String);
    procedure mnWindowClick(Sender: TObject);
    procedure SetCodePage;
    property Progress: Integer Write WProgress;
    property Data:PdConnectionParameters read FData write FData;
    property Console:TxTermConsole read FConsole;
  end;

implementation
{$R *.DFM}

Uses
  AboutBox, Clipbrd, xFTPSrv, kUnits,
  WSocket,  WinSock, InVis,   SelectIP,
  SSLWSock, pgpPKey, qConn,
  SafeMem,  WinSpool,Windows
  {$IFDEF WIN32}, FileCtrl{$ENDIF};
Const
  ctLockTitle        : String = 'LockTitle';
  ctLockPassword     : String = 'LockPassword';
  ctConnectionClosed : String = 'ConnectionClosed';
  ctRedefineKey      : String = 'stiskněte klávesu pro položku menu "%s"';
  ctRealyClose       : String = '%s: Přejete si zavřít aktivní spojení?';
  ctRealyCloseAll1   : String = 'ctRealyCloseAll1';
  ctRealyCloseAll2   : String = 'ctRealyCloseAll2';
  ctFTPStart         : String = 'ctFTPStart';
  ctFTPStop          : String = 'ctFTPStop';
  ctNoDirectPrinter  : String = 'ctNoDirectPrinter';
  ctFTPConReq        : String = 'ctFTPConReq';
  ctFTPConReqDNS     : String = 'ctFTPConReqDNS';
  ctNoPrinter        : String = 'NoPrinter';
  ctNoInitFile       : String = 'NoInitFile';
  ctNoDoneFile       : String = 'NoDoneFile';
  ctNoSSL            : String = 'NoSSL';
  ctNoDLL            : String = 'NoDLL';
  ctStateInvalidState: String = 'invalid state';
  ctStateConnecting  : String = 'connecting';
  ctStateConnected   : String = 'connected';
  ctStateClosed      : String = 'closed';
  ctStateUnknown     : String = 'unknown state';
  ctOTPWillExpire    : String = 'OTPWillExpire';
  ctOTPIsExpired     : String = 'OTPIsExpired';

  ctSC               = '.Shorcut';

  ct_Transfered_str  : String = 'Přijímám data ze vzdáleného systému. Přijato %d kB.';
  ct_Printing_str    : String = 'Probíhá tisk. Vytištěno: %d%%.';
  ct_CantWriteFile   : String = 'Nemohu zapisovat do souboru "%s".';
  ct_CantOpenPort    : String = 'Nemohu otevřít port "%s". Nelze tisknout.';


  MinimumProgresSize = 100;


procedure TfMain.mnFile_OpenClick(Sender: TObject);
begin OpenANSIFile end;
procedure TfMain.mnFile_SaveClick(Sender: TObject);
begin SaveANSIFile end;

procedure TfMain.mnFile_Language_czClick(Sender: TObject);
begin
  SetLanguage('.cz');
  WindowReadMSG;
  CheckLng;
end;{-mnFile_Language_czClick--------------------------------------------------}
procedure TfMain.mnFile_Language_enClick(Sender: TObject);
begin
  SetLanguage('.en');
  WindowReadMSG;
  CheckLng;
end;{-mnFile_Language_enClick--------------------------------------------------}
procedure TfMain.mnFile_LanguageClick(Sender: TObject);
begin
  SetLanguage('.'+Copy(CFG^.KnownLang.Strings[-(Sender as TMenuItem).Tag], 1, 2));
  WindowReadMSG;
end;{-- mnFile_LanguageClick --------------------------------------------------}
procedure TfMain.mnFile_LockClick(Sender: TObject);
Var
  I : Word;
  MI: TMenuItem;
begin
  If not AllocateDialog(_fEnterOneLineDlg) Then Exit;

  fOneLineDlg.Caption  := ctLockTitle;
  fOneLineDlg.UserText := ctLockPassword;
  fOneLineDlg.PassMode := True;
  If fOneLineDlg.ShowModal=mrOk Then
   Begin
     Password:=fOneLineDlg.OneLine;fOneLineDlg.OneLine:='';
     IsLocked:=True;
     For I:=0 To $FFFF Do
      try
        MI:=MainMenu.Items[I];
        If MI<>Nil Then MI.Enabled:=False;
      except
        Break;
      end;
     FConsole.Visible:=False;
   End;
  WindowHideMain;
end;{-mnFile_LockClick---------------------------------------------------------}
procedure TfMain.mnFile_LogClick(Sender: TObject);
begin
  If not mnFile_Log.Enabled Then Exit;
  mnFile_Log.Checked:=not mnFile_Log.Checked;
  pmFile_Log.Checked:=mnFile_Log.Checked;
  CheckStatus;
end;{-mnFile_LogClick----------------------------------------------------------}
procedure TfMain.mnFile_ExitClick(Sender: TObject);
Var
  Quest : PChar;
  I     : Integer;
begin
  Quest := nil;
  If (Telnet.IsConnected)or(CFG^.Windows.Count>1) Then try
    Quest:=StrAlloc(10000); { Trikrat FUJ! FUJ! FUJ! }
    StrPCopy(Quest, ctRealyCloseAll1+#13#10);
    For I:=0 To CFG^.Windows.Count-1 Do StrPCopy(@Quest[StrLen(Quest)], '       '+TForm(CFG^.Windows.Items[I]).Caption+^J);
    StrPCopy(@Quest[StrLen(Quest)], ctRealyCloseAll2);
    If Application.MessageBox(Quest, @ctQuestion[1], MB_YESNO+MB_ICONQUESTION+MB_APPLMODAL) <> ID_YES Then Exit;
  finally
    StrDispose(Quest);
  End;
  PostMessage(fInvisible.Handle, MSG_CLOSE, 0, 0);
end;{-TfMain.mnFile_ExitClick--------------------------------------------------}
function TfMain.GetLocalIP:String;
Var
  S : String;
Label
  Exit;
Begin
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.GetLocalIP', 'Begin');{$ENDIF}
  Result:='127.0.0.1';
  If LocalIPList.Count>1 Then Begin
    AllocateDialog(_fSelectIP);
    If fSelectIP.ShowModal<>mrOk Then Goto Exit;
    S := fSelectIP.SelectedIP;
  End Else
    If LocalIPList.Count=1 Then S := LocalIPList[0];
  Result:=S;
Exit:
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.GetLocalIP', 'End');{$ENDIF}
End;

procedure TfMain.mnFile_LocalIPClick(Sender: TObject);
Var
  S : ShortString;
begin
  S := FLocalIP+#10#13#0;
  If Telnet.IsConnected Then Transmit(@S[1])
  Else
    If Telnet.Socket.State=wsClosed Then Receive(@S[1], StrLen(@S[1]))
    Else MessageBeep(1);

  Invalidate;
  WindowHideMain;
end;{-- mnFile_LocalIPClick ---------------------------------------------------}
procedure TfMain.mnFile_FTPPasswordClick(Sender: TObject);
Var
  S : ShortString;
begin
  CFG^.FTPServer.Password:=RandomPassword;
  S := CFG^.FTPServer.Password+#10#13+#0;
  If Telnet.IsConnected Then Transmit(@S[1])
  Else
    If Telnet.Socket.State=wsClosed Then Receive(@S[1], StrLen(@S[1]))
    Else MessageBeep(1);
end;{-- mnFile_FTPPasswordClick -----------------------------------------------}
procedure TfMain.mnFile_FTPStartStopClick(Sender: TObject);
begin
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.mnFile_FTPStartStopClick', 'Begin');{$ENDIF}
  If not HasFTPServer Then Begin
    FLocalIP                          := GetLocalIP;
    CFG^.FTPServer                    := TxFTPServer.Create(self);
    CFG^.FTPServer.MaxClients         := 1;
    CFG^.FTPServer.OnClientConnect    := FTPServerClientConnect;
    CFG^.FTPServer.OnClientDisconnect := FTPServerClientDisconnect;
    CFG^.FTPServer.OnStart            := FTPServerOnStart;
    CFG^.FTPServer.Password           := RandomPassword;
    HasFTPServer                      := True;
    SetFTPParameters;
    CFG^.FTPServer.Start;
  End Else Begin
    HasFTPServer:=False;
    HasFTPServerLocal:=False;
    CFG^.FTPServer.Free;
    CFG^.FTPServer:=nil;
  End;
  CheckStatus;
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.mnFile_FTPStartStopClick', 'End');{$ENDIF}
end;{-- mnFile_FTPStartStopClick ----------------------------------------------}
procedure TfMain.mnFile_FTPLocalSession(Sender: TObject);
begin
  HasFTPServerLocal:=True;
  mnFile_FTPStartStopClick(Self);
end;{-- mnFile_FTPLocalSession ------------------------------------------------}
procedure TfMain.mnFile_ScreenCopyClick(Sender: TObject);
Var
  I    : Word;
  F    : TextFile;
  S    : PChar;
begin
  AssignPrn(F);
  System.Rewrite(F);

  Printer.Title:='SemTel';
  Printer.Canvas.Font.Name:=FConsole.FontName;
  Printer.Canvas.Font.Pitch:=fpFixed;
  Printer.Canvas.Font.Size:=FConsole.FontSize;
{
  Ps1:='';
  For I:=0 To FConsole.Cols-1 Do Ps1:=Ps1+'W';

  Printer.Canvas.Font.Size:=0;
  Repeat
    Printer.Canvas.Font.Size:=Printer.Canvas.Font.Size+1;
    I:=Printer.Canvas.TextWidth(Ps1);
  Until I>Printer.PageWidth;
  Printer.Canvas.Font.Size:=Printer.Canvas.Font.Size-1;
}
  For I:=0 To FConsole.Rows-1 Do
   Begin
     Progress := Round((I/(FConsole.Rows-1))*100);
     S := FConsole.GetText(0,I,FConsole.Cols-1,I);
     WriteLn(F,S);
     StrDispose(S);
   End;
  System.CloseFile(F);
  Progress:=0;
end;{-- mnFile_ScreenCopyClick ------------------------------------------------}
procedure TfMain.mnFile_PrinterSetupClick(Sender: TObject);
begin
  If not AllocateDialog(_fPrinterSetupDialog) Then Exit;

  fPrinterSetupDialog.Execute;

  WindowHideMain;
end;{-- mnFile_PrinterSetupClick ----------------------------------------------}
procedure TfMain.mnEdit_RefreshClick(Sender: TObject);
begin
  Repaint;
end;{-mnEdit_RefreshClick------------------------------------------------------}
procedure TfMain.mnConnection_SelectClick(Sender: TObject);
begin
  If not AllocateDialog(_fSelectConnection) Then Exit;

  If fSelectConnection.ShowModal=mrOk Then
    ConnectTo(fSelectConnection.ConnectionsList.Items[
                 fSelectConnection.ConnectionsList.ItemIndex], '', '');
  WindowHideMain;
end;{-mnConnection_SelectClick-------------------------------------------------}
Procedure TfMain.ConnectTo(ConnName:String; HostName, Port:String);
Var
  fMain : TfMain;
Begin
  If STConfig.ConnectionFind(ConnName)<>nil Then Begin
    If not Telnet.IsConnected Then fMain:=Self
    Else Begin
      Application.CreateForm(TfMain,fMain);
      fMain.MSGFile  := @STConfig.CFG^.MSG;
      fMain.INIFile  := @STConfig.CFG^.LocalINI;
      fMain.Show;
    End;
    fMain.Data:=STConfig.ConnectionFind(ConnName);
    fMain.Connect(HostName, Port);
    fMain.Show;
  End Else
    mnConnection_SelectClick(Self);
End;

procedure TfMain.mnConnection_OTPClick(Sender: TObject);
begin
  If not AllocateDialog(_fOTPCalc) Then Exit;

  fOTPCalc.ShowModal;

  WindowHideMain;
end;{-mnConnection_OTPClick----------------------------------------------------}
procedure TfMain.mnHelp_AboutClick(Sender: TObject);
begin
  fAboutBox := TfAboutBox.Create(Application);
  fAboutBox.ShowModal;
  fAboutBox.Free;
end;{-mnHelp_AboutClick--------------------------------------------------------}
procedure TfMain.mnEdit_HotKeysClick(Sender: TObject);
begin
  mnEdit_HotKeys.Checked := not mnEdit_HotKeys.Checked;
  CheckMenu;
  CheckStatus;
end;{-- mnEdit_HotKeysClick ---------------------------------------------------}
procedure TfMain.mnEdit_PasteClick(Sender: TObject);
Var
  Data   : PChar;
  xData  : PChar;
  DataH  : THandle;
  I      : Word;
begin
  If OpenClipboard(Handle) Then Begin
    DataH := Clipboard.GetAsHandle(CF_TEXT);
    If DataH>0 Then Begin
      Data  := GlobalLock(DataH);
      xData := strAlloc(strLen(Data)+5);
      strCopy(xData,Data);
      GlobalUnLock(DataH);
      For I:=0 To strLen(xData)-1 Do xData[I]:=CHArray[xData[I]];
      If Telnet.IsConnected Then Transmit(xData)
      Else
        If Telnet.Socket.State=wsClosed Then Receive(xData, StrLen(xData))
        Else MessageBeep(1);
      strDispose(xData);
      CloseClipboard;
    End;
  End;
end;{-- mnEdit_PasteClick -----------------------------------------------------}

{** Telnet stuff **************************************************************}
procedure TfMain.TelnetDataAvailable(Sender: TSSLTnCnx; Buffer: PChar; Len: Integer);
{Var
  I       : Integer;
  xBuffer : PChar;}
begin
(*  xBuffer:=strAlloc(Len+1);
  move(Buffer^, xBuffer^, Len); xBuffer[Len]:=#0;
  I:=0;
  While I<Len Do Begin
    Receive(@xBuffer[I]);
    Inc(I, Max(strLen(@xBuffer[I]),1));
  End;
  strDispose(xBuffer);*)
  Receive(Buffer, Len);
end;{-TelnetDataAvailable------------------------------------------------------}
procedure TfMain.TelnetSessionConnected(Sender: TSSLTnCnx; Error: Word);
begin
  PostMessage(fInvisible.Handle, MSG_GENERATEMENU, 0, 0);
  CheckCursorPos;CheckStatus
end;{-TelnetSessionConnected---------------------------------------------------}
procedure TfMain.TelnetSessionClosed(Sender: TSSLTnCnx; Error: Word);
begin
  Data^.Console.Window.Left := Left;
  Data^.Console.Window.Top  := Top;

  Telnet.Host:='none';
  CheckCursorPos;
  CheckStatus;
  MessageBox(Handle,@ctConnectionClosed[1],@ctInformation[1],
             MB_ICONINFORMATION or MB_OK);
  If CFG^.Windows.Count>1 Then
    Close
  Else
    PostMessage(fInvisible.Handle, MSG_GENERATEMENU, 0, 0);
end;{-TelnetSessionClosed------------------------------------------------------}
Procedure TfMain.Receive(P:PChar; Len: Integer);
Var
  F       : File;
  I, J    : {$IFDEF WIN32}Integer{$ELSE}Word{$ENDIF};
  S, S1   : ShortString;
  P1      : PChar;
Const
  Counter : Integer = 0;
Begin
  {Ulozit do log. souboru je-li to pozadovano}
  If mnFile_Log.Checked and (not FData^.Security.Logging.NoLog) Then
   Begin
     {$I-}
     System.Assign(F,FData^.Security.Logging.LogFile);
     FileMode:=2;
     If FileExists(FData^.Security.Logging.LogFile) Then System.Reset(F,1)
     Else System.Rewrite(F,1);
     System.Seek(F,System.FileSize(F));
     System.BlockWrite(F,P^,Len,I);
     System.Close(F);
     {$I+}
   End;
  Inc(Counter);
  If Counter mod 25 = 0 Then Application.ProcessMessages;
  {Zpracovat na terminal}
  TerminalEmulator.Process(P, Len);
  {Nebyla nahodou vyzva na OTP}
  If OTPMode Then Begin
    While not OTPChallengeOk Do Begin
      S:=StrPas(Console.GetText(OTPPosition.X, OTPPosition.Y,
                                OTPPosition.X, OTPPosition.Y));
      OTPChallengeAdd(S);
    End;
    OTPMode:=False;
    fOTPCalc.OnCount:=OnOTPCount;
    fOTPCalc.OTPChallenge:=OTPChallenge;
    If fOTPCalc.ShowModal=mrOk Then Begin
      S:=fOTPCalc.OTPResponse+#13#0;
      Transmit(@S[1]);
    End;
  End;
  { Stary kod OTP -------------------------------------------------------------- }
  P1:=SysUtils.StrPos(P,OTPCStr);
  If P1<>nil Then Begin
     S:=StrPas(P1);
     System.Delete(S,Pos(#13,S),$FF);
     System.Delete(S,1,Pos(':',S));
     S1:='';J:=0;
     For I:=1 To Length(S) Do Begin
       If S[I]=' ' Then Inc(J);
       If J<3 Then S1:=S1+S[I];
     End;
     fOTPCalc.OTPChallenge:=S1;
     If fOTPCalc.ShowModal=mrOk Then Begin
       S:=fOTPCalc.OTPResponse+#13#0;
       Transmit(@S[1]);
     End;
  End; {------------------------------------------------------------------------}
  if not UserNameUsed then begin
    P1:=SysUtils.StrPos(P,'ogin:');
    If P1<>nil Then Begin
      UserNameUsed:=True;
      S:=CFG^.UserName+TerminalEmulator.VirtT.k_ENTER[ksN]+#0;
      Transmit(@S[1]);
    end;
  end;
End;{-Receive------------------------------------------------------------------}
Procedure TfMain.Transmit(P:PChar);
Var
  F, B : Longint;
Begin
  If P<>nil Then Telnet.Send(P,StrLen(P));
  If not Telnet.LocalEcho Then Begin
    B := FConsole.PenColor  ;
    F := FConsole.PaperColor;

    FConsole.PenColor  :=clrLocalEcho{FData^.Console.Colors.LocalEchoB};
    FConsole.PaperColor:=clrLocalEcho{FData^.Console.Colors.LocalEchoF};

    Receive(P, StrLen(P));

    FConsole.PenColor  :=B;
    FConsole.PaperColor:=F;
{    SetColor(, );}
  End;
End;{-Transmit-----------------------------------------------------------------}

{** Other stuff ***************************************************************}
procedure TfMain.ResizeTimerTimer(Sender: TObject);
begin
  If not Visible Then Exit;
  InResize:=False;
  ResizeTimer.Enabled:=False;
  WindowHideMain;
  PostMessage(Handle, WM_KILLFOCUS, 0, 0);
  PostMessage(Handle, WM_SETFOCUS, 0, 0);
  CheckCursorPos;
end;{-ResizeTimerTimer---------------------------------------------------------}

{** Clipboard stuff ***********************************************************}
Procedure TfMain.DrawMouseRect(X,Y,XX,YY:Integer);
Var
  aX,
  aY: Integer;
Begin
  If (X=XX) or (Y=YY) Then Exit;

  If FData^.Console.Window.FillInArea Then Begin
    Canvas.Brush.Style := bsSolid;
    Canvas.Brush.Color := RealXOR(FData^.Console.Colors.normalB, FData^.Console.Window.AreaColor);
  End Else Begin
    Canvas.Brush.Style := bsClear;
    Canvas.Brush.Color := clBlack;
  End;

  Canvas.Pen.Style   := psSolid;
  Canvas.Pen.Width   := 1;
  Canvas.Pen.Color   := RealXOR(FData^.Console.Colors.normalB, FData^.Console.Window.AreaColor);;
  Canvas.Pen.Mode    := pmXOR;

  Canvas.Rectangle(X,Y,XX,YY);

  aX:=FConsole.CharSize.X;
  aY:=FConsole.CharSize.Y;
  CursorPos.Caption :=
   Format('%dx%d',[Max(X div aX,XX div aX)-Min(X div aX,XX div aX),
                   Max(Y div aY,YY div aY)-Min(Y div aY,YY div aY)]);
End;{-DrawMouseRect------------------------------------------------------------}
Procedure TfMain.CheckMouseRect(Var X,Y:integer);
Var
  aX,aY : Integer;
  _X,_Y : Integer;
Begin
  aX:=FConsole.CharSize.X;
  aY:=FConsole.CharSize.Y;
  _X:=Round(X/aX);
  _Y:=Round(Y/aY);
  If _X<0 Then _X:=0;
  If _Y<0 Then _Y:=0;
  If _X>FConsole.Cols Then _X:=FConsole.Cols;
  If _Y>FConsole.Rows Then _Y:=FConsole.Rows;
  X :=aX*_X;
  Y :=aY*_Y;
End;{-CheckMouseRect-----------------------------------------------------------}
Procedure TfMain.CopyText(X,Y,XX,YY:Integer);
Var
  I,J : Integer;
  P   : PChar;
Begin
  If X>XX Then Begin I:=X; X:=XX; XX:=I; End;
  If Y>YY Then Begin I:=Y; Y:=YY; YY:=I; End;
  I:=FConsole.CharSize.X;
  J:=FConsole.CharSize.Y;
  X :=X  div I; Y :=Y  div J;
  XX:=XX div I; YY:=YY div J;
  If (XX=X)or(YY=Y) Then Exit;

  P:=FConsole.GetText(X, Y, XX-1, YY-1);
  ClipBoard.SetTextBuf(P);
  StrDispose(P);
End;{-CopyText-----------------------------------------------------------------}
procedure TfMain.FConsoleMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  If Button=mbLeft Then
   Begin
     MouseIsDown     := True;
     CheckMouseRect(X,Y);
     MouseStartPoint := Point(X,Y);
     MouseLastPoint  := MouseStartPoint;
     CheckStatus;
   End;
end;{-ConsoleMouseDown---------------------------------------------------------}
procedure TfMain.FConsoleMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  WindowHideMain;
  PostMessage(Handle, WM_KILLFOCUS, 0, 0);
  PostMessage(Handle, WM_SETFOCUS, 0, 0);
  If (Button=mbLeft)and(MouseIsDown) Then
   Begin
     MouseIsDown:=False;
     CheckMouseRect(X,Y);
     DrawMouseRect(MouseStartPoint.X,MouseStartPoint.Y,X,Y);
     CopyText(MouseStartPoint.X,MouseStartPoint.Y,X,Y);
     ResizeTimer.Enabled:=True;
     CheckStatus;
     Exit;
   End
  Else
   If (Button=mbMiddle)or(Button=mbRight) Then mnEdit_PasteClick(self);
end;{-ConsoleMouseUp-----------------------------------------------------------}
procedure TfMain.FConsoleMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  If MouseIsDown Then
   Begin
     CheckMouseRect(X,Y);
     If (MouseLastPoint.X<>X)or(MouseLastPoint.Y<>Y)Then
      Begin
        DrawMouseRect(MouseStartPoint.X,MouseStartPoint.Y,
                      MouseLastPoint.X, MouseLastPoint.Y);
        DrawMouseRect(MouseStartPoint.X,MouseStartPoint.Y,X,Y);
        MouseLastPoint     := Point(X,Y);
      End;
   End;
end;{-ConsoleMouseMove---------------------------------------------------------}

{** Window stuff **************************************************************}
Procedure TfMain.Resize;
Var
  ChX, ChY : Word;
  dxCh,dyCh: Word;
  FD       : PFontData;
begin
  If InResize Then Exit;
  If not Assigned(FData) Then Exit;

  InResize := True;

  Case FData^.Console.Window.WinResizeWillCause of
    rmDimensionChange :
     Begin
       If ClientHeight<50 Then ClientHeight:=50;
       ChX:=(CursorPos.Width+PanelClock.Width+LedStatusPanel.Width+MinimumProgresSize);
       If ClientWidth<ChX Then ClientWidth:=ChX;


       dxCh:= FConsole.CharSize.X;
       dyCh:= FConsole.CharSize.Y;
       ChX := Round((ClientWidth-FConsole.ScrollBarWidth)/dxCh);
       ChY := Round((ClientHeight-StatusPanel.Height)/dyCh);
       FConsole.ResizeTo(ChX,ChY);

       FData^.Console.Window.Rows:=FConsole.Rows;
       FData^.Console.Window.Cols:=FConsole.Cols;
     End;
    rmFontSizeChange:
     Begin
       FD := PFontData(FontData.Items[GetMaxFontHeight(
                         ClientWidth-FConsole.ScrollBarWidth,
                         ClientHeight-StatusPanel.Height)]);
       FConsole.FontHeight:= FD^.Height;
       FData^.Console.Font.Size:=FD^.Size;
     End;
  End;

  ResizeTimer.Enabled:=True;
  CheckWindowSize;
  SetTerminalWindowSize;
  pnRedirectedToPrinter.Left := (FConsole.ScreenWidth - pnRedirectedToPrinter.Width) div 2;
  pnRedirectedToPrinter.Top  := (FConsole.ScreenHeight- pnRedirectedToPrinter.Height) div 2; 

  CheckCursorPos;
  InResize :=False;
End;{-Resize-------------------------------------------------------------------}
Procedure TfMain.SetConsoleParam;
Var
  ColorTable : TColorTable;
  B          : Boolean;
Begin
  B                              :=InResize;
  InResize                       :=True;

  Color                          :=FData^.Console.Colors.NormalB;
  ColorTable.Pen  [clrBlack    ] :=FData^.Console.Colors.BlackF;
  ColorTable.Paper[clrBlack    ] :=FData^.Console.Colors.BlackB;
  ColorTable.Pen  [clrRed      ] :=FData^.Console.Colors.RedF;
  ColorTable.Paper[clrRed      ] :=FData^.Console.Colors.RedB;
  ColorTable.Pen  [clrGreen    ] :=FData^.Console.Colors.GreenF;
  ColorTable.Paper[clrGreen    ] :=FData^.Console.Colors.GreenB;
  ColorTable.Pen  [clrYellow   ] :=FData^.Console.Colors.YellowF;
  ColorTable.Paper[clrYellow   ] :=FData^.Console.Colors.YellowB;
  ColorTable.Pen  [clrBlue     ] :=FData^.Console.Colors.BlueF;
  ColorTable.Paper[clrBlue     ] :=FData^.Console.Colors.BlueB;
  ColorTable.Pen  [clrMagenta  ] :=FData^.Console.Colors.MagentaF;
  ColorTable.Paper[clrMagenta  ] :=FData^.Console.Colors.MagentaB;
  ColorTable.Pen  [clrCyan     ] :=FData^.Console.Colors.CyanF;
  ColorTable.Paper[clrCyan     ] :=FData^.Console.Colors.CyanB;
  ColorTable.Pen  [clrWhite    ] :=FData^.Console.Colors.WhiteF;
  ColorTable.Paper[clrWhite    ] :=FData^.Console.Colors.WhiteB;
  ColorTable.Pen  [clrNormal   ] :=FData^.Console.Colors.NormalF;
  ColorTable.Paper[clrNormal   ] :=FData^.Console.Colors.NormalB;
  ColorTable.Pen  [clrInverse  ] :=FData^.Console.Colors.NormalB;
  ColorTable.Paper[clrInverse  ] :=FData^.Console.Colors.NormalF;
  ColorTable.Pen  [clrBold     ] :=FData^.Console.Colors.BoldF;
  ColorTable.Paper[clrBold     ] :=FData^.Console.Colors.BoldB;
  ColorTable.Pen  [clrUnderline] :=FData^.Console.Colors.UnderlineF;
  ColorTable.Paper[clrUnderline] :=FData^.Console.Colors.UnderlineB;
  ColorTable.Pen  [clrBlink    ] :=FData^.Console.Colors.BlinkF;
  ColorTable.Paper[clrBlink    ] :=FData^.Console.Colors.BlinkB;
  ColorTable.Pen  [clrLocalEcho] :=FData^.Console.Colors.LocalEchoF;
  ColorTable.Paper[clrLocalEcho] :=FData^.Console.Colors.LocalEchoB;

  FConsole.ColorTable            :=ColorTable;
  FConsole.FontName              :=FData^.Console.Font.Name;
  FConsole.FontSize              :=-FData^.Console.Font.Size;
  FConsole.FontBold              :=FData^.Console.Font.Bold;
  FConsole.CursorMode            :=TCursorMode(FData^.Console.Window.CursorMode);
  FConsole.CursorColor           :=FData^.Console.Colors.Cursor;
  Width                          :=FConsole.CharSize.X*FData^.Console.Window.Cols;
  Height                         :=FConsole.CharSize.Y*FData^.Console.Window.Rows;
  Case FData^.Console.Window.WinResizeWillCause of
    rmDimensionChange :
     If FConsole.ScreenWidth>Screen.Width Then
      Begin
        FData^.Console.Window.Cols:=Round((Screen.Width-FConsole.ScrollBarWidth)/FConsole.CharSize.X);
      End;
    rmFontSizeChange :
     Begin
{       FConsole.FontHeight:=GetMaxFontHeight;
       FData^.Console.Font.Size:=FConsole.FontSize;}
     End;
  End;
  FConsole.ResizeTo(FData^.Console.Window.Cols,FData^.Console.Window.Rows);


  CheckWindowSize;
  SetTerminalWindowSize;

  InResize                     :=B;
End;

{** KeyBoard stuff ************************************************************}
Const
  VK_A         = Ord('A');
  VK_B         = Ord('B');
  VK_C         = Ord('C');
  VK_D         = Ord('D');
  VK_E         = Ord('E');
  VK_F         = Ord('F');
  VK_G         = Ord('G');
  VK_H         = Ord('H');
  VK_I         = Ord('I');
  VK_J         = Ord('J');
  VK_K         = Ord('K');
  VK_L         = Ord('L');
  VK_M         = Ord('M');
  VK_N         = Ord('N');
  VK_O         = Ord('O');
  VK_P         = Ord('P');
  VK_Q         = Ord('Q');
  VK_R         = Ord('R');
  VK_S         = Ord('S');
  VK_T         = Ord('T');
  VK_U         = Ord('U');
  VK_V         = Ord('V');
  VK_W         = Ord('W');
  VK_X         = Ord('X');
  VK_Y         = Ord('Y');
  VK_Z         = Ord('Z');
  VK_0         = Ord('0');
  VK_1         = Ord('1');
  VK_2         = Ord('2');
  VK_3         = Ord('3');
  VK_4         = Ord('4');
  VK_5         = Ord('5');
  VK_6         = Ord('6');
  VK_7         = Ord('7');
  VK_8         = Ord('8');
  VK_9         = Ord('9');
  VK_LQuote    = 192; {`}
  VK_Minus     = 189; {-}
  VK_EQU       = 187; {=}
  VK_Backslash = 220; {\}
  VK_LBracket  = 219; {[}
  VK_RBracket  = 221; {]}
  VK_Semicolon = 186; {;}
  VK_RQuoute   = 222; {'}
  VK_Comma     = 188; {,}
  VK_aDecimal  = 190; {.}
  VK_aDivide   = 191; {/}

procedure TfMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
Var
  Buffer   : String;
  KeyState : TKeyState;
//  KeyboardState : TKeyboardState;
//  S: String;

begin
  If IsLocked Then Begin UnLock;Exit End;
  Buffer:='';FIgnoreKeyPress:=False;

  With TerminalEmulator.VirtT Do Begin
    {GetKeyboardState(KeyboardState);
    S := Format('alt %x %x| ctrl %x %x| shift %x %x', [
           KeyboardState[VK_LMENU],    KeyboardState[VK_RMENU],
           KeyboardState[VK_LCONTROL], KeyboardState[VK_RCONTROL],
           KeyboardState[VK_LSHIFT],   KeyboardState[VK_RSHIFT]
         ]);
    WriteToLog(DebugDetailed, kuMain, 'KeyDown', S);}

    KeyState := ksN;
    If Shift=[ssCtrl]                Then KeyState := ksC;
    If Shift=[ssShift]               Then KeyState := ksS;
    If Shift=[ssAlt]                 Then KeyState := ksA;
    If Shift=[ssCtrl, ssShift]       Then KeyState := ksCS;
    If Shift=[ssCtrl, ssAlt]         Then KeyState := ksCA;
    If Shift=[ssShift, ssAlt]        Then KeyState := ksSA;
    If Shift=[ssCtrl, ssShift, ssAlt]Then KeyState := ksCSA;
    { Jestlize je pro danou klavesu v definici terminalu nadefinovan nejaky
      retezec, pouzijemem tento retezec a budeme ignorovat standardni vyznam
      klavesy }
    Case Key of
      VK_ESCAPE    : Buffer:=k_ESC       [KeyState];
      VK_F1        : Buffer:=k_F1        [KeyState];
      VK_F2        : Buffer:=k_F2        [KeyState];
      VK_F3        : Buffer:=k_F3        [KeyState];
      VK_F4        : Buffer:=k_F4        [KeyState];
      VK_F5        : Buffer:=k_F5        [KeyState];
      VK_F6        : Buffer:=k_F6        [KeyState];
      VK_F7        : Buffer:=k_F7        [KeyState];
      VK_F8        : Buffer:=k_F8        [KeyState];
      VK_F9        : Buffer:=k_F9        [KeyState];
      VK_F10       : Buffer:=k_F10       [KeyState];
      VK_F11       : Buffer:=k_F11       [KeyState];
      VK_F12       : Buffer:=k_F12       [KeyState];
      VK_HOME      : Buffer:=k_HOME      [KeyState];
      VK_END       : Buffer:=k_END       [KeyState];
      VK_PRIOR     : Buffer:=k_PGUP      [KeyState];
      VK_NEXT      : Buffer:=k_PGDN      [KeyState];
      VK_UP        : Buffer:=k_UPARROW   [KeyState];
      VK_DOWN      : Buffer:=k_DOWNARROW [KeyState];
      VK_RIGHT     : Buffer:=k_RIGHTARROW[KeyState];
      VK_LEFT      : Buffer:=k_LEFTARROW [KeyState];
      VK_DELETE    : Buffer:=k_DELETE    [KeyState];
      VK_INSERT    : Buffer:=k_INS       [KeyState];
      VK_TAB       : Buffer:=k_TAB       [KeyState];
      VK_RETURN    : Buffer:=k_ENTER     [KeyState];
      VK_BACK      : Buffer:=k_BACK      [KeyState];
      { -- Numeric keypad ---------------------------------------------------- }
      VK_NUMLOCK   : Buffer:=k_N_NumLock [KeyState];
      VK_DIVIDE    : Buffer:=k_N_Divide  [KeyState];
      VK_MULTIPLY  : Buffer:=k_N_Multiply[KeyState];
      VK_SUBTRACT  : Buffer:=k_N_Minus   [KeyState];
      VK_ADD       : Buffer:=k_N_Plus    [KeyState];
      VK_DECIMAL   : Buffer:=k_N_Decimal [KeyState];
      VK_NUMPAD0   : Buffer:=k_N_0       [KeyState];
      VK_NUMPAD1   : Buffer:=k_N_1       [KeyState];
      VK_NUMPAD2   : Buffer:=k_N_2       [KeyState];
      VK_NUMPAD3   : Buffer:=k_N_3       [KeyState];
      VK_NUMPAD4   : Buffer:=k_N_4       [KeyState];
      VK_NUMPAD5   : Buffer:=k_N_5       [KeyState];
      VK_NUMPAD6   : Buffer:=k_N_6       [KeyState];
      VK_NUMPAD7   : Buffer:=k_N_7       [KeyState];
      VK_NUMPAD8   : Buffer:=k_N_8       [KeyState];
      VK_NUMPAD9   : Buffer:=k_N_9       [KeyState];
      { -- alpha keypad -------------------------------------------------------}
      VK_A         : Buffer:=k_A         [KeyState];
      VK_B         : Buffer:=k_B         [KeyState];
      VK_C         : Buffer:=k_C         [KeyState];
      VK_D         : Buffer:=k_D         [KeyState];
      VK_E         : Buffer:=k_E         [KeyState];
      VK_F         : Buffer:=k_F         [KeyState];
      VK_G         : Buffer:=k_G         [KeyState];
      VK_H         : Buffer:=k_H         [KeyState];
      VK_I         : Buffer:=k_I         [KeyState];
      VK_J         : Buffer:=k_J         [KeyState];
      VK_K         : Buffer:=k_K         [KeyState];
      VK_L         : Buffer:=k_L         [KeyState];
      VK_M         : Buffer:=k_M         [KeyState];
      VK_N         : Buffer:=k_N         [KeyState];
      VK_O         : Buffer:=k_O         [KeyState];
      VK_P         : Buffer:=k_P         [KeyState];
      VK_Q         : Buffer:=k_Q         [KeyState];
      VK_R         : Buffer:=k_R         [KeyState];
      VK_S         : Buffer:=k_S         [KeyState];
      VK_T         : Buffer:=k_T         [KeyState];
      VK_U         : Buffer:=k_U         [KeyState];
      VK_V         : Buffer:=k_V         [KeyState];
      VK_W         : Buffer:=k_W         [KeyState];
      VK_X         : Buffer:=k_X         [KeyState];
      VK_Y         : Buffer:=k_Y         [KeyState];
      VK_Z         : Buffer:=k_Z         [KeyState];
      { -- numeric part -------------------------------------------------------}
      VK_0         : Buffer:=k_0         [KeyState];                                                  
      VK_1         : Buffer:=k_1         [KeyState];
      VK_2         : Buffer:=k_2         [KeyState];
      VK_3         : Buffer:=k_3         [KeyState];
      VK_4         : Buffer:=k_4         [KeyState];
      VK_5         : Buffer:=k_5         [KeyState];
      VK_6         : Buffer:=k_6         [KeyState];
      VK_7         : Buffer:=k_7         [KeyState];
      VK_8         : Buffer:=k_8         [KeyState];
      VK_9         : Buffer:=k_9         [KeyState];
      { -- ten zbytek ---------------------------------------------------------}
      VK_LQuote    : Buffer:=k_LQuote    [KeyState];
      VK_Minus     : Buffer:=k_Minus     [KeyState];
      VK_EQU       : Buffer:=k_EQU       [KeyState];
      VK_Backslash : Buffer:=k_Backslash [KeyState];
      VK_LBracket  : Buffer:=k_LBracket  [KeyState];
      VK_RBracket  : Buffer:=k_RBracket  [KeyState];
      VK_Semicolon : Buffer:=k_Semicolon [KeyState];
      VK_RQuoute   : Buffer:=k_RQuoute   [KeyState];
      VK_Comma     : Buffer:=k_Comma     [KeyState];
      VK_aDecimal  : Buffer:=k_Decimal   [KeyState];
      VK_aDivide   : Buffer:=k_Divide    [KeyState];
      VK_CAPITAL   : Buffer:=k_CapsLock  [KeyState];
      VK_SCROLL    : Buffer:=k_ScrollLock[KeyState];
      {Else           Buffer:='['+Char(Lo(Key))+'] '+IntToStr(Key)+' '+IntToHex(Key, 2)+' '^M^J;{}
    End;
    If Buffer<>'' Then Key:=0; {Event was handled}
    FIgnoreKeyPress:=Key=0;

    { Klavesa nebyla predefinovana, zkusime jestli uzivatel nezada rolovani }
    Case Key of
      VK_UP      : FConsole.Scroll(scLineUp);
      VK_DOWN    : FConsole.Scroll(scLineDown);
      VK_HOME    : FConsole.Scroll(scTop);
      VK_END     : FConsole.Scroll(scBottom);
      VK_NEXT    : FConsole.Scroll(scPageDown);
      VK_PRIOR   : FConsole.Scroll(scPageUp);
    End;
  End;{With}

  Buffer:=Buffer+#0;
  If Buffer<>'' Then Begin
    If Telnet.IsConnected Then Transmit(@Buffer[1])
    Else
      If Telnet.Socket.State=wsClosed Then Receive(@Buffer[1], StrLen(@Buffer[1]))
      Else MessageBeep(1);
  End;
end;{-KeyDown------------------------------------------------------------------}
procedure TfMain.FormKeyPress(Sender: TObject; var Key: Char);
Var
  S     : String[3];
begin
  If IsLocked Then Begin UnLock;Exit End;
  If FIgnoreKeyPress Then Begin FIgnoreKeyPress:=False; Exit End;

  If (FData^.CharSet.CharSetEnc)and(FData^.CharSet.KeybCharsetCheckBox) Then Key:=CHArray[Key];

  If FData^.Connection.LineMode Then Begin
    Case Key of
      #13 : Begin
        Line:=Line+#13#10#0;
        If Telnet.IsConnected Then Transmit(@Line[1])
        Else
          If Telnet.Socket.State=wsClosed Then Receive(@Line[1], StrLen(@Line[1]))
          Else MessageBeep(1);
        Line := '';
      End;
      #8  : System.Delete(Line,Length(Line),1);
    Else    Line:=Line+Key;
    End;
    ProgresBar.Caption := Line +  ' ';
  End Else Begin
    If (Key=#13)and(not Telnet.LocalEcho)and(FData^.Connection.CR2CRLF) Then Begin
      SetLength(S,3); S[1]:=Key; S[2]:=#10; S[3]:=#0;
    End Else Begin
      SetLength(S,2); S[1]:=Key; S[2]:=#0;
    End;

    If Telnet.IsConnected Then Transmit(@S[1])
    Else
      If Telnet.Socket.State=wsClosed Then Receive(@S[1], StrLen(@S[1]))
      Else MessageBeep(1);
  End;
end;{-KeyPress-----------------------------------------------------------------}

{** Other stuf ****************************************************************}
Procedure TfMain.UnLock;
Var
  I : Word;
  MI: TMenuItem;
begin
  try
   fOneLineDlg.Caption  := 'Zamknout/Odemknout';
   fOneLineDlg.UserText := 'Heslo:';
   fOneLineDlg.PassMode := True;
   If fOneLineDlg.ShowModal=mrOk Then
    If fOneLineDlg.OneLine=Password Then
     Begin
       IsLocked:=False;
       For I:=0 To $FFFF Do
        try
          MI:=MainMenu.Items[I];
          If MI<>Nil Then MI.Enabled:=True;
        except
          Break;
        end;
       FConsole.Visible:=True;
     End
    Else
     Begin
       fOneLineDlg.OneLine:='';
     End;
  except
  end;
End;{-UnLock-------------------------------------------------------------------}


type
 {$IFDEF WIN32}
   WParameter = LongInt;
 {$ELSE}
   WParameter = Word;
 {$ENDIF}
   LParameter = LongInt;

{New windows procedure for the edit control}
function NewWindowProc(WindowHandle: hWnd; TheMessage: WParameter;
            ParamW: WParameter; ParamL: LParameter): LongInt;
            {$IFDEF WIN32}stdcall;{$ELSE}export;{$ENDIF}
Var
  fMain : TfMain;
begin
  {Call the old edit controls windows procedure}
  Result:= 0;
  fMain := TfMain(WindowGetByHandle(WindowHandle));
  If fMain<>nil Then If fMain.OldEditsWindowProc<>nil Then Begin
    {$IFNDEF WIN32}
    If (GetActiveWindow=fMain.Handle)and(not fMain.HasCaret) Then PostMessage(fMain.Handle, WM_SETFOCUS, 0, 0);
    {$ENDIF}
    Case TheMessage of
      WM_SETFOCUS: begin
        fMain.FConsole.CaretCreate;
        fMain.FConsole.CaretShow;
        fMain.HasCaret:=True;
        If fOTPCalc.Visible Then
          {$IFDEF WIN32}
          SetForegroundWindow(fOTPCalc.Handle)
	  {$ELSE}
          WinProcs.SetFocus(fOTPCalc.Handle)
	  {$ENDIF}
        Else
          fInvisible.MainForm:=fMain;
      end;
      WM_KILLFOCUS: begin
        fMain.FConsole.CaretHide;
        fMain.FConsole.CaretDestroy;
        fMain.HasCaret:=False;
      end;
      MSG_PRNON : fMain.PrinterRealOn;
      MSG_KILLFTP : fMain.mnFile_FTPStartStopClick(fMain);
      MSG_SELECTCONN : fMain.mnConnection_SelectClick(fMain);
    End;
    Result := CallWindowProc(fMain.OldEditsWindowProc, fMain.Handle,
                                    TheMessage, ParamW, ParamL);
  End Else Begin
    Result := CallWindowProc(fMain.DefWndProc, fMain.Handle, TheMessage, ParamW, ParamL);
  End;
end;

{** Init/Destroy stuff ********************************************************}
Constructor TfMain.Create(AOwner : TComponent);
Begin
  Inherited Create(AOwner);

  CFG^.Windows.Add(Self);

  SavePosition                       := True;
  ReadMSG;

  FData                              := ConnDef;
  OTPCStr                            := StrNew('otp-md');

  InResize                           := True;
  InUpdate                           := True;
  ResizeTimer.Enabled                := True;
  MouseIsDown                        := False;
  IsLocked                           := False;
  Password                           := '';
  Progress                           := 0;
  HasFTPServer                       := False;
  HasCaret                           := False;
//  Gauge95.Progress                   := 0;
//  Gauge95.Visible                    := False;
  PRNPrinting                        := False;
  Line                               := '';
  FontData                           := NIL;
  FIgnoreKeyPress                    := False;
  OTPMode                            := False;
  OTPPosition                        := Point(0,0);
  UserNameUsed                       := True;

  FConsole._CursorCreate;

  TerminalEmulator                   := TTerminalEmulator.Create(Self);
  TerminalEmulator.Console           := @FConsole;
  TerminalEmulator.CP                := FData;
  TerminalEmulator.OnOTP             := OnOTP;
  TerminalEmulator.OnPrinterOn       := PrinterOn;
  TerminalEmulator.OnPrinterOff      := PrinterOff;
  TerminalEmulator.OnPrinterPrint    := PrinterPrint;

  Telnet.OnSSLSessionConnected       := TelnetSessionConnected;

  ReadINI;

  SetCodePage;
  CheckLng;         {Zkontroluj zda je označena správná jazyková volba}
  SetConsoleParam;
  CheckWindowSize;  {Zkontroluj zda velikost okna odpovida velikosti konzole}
  CheckStatus;      {Povol/Zakaz casti menu, LED}
  CheckCursorPos;

  InResize                 := False;
  InUpdate                 := False;

  R2Prn_HidePanel;
End;{-Create-------------------------------------------------------------------}
Destructor TfMain.Destroy;
Begin
  SetWindowLong(Handle, GWL_WNDPROC, LongInt(OldEditsWindowProc));
  OldEditsWindowProc := nil;

  If HasCaret Then Begin
    FConsole.CaretHide;
    FConsole.CaretDestroy;
    HasCaret:=False;
  End;

  If HasFTPServer and(CFG^.FTPServer<>nil) Then Begin
    CFG^.FTPServer.Free;
    CFG^.FTPServer:=nil;
  End;

  WriteINI;

  InResize := True; {To je tady aby to nehlasilo GPF}


  TerminalEmulator .Free;  TerminalEmulator := nil;
  FontData_Clear(FontData);
  FontData         .Free;  FontData         := nil;
  strDispose(OTPCStr);     OTPCStr          := nil;
  Inherited Destroy;
End;{-Destroy------------------------------------------------------------------}
Function TfMain.WriteINI:Boolean;
Begin
  Result := Inherited WriteINI;
  If Result Then Begin
    FINIFile^.WriteString(iName,mnFile_Open               .Name+ctSC,ShortCutToText(mnFile_Open.ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_Log                .Name+ctSC,ShortCutToText(mnFile_Log .ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_Lock               .Name+ctSC,ShortCutToText(mnFile_Lock.ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_LocalIP            .Name+ctSC,ShortCutToText(mnFile_LocalIP.ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_FTPPassword        .Name+ctSC,ShortCutToText(mnFile_FTPPassword.ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_FTPStartStop       .Name+ctSC,ShortCutToText(mnFile_FTPStartStop.ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_ScreenCopy         .Name+ctSC,ShortCutToText(mnFile_ScreenCopy.ShortCut      ));
    FINIFile^.WriteString(iName,mnFile_PrinterSetup       .Name+ctSC,ShortCutToText(mnFile_PrinterSetup.ShortCut    ));
    FINIFile^.WriteString(iName,mnFile_Exit               .Name+ctSC,ShortCutToText(mnFile_Exit.ShortCut            ));
    FINIFile^.WriteString(iName,mnFile_FTPStartStop       .Name+ctSC,ShortCutToText(mnFile_FTPStartStop.ShortCut    ));
    FINIFile^.WriteString(iName,mnFile_FTPPassword        .Name+ctSC,ShortCutToText(mnFile_FTPPassword.ShortCut     ));

    FINIFile^.WriteString(iName,mnEdit_Paste              .Name+ctSC,ShortCutToText(mnEdit_Paste.ShortCut           ));
    FINIFile^.WriteString(iName,mnEdit_Refresh            .Name+ctSC,ShortCutToText(mnEdit_Refresh.ShortCut         ));
    FINIFile^.WriteString(iName,mnEdit_LineMode           .Name+ctSC,ShortCutToText(mnEdit_LineMode.ShortCut        ));

    FINIFile^.WriteString(iName,mnConnection_Select       .Name+ctSC,ShortCutToText(mnConnection_Select.ShortCut    ));
    FINIFile^.WriteString(iName,mnConnection_Duplicate    .Name+ctSC,ShortCutToText(mnConnection_Duplicate.ShortCut ));
    FINIFile^.WriteString(iName,mnConnection_Close        .Name+ctSC,ShortCutToText(mnConnection_Close.ShortCut     ));
    FINIFile^.WriteString(iName,mnConnection_QuickConnect .Name+ctSC,ShortCutToText(mnConnection_QuickConnect.ShortCut));
    FINIFile^.WriteString(iName,mnConnection_Parametry    .Name+ctSC,ShortCutToText(mnConnection_Parametry.ShortCut ));
    FINIFile^.WriteString(iName,mnConnection_OTP          .Name+ctSC,ShortCutToText(mnConnection_OTP.ShortCut       ));

    FINIFile^.WriteString(iName,mnHelp_About              .Name+ctSC,ShortCutToText(mnHelp_About.ShortCut           ));
  End;
End;{-WriteINI-----------------------------------------------------------------}
Function TfMain.ReadINI:Boolean;
Begin
  Result := Inherited ReadINI;
  If Result Then Begin
   mnFile_Open.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_Open.Name+ctSC,''));
   mnFile_Log .ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_Log.Name+ctSC,'Ctrl+Alt+L'));
   mnFile_Lock.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_Lock.Name+ctSC,'Ctrl+Alt+K'));
   mnFile_LocalIP.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_LocalIP.Name+ctSC,''));
   mnFile_FTPStartStop.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_FTPStartStop.Name+ctSC,''));
   mnFile_FTPPassword.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_FTPPassword.Name+ctSC,''));
   mnFile_ScreenCopy.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_ScreenCopy.Name+ctSC,'Ctrl+Alt+P'));
   mnFile_PrinterSetup.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_PrinterSetup.Name+ctSC,''));
   mnFile_Exit.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnFile_Exit.Name+ctSC,'Alt+X'));

   mnEdit_Paste.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnEdit_Paste.Name+ctSC,'Ctrl+Ins'));
   mnEdit_Refresh.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnEdit_Refresh.Name+ctSC,'Alt+F5'));
   mnEdit_LineMode.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnEdit_LineMode.Name+ctSC,''));

   mnConnection_Select.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnConnection_Select.Name+ctSC,'Alt+F2'));
   mnConnection_Duplicate.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnConnection_Duplicate.Name+ctSC,'Ctrl+Alt+F2'));
   mnConnection_Close.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnConnection_Close.Name+ctSC,'Ctrl+F4'));
   mnConnection_QuickConnect.ShortCut:=
    TextToShortCut(FINIFile^.ReadString(iName,mnConnection_QuickConnect.Name+ctSC,'Ctrl+Alt+Q'));
   mnConnection_Parametry.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnConnection_Parametry.Name+ctSC,'Ctrl+Alt+S'));
   mnConnection_OTP.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnConnection_OTP.Name+ctSC,'Ctrl+Alt+O'));

   mnHelp_About.ShortCut:=TextToShortCut(FINIFile^.ReadString(iName,mnHelp_About.Name+ctSC,''));
  End;
End;{-ReadINI------------------------------------------------------------------}
Function TfMain.ReadMSG:Boolean;
Begin
  Result := inherited ReadMSG;
  If Result Then Begin
    ctLockTitle                   := ReadMSGString('LockTitle');
    ctLockPassword                := ReadMSGString('LockPassword');
    ctConnectionClosed            := ReadMSGString('ConnectionClosed');
    ctRedefineKey                 := ReadMSGString('RedefineKey');
    ctRealyClose                  := ReadMSGString('RealyClose');
    ctRealyCloseAll1              := ReadMSGString('RealyCloseAll1');
    ctRealyCloseAll2              := ReadMSGString('RealyCloseAll2');
    ctFTPStart                    := ReadMSGString('File_FTPStart');
    ctFTPStop                     := ReadMSGString('File_FTPStop');
    ctNoDirectPrinter             := ReadMSGString('NoDirectPrinter');
    ctNoPrinter                   := ReadMSGString('NoPrinter');
    ctFTPConReq                   := ReadMSGString('FTPConReq');
    ctFTPConReqDNS                := ReadMSGString('FTPConReqDNS');
    ctNoInitFile                  := ReadMSGString('NoInitFile');
    ctNoDoneFile                  := ReadMSGString('NoDoneFile');
    ctNoSSL                       := ReadMSGString('NoSSL');
    ctNoDLL                       := ReadMSGString('NoDLL');
    ctStateInvalidState           := ReadMSGString('stateInvalidState');
    ctStateConnecting             := ReadMSGString('stateConnecting');
    ctStateConnected              := ReadMSGString('stateConnected');
    ctStateClosed                 := ReadMSGString('stateClosed');
    ctStateUnknown                := ReadMSGString('stateUnknown');
    ctOTPWillExpire               := ReadMSGString('OTPWillExpire');
    ctOTPIsExpired                := ReadMSGString('OTPIsExpired');

    pmFTP_Password.Caption        := mnFile_FTPPassword.Caption;
    pmFTP_LocalIP.Caption         := mnFile_LocalIP.Caption;
    mnFTP_LocalSession.Caption    := mnFileFTPLocalSession.Caption;
    pmConnection_Select.Caption   := mnConnection_Select.Caption;
    pmConnection_Close.Caption    := mnConnection_Close.Caption;
    pmFile_Log.Caption            := mnFile_Log.Caption;

    If Assigned(fOneLineDlg          ) Then fOneLineDlg          .ReadMSG;
    If Assigned(fSelectConnection    ) Then fSelectConnection    .ReadMSG;
    If Assigned(fOTPCalc             ) Then fOTPCalc             .ReadMSG;
    If Assigned(fConnectionParameters) Then fConnectionParameters.ReadMSG;
    If Assigned(fSelectIP            ) Then fSelectIP            .ReadMSG;
    If Assigned(fPGPPublicKey        ) Then fPGPPublicKey        .ReadMSG;
    If Assigned(fQuickConnect        ) Then fQuickConnect        .ReadMSG;

    CheckLng;
    CheckStatus;
  End;
End;{-ReadLng------------------------------------------------------------------}

procedure TfMain.mnConnection_CloseClick(Sender: TObject);
Var
  CanClose : Boolean;
begin
  CanClose:=True;
  FormCloseQuery(Self, CanClose);
  If CanClose Then Telnet.Close;
end;

procedure TfMain.mnConnection_ParametryClick(Sender: TObject);
var
  X: TdConnectionParameters;
begin
  If not AllocateDialog(_fConnectionParameters) Then Exit;

  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.mnConnection_ParametryClick', 'Begin');{$ENDIF}

  FData^.Console.Window.Rows     := FConsole.Rows;
  FData^.Console.Window.Cols     := FConsole.Cols;
  FData^.Console.Window.Left     := Left;
  FData^.Console.Window.Top      := Top;
  FData^.Console.Font.Size       := FConsole.FontSize;
  FData^.Security.OTP.DeletePass := fOTPCalc.DeletePassword;
  FData^.Connection.LocalEcho    := not Telnet.LocalEcho;
  FData^.Connection.LineMode     := mnEdit_LineMode.Checked;

  fConnectionParameters.Data:=FData^;
  {$IFDEF DEBUGMSG}
  WriteToLog(DebugDetailed, kuMain, 'TfMain.mnConnection_ParametryClick', 'Opening parameters window');{$ENDIF}
  ConnParamModRes := fConnectionParameters.ShowModal;
  if ConnParamModRes = mrOk Then
   Begin
     {$IFDEF DEBUGMSG}
     WriteToLog(DebugDetailed, kuMain, 'TfMain.mnConnection_ParametryClick', 'Parameters window closed with mrOK');{$ENDIF}
     if fConnectionParameters.ShowOnlyPrinter then begin
       X := fConnectionParameters.Data;
     end else begin
       FData^           := fConnectionParameters.Data;
       Left             := FData^.Console.Window.Left;
       Top              := FData^.Console.Window.Top;
       Telnet.LocalEcho := not FData^.Connection.LocalEcho;
       Telnet.TermType  := FData^.Connection.TerminalType;
       TerminalEmulator.CP := FData;
       TerminalEmulator.SetCommands;
       FConsole.AutoMargin := TerminalEmulator.VirtT.AutoMargin;
       FConsole.CheckBeforeCh := TerminalEmulator.VirtT.CheckBeforeCh;
       WindowSetParameters;
       If HasFTPServer Then SetFTPParameters;
     end;
   End Else
     {$IFDEF DEBUGMSG}
     WriteToLog(DebugDetailed, kuMain, 'TfMain.mnConnection_ParametryClick',
                'Parameters window closed with not mrOK');{$ENDIF}
  WindowHideMain;

  {$IFDEF DEBUGMSG}
  WriteToLog(DebugDetailed, kuMain, 'TfMain.mnConnection_ParametryClick', 'End');{$ENDIF}
end;

Procedure TfMain.SetTerminalWindowSize;
Var
  ChX,
  ChY   : Word;
Begin
  ChX:=FConsole.Cols;
  ChY:=FConsole.Rows;

  If Telnet.IsConnected Then Telnet.WindowSize:=Point(ChX,ChY);
End;

Procedure TfMain.WProgress;
Begin
{  Gauge95.Progress := P;}
End;

Procedure TfMain.DefineSrtCt(Sender : TObject);
Begin
  If not AllocateDialog(_fEditHotKey) Then Exit;
  fEditHotKey.Left       := Left+(Width - fEditHotKey.Width )div 2;
  fEditHotKey.Top        := Top +(Height- fEditHotKey.Height)div 2;
  fEditHotKey.PromptText := Format(ctRedefineKey,[(Sender as TMenuItem).Caption]);
  If fEditHotKey.ShowModal=mrOk Then
   If fEditHotKey.ShortCut=TextToShortCut('Del') Then
   (Sender as TMenuItem).ShortCut:=0
   Else
   (Sender as TMenuItem).ShortCut:=fEditHotKey.ShortCut;
  WindowHideMain;
End;

procedure TfMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
Var
  S : ShortString;
begin
  If Telnet.IsConnected Then Begin
    S:=Format(ctRealyClose+#0,[Caption]);
    CanClose:=MessageBox(Handle,@S[1],@ctQuestion[1],MB_ICONQUESTION or MB_YESNO)=IDYES;
  End Else
    CanClose:=True;
End;

procedure TfMain.mnHelp_ContentsClick(Sender: TObject);
begin
  Application.HelpCommand(HELP_CONTENTS,0);
end;

procedure TfMain.mnWindowClick(Sender: TObject);
Var
  MI : TMenuItem;
  I  : Integer;
  F  : TForm;
Begin
  MI:=(Sender as TMenuItem);
  I := MI.Tag shr 1;
  F := WindowGetP(I);
  If Assigned(F) Then F.Show;
End;

Procedure TfMain.Connect(HostName, Port:String);
{Jestlize promenna neobsahuje % tak je konstanta jinak se zpracuje jako promenna}
Function ProcessVariable(S:String):String;
Begin
  Result:=S;
  If Pos('%', S)>0 Then Begin
    S:=Copy(S, Pos('%', S)+1, $FF);
    If Pos('%', S)>0 Then Begin
      S:=Copy(S, 1, Pos('%', S)-1);
      If (S='SEMTEL_LOCAL_IP') Then Begin
        Result:=LocalIPList[0];
        Exit
      End;
      Result:=EnvGetValueFromOs(S);
    End;
  End;
End;
Var
  Env : TTnEnvironment;
  I   : Integer;
  S   : String;
Begin
  InResize:=True;
  TerminalEmulator.CP:=FData;
  TerminalEmulator.SetCommands;
  FConsole.AutoMargin := TerminalEmulator.VirtT.AutoMargin;
  FConsole.CheckBeforeCh := TerminalEmulator.VirtT.CheckBeforeCh;
  SetCodePage;

  {Nastaveni parametru telnet protokolu}
  If HostName='' Then Begin
    Telnet.Host        := FData^.Connection.Host;
    Telnet.Port        := FData^.Connection.Port;
  End Else Begin
    Telnet.Host        := HostName;
    Telnet.Port        := Port;
  End;

  Telnet.DoNaws        := True;
  Telnet.WindowSize    := Point(FData^.Console.Window.Cols, FData^.Console.Window.Rows);
  Telnet.LocalEcho     := not FData^.Connection.LocalEcho;
  Telnet.TermType      := FData^.Connection.TerminalType;
  Telnet.DebugLevel    := [];
  If FData^.Connection.DebugLevel and 1 = 1 Then Telnet.DebugLevel := Telnet.DebugLevel + [dlStandard];
  If FData^.Connection.DebugLevel and 2 = 2 Then Telnet.DebugLevel := Telnet.DebugLevel + [dlDetail];
  Telnet.UseSSL        := FData^.Connection.SSL and 1 = 1;
  Telnet.RequireSSL    := FData^.Connection.SSL and 2 = 2;
  Telnet.DirectSSL     := FData^.Connection.SSL and 4 = 4;
  Env                  := Telnet.Environment;
  Env.USER             := ProcessVariable(EnvGetValueFromList(FData^.Environment.List, 'USER'       ));
  Env.JOB              := ProcessVariable(EnvGetValueFromList(FData^.Environment.List, 'JOB '       ));
  Env.ACCT             := ProcessVariable(EnvGetValueFromList(FData^.Environment.List, 'ACCT'       ));
  Env.PRINTER          := ProcessVariable(EnvGetValueFromList(FData^.Environment.List, 'PRINTER'    ));
  Env.SYSTEMTYPE       := ProcessVariable(EnvGetValueFromList(FData^.Environment.List, 'SYSTEMTYPE' ));
  Env.DISPLAY          := ProcessVariable(EnvGetValueFromList(FData^.Environment.List, 'DISPLAY'    ));
  Env.UserVars.Clear;
  For I:=0 To FData^.Environment.List.Count-1 Do Begin
    S:=EnvGetVariable(FData^.Environment.List.Strings[I]);
    If (S='USER')or(S='JOB')or(S='ACCT')or(S='PRINTER')or
       (S='SYSTEMTYPE')or(S='DISPLAY') Then Continue;
    Env.UserVars.Add(EnvGetVariable(FData^.Environment.List.Strings[I])+'='+
      ProcessVariable(EnvGetValue(FData^.Environment.List.Strings[I])));
  End;
  Telnet.Environment   := Env;

  {Nastaveni OTP kalkulacky}
  fOTPCalc.DeletePassword:=FData^.Security.OTP.DeletePass;

  {Nastaveni parametru konzole}
  Left := Data^.Console.Window.Left;
  Top  := Data^.Console.Window.Top;

  FConsole.ClrScr;

  SetConsoleParam;
  mnEdit_LineMode.Checked        := FData^.Connection.LineMode;
  CheckWindowSize;  {Zkontroluj zda velikost okna odpovida velikosti konzole}
  CheckCursorPos;
  InResize:=False;

  UserNameUsed := CFG^.UserName='';

  try
    Telnet.Connect;
  except
    on E:ESocketException do begin
      S:= Format('Nemohu navázat spojení s vzdáleným systémem. Prosím, zkontrolujte '+
            'zda je správně '+
            'zadáno jeho jméno a zda je dostupný. Systémové chybové '+
            'hlášení je:'#13#13'%s'#0, [E.Message]);
      MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
    end;
  end;

  CheckStatus;
  InResize:=False;
End;

procedure TfMain.SetCaption;
Function StateToString(State:TSocketState):String;
Begin
  Case State of
    wsInvalidState : Result:= ctStateInvalidState;
    wsConnecting   : Result:= ctStateConnecting;
    wsConnected    : Result:= ctStateConnected;
    wsClosed       : Result:= ctStateClosed;
  Else               Result:= ctStateUnknown;
  End;
End;
begin
  Caption := Format('%s. SemTel [%s] - %s',[WindowNo2Chr(WindowGetNo(Self)+1),
               Telnet.Host, StateToString(Telnet.State)]);
end;

procedure TfMain.SetParameters;
Begin
  {Nastaveni znakove konverze}
  SetCodePage;

  Telnet.WindowSize              := Point(FData^.Console.Window.Cols, FData^.Console.Window.Rows);
  Telnet.LocalEcho               := not FData^.Connection.LocalEcho;

  {Nastaveni OTP kalkulacky}
  fOTPCalc.DeletePassword:=FData^.Security.OTP.DeletePass;

  {Nastaveni parametru konzole}
  SetConsoleParam;
  mnEdit_LineMode.Checked        := FData^.Connection.LineMode;

  CheckStatus;
  RePaint;
End;

procedure TfMain.SetCodePage;
Begin
  CHArray := CodePageFromTo(FData^.Charset.KeybCharSet,    FData^.Charset.HostCP)^;
  HCArray := CodePageFromTo(FData^.Charset.HostCP,         FData^.Charset.LocalCP)^;
  HSArray := CodePageFromTo(FData^.Charset.SemigraphicsCP, FData^.Charset.LocalCP)^;
  TerminalEmulator.CharEncEn     := FData^.CharSet.CharSetEnc;
  TerminalEmulator.CharSetTable  := HCArray;
  TerminalEmulator.SemigrTable   := HSArray;
End;

Procedure TfMain.SetFTPParameters;
  Procedure SetL(List:TStringList;S:String);
  Begin
    List.Clear;
    If S='' Then List.Add('*:/*/*/*');
    While S<>'' Do Begin
      If Pos('|',S)>0 Then Begin
        List.Add(System.Copy(S,1,Pos('|',S)-1));
        System.Delete(S,1,Pos('|',S));
      End Else Begin
        List.Add(S);
        S:='';
      End;
    End;
  End;
Begin
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.SetFTPParameters', 'Begin');{$ENDIF}
  CFG^.FTPServer.HomeDir     := CFG^.FTP.FileSystem.HomeDir;
  If not CFG^.FTP.FileSystem.EnabRO Then
    CFG^.FTPServer.RODirs.Clear
  Else Begin
    SetL(CFG^.FTPServer.RODirs,CFG^.FTP.FileSystem.RODirs);
  End;

  If not CFG^.FTP.FileSystem.EnabRW Then
    CFG^.FTPServer.RWDirs.Clear
  Else Begin
    SetL(CFG^.FTPServer.RWDirs,CFG^.FTP.FileSystem.RWDirs);
  End;
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'TfMain.SetFTPParameters', 'End');{$ENDIF}
End;

procedure TfMain.StatusTimerTimer(Sender: TObject);
begin
  If not Visible Then Exit;
  WindowHideMain;
  CheckStatus;
end;

procedure TfMain.PrinterOn(Sender:TObject);
Var
  S: String;
Begin
  { Create temporary buffer }
  PRNbuffer:=TMemoryStream.Create;
  PRNbuffer_tmp1_cnt:=0;
  { Feedback to user }
  R2Prn_ShowPanel;
  R2Prn_SetTransferedBytes(0);

  if(CFG^.SaveReceivedPRNData<>'') then begin
    FileMode := 2;
    try
      System.Assign(PRNReceivedData, CFG^.SaveReceivedPRNData);
      System.Rewrite(PRNReceivedData, 1);
    except
      on EInOutError do begin
        S:=Format(ct_CantWriteFile+#0, [CFG^.SaveReceivedPRNData]);
        MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
        CFG^.SaveReceivedPRNData:='';
      end;
    end;
  end;

  PostMessage(Handle, MSG_PRNON, 0, 0);
End;

procedure TfMain.PrinterRealOn;
Begin
{  WriteLn('PrinterRealOn - start');}
  CheckStatus;
  CheckWindowSize;

  {Check if is some printer in system installed}
  If Printer.Printers.Count<=0 Then Begin
    MessageBox(Handle, @ctNoPrinter[1], @ctError[1], MB_ICONSTOP or MB_OK);
    PRNPrinting := False;
    PRNLF       := False;
    CheckStatus;
    CheckWindowSize;
    Invalidate;
    Exit;
  End;

  {Check if is some printer instaled in SemTel}
  If CFG^.PrinterProfiles.Count>0 Then
  Else Begin
    SafeGetMem(PRN,SizeOf(TdPrinter));
    PrinterDefault(PRN);
    CFG^.PrinterProfiles.Add(PRN);
  End;

  {Display param window only for printer}
  if not CFG^.DontShowPrnDBP then begin
    AllocateDialog(_fConnectionParameters);
    fConnectionParameters.ShowOnlyPrinter:=True;
    mnConnection_ParametryClick(Self);
    fConnectionParameters.ShowOnlyPrinter:=False;
  end;

  Invalidate;
  WindowHideMain;
{  WriteLn('PrinterOn - exit');}
End;

procedure TfMain.PrinterOff(Sender:TObject);
Begin
  PRNPrinting := True; {Aby nezmizela tiskarnicka}
  Invalidate;

  PRNBuffer.Write(PRNbuffer_tmp1, PRNbuffer_tmp1_cnt);
  PRNbuffer_tmp1_cnt:=0;
  PRNbuffer.Seek(0, soFromBeginning);
  PrinterTimer.Enabled:=True;

  CheckStatus;
  CheckWindowSize;
  Invalidate;
End;

Procedure TfMain.PrinterPrint(Sender:TObject;Buf:PChar;Len:Integer);
Var
  EnableDisplay: Boolean;
  S: String;
Begin
  { Put data into printer buffer }
  if (Len+PRNbuffer_tmp1_cnt)>SizeOf(PRNbuffer_tmp1) then begin
    PRNBuffer.Write(PRNbuffer_tmp1, PRNbuffer_tmp1_cnt);
    PRNbuffer_tmp1_cnt:=0;
  end;
  move(Buf^, PRNbuffer_tmp1[PRNbuffer_tmp1_cnt], Len);
  Inc(PRNbuffer_tmp1_cnt, Len);
  { Save received data to disk }
  if(CFG^.SaveReceivedPRNData<>'') then begin
    try
      System.BlockWrite(PRNReceivedData, Buf^, Len);
    except
      on EInOutError do begin
        S:=Format(ct_CantWriteFile+#0, [CFG^.SaveReceivedPRNData]);
        MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
        CFG^.SaveReceivedPRNData:='';
      end;
    end;
  end;
  { Feedback to user }
  EnableDisplay := (PRNbuffer.Position>R2Prn_Counter+10*1024) or
    ((PRNbuffer.Position<51*1024+1)and(PRNbuffer.Position>R2Prn_Counter+1024+1));
  if EnableDisplay then
    R2Prn_SetTransferedBytes(PRNbuffer.Position div 1024);
End;

procedure TfMain.PrinterTimerTimer(Sender: TObject);
Type
  TXX = Record
    Len  : Word;
    Buff : Array[0..2] of Char;
  End;
Var
  I        : Word;
  XX       : TXX;
  InitFile : Integer;
  DoneFile : Integer;
  buf      : PChar;
  S        : ShortString;
Procedure PrintIt(Flush:Boolean);
Var
  J: Integer;
  S: String;
Begin
  if (not Flush) then begin
    move(XX.Buff, PRNbuffer_tmp1[PRNbuffer_tmp1_cnt], XX.Len);
    Inc(PRNbuffer_tmp1_cnt, XX.Len);
  end;

  if ((XX.Len+PRNbuffer_tmp1_cnt+50)>SizeOf(PRNbuffer_tmp1)) or Flush then begin
    If PRN^.AccessMode=1 Then Begin {pseudo direct acces to printer}
      WriteFile(PRNDirect, PRNbuffer_tmp1, PRNbuffer_tmp1_cnt, J, nil);
      if J<>PRNbuffer_tmp1_cnt Then MessageBox(Handle, 'Neco je spatne, nemuzu zapisovat na tiskarnu', 'Chyba', MB_ICONSTOP or MB_OK);
      if CFG^.SavePrintedPRNData<>'' then begin
        FileMode := 2;
        try
          System.BlockWrite(PRNPrintedData, PRNbuffer_tmp1, PRNbuffer_tmp1_cnt);
        except
          on EInOutError do begin
            S:=Format(ct_CantWriteFile+#0, [CFG^.SavePrintedPRNData]);
            MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
            CFG^.SavePrintedPRNData:='';
          end;
        end;
      end;
      PRNbuffer_tmp1_cnt:=0;
    End Else Begin{acces via windows print spooler}
      //If ((PRNBuffer.Position+3>=PRNBuffer.Size)and((XX.Buff[0]=#$0C)or(XX.Buff[1]=#$0C)or(XX.Buff[2]=#$0C))) Then
      //else
      For J:=0 To PRNbuffer_tmp1_cnt-1 Do System.Write(PRNTF,PRNBuffer_tmp1[J]);
      PRNbuffer_tmp1_cnt:=0;
    End;
  end;
End;
Label
  KonecTisku;
begin
  If not Visible Then Exit;
  PrinterTimer.Enabled:=False;

  If (not PRNPrinting)or(Printer.Printers.Count<=0) Then Exit;

  {Check if user confirm}
  If fConnectionParameters.Visible Then Begin
    PrinterTimer.Enabled:=True;
    Exit;
  End;

  if ConnParamModRes <> mrOk then goto KonecTisku;

  {Initialize printer}
  If PRNbuffer.Position=0 Then Begin
    {Get printer configuration}
    PRN := PrinterGetP(CFG^.Printer);

    {Select printer}
    Printer.PrinterIndex := Printer.Printers.IndexOf(PRN^.PrinterName);
    Printer.Title        := Caption;

    PRNbuffer_tmp1_cnt:=0;
    PRNPrinting := False;
    PRNLF       := False;
    PRNCR       := False;

    {Get charset hacking tables}
    If PRN^.CharsetE Then Begin
      PRNCPArray  := CodePageFromTo(PRN^.HCharset, PRN^.LCharset)^;
      PRNCPSArray := CodePageFromTo(PRN^.LineArt,  PRN^.LCharset)^;
    End Else Begin
      PRNCPArray  := CodePageFromTo('', '')^; {Ident table}
      PRNCPSArray := CodePageFromTo('', '')^; {Ident table}
    End;

    {Setup printer}
    If PRN^.AccessMode=1 Then Begin{Direct}
      if(CFG^.SavePrintedPRNData<>'') then begin
        FileMode := 2;
        try
          System.Assign(PRNPrintedData, CFG^.SavePrintedPRNData);
          System.Rewrite(PRNPrintedData, 1);
        except
          on EInOutError do begin
            S:=Format(ct_CantWriteFile+#0, [CFG^.SavePrintedPRNData]);
            MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
            CFG^.SavePrintedPRNData:='';
          end;
        end;
      end;

      S:=PRN^.PrinterName+#0;
      PRNDirect := Windows.CreateFile(@S[1], GENERIC_WRITE, 0,
                      nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

      if PRNDirect>0 then begin
        PRNPrinting := True;
        {Print activating file}
        If PRN^.InitFile<>'' Then
          If FileExists(PRN^.InitFile) Then Begin
            InitFile := FileOpen(PRN^.InitFile, fmOpenRead);
            SafeGetMem(buf, FileSize(PRN^.InitFile));
            FileRead(InitFile, buf^, FileSize(PRN^.InitFile));
            For I:=0 To FileSize(PRN^.InitFile)-1 Do Begin
              XX.Len := 1;
              XX.Buff[0] := buf[I];
              PrintIt(False);
            End;
            If buf<>nil Then SafeFreeMem(buf, FileSize(PRN^.InitFile));
            If InitFile>0 Then FileClose(InitFile);
          End Else Begin
            S := Format(ctNoInitFile+#0, [PRN^.InitFile]);
            MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
          end;
      end else begin
        S:=Format(ct_CantOpenPort+#0, [PRN^.PrinterName]); 
        MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
        Goto KonecTisku;
      end;
    End Else Begin
      AssignPrn(PRNTF);
      System.Rewrite(PRNTF);
      Printer.Canvas.Font.Name    := PRN^.FontName;
      Printer.Canvas.Font.Size    := PRN^.FontSize;
      {$IFDEF WIN32}
      Printer.Canvas.Font.Charset := EASTEUROPE_CHARSET;
      {$ENDIF}
      PRNPrinting := True;
    End;
  End;{-- Setup printer -------------------------------------------------------}

  If PRNBuffer.Position<PRNBuffer.Size Then Begin
    For I:=0 To 2048-1 Do Begin
      XX.Len := 1;
      If PRNBuffer.Read(XX.Buff, 1)=0 Then Continue;
      { Charset conversion }
      If TerminalEmulator.Semigraphics Then XX.Buff[0] := PRNCPSArray[XX.Buff[0]]
      Else XX.Buff[0] := PRNCPArray[XX.Buff[0]];

      { replacingg LF by CRLF }
      If PRNLF Then Begin
        If XX.Buff[0]=#13 Then Begin {LF is folowed by CR no replacing required}
          XX.Len :=2; XX.Buff[0]:=#13; XX.Buff[1]:=#10;
          PRNLF  :=False;
          PRNCR  :=False;
        End Else Begin {Replace LF by CRLF}
          XX.Len    :=3;
          XX.Buff[2]:=XX.Buff[0]; XX.Buff[0]:=#13; XX.Buff[1]:=#10;
          PRNLF     :=False;
          PRNCR     :=False;
        End;
      End Else Begin
        If(XX.Buff[0]=#10)and(PRN^.LF2CRLF)and(not PRNCR)Then Begin
          PRNLF:=True;
          Continue;
        End;
      End;

      {replacing CR by CRLF}
      If PRNCR Then Begin
        If XX.Buff[0]=#10 Then Begin {CR is folowed by LF no replacing required}
          XX.Len :=2; XX.Buff[0]:=#13; XX.Buff[1]:=#10;
          PRNCR  :=False;
          PRNLF  :=False;
        End Else Begin {Replace CR by CRLF}
          If XX.Buff[0]=#13 Then Begin
            XX.Len    :=2;
            XX.Buff[0]:=#13; XX.Buff[1]:=#10;
            PRNCR     :=True;
            PRNLF     :=False;
            PrintIt(False);
          End Else Begin
            XX.Len    :=3;
            XX.Buff[2]:=XX.Buff[0]; XX.Buff[0]:=#13; XX.Buff[1]:=#10;
            PRNCR     :=False;
            PRNLF     :=False;
          End;
        End;
      End Else Begin
        If(XX.Buff[0]=#13)and(PRN^.CR2CRLF)and(not PRNLF)Then Begin
          PRNCR:=True;
          Continue;
        End;
      End;

      If (not PRNLF)and(not PRNCR) Then PrintIt(False);
    End;

    R2Prn_SetPrintedBytes;
    PrinterTimer.Enabled:=True;
  End Else Begin
    If PRN^.AccessMode=1 Then Begin
      If PRN^.DoneFile<>'' Then
        If FileExists(PRN^.DoneFile) Then Begin
          DoneFile := FileOpen(PRN^.DoneFile, fmOpenRead);
          SafeGetMem(buf, FileSize(PRN^.DoneFile));
          FileRead(DoneFile, buf^, FileSize(PRN^.DoneFile));
          For I:=0 To FileSize(PRN^.DoneFile)-1 Do Begin
            XX.Len := 1;
            XX.Buff[0] := buf[I];
            PrintIt(False);
          End;
          If buf<>nil Then SafeFreeMem(buf, FileSize(PRN^.DoneFile));
          If DoneFile>0 Then FileClose(DoneFile);
        End Else Begin
          S := Format(ctNoDoneFile+#0, [PRN^.InitFile]);
          MessageBox(Handle, @S[1], @ctError[1], MB_ICONSTOP or MB_OK);
        End;
      PrintIt(True);
      CloseHandle(PRNDirect);
    End Else begin
      PrintIt(True);
      System.Close(PRNTF);
    end;
KonecTisku:
    if (CFG^.SaveReceivedPRNData<>'') then System.Close(PRNReceivedData);
    R2Prn_HidePanel;
    PRNbuffer.Free;
    PrinterTimer.Enabled:=False;
    PRNPrinting := False;
    CheckStatus;
    CheckWindowSize;
  End;
End;

Procedure TfMain.OnOTP(Sender:TObject; Challenge:String);
Begin
  OTPMode:=True;
  OTPPosition:=Console.CursorPos;
  OTPChallenge:='';
  OTPChallengeAdd(Challenge);
End;

Procedure TfMain.OTPChallengeAdd(Add:String);
Begin
  If Add='' Then Add:=' ';
  OTPChallenge:=OTPChallenge+Add;
  OTPPosition:=Point(OTPPosition.X+Length(Add), OTPPosition.Y);
End;

Function  TfMain.OTPChallengeOk:Boolean;
Var
  I, J: Integer;
Begin
  J:=0; For I:=1 To Length(OTPChallenge) Do If OTPChallenge[I]=' ' Then Inc(J);
  Result:=J>2;
End;

Procedure TfMain.OnOTPCount(Sender:TObject; Count:Integer);
Var
  S: String;
Begin
  If Count<=0 Then
    MessageBox(Handle, @ctOTPIsExpired[1], @ctError[1], MB_SYSTEMMODAL or MB_ICONSTOP or MB_OK)
  Else If Count<CFG^.OTP.Minimum Then Begin
    S:=Format(ctOTPWillExpire, [Count-1]);
    MessageBox(Handle, @S[1], @ctWarning[1], MB_SYSTEMMODAL or MB_ICONEXCLAMATION or MB_OK);
  End;
End;

Procedure TfMain.FTPServerClientConnect(Sender: TObject; Client: TFtpCtrlSocket; Error: Word);
Function TelnetIP:String;
Begin
  If Telnet.IsConnected Then Begin
    Result:=Telnet.Socket.GetPeerAddr;
  End Else Result:='not conected';
End;
Function TelnetAddr:String;
Var
  Phe: PHostEnt;
Begin
  If Telnet.IsConnected Then Begin
    Phe:=WSocketGetHostByAddr(Telnet.Socket.GetPeerAddr);
    If Phe<>nil Then Result:=strPas(Phe^.h_Name)
    Else Result:='unknown';
  End Else Result:='not conected';
End;
Var
  S,SS: ShortString;
  Phe : PHostEnt;
Begin
  {Allow:=True;}
  Case CFG^.FTP.DifferentIP.Mode of
    0: {Allow:=True};
    1: If TelnetIP<>Client.GetPeerAddr Then Begin
         If CFG^.FTP.DNSResolv Then Begin
           phe:=WSocketGetHostByAddr(Client.GetPeerAddr);
           If Phe<>nil Then SS:=strPas(Phe^.h_Name)
           Else SS:='unknown';
           S := Format(ctFTPConReqDNS+#0,[TelnetAddr,TelnetIP,SS,Client.GetPeerAddr])
         End Else Begin
           S := Format(ctFTPConReq+#0,[TelnetIP,Client.GetPeerAddr]);
         End;
         {Allow:=}
         If MessageBox(Handle,@S[1],@ctQuestion[1],MB_ICONQUESTION or MB_YESNO)<>IDYES Then Client.Free;
       End;
    2: If TelnetIP<>Client.GetPeerAddr Then Client.Free;
  Else Client.Free;
  End;
End;

Procedure TfMain.FTPServerClientDisconnect(Sender: TObject; Client: TFtpCtrlSocket; Error: Word);
Begin
  CFG^.FTPServer.Password:=RandomPassword;
  If HasFTPServerLocal Then PostMessage(Handle, MSG_KILLFTP, 0, 0);
End;


procedure TfMain.CreateParams(Var Params: TCreateParams);
begin
  Inherited CreateParams(Params);
  If Application.MainForm<>nil Then Params.WndParent:=GetDesktopWindow;
end;

procedure TfMain.pmFTP_ParamClick(Sender: TObject);
begin
  AllocateDialog(_fConnectionParameters);
  fConnectionParameters.ShowOnlyFTP:=True;
  mnConnection_ParametryClick(Self); {display param window}
  fConnectionParameters.ShowOnlyFTP:=False;
  WindowHideMain;
end;


procedure TfMain.mnEdit_LineModeClick(Sender: TObject);
begin
  FData^.Connection.LineMode:=not FData^.Connection.LineMode;
  mnEdit_LineMode.Checked   := FData^.Connection.LineMode;
end;


Procedure TfMain.ConnectionSelect;
Begin
  mnConnection_SelectClick(Self);
End;


procedure TfMain.TelnetDisplay(Sender: TSSLTnCnx; Str: String);
begin
  PrintStr(Str);
end;

procedure TfMain.TelnetDebug(Sender: TSSLTnCnx; Str: String);
begin
  PrintStr(Str);
end;



procedure TfMain.FormCreate(Sender: TObject);
begin
{$IFDEF METAL_SHIT}
  mnHelp_Registration.Destroy;
  mnHelp_N1.Destroy;
  mnHelp_www.Destroy;
{$ENDIF}

  {Hook the edit controls window procedure}
  fInvisible.MainForm:=self;
  OldEditsWindowProc := Pointer(SetWindowLong(Handle,
                                GWL_WNDPROC,
                                LongInt(@NewWindowProc)));
end;

Procedure TfMain.PrintStr(S:ShortString);
Begin
//  S:=S+#0;
  Receive(@S[1], Length(S));
End;


{ **************************************************************************** }
{ * !Keyboad support                                                         * }
{ **************************************************************************** }

{ ------------------------------------------------------------------------------
  This method 'traps' TAB key
 ------------------------------------------------------------------------------}
procedure TfMain.CMDialogKey(var msg: TCMDialogKey);
begin
  if msg.Charcode <> VK_TAB then inherited;
end;{-- CMDialogKey -----------------------------------------------------------}



{ **************************************************************************** }
{ * !ANSI files suport                                                       * }
{ **************************************************************************** }

{ ------------------------------------------------------------------------------
 Open and plays file with terminal commands. At this time is suproted only
 ansi because tarminal can't do more.
------------------------------------------------------------------------------ }
Procedure TfMain.OpenANSIFile;
Const
  BlockSize = 8*4096;
Var
  F        : File;
  P        : Array[0..BlockSize] of Byte;
  I        : Integer;
  {$IFDEF SLOW}J : Integer;{$ENDIF}
  S1       : ShortString;
begin
  If not AllocateDialog(_fOpenANSI) Then Exit;

  If fOpenANSI.Execute Then Begin
    FConsole.ClrScr;
    Try
      System.Assign(F,fOpenANSI.FileName);
      System.Reset(F,1);

      Chrono.Raz;
      While not Eof(F) Do Begin
        System.BlockRead(F, P, BlockSize, I);
        Chrono.Start;
        {$IFDEF SLOW}
        For J:=0 To I-1 Do Begin
          Receive(@P[J], 1);
          Sleep(1);
        End;
        {$ELSE}
        Receive(@P, I);
        {$ENDIF}
        Chrono.Stop;
      End;
      Chrono.Stop;
      System.Close(F);
      S1:=Format('Vykresleni trvalo: %dms.',[Chrono.Total])+#0;
      MessageBox(handle,@S1[1],'Info',MB_OK or MB_ICONINFORMATION);
    finally
    End;
  End;
  WindowHideMain;
End;{-- OpenANSIFile ----------------------------------------------------------}

{ ------------------------------------------------------------------------------
  Save content of Console's buffer to given file.
------------------------------------------------------------------------------ }
Procedure TfMain.SaveANSIFile;
Var
  TF  : TextFile;
Begin
  If SaveAs.Execute Then try
    System.Assign(TF,SaveAs.FileName);
    System.Rewrite(TF);
    FConsole.SaveToFile(TF,Pos('TXT',StrUpper(SaveAs.FileName))=0,MSG_PROGRES);
    System.Close(TF);
  except
  End;
End;{-- SaveANSIFile ----------------------------------------------------------}



{ **************************************************************************** }
{ * !FTP supoRWErt routines                                                     * }
{ **************************************************************************** }

{ ------------------------------------------------------------------------------
  Create random password. Random number generator is initalized by number
  of messages received by fInvisible
------------------------------------------------------------------------------ }
Const
  FTPPasswd : ShortString
             = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
Function TfMain.RandomPassword:String;
Var
  S : String;
  I : Integer;
Begin
  If not fInvisible.RandUsed Then Begin
    fInvisible.RandUsed:=True;
    RandSeed:=fInvisible.Rand;
  End;
  SetLength(S,{I+1}8);
  For I:=0 To 7 Do S[I+1]:=FTPPasswd[Trunc(1+Random*Length(FTPPasswd))];
  Result:=S;
End;



{ **************************************************************************** }
{ * !Window managment                                                        * }
{ **************************************************************************** }

{ ------------------------------------------------------------------------------
  Providing 'discrete' sizing for Win32.
------------------------------------------------------------------------------ }
{$IFDEF WIN32}Procedure TfMain.WMSIZING(Var msg:tmessage);
Var
  R            :^TRect;
  Height       : Integer; {Vypočítaná výška okna včetně NC}
  Width        : Integer;
  ClientHeight : Integer; {Vypočítaná velikost klientské oblasti}
  ClientWidth  : Integer;
  LostHeight   : Integer; {Height-ClientHeight}
  LostWidth    : Integer;
  ChngHeight   : Integer;
  ChngWidth    : Integer;
  FD           : PFontData;
Begin
  R:=Pointer(msg.lParam);
  Height       := R^.Bottom-R^.Top;
  Width        := R^.Right-R^.Left;
  LostHeight   := (Self.Height-Self.ClientHeight)+ {Titulek a asi něco na rámečky}
                  StatusPanel.Height;
  LostWidth    := (Self.Width-Self.ClientWidth)+
                  FConsole.ScrollBarWidth;
  ClientHeight := Height-LostHeight;
  ClientWidth  := Width-LostWidth;

  Case FData^.Console.Window.WinResizeWillCause of
    rmDimensionChange: Begin
      ChngHeight   := (ClientHeight div FConsole.CharSize.y)*FConsole.CharSize.y;
      ChngWidth    := (ClientWidth div FConsole.CharSize.x)*FConsole.CharSize.x;
      If msg.wParam in [WMSZ_BOTTOM, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT] Then R^.Bottom:=R^.Top+LostHeight+ChngHeight;
      If msg.WParam in [WMSZ_RIGHT, WMSZ_TOPRIGHT, WMSZ_BOTTOMRIGHT] Then R^.Right:=R^.Left+LostWidth+ChngWidth;
      If msg.WParam in [WMSZ_TOP, WMSZ_TOPLEFT, WMSZ_TOPRIGHT] Then R^.Top:=R^.Bottom-LostHeight-ChngHeight;
      If msg.WParam in [WMSZ_LEFT,WMSZ_TOPLEFT, WMSZ_BOTTOMLEFT] Then R^.Left:=R^.Right-LostWidth-ChngWidth;
      msg.Result:=1;
    End;
    rmFontSizeChange: Begin
      FD         := PFontData(FontData.Items[GetMaxFontHeight(ClientWidth,ClientHeight)]);
      ChngHeight := FD^.Height*FConsole.Rows;
      ChngWidth  := FD^.Width*FConsole.Cols;
      If msg.wParam in [{WMSZ_BOTTOM,} WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT] Then R^.Bottom:=R^.Top+LostHeight+ChngHeight;
      If msg.WParam in [{WMSZ_RIGHT,} WMSZ_TOPRIGHT, WMSZ_BOTTOMRIGHT] Then R^.Right:=R^.Left+LostWidth+ChngWidth;
      If msg.WParam in [{WMSZ_TOP,} WMSZ_TOPLEFT, WMSZ_TOPRIGHT] Then R^.Top:=R^.Bottom-LostHeight-ChngHeight;
      If msg.WParam in [{WMSZ_LEFT,}WMSZ_TOPLEFT, WMSZ_BOTTOMLEFT] Then R^.Left:=R^.Right-LostWidth-ChngWidth;
      If msg.WParam in [WMSZ_BOTTOM, WMSZ_RIGHT, WMSZ_TOP, WMSZ_LEFT] Then Begin
        R^.Left  :=Self.Left;
        R^.Top   :=Self.Top;
        R^.Right :=Self.Left+Self.Width;
        R^.Bottom:=Self.Top+Self.Height;
      End;
      msg.Result:=1;
    End;
    rmNoChange: Begin
      R^.Left  :=Self.Left;
      R^.Top   :=Self.Top;
      R^.Right :=Self.Left+Self.Width;
      R^.Bottom:=Self.Top+Self.Height;
      msg.Result:=1;
    End;
  End;
End;{$ENDIF}{-- WMSIZING ------------------------------------------------------}

{ ------------------------------------------------------------------------------
  Check menu item in depend on selected lanuage
------------------------------------------------------------------------------ }
Procedure TfMain.CheckLng;
Var
  MI : TMenuItem;
  I  : Integer;
  S  : String;
Begin
  { Delete old menu items }
  While mnFile_Language.Count>0 Do mnFile_Language.Delete(0);
  { Create new menu }
  For I:=0 To CFG^.KnownLang.Count-1 Do Begin
    S:=CFG^.KnownLang.Strings[I];
    MI:=TMenuItem.Create(mnFile_Language);
    MI.Visible:=True;
    MI.Caption:=Trim(Copy(S, Pos(';', S)+1, 256));
    MI.Checked:='.'+Copy(S, 1, 2)=CFG^.Language;
    MI.OnClick:=mnFile_LanguageClick;
    MI.Tag:=-I;
    mnFile_Language.Add(MI);
  End;
End;{--CheckLng----------------------------------------------------------------}

{ ------------------------------------------------------------------------------
  Displays cursor postion or if ResizeTimer.Enabled show window size after
  resizing;
------------------------------------------------------------------------------ }
Procedure TfMain.CheckCursorPos;
Begin
  If ResizeTimer.Enabled Then
    CursorPos.Caption:=Format('%dx%d',[FConsole.Cols,FConsole.Rows])
  Else
    CursorPos.Caption:=Format('%d:%d',[FConsole.CursorPos.X+1,FConsole.CursorPos.Y+1])
End;{-CheckCursorPos-----------------------------------------------------------}

{ ------------------------------------------------------------------------------
  This method swap menu response to betwen standard handling and defining
  shortcut.
------------------------------------------------------------------------------ }
Procedure TfMain.CheckMenu;
Begin
  If mnEdit_HotKeys.Checked Then
   Begin
     mnFile_Open.OnClick               := DefineSrtCt;
     mnFile_Save.OnClick               := DefineSrtCt;
     mnFile_Log .OnClick               := DefineSrtCt;
     mnFile_Lock.OnClick               := DefineSrtCt;
     mnFile_FTPStartStop.OnClick       := DefineSrtCt;
     mnFile_FTPPassword.OnClick        := DefineSrtCt;
     mnFile_LocalIP.OnClick            := DefineSrtCt;
     mnFile_ScreenCopy.OnClick         := DefineSrtCt;
     mnFile_PrinterSetup.OnClick       := DefineSrtCt;
     mnFile_Exit.OnClick               := DefineSrtCt;
                                       
     mnEdit_Paste.OnClick              := DefineSrtCt;
     mnEdit_Refresh.OnClick            := DefineSrtCt;
     mnEdit_LineMode.OnClick           := DefineSrtCt;
                                       
     mnConnection_Select.OnClick       := DefineSrtCt;
     mnConnection_Duplicate.OnClick    := DefineSrtCt;
     mnConnection_Close.OnClick        := DefineSrtCt;
     mnConnection_QuickConnect.OnClick := DefineSrtCt;
     mnConnection_Parametry.OnClick    := DefineSrtCt;
     mnConnection_OTP.OnClick          := DefineSrtCt;
                                       
     mnHelp_About.OnClick              := DefineSrtCt;
   End
  Else
   Begin
     mnFile_Open.OnClick           := mnFile_OpenClick;
     mnFile_Save.OnClick           := mnFile_SaveClick;
     mnFile_Log .OnClick           := mnFile_LogClick;
     mnFile_Lock.OnClick           := mnFile_LockClick;
     mnFile_LocalIP.OnClick        := mnFile_LocalIPClick;
     mnFile_FTPStartStop.OnClick   := mnFile_FTPStartStopClick;
     mnFile_FTPPassword.OnClick    := mnFile_FTPPasswordClick;
     mnFile_ScreenCopy.OnClick     := mnFile_ScreenCopyClick;
     mnFile_PrinterSetup.OnClick   := mnFile_PrinterSetupClick;
     mnFile_Exit.OnClick           := mnFile_ExitClick;

     mnEdit_Paste.OnClick          := mnEdit_PasteClick;
     mnEdit_Refresh.OnClick        := mnEdit_RefreshClick;
     mnEdit_LineMode.OnClick       := mnEdit_LineModeClick;

     mnConnection_Select.OnClick   := mnConnection_SelectClick;
     mnConnection_Duplicate.OnClick:= mnConnection_DuplicateClick;
     mnConnection_Close.OnClick    := mnConnection_CloseClick;
     mnConnection_Parametry.OnClick:= mnConnection_ParametryClick;
     mnConnection_QuickConnect.OnClick := mnConnection_QuickConnectClick;
     mnConnection_OTP.OnClick      := mnConnection_OTPClick;

     mnHelp_About.OnClick          := mnHelp_AboutClick;
   End;
End;{-- CheckMenu -------------------------------------------------------------}

{ ------------------------------------------------------------------------------
  Check if is enabled only valid menu items and check status bar.
------------------------------------------------------------------------------ }
Procedure TfMain.CheckStatus;
Begin
  If HasFTPServer Then Begin
    mnFile_FTPPassword.Enabled:=True;
    mnFile_FTPStartStop.Caption:=ctFTPStop;
    pmFTP_Password.Enabled:=True;
    pmFTP_StartStop.Caption:=ctFTPStop;
    pmFTP_Param.Enabled:=True;
    mnFileFTPLocalSession.Enabled:=False;
    mnFTP_LocalSession.Enabled:=False;
  End Else
    If CFG^.FTPServer=nil Then Begin
      mnFile_FTPPassword.Enabled:=False;
      mnFile_FTPStartStop.Caption:=ctFTPStart;
      mnFileFTPLocalSession.Enabled:=True;
      mnFTP_LocalSession.Enabled:=True;
      pmFTP_Password.Enabled:=False;
      pmFTP_StartStop.Caption:=ctFTPStart;
      pmFTP_Param.Enabled:=True;
    End Else Begin
      mnFile_FTPPassword.Enabled:=False;
      mnFile_FTPStartStop.Enabled:=False;
      mnFile_FTPStartStop.Caption:=ctFTPStart;
      mnFileFTPLocalSession.Enabled:=False;       
      mnFTP_LocalSession.Enabled:=False;
      pmFTP_Password.Enabled:=False;
      pmFTP_StartStop.Enabled:=False;
      pmFTP_StartStop.Caption:=ctFTPStart;
      pmFTP_Param.Enabled:=False;
    End;

  If Assigned(CFG^.FTPServer) Then Begin
    FTPRunning.LedStatus:=lsOn;
  End Else Begin
    FTPRunning.LedStatus:=lsOff;
    FTPRunning.Hint:='';
  End;

  If mnEdit_HotKeys.Checked Then Begin   
    mnFile_Log.Enabled             := True;
    pmFile_Log.Enabled             := True;
    mnEdit_Paste.Enabled           := True;
    mnFile_FTPPassword.Enabled     := True;
    mnConnection_Select.Enabled    := True;
    mnConnection_QuickConnect.Enabled := True;
    mnConnection_Close.Enabled     := True;
    mnConnection_Duplicate.Enabled     := True;
    mnConnection_Parametry.Enabled := True;
  end else begin
    mnFile_Log.Enabled             := Telnet.IsConnected;
    pmFile_Log.Enabled             := Telnet.IsConnected;
    mnConnection_Close.Enabled     := Telnet.IsConnected;
    mnConnection_Duplicate.Enabled := Telnet.IsConnected;
    pmConnection_Close.Enabled     := Telnet.IsConnected;
   end;

  SetCaption;

  If MouseIsDown Then ConnStatus.LedStatus:=lsBlink;

  If mnFile_Log.Checked Then
    Logging.LedStatus:=lsBlink
  else
    Logging.LedStatus:=lsOff;

  If Telnet.IsConnected Then Begin
    ConnStatus.LedStatus:=lsOn;
    {$IFNDEF NOSSL}
    If Telnet.Socket.SSLState=sslConnected Then
      SSLStatus.LedStatus :=lsOn
    Else
      SSLStatus.LedStatus :=lsOff;{$ENDIF}
  End else Begin
    ConnStatus.LedStatus:=lsOff;
    SSLStatus.LedStatus :=lsOff;
  End;


  If (TerminalEmulator.PrinterActive)or(PRNPrinting) Then
   Begin
     LedStatusPanel.Width   := 4*18+20;
     {AnimatedPrinter.Active := True;}
   End
  Else
   Begin
     LedStatusPanel.Width   := 4*18-1;
     {AnimatedPrinter.Active := False;}
   End;
End;{-- CheckStatus -----------------------------------------------------------}

{ ------------------------------------------------------------------------------
  Check and fix form window size to corespond with console size
------------------------------------------------------------------------------ }
Procedure TfMain.CheckWindowSize;
Begin
  If GetActiveWindow=Handle Then Begin { pridano 22.10.1998, bez toho si okna }
    FConsole.CaretHide;                { obcas kradla kurzor obcas se nezobrazoval }
    FConsole.CaretDestroy;             { v dialogovych oknech a tak podobne}
    FConsole.CaretCreate;
    FConsole.CaretShow;
  End;
  ClientWidth         := FConsole.ScreenWidth;
  ClientHeight        := FConsole.ScreenHeight+StatusPanel.Height;
  LedStatusPanel.Left := ClientWidth-LedStatusPanel.Width;
  PanelClock.Left     := ClientWidth-PanelClock.Width-LedStatusPanel.Width;
  ProgresBar.Width    := ClientWidth-PanelClock.Width-LedStatusPanel.Width-
                         CursorPos.Width;
End;{-- CheckWindowSize -------------------------------------------------------}

{ ------------------------------------------------------------------------------
  Return maximum console font height for actual size of window
------------------------------------------------------------------------------ }
function TfMain.GetMaxFontHeight(X,Y:Integer):Integer;
Var
  S            : ShortString;
  I            : Integer;

  ChngHeight   : Integer;
  ChngWidth    : Integer;

Begin
  S          := FConsole.FontName+#0;

  If FontData=nil Then FontData := TSortedList.Create
  Else FontData_Clear(FontData);

  FontData_Enum(FontData, @S[1], FConsole.FontBold);

  I:=0;
  If FontData.Count>1 Then Begin
    For I:=0 To FontData.Count-1 Do Begin
       ChngHeight:=PFontData(FontData.Items[I])^.Height*FConsole.Rows;
       ChngWidth :=PFontData(FontData.Items[I])^.Width* FConsole.Cols;
       If (ChngWidth>X)or(ChngHeight>Y)Then Break;
    End;dec(I);
  End;
  Result:=I;
End;{-- GetMaxFontHeight ------------------------------------------------------}


{ **************************************************************************** }
{ * !OTHER STUFF                                                             * }
{ **************************************************************************** }


procedure TfMain.FormShow(Sender: TObject);
begin
  PostMessage(fInvisible.Handle, MSG_GENERATEMENU, 0, 0);
end;

procedure TfMain.TelnetError(Sender: TSSLTnCnx; Error: Word);
begin
  Case Error of
    seNoDDL         : MessageBox(Handle, @ctNoDLL[1], @ctInformation[1], MB_ICONINFORMATION or MB_OK);
    seNoSSLAvaiable : MessageBox(Handle, @ctNoSSL[1], @ctInformation[1], MB_ICONINFORMATION or MB_OK);
  End;
end;

procedure TfMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  PostMessage(fInvisible.Handle, MSG_KILLME, Handle, LongInt(Self));
end;

procedure TfMain.mnFTP_LocalSessionClick(Sender: TObject);
begin
  mnFileFTPLocalSession.Click;
end;

Procedure TfMain.FTPServerOnStart(Sender: TObject);
Var
  S : ShortString;
Begin
  If HasFTPServerLocal Then Begin
    S := 'ftp '#0;
    If Telnet.IsConnected Then Transmit(@S[1])
    Else
      If Telnet.Socket.State=wsClosed Then Receive(@S[1], StrLen(@S[1]))
      Else MessageBeep(1);
    mnFile_LocalIPClick(Self);
  End;
  CheckStatus;
End;

procedure TfMain.mnHelp_PublicKeyClick(Sender: TObject);
begin
  If not AllocateDialog(_fPGPPublicKey) Then Exit;

  fPGPPublicKey.ShowModal;

  WindowHideMain;
end;


procedure TfMain.mnHelp_wwwClick(Sender: TObject);
Var
  S : ShortString;
begin
  S:='http://www.tomasek.cz/semtel_'+Copy(CFG^.Language, 2, 2)+'.html'#0;
  ShellExecute(application.handle,'open', @S[1], nil, nil, SW_SHOWNORMAL);
end;

procedure TfMain.mnConnection_QuickConnectClick(Sender: TObject);
begin
  AllocateDialog(_fQuickConnect);
  If fQuickConnect.ShowModal=mrOk Then Begin
    ConnectTo(fQuickConnect.Definition.Text,
              fQuickConnect.HostName.Text,
              fQuickConnect.Port.Text);
  End;
end;

procedure TfMain.mnConnection_DuplicateClick(Sender: TObject);
begin
  ConnectTo(FData^.Connection.Caption, '', '');
end;

procedure TfMain.R2Prn_HidePanel;
begin
  pnRedirectedToPrinter.Visible := False;
end;

procedure TfMain.R2Prn_ShowPanel;
begin
  RedirectedToPrinter_Gauge.Visible := False;
  pnRedirectedToPrinter.Visible := True;
  R2Prn_Counter := 0;
end;

procedure TfMain.R2Prn_SetTransferedBytes(B:Integer);
begin
  R2Prn_Counter := B*1024;
  pnRedirectedToPrinter_Action.Caption := Format(ct_Transfered_str, [B]);
  pnRedirectedToPrinter.Update;
end;

procedure TfMain.R2Prn_SetPrintedBytes;
begin
  R2Prn_Counter := Round(100*PRNbuffer.Position/PRNBuffer.Size);
  RedirectedToPrinter_Gauge.Visible := True;
  RedirectedToPrinter_Gauge.Position := R2Prn_Counter;
  pnRedirectedToPrinter_Action.Caption := Format(ct_Printing_str, [R2Prn_Counter]);
  pnRedirectedToPrinter.Update;
end;

initialization
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'initialization', '');{$ENDIF}
{$IFDEF Win32}finalization
  {$IFDEF DEBUGMSG}WriteToLog(DebugDetailed, kuMain, 'finalization', '');{$ENDIF}{$ENDIF}
End.
