<?xml version="1.0" encoding="utf-8"?>
<CrossEngineApp Version="1">
  <Options>object ProjOption: TProjectOptions
  Title = 'sercatgui'
  AppName = 'sercatgui'
  Language = 'PASCAL'
  AppIcon.Data = {
[encoded data, 7038 characters]
    1FFF
  }
  AppAutor = 'Copyright(c) 2020-2023 Alexey Kuryakin kouriakine@mail.ru'
  MinVMajor = 2
  MinVMinor = 1
  MinVRevision = 2
  ExternalPath = '$DIESELPASCAL_EXTERNAL;$DIESEL_LOCALSET_DIR/external;$DIESEL_EXE_DIR/external;'
  AutoCreateExternal.Strings = (
    'dpAntiZombie'
    'dpGuiResMain'
    'dpGuiResTools'
  )
  StartParametrs = '--ini sercatgui_1.ini'
end
</Options>
  <Metadata>
    <sercatgui ImageIndex="2">
      <Object ClassName=""/>
      <Code>program sercatgui;

uses dpCmdArgs,dpSystem,dpSysUtils,dpWindows,dpVbs,dpCrwDaqSys,dpDaqConfig,
     dpGuiResMain,dpGuiResTools,sercatlib,Main;

begin
  InitGuiResMain;  // Init GUI Resources - Main
  InitGuiResTools; // Init GUI Resources - Tools
  SetCrwDaqChildTitle(GetScriptName+' --number '+IntToStr(InstanceNumber));
  if InstanceRunning(GetCrwDaqChildTitle,true) then begin
   AppActivateByClassTitle('Window',GetCrwDaqChildTitle);
   Application.Terminate;
   Exit;
  end;
  MainForm := TMainForm.Create(Application);
