{$I OVC.INC}

{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{$W-} {Windows Stack Frame}
{$X+} {Extended Syntax}

{$IFNDEF Win32}
{$G+} {286 Instructions}
{$N+} {Numeric Coprocessor}
{$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
{$ENDIF}

{*********************************************************}
{*                   OVCCMD.PAS 2.00                     *}
{*     Copyright (c) TurboPower Software Co 1995-96      *}
{*                 All rights reserved.                  *}
{*********************************************************}

unit OvcCmd;
  {-Translates messages into commands}

interface

uses
  {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  Classes, Forms, Menus, Messages, SysUtils,
  OvcConst, OvcData, OvcExcpt, OvcMisc;

const
  {default primary command/key table}
  DefMaxCommands = 64;
  DefCommandTable : array[0..DefMaxCommands-1] of TOvcCmdRec = (
 {Key #1          Shift state #1
  Key #2          Shift state #2              Command}
 (Key1:VK_LEFT;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLeft),
 (Key1:VK_RIGHT;  SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRight),
 (Key1:VK_LEFT;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordLeft),
 (Key1:VK_RIGHT;  SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordRight),
 (Key1:VK_HOME;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccHome),
 (Key1:VK_END;    SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccEnd),
 (Key1:VK_DELETE; SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDel),
 (Key1:VK_BACK;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
 (Key1:VK_BACK;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
 (Key1:VK_PRIOR;  SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTopOfPage),
 (Key1:VK_NEXT;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBotOfPage),
 (Key1:VK_INSERT; SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccIns),
 (Key1:VK_Z;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUndo),
 (Key1:VK_BACK;   SS1:ss_Alt;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRestore),
 (Key1:VK_UP;     SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUp),
 (Key1:VK_DOWN;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDown),
 (Key1:VK_RETURN; SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNewLine),
 (Key1:VK_LEFT;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendLeft),
 (Key1:VK_RIGHT;  SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendRight),
 (Key1:VK_HOME;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendHome),
 (Key1:VK_END;    SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendEnd),
 (Key1:VK_LEFT;   SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordLeft),
 (Key1:VK_RIGHT;  SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordRight),
 (Key1:VK_PRIOR;  SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgUp),
 (Key1:VK_NEXT;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgDn),
 (Key1:VK_UP;     SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendUp),
 (Key1:VK_DOWN;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendDown),
 (Key1:VK_HOME;   SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtFirstPage),
 (Key1:VK_END;    SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtLastPage),
 (Key1:VK_PRIOR;  SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtTopOfPage),
 (Key1:VK_NEXT;   SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtBotOfPage),
 (Key1:VK_DELETE; SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCut),
 (Key1:VK_X;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCut),
 (Key1:VK_INSERT; SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCopy),
 (Key1:VK_C;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCopy),
 (Key1:VK_INSERT; SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPaste),
 (Key1:VK_V;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPaste),
 (Key1:VK_PRIOR;  SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPrevPage),
 (Key1:VK_NEXT;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNextPage),
 (Key1:VK_HOME;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccFirstPage),
 (Key1:VK_END;    SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLastPage),
 (Key1:VK_TAB;    SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTab),
 (Key1:VK_TAB;    SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTab),
 (Key1:VK_Z;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRedo),
 (Key1:VK_0;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker0),
 (Key1:VK_1;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker1),
 (Key1:VK_2;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker2),
 (Key1:VK_3;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker3),
 (Key1:VK_4;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker4),
 (Key1:VK_5;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker5),
 (Key1:VK_6;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker6),
 (Key1:VK_7;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker7),
 (Key1:VK_8;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker8),
 (Key1:VK_9;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker9),
 (Key1:VK_0;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker0),
 (Key1:VK_1;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker1),
 (Key1:VK_2;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker2),
 (Key1:VK_3;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker3),
 (Key1:VK_4;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker4),
 (Key1:VK_5;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker5),
 (Key1:VK_6;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker6),
 (Key1:VK_7;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker7),
 (Key1:VK_8;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker8),
 (Key1:VK_9;      SS1:ss_Ctrl+ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker9));

  {default WordStar command-key table}
  DefWsMaxCommands = 40;
  DefWsCommandTable : array[0..DefWsMaxCommands-1] of TOvcCmdRec = (
 {Key #1          Shift state #1
  Key #2          Shift state #2              Command}
 (Key1:VK_S;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLeft),
 (Key1:VK_D;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRight),
 (Key1:VK_E;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUp),
 (Key1:VK_X;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDown),
 (Key1:VK_R;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPrevPage),
 (Key1:VK_C;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNextPage),
 (Key1:VK_W;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccScrollUp),
 (Key1:VK_Z;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccScrollDown),
 (Key1:VK_A;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordLeft),
 (Key1:VK_F;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordRight),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_S;      SS2:ss_Wordstar;            Cmd:ccHome),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_D;      SS2:ss_Wordstar;            Cmd:ccEnd),
 (Key1:VK_G;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDel),
 (Key1:VK_H;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
 (Key1:VK_Y;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDelLine),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_Y;      SS2:ss_Wordstar;            Cmd:ccDelEol),
 (Key1:VK_V;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccIns),
 (Key1:VK_T;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDelWord),
 (Key1:VK_P;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCtrlChar),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_L;      SS2:ss_Wordstar;            Cmd:ccRestore),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_0;      SS2:ss_Wordstar;            Cmd:ccGotoMarker0),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_1;      SS2:ss_Wordstar;            Cmd:ccGotoMarker1),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_2;      SS2:ss_Wordstar;            Cmd:ccGotoMarker2),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_3;      SS2:ss_Wordstar;            Cmd:ccGotoMarker3),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_4;      SS2:ss_Wordstar;            Cmd:ccGotoMarker4),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_5;      SS2:ss_Wordstar;            Cmd:ccGotoMarker5),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_6;      SS2:ss_Wordstar;            Cmd:ccGotoMarker6),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_7;      SS2:ss_Wordstar;            Cmd:ccGotoMarker7),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_8;      SS2:ss_Wordstar;            Cmd:ccGotoMarker8),
 (Key1:VK_Q;      SS1:ss_Ctrl;
  Key2:VK_9;      SS2:ss_Wordstar;            Cmd:ccGotoMarker9),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_0;      SS2:ss_Wordstar;            Cmd:ccSetMarker0),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_1;      SS2:ss_Wordstar;            Cmd:ccSetMarker1),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_2;      SS2:ss_Wordstar;            Cmd:ccSetMarker2),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_3;      SS2:ss_Wordstar;            Cmd:ccSetMarker3),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_4;      SS2:ss_Wordstar;            Cmd:ccSetMarker4),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_5;      SS2:ss_Wordstar;            Cmd:ccSetMarker5),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_6;      SS2:ss_Wordstar;            Cmd:ccSetMarker6),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_7;      SS2:ss_Wordstar;            Cmd:ccSetMarker7),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_8;      SS2:ss_Wordstar;            Cmd:ccSetMarker8),
 (Key1:VK_K;      SS1:ss_Ctrl;
  Key2:VK_9;      SS2:ss_Wordstar;            Cmd:ccSetMarker9));

  {default Orpheus Table command/key table}
  DefGridMaxCommands = 38;
  DefGridCommandTable : array[0..DefGridMaxCommands-1] of TOvcCmdRec = (
 {Key #1          Shift state #1
  Key #2          Shift state #2              Command}
 (Key1:VK_LEFT;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLeft),
 (Key1:VK_RIGHT;  SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRight),
 (Key1:VK_LEFT;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPageLeft),
 (Key1:VK_RIGHT;  SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPageRight),
 (Key1:VK_HOME;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccHome),
 (Key1:VK_END;    SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccEnd),
 (Key1:VK_DELETE; SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDel),
 (Key1:VK_BACK;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
 (Key1:VK_NEXT;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBotOfPage),
 (Key1:VK_PRIOR;  SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTopOfPage),
 (Key1:VK_INSERT; SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccIns),
 (Key1:VK_Z;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRestore),
 (Key1:VK_UP;     SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUp),
 (Key1:VK_DOWN;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDown),
 (Key1:VK_LEFT;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendLeft),
 (Key1:VK_RIGHT;  SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendRight),
 (Key1:VK_HOME;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendHome),
 (Key1:VK_END;    SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendEnd),
 (Key1:VK_LEFT;   SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordLeft),
 (Key1:VK_RIGHT;  SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordRight),
 (Key1:VK_PRIOR;  SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgUp),
 (Key1:VK_NEXT;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgDn),
 (Key1:VK_UP;     SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendUp),
 (Key1:VK_DOWN;   SS1:ss_Shift;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendDown),
 (Key1:VK_HOME;   SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtFirstPage),
 (Key1:VK_END;    SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtLastPage),
 (Key1:VK_PRIOR;  SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtTopOfPage),
 (Key1:VK_NEXT;   SS1:ss_Shift+ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtBotOfPage),
 (Key1:VK_X;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCut),
 (Key1:VK_C;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCopy),
 (Key1:VK_V;      SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPaste),
 (Key1:VK_PRIOR;  SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPrevPage),
 (Key1:VK_HOME;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccFirstPage),
 (Key1:VK_NEXT;   SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNextPage),
 (Key1:VK_END;    SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLastPage),
 (Key1:VK_UP;     SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTopLeftCell),
 (Key1:VK_DOWN;   SS1:ss_Ctrl;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBotRightCell),
 (Key1:VK_F2;     SS1:ss_None;
  Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTableEdit));

type
  {command processor states}
  TState = (stNone, stPartial, stLiteral);

  {user command notify event}
  TUserCommandEvent =
    procedure(Sender : TObject; Command : Word)
    of object;

  {forward class declarations}
  TOvcCommandProcessor = class;

  TOvcCommandTable = class(TPersistent)
  {.Z+}
  protected {private}
    FActive      : Boolean; {true to use this command table}
    FCommandList : TList;   {list of command/key mappings}
    FTableName   : string;  {the name of this command table}

    {property methods}
    function GetCmdRec(Index : Integer) : TOvcCmdRec;
      {-return the list item corresponding to "Index"}
    function GetCount : Integer;
      {-return the number of records in the list}
    procedure PutCmdRec(Index : Integer; const CR : TOvcCmdRec);
      {-store a new command entry to the list at "Index" position}

    {internal methods}
    procedure ctDisposeCommandEntry(P : POvcCmdRec);
      {-dispose of a command entry record}
    function ctNewCommandEntry(const CR : TOvcCmdRec): POvcCmdRec;
      {-allocate a new command entry record}
    procedure ctReadData(Reader : TReader);
      {-called to read the table from the stream}
    procedure ctWriteData(Writer : TWriter);
      {-called to store the table on the stream}

  protected
    procedure DefineProperties(Filer : TFiler);
      override;
  {.Z-}

  public
    constructor Create;
    destructor Destroy;
      override;

    function AddRec(const CR : TOvcCmdRec) : Integer;
      {-add a record to the list}
    procedure Clear;
      {-delete all records from the list}
    procedure Delete(Index : Integer);
      {-delete a record from the list}
    procedure Exchange(Index1, Index2 : Integer);
      {-exchange list locations of the two specified records}
    function IndexOf(const CR : TOvcCmdRec) : Integer;
      {-return the index of the specified record}
    procedure InsertRec(Index : Integer; const CR : TOvcCmdRec);
      {-insert a record at the specified index}
    procedure LoadFromFile(const FileName: string);
      {-read command entries from a text file}
    procedure Move(CurIndex, NewIndex : Integer);
      {-move one record to anothers index location}
    procedure SaveToFile(const FileName: string);
      {-write command entries to a text file}

    property Commands[Index : Integer] : TOvcCmdRec
      read GetCmdRec
      write PutCmdRec;
      default;

    property Count : Integer
      read GetCount
      stored False;

    property IsActive : Boolean
      read FActive
      write FActive;

    property TableName : string
      read FTableName
      write FTableName;
  end;

  TOvcCommandProcessor = class(TPersistent)
  {.Z+}
  protected {private}
    {property variables}
    FTableList  : TList;    {list of command tables}

    {internal variables}
    cpState     : TState;   {current state}
    cpSaveKey   : Byte;     {saved last key processed}
    cpSaveSS    : Byte;     {saved shift key state}

    {property methods}
    function GetCount: Integer;
      {-return the number of tables in the list}
    function GetTable(Index : Integer) : TOvcCommandTable;
      {-return the table referenced by "Index"}
    procedure SetTable(Index : Integer; CT : TOvcCommandTable);
      {-store a command table at position "Index"}

    {internal methods}
    function cpFillCommandRec(Key1, ShiftState1,
                              Key2, ShiftState2 : Byte;
                              Command : Word) : TOvcCmdRec;
      {-fill a command record}
    procedure cpReadData(Reader: TReader);
      {-called to read the command processor from the stream}
    function cpScanTable(CT : TOvcCommandTable; Key, SFlags : Byte) : Word;
      {-Scan the command table for a match}
    procedure cpWriteData(Writer: TWriter);
      {-called to store the command processor to the stream}

  protected
    procedure DefineProperties(Filer: TFiler);
      override;
{.Z-}

  public
    constructor Create;
    destructor Destroy;
      override;

    procedure Add(CT : TOvcCommandTable);
      {-add a command table to the list of tables}
    procedure AddCommand(const TableName: string;
                         Key1, ShiftState1,
                         Key2, ShiftState2 : Byte;
                         Command : Word);
      {-add a command and key sequence to the command table}
    procedure AddCommandRec(const TableName: string; const CR : TOvcCmdRec);
      {-add a command record to the command table}
    procedure ChangeTableName(const OldName, NewName: string);
      {-change the name of a table}
    procedure Clear;
      {-delete all tables from the list}
    function CreateCommandTable(const TableName : string; Active : Boolean) : Integer;
      {-create a command table and add it to the table list}
    procedure Delete(Index : Integer);
      {-delete the "Index" table from the list of tables}
    procedure DeleteCommand(const TableName: string;
                            Key1, ShiftState1,
                            Key2, ShiftState2 : Byte);
      {-delete a command and key sequence from a command table}
    procedure DeleteCommandTable(const TableName : string);
      {-delete a command table and remove it from the table list}
    procedure Exchange(Index1, Index2 : Integer);
      {-exchange list locations of the two specified command tables}
    function GetCommandCount(const TableName : string) : Integer;
      {-return the number of commands in the command table}
    function GetCommandTable(const TableName : string) : TOvcCommandTable;
      {-return a pointer to the specified command table or nil}
    function GetCommandTableIndex(const TableName : string) : Integer;
      {-return index to the specified command table or -1 for failure}
    function LoadCommandTable(const FileName : string) : Integer; virtual;
      {-creates and then fills a command table from a text file}
    procedure ResetCommandProcessor;
      {-reset the command processor}
    procedure SaveCommandTable(const TableName, FileName : string); virtual;
      {-save a command table to a text file}
    procedure SetScanPriority(Names : array of string);
      {-reorder the list of tables based on this array}
    function Translate(var Msg : TMessage) : Word;
      {-translate a message into a command}
    function TranslateUsing(Tables : array of string; var Msg : TMessage) : Word;
      {-translate a message into a command using the given tables}
    function TranslateKey(Key : Word; ShiftState : TShiftState) : Word;
      {-translate a key and shift-state into a command}
    function TranslateKeyUsing(Tables : array of string; Key : Word; ShiftState : TShiftState) : Word;
      {-translate a key and shift-state into a command using the given tables}

    property Count: Integer
      read GetCount
      stored False;

    property Table[Index : Integer]: TOvcCommandTable
      read GetTable
      write SetTable;
      default;
  end;


implementation