end.
</Code>
      <Child>
        <Main ImageIndex="1">
          <Object ClassName="TMainForm">object MainForm: TForm
  Left = 301
  Height = 600
  Top = 117
  Width = 820
  BorderWidth = 4
  Caption = 'MainForm'
  ClientHeight = 600
  ClientWidth = 820
  Constraints.MinHeight = 600
  Constraints.MinWidth = 820
  DoubleBuffered = True
  Font.Height = -13
  Font.Name = 'PT Mono'
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  ParentDoubleBuffered = False
  ShowHint = True
  LCLVersion = '2.2.6.0'
  object PanelMain: TPanel
    Left = 4
    Height = 592
    Top = 4
    Width = 812
    Align = alClient
    BorderWidth = 4
    ClientHeight = 592
    ClientWidth = 812
    TabOrder = 0
    object PageControlMain: TPageControl
      Left = 5
      Height = 582
      Top = 5
      Width = 802
      ActivePage = TabSheetSercat
      Align = alClient
      Images = DataModuleGuiResMain.ImageListMain32x32
      TabIndex = 0
      TabOrder = 0
      object TabSheetSercat: TTabSheet
        Caption = 'sercat '
        ClientHeight = 538
        ClientWidth = 792
        ImageIndex = 289
        object PanelSercatCtrl: TPanel
          Left = 0
          Height = 142
          Top = 0
          Width = 792
          Align = alTop
          BorderWidth = 4
          ClientHeight = 142
          ClientWidth = 792
          TabOrder = 0
          object PanelSercatButtons: TPanel
            Left = 5
            Height = 56
            Top = 80
            Width = 782
            Align = alTop
            BorderWidth = 4
            ClientHeight = 56
            ClientWidth = 782
            TabOrder = 0
            object BitBtnSercatUpdate: TBitBtn
              Left = 128
              Height = 46
              Top = 4
              Width = 115
              Action = ActionSercatUpdate
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 298
              TabOrder = 1
            end
            object BitBtnSercatStop: TBitBtn
              Left = 248
              Height = 46
              Top = 4
              Width = 115
              Action = ActionSercatStop
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 115
              TabOrder = 2
            end
            object BitBtnSercatRun: TBitBtn
              Left = 368
              Height = 46
              Top = 4
              Width = 115
              Action = ActionSercatRun
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 114
              TabOrder = 3
            end
            object BitBtnSercatHelp: TBitBtn
              Left = 8
              Height = 46
              Top = 4
              Width = 115
              Action = ActionSercatHelp
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 124
              TabOrder = 0
            end
            object BitBtnSercatKillAll: TBitBtn
              Left = 660
              Height = 46
              Top = 4
              Width = 115
              Action = ActionSercatKillAll
              Anchors = [akTop, akRight]
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 23
              TabOrder = 4
            end
          end
          object StatusBarSercatPort: TStatusBar
            Left = 5
            Height = 17
            Top = 5
            Width = 782
            Align = alTop
            Panels = &lt;&gt;
            SimpleText = ' sercat: stopped'
          end
          object PanelSercatPort: TPanel
            Left = 5
            Height = 58
            Top = 22
            Width = 782
            Align = alTop
            BorderWidth = 4
            ClientHeight = 58
            ClientWidth = 782
            TabOrder = 2
            object LabelSercatPort: TLabel
              Left = 8
              Height = 15
              Top = 8
              Width = 72
              Caption = 'COM Port:'
              ParentColor = False
            end
            object ComboBoxSercatPort: TComboBox
              Left = 8
              Height = 27
              Hint = 'Serial COM port name, path and driver type.'
              Top = 24
              Width = 272
              DropDownCount = 25
              ItemHeight = 0
              TabOrder = 0
            end
            object LabelSercatBaudRate: TLabel
              Left = 284
              Height = 15
              Top = 8
              Width = 64
              Caption = 'BaudRate'
              ParentColor = False
            end
            object ComboBoxSercatBaudRate: TComboBox
              Left = 284
              Height = 27
              Hint = 'Baudrate - data transfer speed, bits per second.'
              Top = 24
              Width = 108
              DropDownCount = 25
              ItemHeight = 0
              ItemIndex = 12
              Items.Strings = (
                '50'
                '75'
                '110'
                '134'
                '150'
                '200'
                '300'
                '600'
                '1200'
                '1800'
                '2400'
                '4800'
                '9600'
                '19200'
                '38400'
                '57600'
                '115200'
                '230400'
                '460800'
                '500000'
                '576000'
                '921600'
                '1000000'
                '1152000'
                '1500000'
                '2000000'
                '2500000'
                '3000000'
                '3500000'
                '4000000'
              )
              Style = csDropDownList
              TabOrder = 1
              Text = '9600'
            end
            object LabelSercatDataBits: TLabel
              Left = 400
              Height = 15
              Hint = 'ByteSize, number of data bits per byte.'
              Top = 8
              Width = 64
              Caption = 'DataBits'
              ParentColor = False
            end
            object ComboBoxSercatDataBits: TComboBox
              Left = 396
              Height = 27
              Hint = 'ByteSize - number of Data Bits per byte.'
              Top = 24
              Width = 72
              ItemHeight = 0
              ItemIndex = 3
              Items.Strings = (
                '5'
                '6'
                '7'
                '8'
              )
              Style = csDropDownList
              TabOrder = 2
              Text = '8'
            end
            object LabelSercatParity: TLabel
              Left = 476
              Height = 15
              Top = 8
              Width = 48
              Caption = 'Parity'
              ParentColor = False
            end
            object ComboBoxSercatParity: TComboBox
              Left = 472
              Height = 27
              Hint = 'Parity control type.'
              Top = 24
              Width = 72
              ItemHeight = 0
              ItemIndex = 0
              Items.Strings = (
                'NONE'
                'ODD'
                'EVEN'
              )
              Style = csDropDownList
              TabOrder = 3
              Text = 'NONE'
            end
            object LabelSercatStopBits: TLabel
              Left = 552
              Height = 15
              Top = 8
              Width = 64
              Caption = 'StopBits'
              ParentColor = False
            end
            object ComboBoxSercatStopBits: TComboBox
              Left = 548
              Height = 27
              Hint = 'Number of stop bits.'
              Top = 24
              Width = 72
              ItemHeight = 0
              ItemIndex = 0
              Items.Strings = (
                '1'
                '2'
              )
              OnChange = ComboBoxSercatStopBitsChange
              Style = csDropDownList
              TabOrder = 4
              Text = '1'
            end
            object CheckListBoxSercatOptions: TCheckListBox
              Left = 624
              Height = 48
              Hint = 'sercat Options and Flags.'
              Top = 4
              Width = 152
              Anchors = [akTop, akLeft, akRight]
              Items.Strings = (
                '--verbose'
                '--flags CRTSCTS'
              )
              ItemHeight = 19
              TabOrder = 5
              Data = {
                020000000000
              }
            end
          end
        end
        object PanelSercatInput: TPanel
          Left = 0
          Height = 90
          Top = 142
          Width = 792
          Align = alTop
          BorderWidth = 4
          ClientHeight = 90
          ClientWidth = 792
          TabOrder = 1
          object PageControlSercatIOMode: TPageControl
            Left = 547
            Height = 80
            Top = 5
            Width = 240
            ActivePage = TabSheetSercatInputMode
            Align = alRight
            TabIndex = 0
            TabOrder = 0
            object TabSheetSercatInputMode: TTabSheet
              Caption = 'Input'
              ClientHeight = 53
              ClientWidth = 230
              object LabelSercatInputMode: TLabel
                Left = 4
                Height = 15
                Top = 4
                Width = 32
                Caption = 'Mode'
                ParentColor = False
              end
              object ComboBoxSercatInputMode: TComboBox
                Left = 4
                Height = 27
                Top = 20
                Width = 72
                ItemHeight = 0
                ItemIndex = 0
                Items.Strings = (
                  'DEF'
                  'RAW'
                  'HEX'
                  'ESC'
                )
                Style = csDropDownList
                TabOrder = 0
                Text = 'DEF'
              end
              object LabelSercatChecksum: TLabel
                Left = 84
                Height = 15
                Top = 4
                Width = 64
                Caption = 'Checksum'
                ParentColor = False
              end
              object ComboBoxSercatChecksum: TComboBox
                Left = 80
                Height = 27
                Top = 20
                Width = 76
                ItemHeight = 0
                ItemIndex = 0
                Items.Strings = (
                  'NONE'
                  'DCON'
                )
                Style = csDropDownList
                TabOrder = 1
                Text = 'NONE'
              end
              object LabelSercatEol: TLabel
                Left = 164
                Height = 15
                Top = 4
                Width = 24
                Caption = 'EOL'
                ParentColor = False
              end
              object ComboBoxSercatEol: TComboBox
                Left = 160
                Height = 27
                Top = 20
                Width = 64
                ItemHeight = 0
                ItemIndex = 3
                Items.Strings = (
                  'NONE'
                  'CR'
                  'LF'
                  'CRLF'
                )
                Style = csDropDownList
                TabOrder = 2
                Text = 'CRLF'
              end
            end
            object TabSheetSercatOutputMode: TTabSheet
              Caption = 'Output'
              ClientHeight = 53
              ClientWidth = 230
              object LabelSercatOutputMode: TLabel
                Left = 4
                Height = 15
                Top = 4
                Width = 32
                Caption = 'Mode'
                ParentColor = False
              end
              object ComboBoxSercatOutputMode: TComboBox
                Left = 4
                Height = 27
                Top = 20
                Width = 72
                ItemHeight = 0
                ItemIndex = 0
                Items.Strings = (
                  'DEF'
                  'RAW'
                  'HEX'
                  'ESC'
                )
                Style = csDropDownList
                TabOrder = 0
                Text = 'DEF'
              end
              object CheckBoxSercatShowAnsNoAsk: TCheckBox
                Left = 82
                Height = 21
                Top = 4
                Width = 136
                Caption = 'Show Ans/NoAsk'
                TabOrder = 1
              end
              object CheckBoxSercatDropTailEol: TCheckBox
                Left = 82
                Height = 21
                Hint = 'Drop trailing EOL from sercat Request/Reply.'
                Top = 24
                Width = 128
                Caption = 'Drop tail EOL'
                Checked = True
                State = cbChecked
                TabOrder = 2
              end
            end
            object TabSheetSercatTimeMode: TTabSheet
              Caption = 'Time'
              ClientHeight = 53
              ClientWidth = 230
              object CheckBoxSercatWaitEol: TCheckBox
                Left = 4
                Height = 21
                Hint = 'Wait for EOL or Timeout to read Reply.'
                Top = 4
                Width = 152
                Caption = 'Wait:EOL/Timeout'
                Checked = True
                State = cbChecked
                TabOrder = 0
              end
              object SpinEditSercatRxTimeout: TSpinEdit
                Left = 164
                Height = 25
                Hint = 'Timeout to wait for Reply, ms.'
                Top = 4
                Width = 58
                Increment = 50
                MaxValue = 10000
                MinValue = 50
                TabOrder = 1
                Value = 250
              end
              object CheckBoxSercatOptPoll: TCheckBox
                Left = 4
                Height = 21
                Hint = 'Include --poll p option  to set sercat polling period (p), ms.'
                Top = 28
                Width = 160
                Caption = '--poll option, ms'
                OnChange = CheckBoxSercatOptPollChange
                TabOrder = 2
              end
              object SpinEditSercatOptPoll: TSpinEdit
                Left = 164
                Height = 25
                Hint = 'sercat polling period, ms.'
                Top = 28
                Width = 58
                MaxValue = 1000
                MinValue = 1
                TabOrder = 3
                Value = 4
              end
            end
          end
          object PageControlSercatInput: TPageControl
            Left = 5
            Height = 80
            Top = 5
            Width = 542
            ActivePage = TabSheetSercatInput
            Align = alClient
            TabIndex = 0
            TabOrder = 1
            object TabSheetSercatInput: TTabSheet
              Caption = 'sercat - Input'
              ClientHeight = 53
              ClientWidth = 532
              object BitBtnSercatSend: TBitBtn
                Left = 4
                Height = 46
                Top = 4
                Width = 115
                Action = ActionSercatSend
                Images = DataModuleGuiResMain.ImageListMain32x32
                ImageIndex = 60
                TabOrder = 0
              end
              object LabelSercatInput: TLabel
                Left = 128
                Height = 15
                Top = 4
                Width = 104
                Caption = 'Data to send:'
                ParentColor = False
              end
              object ComboBoxSercatInputDecode: TComboBox
                Left = 448
                Height = 27
                Hint = 'Encoding method for Input string.'
                Top = 0
                Width = 80
                Anchors = [akTop, akRight]
                ItemHeight = 0
                ItemIndex = 0
                Items.Strings = (
                  'DEF'
                  'RAW'
                  'HEX'
                  'ESC'
                  'URL'
                  'B64'
                )
                Style = csDropDownList
                TabOrder = 2
                Text = 'DEF'
              end
              object LabelSercatInputDecode: TLabel
                Left = 376
                Height = 15
                Top = 4
                Width = 64
                Anchors = [akTop, akRight]
                Caption = 'Encoding'
                ParentColor = False
              end
              object ComboBoxSercatInput: TComboBox
                Left = 127
                Height = 27
                Top = 24
                Width = 401
                Anchors = [akTop, akLeft, akRight]
                ItemHeight = 0
                OnKeyDown = ComboBoxSercatInputKeyDown
                TabOrder = 1
              end
            end
            object TabSheetSercatAdamScan: TTabSheet
              Caption = 'ADAM Scan'
              ClientHeight = 53
              ClientWidth = 532
              object CheckBoxSercatAdamScan: TCheckBox
                Left = 4
                Height = 21
                Top = 4
                Width = 184
                Caption = 'ADAM Scanner from/to'
                OnChange = CheckBoxSercatAdamScanChange
                TabOrder = 0
              end
              object SpinEditSercatAdamScanLo: TSpinEdit
                Left = 80
                Height = 25
                Top = 24
                Width = 54
                MaxValue = 255
                TabOrder = 1
              end
              object SpinEditSercatAdamScanHi: TSpinEdit
                Left = 136
                Height = 25
                Top = 24
                Width = 54
                MaxValue = 255
                TabOrder = 2
                Value = 255
              end
              object LabelSercatAdamScanAddr: TLabel
                Left = 4
                Height = 15
                Top = 32
                Width = 72
                Caption = 'Addr: $00'
                ParentColor = False
              end
            end
          end
        end
        object PanelSercatOutput: TPanel
          Left = 0
          Height = 306
          Top = 232
          Width = 792
          Align = alClient
          BorderWidth = 4
          ClientHeight = 306
          ClientWidth = 792
          TabOrder = 2
          object PageControlSercatOutput: TPageControl
            Left = 5
            Height = 296
            Top = 5
            Width = 782
            ActivePage = TabSheetSercatLog
            Align = alClient
            Images = DataModuleGuiResMain.ImageListMain16x16
            TabIndex = 0
            TabOrder = 0
            OnChange = PageControlSercatOutputChange
            object TabSheetSercatLog: TTabSheet
              Caption = 'Log'
              ClientHeight = 268
              ClientWidth = 772
              ImageIndex = 53
              object PanelSercatLog: TPanel
                Left = 0
                Height = 268
                Top = 0
                Width = 714
                Align = alClient
                BorderWidth = 4
                ClientHeight = 268
                ClientWidth = 714
                TabOrder = 0
                object MemoSercatLog: TMemo
                  Left = 5
                  Height = 258
                  Top = 5
                  Width = 704
                  Align = alClient
                  Color = clInfoBk
                  HideSelection = False
                  ReadOnly = True
                  ScrollBars = ssAutoBoth
                  TabOrder = 0
                  WordWrap = False
                end
              end
              object PanelSercatLogButtons: TPanel
                Left = 714
                Height = 268
                Top = 0
                Width = 58
                Align = alRight
                BorderWidth = 4
                ClientHeight = 268
                ClientWidth = 58
                TabOrder = 1
                object BitBtnSercatLogCopy: TBitBtn
                  Left = 4
                  Height = 46
                  Top = 4
                  Width = 47
                  Action = ActionSercatLogCopy
                  Images = DataModuleGuiResMain.ImageListMain32x32
                  ImageIndex = 25
                  TabOrder = 0
                end
                object BitBtnSercatLogReset: TBitBtn
                  Left = 4
                  Height = 46
                  Top = 215
                  Width = 47
                  Action = ActionSercatLogReset
                  Anchors = [akLeft, akBottom]
                  Images = DataModuleGuiResMain.ImageListMain32x32
                  ImageIndex = 23
                  TabOrder = 1
                end
              end
            end
            object TabSheetSercatAskAns: TTabSheet
              Caption = 'Ask/Ans'
              ClientHeight = 268
              ClientWidth = 772
              ImageIndex = 304
              object PanelSercatAskAns: TPanel
                Left = 0
                Height = 268
                Top = 0
                Width = 714
                Align = alClient
                BorderWidth = 4
                ClientHeight = 268
                ClientWidth = 714
                TabOrder = 0
                object StringGridSercatAskAns: TStringGrid
                  Left = 5
                  Height = 258
                  Top = 5
                  Width = 704
                  Align = alClient
                  Color = clInfoBk
                  GridLineWidth = 3
                  Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goAutoAddRows, goSmoothScroll, goCellEllipsis]
                  Options2 = [goScrollToLastRow]
                  TabOrder = 0
                end
              end
              object PanelSercatAskAnsButtons: TPanel
                Left = 714
                Height = 268
                Top = 0
                Width = 58
                Align = alRight
                BorderWidth = 4
                ClientHeight = 268
                ClientWidth = 58
                TabOrder = 1
                OnClick = PanelSercatAskAnsButtonsClick
                object BitBtnSercatAskAnsReset: TBitBtn
                  Left = 4
                  Height = 46
                  Top = 215
                  Width = 47
                  Action = ActionSercatAskAnsReset
                  Anchors = [akLeft, akBottom]
                  Images = DataModuleGuiResMain.ImageListMain32x32
                  ImageIndex = 23
                  TabOrder = 0
                end
                object BitBtnSercatAskAnsAutoSize: TBitBtn
                  Left = 4
                  Height = 46
                  Top = 4
                  Width = 47
                  Action = ActionSercatAskAnsAutoSize
                  Images = DataModuleGuiResMain.ImageListMain32x32
                  ImageIndex = 304
                  TabOrder = 1
                end
                object BitBtnSercatAskAnsCopy: TBitBtn
                  Left = 4
                  Height = 46
                  Top = 52
                  Width = 47
                  Action = ActionSercatAskAnsCopy
                  Images = DataModuleGuiResMain.ImageListMain32x32
                  ImageIndex = 25
                  TabOrder = 2
                end
              end
            end
          end
        end
      end
      object TabSheetTools: TTabSheet
        Caption = 'Tools '
        ClientHeight = 538
        ClientWidth = 792
        ImageIndex = 161
        object PanelToolsContent: TPanel
          Left = 0
          Height = 338
          Top = 134
          Width = 792
          Align = alClient
          BorderWidth = 8
          ClientHeight = 338
          ClientWidth = 792
          TabOrder = 0
          object LabelMainExecUserCmnd: TLabel
            Left = 9
            Height = 15
            Top = 9
            Width = 774
            Align = alTop
            Caption = 'Result:'
            ParentColor = False
          end
          object MemoMainExecUserCmnd: TMemo
            Left = 9
            Height = 305
            Top = 24
            Width = 774
            Align = alClient
            Color = clInfoBk
            ReadOnly = True
            ScrollBars = ssAutoBoth
            TabOrder = 0
            WordWrap = False
          end
        end
        object PanelMainButtons: TPanel
          Left = 0
          Height = 66
          Top = 472
          Width = 792
          Align = alBottom
          BorderWidth = 8
          ClientHeight = 66
          ClientWidth = 792
          TabOrder = 1
          object LabeMainSendUserCmnd: TLabel
            Left = 8
            Height = 15
            Top = 11
            Width = 160
            Anchors = [akLeft, akBottom]
            Caption = 'User command to send'
            ParentColor = False
          end
          object EditMainSendUserCmnd: TEdit
            Left = 8
            Height = 27
            Hint = 'Input command to send to CRW-DAQ console.'
            Top = 27
            Width = 366
            Anchors = [akLeft, akRight, akBottom]
            TabOrder = 0
            Text = '@echo Hello, CRW-DAQ'
          end
          object BitBtnMainSendUserCmnd: TBitBtn
            Left = 378
            Height = 46
            Top = 12
            Width = 103
            Action = ActionMainSendUserCmnd
            Anchors = [akRight, akBottom]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 59
            TabOrder = 1
          end
          object BitBtnMainExecUserCmnd: TBitBtn
            Left = 484
            Height = 46
            Top = 12
            Width = 91
            Action = ActionMainExecUserCmnd
            Anchors = [akRight, akBottom]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 114
            TabOrder = 2
          end
          object BitBtnMainProgramExit: TBitBtn
            Left = 580
            Height = 46
            Top = 12
            Width = 91
            Action = ActionMainProgramExit
            Anchors = [akRight, akBottom]
            ModalResult = 11
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 113
            TabOrder = 3
          end
          object BitBtnMainParentShow: TBitBtn
            Left = 676
            Height = 46
            Top = 12
            Width = 103
            Action = ActionMainParentShow
            Anchors = [akRight, akBottom]
            ModalResult = 11
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 234
            TabOrder = 4
          end
        end
        object PanelSercatParams: TPanel
          Left = 0
          Height = 134
          Top = 0
          Width = 792
          Align = alTop
          BorderWidth = 4
          ClientHeight = 134
          ClientWidth = 792
          TabOrder = 2
          OnClick = PanelSercatParamsClick
          object GroupBoxSercatParams: TGroupBox
            Left = 5
            Height = 124
            Top = 5
            Width = 782
            Align = alClient
            Caption = ' Parameters and Settings: '
            ClientHeight = 108
            ClientWidth = 780
            TabOrder = 0
            object BitBtnDisplayLanguageRussian: TBitBtn
              Left = 8
              Height = 46
              Top = 8
              Width = 135
              Action = ActionDisplayLanguageRussian
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 200
              TabOrder = 0
            end
            object BitBtnDisplayLanguageEnglish: TBitBtn
              Left = 148
              Height = 46
              Top = 8
              Width = 135
              Action = ActionDisplayLanguageEnglish
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 201
              TabOrder = 1
            end
            object LabelSercatKillTimeout: TLabel
              Left = 292
              Height = 15
              Top = 8
              Width = 120
              Caption = 'Timeout on Stop'
              ParentColor = False
            end
            object SpinEditSercatKillTimeout: TSpinEdit
              Left = 288
              Height = 25
              Hint = 'Timeout (ms) on Stop sercat.'
              Top = 28
              Width = 134
              Increment = 100
              MaxValue = 60000
              MinValue = 100
              TabOrder = 2
              Value = 500
            end
            object LabelSercatTimeoutMark: TLabel
              Left = 432
              Height = 15
              Top = 8
              Width = 96
              Caption = 'Timeout Mark'
              ParentColor = False
            end
            object ComboBoxSercatTimeoutMark: TComboBox
              Left = 428
              Height = 27
              Hint = 'Marker on No Reply TimeOut.'
              Top = 28
              Width = 132
              ItemHeight = 0
              ItemIndex = 0
              Items.Strings = (
                ''
                '&lt;NONE&gt;'
                '&lt;EMPTY&gt;'
                '&lt;TIMEOUT&gt;'
              )
              TabOrder = 3
            end
            object CheckBoxSercatUseKill: TCheckBox
              Left = 568
              Height = 21
              Hint = 'sercat use KILL command on Stop.'
              Top = 8
              Width = 152
              Caption = 'Use KILL on Stop'
              Checked = True
              State = cbChecked
              TabOrder = 4
            end
            object BitBtnSercatSaveIni: TBitBtn
              Left = 8
              Height = 46
              Top = 56
              Width = 135
              Action = ActionSercatSaveIni
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 5
              TabOrder = 5
            end
            object BitBtnSercatLoadIni: TBitBtn
              Left = 148
              Height = 46
              Top = 56
              Width = 135
              Action = ActionSercatLoadIni
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 3
              TabOrder = 6
            end
            object BitBtnSercatDropIni: TBitBtn
              Left = 288
              Height = 46
              Top = 56
              Width = 135
              Action = ActionSercatDropIni
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 23
              TabOrder = 7
            end
            object CheckBoxSercatUseShell: TCheckBox
              Left = 568
              Height = 21
              Hint = 'Use SHELL to Run sercat.'
              Top = 32
              Width = 152
              Caption = 'Use SHELL to Run'
              Checked = True
              State = cbChecked
              TabOrder = 8
            end
          end
        end
      end
      object TabSheetLogEvents: TTabSheet
        BorderWidth = 8
        Caption = 'Log  '
        ClientHeight = 538
        ClientWidth = 792
        ImageIndex = 168
        object PanelLogEventsContent: TPanel
          Left = 0
          Height = 476
          Top = 0
          Width = 792
          Align = alClient
          BorderWidth = 8
          ClientHeight = 476
          ClientWidth = 792
          TabOrder = 0
          object LabelLogEvents: TLabel
            Left = 9
            Height = 15
            Top = 9
            Width = 774
            Align = alTop
            Caption = 'Event log (list of events occurred):'
            ParentColor = False
          end
          object MemoLogEvents: TMemo
            Left = 9
            Height = 426
            Top = 24
            Width = 774
            Align = alClient
            Color = clInfoBk
            ReadOnly = True
            ScrollBars = ssAutoBoth
            TabOrder = 0
            WordWrap = False
          end
          object StatusBarLogEvents: TStatusBar
            Left = 9
            Height = 17
            Top = 450
            Width = 774
            Panels = &lt;&gt;
          end
        end
        object PanelLogEventsButtons: TPanel
          Left = 0
          Height = 62
          Top = 476
          Width = 792
          Align = alBottom
          BorderWidth = 8
          ClientHeight = 62
          ClientWidth = 792
          TabOrder = 1
          object BitBtnLogEventsTest: TBitBtn
            Left = 481
            Height = 46
            Hint = 'Raise exception for test.'
            Top = 8
            Width = 95
            Anchors = [akTop, akRight]
            Caption = ' Test'
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 115
            OnClick = BitBtnLogEventsTestClick
            TabOrder = 0
          end
          object BitBtnLogEventsClear: TBitBtn
            Left = 581
            Height = 46
            Top = 8
            Width = 103
            Action = ActionLogEventsClear
            Anchors = [akTop, akRight]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 119
            TabOrder = 1
          end
          object BitBtnLogEventsGoBack: TBitBtn
            Left = 689
            Height = 46
            Top = 8
            Width = 95
            Action = ActionLogEventsGoBack
            Anchors = [akTop, akRight]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 59
            TabOrder = 2
          end
          object LabelMainListSysInfo: TLabel
            Left = 8
            Height = 15
            Top = 8
            Width = 88
            Caption = 'Info topic:'
            ParentColor = False
          end
          object ComboBoxMainListSysInfo: TComboBox
            Left = 8
            Height = 27
            Top = 24
            Width = 176
            DropDownCount = 24
            ItemHeight = 0
            Items.Strings = (
              'list environ'
              'list session'
              'list modules 0'
              'list process 0 0 *'
              'list windows 0 * *'
            )
            TabOrder = 3
            Text = 'list environ'
          end
          object LabelMainListSysInfoTimeOut: TLabel
            Left = 188
            Height = 15
            Top = 8
            Width = 56
            Caption = 'TimeOut'
            ParentColor = False
          end
          object SpinEditMainListSysInfoTimeOut: TSpinEdit
            Left = 188
            Height = 25
            Hint = 'Timeout for execution, sec.'
            Top = 24
            Width = 54
            MaxValue = 60
            MinValue = 1
            TabOrder = 4
            Value = 5
          end
          object BitBtnMainListSysInfo: TBitBtn
            Left = 244
            Height = 46
            Top = 8
            Width = 91
            Action = ActionMainListSysInfo
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 124
            TabOrder = 5
          end
        end
      end
    end
    object BitBtnSercatExit: TBitBtn
      Left = 713
      Height = 46
      Top = 0
      Width = 91
      Action = ActionMainProgramExit
      Anchors = [akTop, akRight]
      ModalResult = 11
      Images = DataModuleGuiResMain.ImageListMain32x32
      ImageIndex = 113
      TabOrder = 1
    end
  end
  object TimerLogEventsUpdater: TTimer
    OnTimer = TimerLogEventsUpdaterTimer
    Left = 356
  end
  object ActionListMain: TActionList
    Images = DataModuleGuiResMain.ImageListMain32x32
    Left = 320
    object ActionMainProgramExit: TAction
      Caption = 'Exit'
      Hint = 'Exit program.'
      ImageIndex = 113
      OnExecute = ActionMainExitExecute
    end
    object ActionMainParentShow: TAction
      Caption = 'Show'
      Hint = 'Open (activate) patent Crw32 program window.'
      ImageIndex = 234
      OnExecute = ActionMainParentShowExecute
    end
    object ActionMainFormShow: TAction
      Caption = 'Show MainForm'
      ImageIndex = 164
      OnExecute = ActionMainFormShowExecute
    end
    object ActionMainSendUserCmnd: TAction
      Caption = 'Send'
      Hint = 'Send command to CRW-DAQ  console.'
      ImageIndex = 59
      OnExecute = ActionMainSendUserCmndExecute
    end
    object ActionMainExecUserCmnd: TAction
      Caption = 'Exec'
      Hint = 'Run command from Crw32.ini list.'
      ImageIndex = 114
      OnExecute = ActionMainExecUserCmndExecute
    end
    object ActionLogEventsClear: TAction
      Caption = 'Clear'
      Hint = 'Clear event log.'
      ImageIndex = 119
      OnExecute = ActionLogEventsClearExecute
    end
    object ActionLogEventsGoBack: TAction
      Caption = 'Back'
      Hint = 'Go back to main page.'
      ImageIndex = 59
      OnExecute = ActionLogEventsGoBackExecute
    end
    object ActionMainListSysInfo: TAction
      Caption = 'Info'
      Hint = 'Print system information on specified topic.'
      ImageIndex = 124
      OnExecute = ActionMainListSysInfoExecute
    end
    object ActionSercatUpdate: TAction
      Caption = 'Update'
      Hint = 'Update list of Serial COM Ports.'
      ImageIndex = 298
      OnExecute = ActionSercatUpdateExecute
    end
    object ActionSercatStop: TAction
      Caption = 'Stop'
      Hint = 'Stop sercat process.'
      ImageIndex = 115
      OnExecute = ActionSercatStopExecute
    end
    object ActionSercatRun: TAction
      Caption = 'Run'
      Hint = 'Run sercat process.'
      ImageIndex = 114
      OnExecute = ActionSercatRunExecute
    end
    object ActionSercatSend: TAction
      Caption = 'Send'
      Hint = 'Send data to seriaal port.'
      ImageIndex = 60
      OnExecute = ActionSercatSendExecute
    end
    object ActionSercatHelp: TAction
      Caption = 'Help'
      Hint = 'Show Help on sercat.'
      ImageIndex = 124
      OnExecute = ActionSercatHelpExecute
    end
    object ActionSercatKillAll: TAction
      Caption = 'Kill All'
      Hint = 'Kill All running sercat process(es).'
      ImageIndex = 23
      OnExecute = ActionSercatKillAllExecute
    end
    object ActionDisplayLanguageRussian: TAction
      Caption = 'Russian'
      Hint = 'Set Display Language Russian.'
      ImageIndex = 200
      OnExecute = ActionDisplayLanguageRussianExecute
    end
    object ActionDisplayLanguageEnglish: TAction
      Caption = 'English'
      Hint = 'Set Display Language English.'
      ImageIndex = 201
      OnExecute = ActionDisplayLanguageEnglishExecute
    end
    object ActionSercatAskAnsReset: TAction
      Hint = 'Reset Ask/Ans table.'
      ImageIndex = 23
      OnExecute = ActionSercatAskAnsResetExecute
    end
    object ActionSercatAskAnsAutoSize: TAction
      Hint = 'Auto Size table columns.'
      ImageIndex = 304
      OnExecute = ActionSercatAskAnsAutoSizeExecute
    end
    object ActionSercatSaveIni: TAction
      Caption = 'Save INI'
      Hint = 'Save sercat settings to INI file.'
      ImageIndex = 5
      OnExecute = ActionSercatSaveIniExecute
    end
    object ActionSercatLoadIni: TAction
      Caption = 'Load INI'
      Hint = 'Load sercat settingss from INI file.'
      ImageIndex = 3
      OnExecute = ActionSercatLoadIniExecute
    end
    object ActionSercatDropIni: TAction
      Caption = 'Drop INI'
      Hint = 'Drop (remove) sercat INI file.'
      ImageIndex = 23
      OnExecute = ActionSercatDropIniExecute
    end
    object ActionSercatAdamScanToggle: TAction
      Caption = 'Adam Scan'
      Hint = 'Scan ADAM addresses.'
      ImageIndex = 265
      OnExecute = ActionSercatAdamScanToggleExecute
    end
    object ActionSercatAskAnsCopy: TAction
      Hint = 'Copy Ask/Ans table to Clipboard.'
      ImageIndex = 25
      OnExecute = ActionSercatAskAnsCopyExecute
    end
    object ActionSercatLogCopy: TAction
      Hint = 'Copy sercat Log to Clipboard.'
      ImageIndex = 25
      OnExecute = ActionSercatLogCopyExecute
    end
    object ActionSercatLogReset: TAction
      Hint = 'Reset (clear) sercat Log.'
      ImageIndex = 23
      OnExecute = ActionSercatLogResetExecute
    end
  end
  object TrayIconMain: TTrayIcon
    PopUpMenu = PopupMenuTray
    Icon.Data = {
[encoded data, 7242 characters]
      1FFF
    }
    OnClick = TrayIconMainClick
    OnDblClick = TrayIconMainDblClick
    Left = 392
  end
  object PopupMenuTray: TPopupMenu
    Images = DataModuleGuiResMain.ImageListMain32x32
    Left = 432
    object MenuItemTrayFormShow: TMenuItem
      Action = ActionMainFormShow
    end
    object MenuItemTrayParentShow: TMenuItem
      Action = ActionMainParentShow
    end
    object N1: TMenuItem
      Caption = '-'
    end
    object MenuItemTrayProgramExit: TMenuItem
      Action = ActionMainProgramExit
    end
  end
  object Timer1000ms: TTimer
    OnTimer = Timer1000msTimer
    Left = 468
  end
  object TimerSercatPoll: TTimer
    Interval = 4
    OnTimer = TimerSercatPollTimer
    Left = 504
  end
  object TimerSercatAdamScan: TTimer
    Enabled = False
    Interval = 500
    OnTimer = TimerSercatAdamScanTimer
    Left = 544
  end
end
</Object>
          <Code>unit Main;

uses  dpCmdArgs,dpSystem,dpSysUtils,dpVbs,dpWindows,dpGuiUtils,
      dpCrwDaqSys,dpDaqConfig,dpAntiZombie,dpGuiResMain,dpLinux,
      dpTask,sercatlib;

type
  TMainForm = class(TForm)
    TimerLogEventsUpdater: TTimer;
    ActionListMain: TActionList;
    ActionMainProgramExit: TAction;
    ActionMainParentShow: TAction;
    ActionMainFormShow: TAction;
    ActionMainSendUserCmnd: TAction;
    ActionMainExecUserCmnd: TAction;
    ActionLogEventsClear: TAction;
    ActionLogEventsGoBack: TAction;
    // TrayIcon
    TrayIconMain: TTrayIcon;
    PopupMenuTray: TPopupMenu;
    MenuItemTrayFormShow: TMenuItem;
    MenuItemTrayParentShow: TMenuItem;
    MenuItemTrayProgramExit: TMenuItem;
    MenuItemTrayProgramExitSeparator: TMenuItem;
    // Main Panel
    PanelMain: TPanel;
    // Main TabSheep
    TabSheetTools: TTabSheet;
    PageControlMain: TPageControl;
    PanelToolsContent: TPanel;
    LabelMainExecUserCmnd: TLabel;
    PanelMainButtons: TPanel;
    LabeMainSendUserCmnd: TLabel;
    EditMainSendUserCmnd: TEdit;
    BitBtnMainSendUserCmnd: TBitBtn;
    BitBtnMainExecUserCmnd: TBitBtn;
    BitBtnMainProgramExit: TBitBtn;
    BitBtnMainParentShow: TBitBtn;
    // LogEvents TabSheet
    TabSheetLogEvents: TTabSheet;
    PanelLogEventsContent: TPanel;
    LabelLogEvents: TLabel;
    MemoLogEvents: TMemo;
    StatusBarLogEvents: TStatusBar;
    PanelLogEventsButtons: TPanel;
    BitBtnLogEventsTest: TBitBtn;
    BitBtnLogEventsClear: TBitBtn;
    BitBtnLogEventsGoBack: TBitBtn;
    MemoMainExecUserCmnd: TMemo;
    LabelMainListSysInfo: TLabel;
    ComboBoxMainListSysInfo: TComboBox;
    LabelMainListSysInfoTimeOut: TLabel;
    SpinEditMainListSysInfoTimeOut: TSpinEdit;
    BitBtnMainListSysInfo: TBitBtn;
    ActionMainListSysInfo: TAction;
    TabSheetSercat: TTabSheet;
    PanelSercatCtrl: TPanel;
    ActionSercatUpdate: TAction;
    ActionSercatStop: TAction;
    Timer1000ms: TTimer;
    ActionSercatRun: TAction;
    TimerSercatPoll: TTimer;
    ActionSercatSend: TAction;
    PanelSercatInput: TPanel;
    ActionSercatHelp: TAction;
    PanelSercatButtons: TPanel;
    BitBtnSercatUpdate: TBitBtn;
    BitBtnSercatStop: TBitBtn;
    BitBtnSercatRun: TBitBtn;
    BitBtnSercatHelp: TBitBtn;
    StatusBarSercatPort: TStatusBar;
    PanelSercatPort: TPanel;
    LabelSercatPort: TLabel;
    ComboBoxSercatPort: TComboBox;
    LabelSercatBaudRate: TLabel;
    ComboBoxSercatBaudRate: TComboBox;
    LabelSercatDataBits: TLabel;
    ComboBoxSercatDataBits: TComboBox;
    LabelSercatParity: TLabel;
    ComboBoxSercatParity: TComboBox;
    LabelSercatStopBits: TLabel;
    ComboBoxSercatStopBits: TComboBox;
    CheckListBoxSercatOptions: TCheckListBox;
    ActionSercatKillAll: TAction;
    BitBtnSercatKillAll: TBitBtn;
    PanelSercatParams: TPanel;
    GroupBoxSercatParams: TGroupBox;
    ActionDisplayLanguageRussian: TAction;
    ActionDisplayLanguageEnglish: TAction;
    BitBtnDisplayLanguageRussian: TBitBtn;
    BitBtnDisplayLanguageEnglish: TBitBtn;
    LabelSercatKillTimeout: TLabel;
    SpinEditSercatKillTimeout: TSpinEdit;
    PanelSercatOutput: TPanel;
    PageControlSercatOutput: TPageControl;
    TabSheetSercatLog: TTabSheet;
    PanelSercatLog: TPanel;
    MemoSercatLog: TMemo;
    TabSheetSercatAskAns: TTabSheet;
    PanelSercatAskAns: TPanel;
    StringGridSercatAskAns: TStringGrid;
    PanelSercatAskAnsButtons: TPanel;
    ActionSercatAskAnsReset: TAction;
    BitBtnSercatAskAnsReset: TBitBtn;
    ActionSercatAskAnsAutoSize: TAction;
    BitBtnSercatAskAnsAutoSize: TBitBtn;
    LabelSercatTimeoutMark: TLabel;
    ComboBoxSercatTimeoutMark: TComboBox;
    PageControlSercatIOMode: TPageControl;
    TabSheetSercatInputMode: TTabSheet;
    LabelSercatInputMode: TLabel;
    ComboBoxSercatInputMode: TComboBox;
    LabelSercatChecksum: TLabel;
    ComboBoxSercatChecksum: TComboBox;
    LabelSercatEol: TLabel;
    ComboBoxSercatEol: TComboBox;
    TabSheetSercatOutputMode: TTabSheet;
    LabelSercatOutputMode: TLabel;
    ComboBoxSercatOutputMode: TComboBox;
    TabSheetSercatTimeMode: TTabSheet;
    CheckBoxSercatWaitEol: TCheckBox;
    SpinEditSercatRxTimeout: TSpinEdit;
    CheckBoxSercatShowAnsNoAsk: TCheckBox;
    CheckBoxSercatUseKill: TCheckBox;
    ActionSercatSaveIni: TAction;
    BitBtnSercatSaveIni: TBitBtn;
    ActionSercatLoadIni: TAction;
    BitBtnSercatLoadIni: TBitBtn;
    ActionSercatDropIni: TAction;
    BitBtnSercatDropIni: TBitBtn;
    PageControlSercatInput: TPageControl;
    TabSheetSercatInput: TTabSheet;
    BitBtnSercatSend: TBitBtn;
    LabelSercatInput: TLabel;
    ComboBoxSercatInput: TComboBox;
    TabSheetSercatAdamScan: TTabSheet;
    CheckBoxSercatAdamScan: TCheckBox;
    SpinEditSercatAdamScanLo: TSpinEdit;
    SpinEditSercatAdamScanHi: TSpinEdit;
    TimerSercatAdamScan: TTimer;
    LabelSercatAdamScanAddr: TLabel;
    ActionSercatAdamScanToggle: TAction;
    CheckBoxSercatUseShell: TCheckBox;
    CheckBoxSercatDropTailEol: TCheckBox;
    ActionSercatAskAnsCopy: TAction;
    BitBtnSercatAskAnsCopy: TBitBtn;
    PanelSercatLogButtons: TPanel;
    ActionSercatLogCopy: TAction;
    BitBtnSercatLogCopy: TBitBtn;
    ActionSercatLogReset: TAction;
    BitBtnSercatLogReset: TBitBtn;
    CheckBoxSercatOptPoll: TCheckBox;
    SpinEditSercatOptPoll: TSpinEdit;
    ComboBoxSercatInputDecode: TComboBox;
    LabelSercatInputDecode: TLabel;
    BitBtnSercatExit: TBitBtn;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure TrayIconMainClick(Sender: TObject);
    procedure TrayIconMainDblClick(Sender: TObject);
    procedure TimerLogEventsUpdaterTimer(Sender: TObject);
    procedure ActionMainExitExecute(Sender: TObject);
    procedure ActionMainParentShowExecute(Sender: TObject);
    procedure ActionMainFormShowExecute(Sender: TObject);
    procedure ActionMainSendUserCmndExecute(Sender: TObject);
    procedure ActionMainExecUserCmndExecute(Sender: TObject);
    procedure ActionLogEventsClearExecute(Sender: TObject);
    procedure ActionLogEventsGoBackExecute(Sender: TObject);
    procedure ActionMainListSysInfoExecute(Sender: TObject);
    procedure BitBtnLogEventsTestClick(Sender: TObject);
    procedure ActionSercatStopExecute(Sender: TObject);
    procedure ActionSercatUpdateExecute(Sender: TObject);
    procedure Timer1000msTimer(Sender: TObject);
    procedure TimerSercatPollTimer(Sender: TObject);
    procedure ActionSercatRunExecute(Sender: TObject);
    procedure ActionSercatSendExecute(Sender: TObject);
    procedure ComboBoxSercatInputKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure ActionSercatHelpExecute(Sender: TObject);
    procedure ActionSercatKillAllExecute(Sender: TObject);
    procedure ActionDisplayLanguageRussianExecute(Sender: TObject);
    procedure ActionDisplayLanguageEnglishExecute(Sender: TObject);
    procedure ActionSercatAskAnsResetExecute(Sender: TObject);
    procedure ActionSercatAskAnsAutoSizeExecute(Sender: TObject);
    procedure PageControlSercatOutputChange(Sender: TObject);
    procedure ActionSercatSaveIniExecute(Sender: TObject);
    procedure ActionSercatLoadIniExecute(Sender: TObject);
    procedure ActionSercatDropIniExecute(Sender: TObject);
    procedure TimerSercatAdamScanTimer(Sender: TObject);
    procedure ActionSercatAdamScanToggleExecute(Sender: TObject);
    procedure CheckBoxSercatAdamScanChange(Sender: TObject);
    procedure ActionSercatAskAnsCopyExecute(Sender: TObject);
    procedure ActionSercatLogCopyExecute(Sender: TObject);
    procedure ActionSercatLogResetExecute(Sender: TObject);
    procedure CheckBoxSercatOptPollChange(Sender: TObject);
  private
    myLastNum   : Integer;
    mySerPort   : Integer;
    mySerTask   : Integer;
    mySentTime  : Double;
    mySentData  : String;
    mySerCatExe : String;
    myRxBuffer  : String;
    myScanAddr  : Integer;
  protected
    EngCaptions : TStringList;
    EngHints    : TStringList;
    RusCaptions : TStringList;
    RusHints    : TStringList;
  protected
    function  GetSercatInputText:String;
    function  SetSercatInputText(aText:String);
  public
    procedure ShowTrayIcon;
    procedure AdjustComponents;
    procedure UpdateGuiLanguage(lng:Integer);
    function  SercatExe(args:String=''):String;
    function  SercatCmd(args:String=''):String;
    procedure BugReport(E:Exception; Sender:TObject; Where:String);
    procedure SendCommandToCrwDaq(S:String; Activate:Boolean=true);
    procedure PostCommandToCrwDaq(S:String);
  public
    property  SercatInputText : String read GetSercatInputText write SetSercatInputText;
  public
    procedure SercatStop(Head:Boolean=false);
    procedure ResetActivePages(Which:Integer=-1);
    procedure SercatLog(When:Double; What:String);
    function  SercatAppendEol(data:String):String;
    function  SercatAddChecksum(data:String):String;
    function  SercatInputDecode(data:String):String;
    function  SercatInputEncode(data:String; Mode:Integer):String;
    function  SercatWaitEol:Boolean;
    function  SercatUseKill:Boolean;
    function  SercatRxTimeout:Integer;
    function  SercatInputMode:Integer;
    function  SercatOutputMode:Integer;
    function  SercatKillTimeout:Integer;
    function  SercatTimeoutMark:String;
    function  SercatOptPoll:String;
    function  SercatNextScanAddr(Step:Integer):Integer;
    procedure SercatAskAnsAdd(datetime,ask,ans,delay:String);
  end;

var MainForm: TMainForm;

implementation

procedure TMainForm.FormCreate(Sender: TObject);
begin
 try
  defIpcInit;
  defParamsInit;
  SetDefaultFontName(Font);
  InitAntiZombie(1000,true);
  Caption:=GetCrwDaqChildTitle;
  FormCenterToScreen(Self,0,0);
  SetButtonCursorToHandPoint(Self);
  StatusBarLogEvents.Font.Size:=10;
  LogEvents(Now,GetBriefEngineScriptInfo);
  LogEvents(Now,'Start.');
  EngCaptions:=TStringList.Create;
  RusCaptions:=TStringList.Create;
  EngHints:=TStringList.Create;
  RusHints:=TStringList.Create;
  EngCaptions.Sorted:=true;
  RusCaptions.Sorted:=true;
  EngHints.Sorted:=true;
  RusHints.Sorted:=true;
  myLastNum:=0;
  mySerPort:=0;
  mySerTask:=0;
  mySentTime:=0;
  mySentData:='';
  mySercatExe:='';
  myRxBuffer:='';
  GetOptIniFile(1);
  AdjustComponents;
  ShowTrayIcon;
  if (CRW_DAQ_SYS_EXE_PID=0) then begin
   ActionMainParentShow.Enabled:=false;
   ActionMainSendUserCmnd.Enabled:=false;
   //RaiseException('Parent Crw32.exe process is not specified.');
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'FormCreate');
 end;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
 ActionSercatStop.Execute;
end;

procedure TMainForm.ShowTrayIcon;
begin
 Application.Title:=GetScriptName;
 TrayIconMain.Visible:=true;
 TrayIconMain.Hint:=GetScriptName+EOL+Caption;
 MenuItemTrayFormShow.Caption:=FormatVar('Show Window [%s]',Caption);
 MenuItemTrayProgramExit.Caption:=FormatVar('Exit from [%s]',Caption);
 MenuItemTrayParentShow.Caption:=FormatVar('Show Parent Window [%s]',ParentCrwDaqTitle);
 HideApplicationIconFromTaskBar(true);
end;

procedure TMainForm.AdjustComponents;
 procedure SaveFormComponentsCaptionsHints(aForm:TForm);
 var aName,aCaption,aHint:String; i:Integer;
 begin
  if not Assigned(aForm) then Exit;
  for i:=0 to aForm.ComponentCount-1 do begin
   aName:=aForm.Components[i].Name;
   aHint:=GetHintOfComponent(aForm.Components[i]);
   aCaption:=GetCaptionOfComponent(aForm.Components[i]);
   if not IsEmptyStr(aHint) then EngHints.Values[aName]:=RecodeStr(aHint,'rawbyte,base64');
   if not IsEmptyStr(aCaption) then EngCaptions.Values[aName]:=RecodeStr(aCaption,'rawbyte,base64');
  end;
 end;
begin
 ResetActivePages;
 ComboBoxMainListSysInfo.Items.Text:=GetItemsOfListSysInfoAsText;
 ComboBoxMainListSysInfo.ItemIndex:=0;
 MemoLogEvents.Font.Size:=10;
 SetDefaultSansFontName(LabelMainListSysInfoTimeOut.Font);
 CheckListBoxSercatOptions.Font.Size:=10;
 ComboBoxSercatInputDecode.Font.Size:=8;
 if FileExists(SercatExe)
 then LogEvents(Now,'Found sercat: '+SercatExe)
 else LogEvents(Now,'Could not find sercat');
 if SameText(GetEnv('LANG'),'ru_RU.UTF-8') then LanguageId:=lng_Russian;
 if (GetOptIniFile&lt;&gt;'') then ActionSercatLoadIni.Execute;
 SaveFormComponentsCaptionsHints(Self);
 LanguageId:=GetOptLanguage(LanguageId);
 UpdateGuiLanguage(LanguageId);
 ActionSercatUpdate.Execute;
 ActionSercatAskAnsReset.Execute;
end;

procedure TMainForm.ResetActivePages(Which:Cardinal=-1);
begin
 if HasFlags(Which,1) then PageControlMain.ActivePage:=TabSheetSercat;
 if HasFlags(Which,2) then PageControlSercatOutput.ActivePage:=TabSheetSercatLog;
 if HasFlags(Which,4) then PageControlSercatInput.ActivePage:=TabSheetSercatInput;
 if HasFlags(Which,8) then PageControlSercatIOMode.ActivePage:=TabSheetSercatInputMode;
end;

procedure TMainForm.UpdateGuiLanguage(lng:Integer);
 procedure AddRusCaptions(Comp:TComponent; S:String);
 begin
  if (Comp=nil) then Exit;
  if (RusCaptions.IndexOfName(Comp.Name)&gt;=0) then Exit;
  RusCaptions.Values[Comp.Name]:=RecodeStr(S,'rawbyte,base64');
 end;
 procedure TranslateCaption(Comp:TComponent; ruCaption:String);
 var aCaption:String;
 begin
  if (Comp=nil) then Exit;
  AddRusCaptions(Comp,ruCaption);
  aCaption:=GetCaptionOfComponent(Comp);
  if (lng=lng_Russian) then aCaption:=RecodeStr(RusCaptions.Values[Comp.Name],'base64,rawbyte');
  if (lng=lng_English) then aCaption:=RecodeStr(EngCaptions.Values[Comp.Name],'base64,rawbyte');
  if (aCaption&lt;&gt;GetCaptionOfComponent(Comp))
  then SetCaptionOfComponent(Comp,aCaption);
 end;
 procedure AddRusHints(Comp:TComponent; S:String);
 begin
  if (Comp=nil) then Exit;
  if (RusHints.IndexOfName(Comp.Name)&gt;=0) then Exit;
  RusHints.Values[Comp.Name]:=RecodeStr(S,'rawbyte,base64');
 end;
 procedure TranslateTheHint(Comp:TComponent; ruHint:String);
 var aHint:String;
 begin
  if (Comp=nil) then Exit;
  AddRusHints(Comp,ruHint);
  aHint:=GetHintOfComponent(Comp);
  if (lng=lng_Russian) then aHint:=RecodeStr(RusHints.Values[Comp.Name],'base64,rawbyte');
  if (lng=lng_English) then aHint:=RecodeStr(EngHints.Values[Comp.Name],'base64,rawbyte');
  if (aHint&lt;&gt;GetHintOfComponent(Comp))
  then SetHintOfComponent(Comp,aHint);
 end;
begin
 case lng of
  lng_Unknown : LanguageId:=lng;
  lng_English : LanguageId:=lng;
  lng_Russian : LanguageId:=lng;
  else          Exit;
 end;
 ///////////////////////////////////////////////
 TranslateTheHint(ComboBoxSercatPort,           'Список доступных COM портов.');
 TranslateTheHint(ComboBoxSercatBaudRate,       'Скорость обмена данными, бит/сек.');
 TranslateTheHint(ComboBoxSercatDataBits,       'Размер байта - число бит на байт.');
 TranslateTheHint(ComboBoxSercatParity,         'Тип контроля данных по чётности.');
 TranslateTheHint(ComboBoxSercatStopBits,       'Число стоповых бит в конце байта.');
 TranslateTheHint(CheckListBoxSercatOptions,    'Дополнительные ффлаги и опции sercat.');
 TranslateCaption(ActionSercatHelp,             'Помощь');
 TranslateTheHint(BitBtnSercatHelp,             'Справка по программе sercat.');
 TranslateCaption(ActionSercatStop,             'Стоп');
 TranslateTheHint(BitBtnSercatStop,             'Остановить (завершить) программу sercat.');
 TranslateCaption(ActionSercatRun,              'Пуск');
 TranslateTheHint(BitBtnSercatRun,              'Запустить программу sercat.');
 TranslateCaption(ActionSercatKillAll,          'Стоп ВСЕ');
 TranslateTheHint(BitBtnSercatKillAll,          'Завершить все работающие программы sercat.');
 TranslateCaption(ActionSercatUpdate,           'Обновить');
 TranslateTheHint(BitBtnSercatUpdate,           'Обновить список COM портов с помощью программы sercat.');
 TranslateCaption(TabSheetSercatInput,          ' sercat - Ввод ');
 TranslateCaption(LabelSercatInput,             ' Данные для посылки: ');
 TranslateCaption(ActionSercatSend,             'Послать');
 TranslateTheHint(BitBtnSercatSend,             'Послать строку данных в COM порт с помощью программы sercat.');
 TranslateCaption(TabSheetSercatInputMode,      'Ввод');
 TranslateCaption(LabelSercatInputDecode,       'В кодировке');
 TranslateTheHint(ComboBoxSercatInputDecode,    'Метод кодирования строки Ввода sercat.');
 TranslateCaption(LabelSercatInputMode,         'Режим');
 TranslateTheHint(ComboBoxSercatInputMode,      'Режим кодировки ввода данных sercat.');
 TranslateTheHint(ComboBoxSercatChecksum,       'Режим использования контрольных сумм sercat.');
 TranslateTheHint(ComboBoxSercatEol,            'Тип маркер конца строки EOL в запросах sercat.');
 TranslateCaption(TabSheetSercatOutputMode,     'Вывод');
 TranslateCaption(LabelSercatOutputMode,        'Режим');
 TranslateTheHint(ComboBoxSercatOutputMode,     'Режим кодировки вывода данных sercat.');
 TranslateCaption(CheckBoxSercatShowAnsNoAsk,   'Зрим Все Ответы');
 TranslateTheHint(CheckBoxSercatShowAnsNoAsk,   'Выводить все Ответы - даже без Запросов.');
 TranslateCaption(CheckBoxSercatDropTailEol,    'Без EOL в конце');
 TranslateTheHint(CheckBoxSercatDropTailEol,    'Выводить запросы/ответы без EOL в конце.');
 TranslateCaption(TabSheetSercatTimeMode,       'Время');
 TranslateCaption(CheckBoxSercatWaitEol,        'Ждём:EOL/Timeout');
 TranslateTheHint(CheckBoxSercatWaitEol,        'Ожидать EOL в конце Ответа или предельное Время Ожидания.');
 TranslateTheHint(SpinEditSercatRxTimeout,      'Время Ожидания Ответа, мс.');
 TranslateCaption(CheckBoxSercatOptPoll,        '--poll опция, мс');
 TranslateTheHint(CheckBoxSercatOptPoll,        'Включить опцию --poll p, задающую период (p) опроса sercat, мс.');
 TranslateTheHint(SpinEditSercatOptPoll,        'Период цикла опроса программы sercat, мс.');
 TranslateCaption(TabSheetSercatLog,            ' sercat - Журнал ');
 TranslateTheHint(BitBtnSercatLogCopy,          'Копирование Журнала в Буфер Обмена.');
 TranslateTheHint(BitBtnSercatLogReset,         'Сброс (очистка) Журнала.');
 TranslateCaption(TabSheetSercatAskAns,         ' Запрос/Ответ ');
 TranslateTheHint(BitBtnSercatAskAnsAutoSize,   'Подгонка ширины столбцов таблицы Запросов/Ответов.');
 TranslateTheHint(BitBtnSercatAskAnsCopy,       'Копирование таблицы Запросов/Ответов в Буфер Обмена.');
 TranslateTheHint(BitBtnSercatAskAnsReset,      'Сброс (очистка) таблицы Запросов/Ответов.');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetTools,                ' Инструменты ');
 TranslateCaption(GroupBoxSercatParams,         ' Параметры и настройки: ');
 TranslateCaption(BitBtnDisplayLanguageRussian, ' Русский ');
 TranslateTheHint(BitBtnDisplayLanguageRussian, 'Установить для отображения Русский язык.');
 TranslateCaption(BitBtnDisplayLanguageEnglish, ' Английский ');
 TranslateTheHint(BitBtnDisplayLanguageEnglish, 'Установить для отображения Английский язык.');
 TranslateCaption(LabelSercatKillTimeout,       'Время на Стоп,мс');
 TranslateTheHint(SpinEditSercatKillTimeout,    'Время на Стоп (мс) при остановке работы sercat.');
 TranslateCaption(LabelSercatTimeoutMark,       'Маркер Таймаута');
 TranslateTheHint(ComboBoxSercatTimeoutMark,    'Маркер для события "Нет Ответа за Время Ожидания".');
 TranslateCaption(ActionSercatSaveIni,          'Запись INI');
 TranslateTheHint(BitBtnSercatSaveIni,          'Запись настроек в INI файл.');
 TranslateCaption(ActionSercatLoadIni,          'Чтение INI');
 TranslateTheHint(BitBtnSercatLoadIni,          'Чтение настроек из INI файла.');
 TranslateCaption(ActionSercatDropIni,          'Сброс INI');
 TranslateTheHint(BitBtnSercatDropIni,          'Сброс (удаление) INI файла настроек.');
 TranslateCaption(CheckBoxSercatUseKill,        'Стоп через KILL');
 TranslateTheHint(CheckBoxSercatUseKill,        'Стоп sercat с помощью команды kill.');
 TranslateCaption(CheckBoxSercatUseShell,       'Пуск через SHELL');
 TranslateTheHint(CheckBoxSercatUseShell,       'Пуск sercat с помощью оболочки SHELL.');
 TranslateCaption(LabeMainSendUserCmnd,         'Послать введенную команду');
 TranslateTheHint(EditMainSendUserCmnd,         'Ввод команды для Консоли CRW-DAQ.');
 TranslateCaption(ActionMainSendUserCmnd,       'Послать');
 TranslateTheHint(BitBtnMainSendUserCmnd,       'Послать команду в консоль CRW-DAQ.');
 TranslateCaption(ActionMainExecUserCmnd,       'Пуск');
 TranslateTheHint(BitBtnMainExecUserCmnd,       'Запустить команду.');
 TranslateCaption(ActionMainFormShow,           'Открыть форму');
 TranslateTheHint(ActionMainFormShow,           'Открыть главную форму программы.');
 TranslateCaption(ActionMainProgramExit,        'Выход');
 TranslateTheHint(BitBtnMainProgramExit,        'Выйти из программы.');
 TranslateCaption(ActionMainParentShow,         'Открыть');
 TranslateTheHint(BitBtnMainParentShow,         'Открыть (активировать) родительский процесс CRW-DAQ.');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetLogEvents,            ' Журнал ');
 TranslateCaption(LabelLogEvents,               'Журнал событий:');
 TranslateCaption(LabelMainListSysInfo,         'Инфо тема:');
 TranslateCaption(LabelMainListSysInfoTimeOut,  'TimeOut');
 TranslateTheHint(SpinEditMainListSysInfoTimeOut, 'Время ожидания при запуске команд, мс.');
 TranslateCaption(ActionMainListSysInfo,        'Инфо');
 TranslateTheHint(BitBtnMainListSysInfo,        'Печать системной информации на выбранную тему.');
 TranslateCaption(BitBtnLogEventsTest,          ' Тест');
 TranslateTheHint(BitBtnLogEventsTest,          'Возбудить тестовое исключение.');
 TranslateCaption(ActionLogEventsClear,         'Очистка');
 TranslateTheHint(BitBtnLogEventsClear,         'Очистить журнал событий.');
 TranslateCaption(ActionLogEventsGoBack,        'Назад');
 TranslateTheHint(BitBtnLogEventsGoBack,        'Назад, на главную страницу.');
 ///////////////////////////////////////////////
end;

function TMainForm.SercatCmd(args:String=''):String;
begin
 Result:='unix sercat';
 if not IsEmptyStr(args) then Result:=Result+' '+Trim(args);
end;

function TMainForm.SercatExe(args:String=''):String;
begin
 if (mySercatExe='') then begin
  if RunCommand('unix which sercat',mySercatExe)
  then mySercatExe:=Trim(mySercatExe) else mySercatExe:='';
  if IsEmptyStr(mySercatExe) or not FileExists(mySercatExe) then mySercatExe:='';
 end;
 Result:=mySercatExe;
 if (Result&lt;&gt;'') and not IsEmptyStr(args) then Result:=Result+' '+Trim(args);
end;

procedure TMainForm.BugReport(E:Exception; Sender:TObject; Where:String);
begin
 SystemBugReport(E,Sender,Where);
 PageControlMain.ActivePage:=TabSheetLogEvents;
end;

procedure TMainForm.SendCommandToCrwDaq(S:String; Activate:Boolean=true);
begin
 try
  if (CRW_DAQ_SYS_EXE_PID=0)
  then RaiseException('Parent Crw32.exe process is not specified.');
  S:=Trim(S); if (S='') then Exit;
  if (CRW_DAQ_SYS_EXE_PID=0) then Exit;
  if Activate then AppActivateByTitle(ParentCrwDaqTitle);
  if (Send2CrwDaq(CRW_DAQ_SYS_EXE_PID,S,Handle)=0)
  then LogEvents(Now,'Sent command: '+S)
  else LogEvents(Now,'Fail command: '+S);
 except
  on E:Exception do Self.BugReport(E,Self,'SendCommandToCrwDaq');
 end;
end;

procedure TMainForm.PostCommandToCrwDaq(S:String);
begin
 SendCommandToCrwDaq(S,false);
end;

procedure TMainForm.TrayIconMainClick(Sender: TObject);
begin
 ActionMainFormShow.Execute;
end;

procedure TMainForm.TrayIconMainDblClick(Sender: TObject);
begin
 ActionMainFormShow.Execute;
end;

procedure TMainForm.TimerLogEventsUpdaterTimer(Sender: TObject);
begin
 try
  MoveBugReportListToLogger(nil);
  MoveLogEventsListToLoggerMemo(MemoLogEvents);
  if (PageControlMain.ActivePage=TabSheetLogEvents) then
  StatusBarLogEvents.SimpleText:=DateTimePrompt(Now)+GetHeapStatusBrief
   +FormatVar('. Events: %d',LogCountTotal)
   +FormatVar(', Bugs: %d',BugCountTotal)+'.';
   HandlePendingHideApplicationIconFromTaskBar;
 except
  on E:Exception do Self.BugReport(E,Self,'TimerLogEventsUpdaterTimer');
 end;
end;

procedure TMainForm.ActionMainExitExecute(Sender: TObject);
begin
 Application.Terminate;
end;

procedure TMainForm.ActionMainParentShowExecute(Sender: TObject);
begin
 AppActivateByTitle(ParentCrwDaqTitle);
end;

procedure TMainForm.ActionMainFormShowExecute(Sender: TObject);
begin
 ShowAndActivateFormByReference(Self,SW_SHOW);
end;

procedure TMainForm.ActionMainSendUserCmndExecute(Sender: TObject);
begin
 try
  if (CRW_DAQ_SYS_EXE_PID=0)
  then RaiseException('Parent Crw32.exe process is not specified.');
  EditMainSendUserCmnd.Text:=Trim(EditMainSendUserCmnd.Text);
  if (Pos('@',EditMainSendUserCmnd.Text)&lt;&gt;1)
  then RaiseException('Invalid format of command.');
  SendCommandToCrwDaq(EditMainSendUserCmnd.Text);
 except
  on E:Exception do Self.BugReport(E,Self,'ActionMainSendUserCmndExecute');
 end;
end;

procedure TMainForm.ActionMainExecUserCmndExecute(Sender: TObject);
begin
 try
  MemoMainExecUserCmnd.Lines.Text:=DateTimePrompt(Now)+'Exec user command:'+EOL
   +'ListOfProcesses:'+EOL
   +'****************'+EOL
   +GetListOfProcesses(0,0,'')+EOL;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionMainExecUserCmndExecute');
 end;
end;

procedure TMainForm.ActionLogEventsClearExecute(Sender: TObject);
begin
 MemoLogEvents.Lines.Clear;
 LogCountTotal:=0; BugCountTotal:=0;
 LogEvents(Now,GetBriefEngineScriptInfo);
 LogEvents(Now,'Start.');
end;

procedure TMainForm.ActionLogEventsGoBackExecute(Sender: TObject);
begin
 PageControlMain.ActivePage:=TabSheetSercat;
end;

var BugTestNum:Integer=0;

procedure TMainForm.BitBtnLogEventsTestClick(Sender: TObject);
begin
 try
  Inc(BugTestNum);
  RaiseException('This is exception test '+IntToStr(BugTestNum));
 except
  on E:Exception do Self.BugReport(E,Self,'BitBtnLogEventsTestClick');
 end;
end;

procedure TMainForm.SercatStop(Head:Boolean=false);
var pid,ecode:Integer; cmd,msg,hdr:String;
begin
 try
  msg:=''; hdr:='';
  ResetActivePages;
  if (mySerTask&lt;&gt;0) then begin
   pid:=task_pid(mySerTask);
   cmd:=FormatVar('kill %d',pid);
   if IsWindows then cmd:=FormatVar('taskkill /pid %d',pid);
   if SercatUseKill then begin
    if (pid&lt;&gt;0) and task_wait(mySerTask,0) then
    if RunCommand(cmd,msg) then begin
     if Head then hdr:=ActionSercatStop.Name+EOL;
     if not task_wait(mySerTask,SercatKillTimeout)
     then SercatLog(Now,hdr+cmd);
    end;
   end;
   if task_wait(mySerTask,0)
   then task_kill(mySerTask,1,0,SercatKillTimeout);
   ecode:=task_result(mySerTask);
   msg:=FormatVar('PID %d ',pid)
       +RusEng('завершён с кодом ','stopped with exit code')
       +FormatVar(' %d',ecode);
   SercatLog(Now,msg);
   LogEvents(Now,msg);
   task_free(mySerTask);
  end;
  mySerTask:=0;
  mySerPort:=0;
 except
  on E:Exception do Self.BugReport(E,Self,'SercatStop');
 end;
end;

procedure TMainForm.SercatLog(When:Double; What:String);
begin
 if (What='') then Exit;
 if (When&lt;0)
 then AddTextToLogger(MemoSercatLog.Lines,What)
 else AddTextAsEventLog(MemoSercatLog.Lines,When,What);
 MemoSercatLog.SelStart:=MaxInt;
end;

procedure TMainForm.ActionSercatStopExecute(Sender: TObject);
begin
 SercatStop(true);
end;

procedure TMainForm.ActionSercatUpdateExecute(Sender: TObject);
var cmd,serList,msg:String; n,p:Integer;
begin
 serList:='';
 try
  ResetActivePages;
  cmd:=SercatCmd('--list');
  if RunCommand(cmd,serList) and not IsEmptyStr(serList) then begin
   serList:=Trim(AdjustLineBreaks(serList));
   ComboBoxSercatPort.Items.Text:=serList;
  end;
  n:=ComboBoxSercatPort.Items.Count;
  msg:=IntToStr(n)+RusEng(' COM порт(ов) найдено',' COM port(s) found');
  LabelSercatPort.Caption:=RusEng('COM Порт: ','COM Port: ')+msg;
  SercatLog(Now,ActionSercatUpdate.Name+EOL+cmd);
  SercatLog(-1,msg+EOL+serList);
  p:=myLastNum;
  if (p&gt;=1) and (p&lt;=n) then ComboBoxSercatPort.ItemIndex:=p-1;
  if (n&gt;0) and (ComboBoxSercatPort.ItemIndex&lt;0) then ComboBoxSercatPort.ItemIndex:=0;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatUpdateExecute');
 end;
end;

function PidStatus(tid:Integer):String;
var pid:Integer;
begin
 if (tid&lt;&gt;0) then pid:=task_pid(tid) else pid:=0;
 if (pid&lt;&gt;0) and task_wait(tid,0)
 then Result:=RusEng('работает','running')
 else Result:=RusEng('остановлен','stopped');
 if (pid&lt;&gt;0) then Result:=Result+' PID '+IntToStr(pid);
end;

procedure TMainForm.Timer1000msTimer(Sender: TObject);
begin
 try
  BitBtnSercatRun.Enabled:=(mySerTask=0);
  BitBtnSercatStop.Enabled:=(mySerTask&lt;&gt;0);
  BitBtnSercatUpdate.Enabled:=(mySerTask=0);
  PanelSercatPort.Enabled:=(mySerTask=0);
  ComboBoxSercatStopBits.Enabled:=(mySerTask=0);
  PageControlSercatInput.Enabled:=(mySerTask&lt;&gt;0);
  PageControlSercatIOMode.Enabled:=(mySerTask=0);
  GroupBoxSercatParams.Enabled:=(mySerTask=0);
  StatusBarSercatPort.SimpleText:=' sercat - '+PidStatus(mySerTask);
 except
  on E:Exception do Self.BugReport(E,Self,'Timer1000msTimer');
 end;
end;

procedure TMainForm.TimerSercatPollTimer(Sender: TObject);
var nrx:Integer; msg:String; ms:Double; request,complete,timeout:Boolean;
const msPerDay=24*3600*1e3;
 function DropTailEol(s:String):String;
 var n:Integer;
 begin
  Result:=s; n:=Length(s);
  while (n&gt;0) and (Pos(s[n],vbCrLf)&gt;0) do Dec(n);
  if (n&lt;&gt;Length(s)) then Result:=Copy(s,1,n);
 end;
 function FormatSentTime:String;
 begin
  if (mySentTime&gt;0)
  then Result:=FormatDateTime('yyyy.mm.dd-hh:nn:ss.zzz',mySentTime)
  else Result:='No Request';
 end;
 function FormatSentData:String;
 begin
  Result:=mySentData;
  if CheckBoxSercatDropTailEol.Checked then Result:=DropTailEol(Result);
 end;
 function FormatRxBuffer:String;
 begin
  Result:=myRxBuffer;
  if CheckBoxSercatDropTailEol.Checked then Result:=DropTailEol(Result);
  //Result:=ExtractWord(1,myRxBuffer,vbCrLf)
 end;
 function FormatDelay(ms:Double):String;
 begin
  if (mySentTime&gt;0)
  then Result:=FormatVar('%1.0f',ms)
  else Result:='0';
 end;
begin
 try
  if (mySerTask&lt;&gt;0) then begin
   nrx:=task_rxcount(mySerTask);
   if (nrx&gt;0) then myRxBuffer:=myRxBuffer+task_recv(mySerTask,nrx);
   ms:=(Now-mySentTime)*msPerDay;
   request:=(mySentTime&gt;0); timeout:=(ms&gt;SercatRxTimeout);
   if SercatWaitEol and (Pos(vbCr,myRxBuffer)+Pos(vbLf,myRxBuffer)&gt;0)
   then complete:=true else complete:=timeout and (myRxBuffer&lt;&gt;'');
   if request and timeout and not complete then begin
    msg:=RusEng('Нет ответа после ожидания.','No response after timeout.');
    SercatAskAnsAdd(FormatSentTime,FormatSentData,SercatTimeoutMark,FormatDelay(ms));
    SercatLog(Now,msg);
    myRxBuffer:='';
    mySentData:='';
    mySentTime:=0;
   end else
   if complete then begin
    msg:=FormatVar(RusEng('Принято %d байт(ов)','Read %d byte(s)'),Length(myRxBuffer));
    if request then msg:=msg+FormatVar(RusEng(' с задержкой %1.0f мс',' with delay %1.0f ms'),ms);
    if request or CheckBoxSercatShowAnsNoAsk.Checked then
    SercatAskAnsAdd(FormatSentTime,FormatSentData,FormatRxBuffer,FormatDelay(ms));
    msg:=msg+EOL+myRxBuffer;
    SercatLog(Now,msg);
    myRxBuffer:='';
    mySentData:='';
    mySentTime:=0;
   end;
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'TimerSerPollTimer');
 end;
end;

procedure TMainForm.TimerSercatAdamScanTimer(Sender: TObject);
begin
 try
  if (mySerTask=0) then CheckBoxSercatAdamScan.Checked:=false;
  if CheckBoxSercatAdamScan.Checked then begin
   LabelSercatAdamScanAddr.Caption:=FormatVar('$%2.2XM',SercatNextScanAddr(0));
   SercatInputText:=FormatVar('$%2.2XM',SercatNextScanAddr(0));
   ActionSercatSend.Execute;
   myScanAddr:=SercatNextScanAddr(1);
  end else TimerSercatAdamScan.Enabled:=false;
 except
  on E:Exception do Self.BugReport(E,Self,'TimerSercatAdamScanTimer');
 end;
end;

procedure TMainForm.ActionSercatAdamScanToggleExecute(Sender: TObject);
begin
 try
  if CheckBoxSercatAdamScan.Checked then begin
   TimerSercatAdamScan.Interval:=SercatRxTimeout*2;
   TimerSercatAdamScan.Enabled:=true;
   myScanAddr:=SercatNextScanAddr(256);
  end else TimerSercatAdamScan.Enabled:=false;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatAdamScanToggleExecute');
 end;
end;

procedure TMainForm.CheckBoxSercatAdamScanChange(Sender: TObject);
begin
 ActionSercatAdamScanToggle.Execute;
end;

procedure TMainForm.ActionSercatAskAnsCopyExecute(Sender: TObject);
begin
 StringGridSercatAskAns.CopyToClipboard;
end;

procedure TMainForm.ActionSercatLogCopyExecute(Sender: TObject);
begin
 if (MemoSercatLog.SelLength&gt;0)
 then Clipboard.AsText:=MemoSercatLog.SelText
 else Clipboard.AsText:=MemoSercatLog.Lines.Text;
end;

procedure TMainForm.ActionSercatLogResetExecute(Sender: TObject);
begin
 MemoSercatLog.Lines.Clear;
end;

procedure TMainForm.CheckBoxSercatOptPollChange(Sender: TObject);
begin
 if CheckBoxSercatOptPoll.Checked
 then TimerSercatPoll.Interval:=iMax(1,iMin(DefPollPeriod,SpinEditSercatOptPoll.Value))
 else TimerSercatPoll.Interval:=DefPollPeriod;
end;

function TMainForm.SercatAppendEol(data:String):String;
var test:String;
begin
 Result:=data;
 test:=ComboBoxSercatEol.Text;
 if SameText(test,'CR')   then Result:=Result+vbCr else
 if SameText(test,'LF')   then Result:=Result+vbLf else
 if SameText(test,'CRLF') then Result:=Result+vbCrLf;
end;

function TMainForm.SercatAddChecksum(data:String):String;
var test:String; i,cs:Integer;
begin
 Result:=data;
 test:=ComboBoxSercatChecksum.Text;
 if SameText(test,'DCON') then begin
  cs:=0;
  for i:=1 to Length(data) do cs:=cs+Ord(data[i]);
  cs:=cs and 255;
  Result:=Result+FormatVar('%2.2X',cs);
 end;
end;

function TMainForm.GetSercatInputText:String;
begin
 Result:=ComboBoxSercatInput.Text;
end;

function TMainForm.SetSercatInputText(aText:String);
begin
 ComboBoxSercatInput.Text:=aText;
end;

function TMainForm.SercatWaitEol:Boolean;
begin
 Result:=CheckBoxSercatWaitEol.Checked;
end;

function TMainForm.SercatUseKill:Boolean;
begin
 Result:=CheckBoxSercatUseKill.Checked;
end;

function TMainForm.SercatRxTimeout:Integer;
begin
 Result:=SpinEditSercatRxTimeout.Value;
end;

function TMainForm.SercatInputMode:Integer;
begin
 Result:=ComboBoxSercatInputMode.ItemIndex;
end;

function TMainForm.SercatOutputMode:Integer;
begin
 Result:=ComboBoxSercatOutputMode.ItemIndex;
end;

function TMainForm.SercatKillTimeout:Integer;
begin
 Result:=SpinEditSercatKillTimeout.Value;
end;

function TMainForm.SercatTimeoutMark:String;
begin
 Result:=ComboBoxSercatTimeoutMark.Text;
end;

function TMainForm.SercatOptPoll:String;
begin
 if CheckBoxSercatOptPoll.Checked
 then Result:=' --poll '+IntToStr(SpinEditSercatOptPoll.Value)
 else Result:='';
end;

function TMainForm.SercatInputDecode(data:String):String;
begin
 case ComboBoxSercatInputDecode.ItemIndex of
  io_hex:data:=RecodeStr(data,'hex,rawbyte');
  io_url:data:=RecodeStr(data,'url,rawbyte');
  io_b64:data:=RecodeStr(data,'base64,rawbyte');
 end;
 Result:=data;
end;

function TMainForm.SercatInputEncode(data:String; Mode:Integer):String;
begin
 case Mode of
  io_hex:data:=StrToHex(data);
 end;
 Result:=data;
end;

function TMainForm.SercatNextScanAddr(Step:Integer):Integer;
begin
 Result:=myScanAddr+Step;
 if (Result&lt;SpinEditSercatAdamScanLo.Value)
 or (Result&gt;SpinEditSercatAdamScanHi.Value)
 then Result:=SpinEditSercatAdamScanLo.Value;
end;

procedure TMainForm.SercatAskAnsAdd(datetime,ask,ans,delay:String);
var row:Integer;
begin
 try
  row:=StringGridSercatAskAns.RowCount;
  StringGridSercatAskAns.RowCount:=row+1;
  StringGridSercatAskAns.Cells[0,row]:=IntToStr(row);
  StringGridSercatAskAns.Cells[1,row]:=datetime;
  StringGridSercatAskAns.Cells[2,row]:=ask;
  StringGridSercatAskAns.Cells[3,row]:=ans;
  StringGridSercatAskAns.Cells[4,row]:=delay;
  StringGridSercatAskAns.Row:=row;
 except
  on E:Exception do Self.BugReport(E,Self,'SercatAskAnsAdd');
 end;
end;

procedure TMainForm.ActionSercatSendExecute(Sender: TObject);
var data:String; ntx:Integer;
begin
 try
  data:=SercatInputText;
  if IsEmptyStr(data) then Exit;
  if not CheckBoxSercatAdamScan.Checked then
  if (ComboBoxSercatInput.Items.IndexOf(data)&lt;0)
  then ComboBoxSercatInput.Items.Add(data);
  if (mySerTask&lt;&gt;0) and (data&lt;&gt;'') then begin
   data:=SercatInputDecode(data);
   data:=SercatAddChecksum(data);
   data:=SercatAppendEol(data);
   data:=SercatInputEncode(data,SercatInputMode);
   ntx:=task_send(mySerTask,data);
   mySentData:=data; mySentTime:=Now;
   SercatLog(Now,FormatVar(RusEng('Послано %d байт(ов)','Sent %d byte(s)'),ntx)+EOL+data);
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatSendExecute');
 end;
end;

procedure TMainForm.ComboBoxSercatInputKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
 if (Key=VK_RETURN) then ActionSercatSend.Execute;
end;

procedure TMainForm.ActionSercatHelpExecute(Sender: TObject);
var cmd,msg:String;
begin
 try
  cmd:=SercatCmd('--help'); msg:='';
  if RunCommand(cmd,msg) then begin
   SercatLog(Now,ActionSercatHelp.Name+EOL+cmd);
   if (msg&lt;&gt;'') then SercatLog(-1,msg);
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatHelpExecute');
 end;
end;

procedure TMainForm.ActionSercatKillAllExecute(Sender: TObject);
var cmd,msg:String;
begin
 try
  msg:='';
  ResetActivePages;
  cmd:=GetShell+' -c "exec killall --verbose sercat 2&gt;&amp;1"';
  if RunCommand(cmd,msg) then begin
   SercatLog(Now,ActionSercatKillAll.Name+EOL+cmd);
   if (msg&lt;&gt;'') then SercatLog(-1,msg);
  end;
  SercatStop;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatKillAllExecute');
 end;
end;

procedure TMainForm.ActionDisplayLanguageRussianExecute(Sender: TObject);
begin
 UpdateGuiLanguage(lng_Russian);
 ResetActivePages;
end;

procedure TMainForm.ActionDisplayLanguageEnglishExecute(Sender: TObject);
begin
 UpdateGuiLanguage(lng_English);
 ResetActivePages;
end;

procedure TMainForm.ActionSercatAskAnsResetExecute(Sender: TObject);
begin
 try
  StringGridSercatAskAns.FixedCols:=1;
  StringGridSercatAskAns.FixedRows:=1;
  StringGridSercatAskAns.ColCount:=5;
  StringGridSercatAskAns.RowCount:=1;
  StringGridSercatAskAns.Cells[0,0]:=RusEng('Номер','Number');
  StringGridSercatAskAns.Cells[1,0]:=RusEng('Дата-Время_Запроса','Date-Time_of_Request');
  StringGridSercatAskAns.Cells[2,0]:=RusEng('Запрос','Request')+'(Ask)';
  StringGridSercatAskAns.Cells[3,0]:=RusEng('Ответ','Reply')+'(Ans)';
  StringGridSercatAskAns.Cells[4,0]:=RusEng('Задержка,мс','Delay,ms');
  ActionSercatAskAnsAutoSize.Execute;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatAskAnsResetExecute');
 end;
end;

procedure TMainForm.ActionSercatAskAnsAutoSizeExecute(Sender: TObject);
begin
 try
  StringGridSercatAskAns.AutoSizeColumn(0);
  StringGridSercatAskAns.AutoSizeColumn(1);
  StringGridSercatAskAns.AutoSizeColumn(2);
  StringGridSercatAskAns.AutoSizeColumn(3);
  StringGridSercatAskAns.AutoSizeColumn(4);
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatAskAnsAutoSizeExecute');
 end;
end;

procedure TMainForm.PageControlSercatOutputChange(Sender: TObject);
begin
 if (PageControlSercatOutput.ActivePage=TabSheetSercatAskAns)
 then ActionSercatAskAnsAutoSize.Execute;
end;

procedure TMainForm.ActionSercatSaveIniExecute(Sender: TObject);
var IniPath:String; IniFile:TIniFile;
begin
 try
  IniPath:=GetOptIniFile(3);
  IniFile:=TIniFile.Create(IniPath);
  try
   IniFile.WriteString('sercat','Language',RusEng('russian','english'));
   IniFile.WriteString('sercat','ComPort',IntToStr(myLastNum));
   IniFile.WriteString('sercat','BaudRate',ComboBoxSercatBaudRate.Text);
   IniFile.WriteString('sercat','DataBits',ComboBoxSercatDataBits.Text);
   IniFile.WriteString('sercat','Parity',ComboBoxSercatParity.Text);
   IniFile.WriteString('sercat','StopBits',ComboBoxSercatStopBits.Text);
   IniFile.WriteString('sercat','Options',IntToStr(GetCheckListBoxCheckedBits(CheckListBoxSercatOptions)));
   IniFile.WriteString('sercat','InputDecode',ComboBoxSercatInputDecode.Text);
   IniFile.WriteString('sercat','InputMode',ComboBoxSercatInputMode.Text);
   IniFile.WriteString('sercat','OutputMode',ComboBoxSercatOutputMode.Text);
   IniFile.WriteString('sercat','Checksum',ComboBoxSercatChecksum.Text);
   IniFile.WriteString('sercat','EOL',ComboBoxSercatEOL.Text);
   IniFile.WriteString('sercat','KillTimeout',IntToStr(SpinEditSercatKillTimeout.Value));
   IniFile.WriteString('sercat','TimeoutMark',ComboBoxSercatTimeoutMark.Text);
   IniFile.WriteString('sercat','UseKill',IntToStr(Ord(CheckBoxSercatUseKill.Checked)));
   IniFile.WriteString('sercat','UseShell',IntToStr(Ord(CheckBoxSercatUseShell.Checked)));
   IniFile.WriteString('sercat','ShowAnsNoAsk',IntToStr(Ord(CheckBoxSercatShowAnsNoAsk.Checked)));
   IniFile.WriteString('sercat','DropTailEOL',IntToStr(Ord(CheckBoxSercatDropTailEol.Checked)));
   IniFile.WriteString('sercat','WaitEOL',IntToStr(Ord(CheckBoxSercatWaitEol.Checked)));
   IniFile.WriteString('sercat','RxTimeout',IntToStr(SpinEditSercatRxTimeout.Value));
   IniFile.WriteString('sercat','OptPoll',IntToStr(Ord(CheckBoxSercatOptPoll.Checked)));
   IniFile.WriteString('sercat','PollPeriod',IntToStr(SpinEditSercatOptPoll.Value));
   LogEvents(Now,ActionSercatSaveIni.Name+' '+IniPath);
   SercatLog(Now,ActionSercatSaveIni.Name+' '+IniPath);
   ResetActivePages;
  finally
   IniFile.UpdateFile;
   IniFile.Free;
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatSaveIniExecute');
 end;
end;

procedure TMainForm.ActionSercatLoadIniExecute(Sender: TObject);
var IniPath:String; IniFile:TIniFile;
 procedure SetLanguage(arg:String);
 begin
  if (arg='') then Exit;
  if SameText(arg,'english') then LanguageId:=lng_English;
  if SameText(arg,'russian') then LanguageId:=lng_Russian;
 end;
 procedure SetLastNum(arg:String);
 var n:Integer;
 begin
  n:=StrToIntDef(arg,0);
  if (n&gt;=1) and (n&lt;=ComboBoxSercatPort.Items.Count) then myLastNum:=n;
 end;
 procedure SetOptions(arg:String);
 var n:Integer;
 begin
  if TryStrToInt(arg,n)
  then SetCheckListBoxCheckedBits(CheckListBoxSercatOptions,n);
 end;
 procedure SetComboBoxItem(arg:String; cb:TComboBox);
 var i:Integer;
 begin
  if (cb=nil) then Exit;
  if (arg='') then Exit;
  i:=cb.Items.IndexOf(arg);
  if (i&gt;=0) then cb.ItemIndex:=i;
 end;
 procedure SetComboBoxText(arg:String; cb:TComboBox);
 begin
  if (cb=nil) then Exit;
  cb.Text:=arg;
 end;
 procedure SetSpinEditValue(arg:String; se:TSpinEdit);
 var iv:Integer;
 begin
  if (se=nil) then Exit;
  if (arg='') then Exit;
  if not TryStrToInt(arg,iv) then Exit;
  if (se.MinValue&lt;se.MaxValue) and (iv&lt;se.MinValue) or (iv&gt;se.MaxValue) then Exit;
  se.Value:=iv;
 end;
 procedure SetCheckBoxState(arg:String; cb:TCheckBox);
 var iv:Integer;
 begin
  if (cb=nil) then Exit;
  if (arg='') then Exit;
  if not TryStrToInt(arg,iv) then Exit;
  cb.Checked:=(iv&gt;0);
 end;
 procedure SetRadioGroupState(arg:String; rg:TRadioGroup);
 var iv:Integer;
 begin
  if (rg=nil) then Exit;
  if (arg='') then Exit;
  if not TryStrToInt(arg,iv) then Exit;
  if (iv&lt;-1) or (iv&gt;=rg.Items.Count) then Exit;
  rg.ItemIndex:=iv;
 end;
begin
 try
  IniPath:=GetOptIniFile(3);
  IniFile:=TIniFile.Create(IniPath);
  try
   SetLanguage(IniFile.ReadString('sercat','Language',''));
   SetLastNum(IniFile.ReadString('sercat','ComPort',''));
   SetComboBoxItem(IniFile.ReadString('sercat','BaudRate',''),ComboBoxSercatBaudRate);
   SetComboBoxItem(IniFile.ReadString('sercat','DataBits',''),ComboBoxSercatDataBits);
   SetComboBoxItem(IniFile.ReadString('sercat','Parity',''),ComboBoxSercatParity);
   SetComboBoxItem(IniFile.ReadString('sercat','StopBits',''),ComboBoxSercatStopBits);
   SetOptions(IniFile.ReadString('sercat','Options',''));
   SetComboBoxItem(IniFile.ReadString('sercat','InputDecode',''),ComboBoxSercatInputDecode);
   SetComboBoxItem(IniFile.ReadString('sercat','InputMode',''),ComboBoxSercatInputMode);
   SetComboBoxItem(IniFile.ReadString('sercat','OutputMode',''),ComboBoxSercatOutputMode);
   SetComboBoxItem(IniFile.ReadString('sercat','Checksum',''),ComboBoxSercatChecksum);
   SetComboBoxItem(IniFile.ReadString('sercat','EOL',''),ComboBoxSercatEOL);
   SetSpinEditValue(IniFile.ReadString('sercat','KillTimeout',''),SpinEditSercatKillTimeout);
   SetComboBoxText(IniFile.ReadString('sercat','TimeoutMark',''),ComboBoxSercatTimeoutMark);
   SetCheckBoxState(IniFile.ReadString('sercat','UseKill',''),CheckBoxSercatUseKill);
   SetCheckBoxState(IniFile.ReadString('sercat','UseShell',''),CheckBoxSercatUseShell);
   SetCheckBoxState(IniFile.ReadString('sercat','ShowAnsNoAsk',''),CheckBoxSercatShowAnsNoAsk);
   SetCheckBoxState(IniFile.ReadString('sercat','DropTailEOL',''),CheckBoxSercatDropTailEol);
   SetCheckBoxState(IniFile.ReadString('sercat','WaitEOL',''),CheckBoxSercatWaitEol);
   SetSpinEditValue(IniFile.ReadString('sercat','RxTimeout',''),SpinEditSercatRxTimeout);
   SetCheckBoxState(IniFile.ReadString('sercat','OptPoll',''),CheckBoxSercatOptPoll);
   SetSpinEditValue(IniFile.ReadString('sercat','PollPeriod',''),SpinEditSercatOptPoll);
   LogEvents(Now,ActionSercatLoadIni.Name+' '+IniPath);
   SercatLog(Now,ActionSercatLoadIni.Name+' '+IniPath);
   ResetActivePages;
  finally
   IniFile.Free;
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatLoadIniExecute');
 end;
end;

procedure TMainForm.ActionSercatDropIniExecute(Sender: TObject);
var IniPath:String;
begin
 try
  IniPath:=GetOptIniFile(3);
  if DeleteFile(IniPath) then begin
   LogEvents(Now,ActionSercatDropIni.Name+' '+IniPath);
   SercatLog(Now,ActionSercatDropIni.Name+' '+IniPath);
  end else SercatLog(Now,RusEng('Не найден ','Not found ')+IniPath);
  ResetActivePages;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatDropIniExecute');
 end;
end;

function ExtractCheckListBoxOptions(CheckListBox:TCheckListBox):String;
var i:Integer;
begin
 Result:='';
 if (CheckListBox=nil) then Exit;
 for i:=0 to CheckListBox.Items.Count-1 do
 if CheckListBox.Checked[i] then begin
  Result:=Result+' '+CheckListBox.Items.Strings[i];
 end;
end;

procedure TMainForm.ActionSercatRunExecute(Sender: TObject);
const Delims=' '+vbTab+vbCrLf;
var arg,cmd,msg:String;
begin
 try
  ResetActivePages;
  ActionSercatAskAnsReset.Execute;
  arg:=ExtractWord(1,ComboBoxSercatPort.Text,Delims);
  case SercatInputMode of
   io_raw: arg:=arg+' --rawin ';
   io_hex: arg:=arg+' --hexin ';
   io_esc: arg:=arg+' --escin ';
  end;
  case SercatOutputMode of
   io_hex: arg:=arg+' --hexout ';
   io_esc: arg:=arg+' --escout ';
  end;
  arg:=arg+SercatOptPoll;
  arg:=arg+' --baudrate '+Trim(ComboBoxSercatBaudRate.Text);
  arg:=arg+' --databits '+Trim(ComboBoxSercatDataBits.Text);
  arg:=arg+' --parity '+Trim(ComboBoxSercatParity.Text);
  arg:=arg+' --stopbits '+Trim(ComboBoxSercatStopBits.Text);
  arg:=arg+ExtractCheckListBoxOptions(CheckListBoxSercatOptions);
  cmd:=SercatCmd(arg);
  if CheckBoxSercatUseShell.Checked and IsUnix
  then cmd:=GetShell+FormatVar(' -c "exec %s 2&gt;&amp;1"',cmd);
  SercatLog(Now,ActionSercatRun.name+EOL+cmd);
  SercatStop;
  mySerTask:=task_init(cmd);
  task_ctrl(mySerTask,'StdInPipeSize='+IntToStr(1024*8));
  task_ctrl(mySerTask,'StdOutPipeSize='+IntToStr(1024*8));
  task_ctrl(mySerTask,'Display=SW_HIDE');
  if task_run(mySerTask) then begin
   msg:=FormatVar('PID %d ',task_pid(mySerTask))+RusEng('запущен','started');
   LogEvents(Now,cmd+EOL+msg);
   SercatLog(Now,msg);
   mySerPort:=ComboBoxSercatPort.ItemIndex+1;
   myLastNum:=mySerPort;
  end else begin
   msg:=RusEng('Не могу запустить sercat.','Could not start sercat.');
   LogEvents(Now,cmd+EOL+msg);
   SercatLog(Now,msg);
   SercatStop;
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionSercatRunExecute');
 end;
end;

procedure TMainForm.ActionMainListSysInfoExecute(Sender: TObject);
var What,Info:String; Timeout:Integer;
begin
 Timeout:=1000*SpinEditMainListSysInfoTimeOut.Value;
 What:=Trim(ComboBoxMainListSysInfo.Text);
 Info:=ListSysInfoAsText(What,Timeout);
 LogEvents(Now,What);
 LogEvents(0,Info);
end;

end.
</Code>
        </Main>
        <sercatlib ImageIndex="2">
          <Object ClassName=""/>
          <Code>unit sercatlib;

interface

uses  dpCmdArgs,dpSystem,dpSysUtils,dpVbs,dpWindows,dpGuiUtils,
      dpCrwDaqSys,dpDaqConfig,dpAntiZombie,dpGuiResMain,dpLinux,
      dpTask;

const      // Sercat input/output modes
 io_Def=0; // Default (as is)
 io_Raw=1; // Raw (not CANONIC, not ECHO)
 io_Hex=2; // Hexadecimal
 io_Esc=3; // Escape with backslash
 io_Url=4; // URL encode
 io_B64=5; // Base64
 io_LST='DEF,RAW,HEX,ESC,URL,B64';

const
 DefPollPeriod = 4; // Default polling period, ms

function  GetCaptionOfComponent(Comp:TComponent):String;
procedure SetCaptionOfComponent(Comp:TComponent; aCaption:String);
function  GetHintOfComponent(Comp:TComponent):String;
procedure SetHintOfComponent(Comp:TComponent; aHint:String);

function  GetCheckListBoxCheckedBits(clb:TCheckListBox):Cardinal;
procedure SetCheckListBoxCheckedBits(clb:TCheckListBox; Bits:Cardinal);

var
 InstanceNumber : Integer = 1;

function GetOptNumber(def:Integer):Integer;
function GetOptIniFile(Mode:Integer=1):String;
function GetOptLanguage(def:Integer):Integer;

implementation

function GetCaptionOfComponent(Comp:TComponent):String;
begin
 if (Comp is TMenuItem)         then Result:=TMenuItem(Comp).Caption;
 if (Comp is TLabel)            then Result:=TLabel(Comp).Caption;
 if (Comp is TButton)           then Result:=TButton(Comp).Caption;
 if (Comp is TCheckBox)         then Result:=TCheckBox(Comp).Caption;
 if (Comp is TRadioButton)      then Result:=TRadioButton(Comp).Caption;
 if (Comp is TToggleBox)        then Result:=TToggleBox(Comp).Caption;
 if (Comp is TGroupBox)         then Result:=TGroupBox(Comp).Caption;
 if (Comp is TRadioGroup)       then Result:=TRadioGroup(Comp).Caption;
 if (Comp is TCheckGroup)       then Result:=TCheckGroup(Comp).Caption;
 if (Comp is TPanel)            then Result:=TPanel(Comp).Caption;
 if (Comp is TCustomAction)     then Result:=TCustomAction(Comp).Caption;
 if (Comp is TAction)           then Result:=TAction(Comp).Caption;
 if (Comp is TBitBtn)           then Result:=TBitBtn(Comp).Caption;
 if (Comp is TSpeedButton)      then Result:=TSpeedButton(Comp).Caption;
 if (Comp is TStaticText)       then Result:=TStaticText(Comp).Caption;
 if (Comp is TToolBar)          then Result:=TToolBar(Comp).Caption;
 if (Comp is TToolButton)       then Result:=TToolButton(Comp).Caption;
 if (Comp is TTabSheet)         then Result:=TTabSheet(Comp).Caption;
 if (Comp is TForm)             then Result:=TForm(Comp).Caption;
 if (Comp is TDBCheckBox)       then Result:=TDBCheckBox(Comp).Caption;
 if (Comp is TDBRadioGroup)     then Result:=TDBRadioGroup(Comp).Caption;
 if (Comp is TDBNavigator)      then Result:=TDBNavigator(Comp).Caption;
 if (Comp is TDBNavButton)      then Result:=TDBNavButton(Comp).Caption;
 if (Comp is TxSpeedBtn)        then Result:=TxSpeedBtn(Comp).Caption;
 if (Comp is TxBitBtn)          then Result:=TxBitBtn(Comp).Caption;
 if (Comp is TEmbededLabel)     then Result:=TEmbededLabel(Comp).Caption;
 if (Comp is TxDBCheckBox)      then Result:=TxDBCheckBox(Comp).Caption;
 if (Comp is TSuFrame)          then Result:=TSuFrame(Comp).Caption;
 if (Comp is TColorButton)      then Result:=TColorButton(Comp).Caption;
 if (Comp is TPanelBitBtn)      then Result:=TPanelBitBtn(Comp).Caption;
 if (Comp is TfrPreview)        then Result:=TfrPreview(Comp).Caption;
end;
procedure SetCaptionOfComponent(Comp:TComponent; aCaption:String);
begin
 if (Comp is TMenuItem)         then TMenuItem(Comp).Caption:=aCaption;
 if (Comp is TLabel)            then TLabel(Comp).Caption:=aCaption;
 if (Comp is TButton)           then TButton(Comp).Caption:=aCaption;
 if (Comp is TCheckBox)         then TCheckBox(Comp).Caption:=aCaption;
 if (Comp is TRadioButton)      then TRadioButton(Comp).Caption:=aCaption;
 if (Comp is TToggleBox)        then TToggleBox(Comp).Caption:=aCaption;
 if (Comp is TGroupBox)         then TGroupBox(Comp).Caption:=aCaption;
 if (Comp is TRadioGroup)       then TRadioGroup(Comp).Caption:=aCaption;
 if (Comp is TCheckGroup)       then TCheckGroup(Comp).Caption:=aCaption;
 if (Comp is TPanel)            then TPanel(Comp).Caption:=aCaption;
 if (Comp is TCustomAction)     then TCustomAction(Comp).Caption:=aCaption;
 if (Comp is TAction)           then TAction(Comp).Caption:=aCaption;
 if (Comp is TBitBtn)           then TBitBtn(Comp).Caption:=aCaption;
 if (Comp is TSpeedButton)      then TSpeedButton(Comp).Caption:=aCaption;
 if (Comp is TStaticText)       then TStaticText(Comp).Caption:=aCaption;
 if (Comp is TToolBar)          then TToolBar(Comp).Caption:=aCaption;
 if (Comp is TToolButton)       then TToolButton(Comp).Caption:=aCaption;
 if (Comp is TTabSheet)         then TTabSheet(Comp).Caption:=aCaption;
 if (Comp is TForm)             then TForm(Comp).Caption:=aCaption;
 if (Comp is TDBCheckBox)       then TDBCheckBox(Comp).Caption:=aCaption;
 if (Comp is TDBRadioGroup)     then TDBRadioGroup(Comp).Caption:=aCaption;
 if (Comp is TDBNavigator)      then TDBNavigator(Comp).Caption:=aCaption;
 if (Comp is TDBNavButton)      then TDBNavButton(Comp).Caption:=aCaption;
 if (Comp is TxSpeedBtn)        then TxSpeedBtn(Comp).Caption:=aCaption;
 if (Comp is TxBitBtn)          then TxBitBtn(Comp).Caption:=aCaption;
 if (Comp is TEmbededLabel)     then TEmbededLabel(Comp).Caption:=aCaption;
 if (Comp is TxDBCheckBox)      then TxDBCheckBox(Comp).Caption:=aCaption;
 if (Comp is TSuFrame)          then TSuFrame(Comp).Caption:=aCaption;
 if (Comp is TColorButton)      then TColorButton(Comp).Caption:=aCaption;
 if (Comp is TPanelBitBtn)      then TPanelBitBtn(Comp).Caption:=aCaption;
 if (Comp is TfrPreview)        then TfrPreview(Comp).Caption:=aCaption;
end;
function GetHintOfComponent(Comp:TComponent):String;
begin
 if (Comp is TControl) then Result:=TControl(Comp).Hint;
end;
procedure SetHintOfComponent(Comp:TComponent; aHint:String);
begin
 if (Comp is TControl) then TControl(Comp).Hint:=aHint;
end;

function GetCheckListBoxCheckedBits(clb:TCheckListBox):Cardinal;
var i:Integer;
begin
 Result:=0;
 if (clb=nil) then Exit;
 for i:=0 to clb.Items.Count-1 do
 if clb.Checked[i] then Result:=Result or (1 shl i);
end;

procedure SetCheckListBoxCheckedBits(clb:TCheckListBox; Bits:Cardinal);
var i:Integer;
begin
 if (clb=nil) then Exit;
 for i:=0 to clb.Items.Count-1 do clb.Checked[i]:=IsBit(Bits,i);
end;

function GetOptNumber(def:Integer):Integer;
var snum:String;
begin
 Result:=def; snum:='';
 if (snum='') then snum:=CmdArgs.GetOptionValue('-n');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--n');
 if (snum='') then snum:=CmdArgs.GetOptionValue('-num');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--num');
 if (snum='') then snum:=CmdArgs.GetOptionValue('-number');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--number');
 if (snum&lt;&gt;'') then Result:=iMax(1,StrToIntDef(snum,def));
end;

function GetOptIniFile(Mode:Integer=1):String;
var DataDir:String; ini,def:Boolean;
begin
 Result:=''; DataDir:='';
 ini:=HasFlags(Mode,1); def:=HasFlags(Mode,2);
 DataDir:=GetAppDataDir(false,true);
 if IsEmptyStr(DataDir) then Exit;
 if not DirectoryExists(DataDir) then MakeDir(DataDir);
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('-ini');
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('--ini');
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('-inifile');
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('--inifile');
 if (Result='') then if def then Result:=GetScriptBaseName+'_'+IntToStr(InstanceNumber);
 if (Result&lt;&gt;'') and (ExtractFileExt(Result)='') then Result:=ReplaceFileExt(Result,'.ini');
 if (Result&lt;&gt;'') and (ExtractFileDir(Result)='') then Result:=AddPathDelim(DataDir)+Result;
end;

function GetOptLanguage(def:Integer):Integer;
var slng:String;
begin
 Result:=def; slng:='';
 if (slng='') then slng:=CmdArgs.GetOptionValue('-l');
 if (slng='') then slng:=CmdArgs.GetOptionValue('-lng');
 if (slng='') then slng:=CmdArgs.GetOptionValue('-lang');
 if (slng='') then slng:=CmdArgs.GetOptionValue('-language');
 if (slng='') then slng:=CmdArgs.GetOptionValue('--lng');
 if (slng='') then slng:=CmdArgs.GetOptionValue('--lang');
 if (slng='') then slng:=CmdArgs.GetOptionValue('--language');
 if (slng='') then Exit;
 if WordIndex(slng,'ru,rus,russian',', ')&gt;0 then Result:=lng_Russian;
 if WordIndex(slng,'en,eng,english',', ')&gt;0 then Result:=lng_English;
end;

procedure InitSercatLib;
begin
 try
  InstanceNumber:=GetOptNumber(1);
 except
  on E:Exception do BugReport(E,Application,'InitSercatLib');
 end;
end;

initialization

 InitSercatLib;

end.
</Code>
        </sercatlib>
      </Child>
    </sercatgui>
  </Metadata>
</CrossEngineApp>
