{*********************************************************}
{*                   OOMISC.PAS 3.00                     *}
{*    Copyright (c) TurboPower Software 1996-2000        *}
{*                 All rights reserved.                  *}
{*********************************************************}

{Global defines potentially affecting this unit}
{$I AWDEFINE.INC}

{Options required for this unit}
{$V-,I-,X+}
{$IFNDEF Win32}
{$L-}
{$ENDIF}

unit OoMisc;
  {-Unit for miscellaneous routines}

interface

uses
  WinTypes,
  WinProcs,
  {$IFNDEF PrnDrv}
   {$IFNDEF DrvInst}
  Graphics,
   {$ENDIF}
  {$ENDIF}
  SysUtils,
  Messages,
  {$IFNDEF PrnDrv}
  Classes,
  Controls,
  {$ENDIF}
  MMSystem;

{$IFDEF Win32}
{$R APRO.R32}
{$ELSE}
{$R APRO.R16}
{$ENDIF}

const
{$IFDEF TRIALRUN}
  ApVersionStr = 'v3.00 Trial';
{$ELSE}
  ApVersionStr = 'v3.00';
{$ENDIF}
  {$IFDEF Win32}
  fsPathName  = 255;
  fsDirectory = 255;
  fsFileName  = 255;
  fsExtension = 255;
  fsName      = 255;
  {$ELSE}
  fsPathName  = 79;
  fsDirectory = 67;
  fsFileName  = 8;
  fsExtension = 4;
  fsName      = 12;
  {$ENDIF}

  {shareable reading file mode}
  ShareFileRead = $40;

const
  DefFileName   = 'C:\DEFAULT.APF';
  PipeTimeout   = 5000; { ms }
  PipeName      = '\\.\pipe\ApFaxCnv';
  SemaphoreName = 'ApFaxCnvSem';
  RegKey        = '\SOFTWARE\TurboPower\ApFaxCnv\Settings';
  IniFileName   = 'APFPDENG.INI';
  IniSection    = 'Settings';
  IniKey        = 'AutoExec';

  {Event codes: (inbound)}
  eNull        = 0;
  eStartDoc    = 1;
  eEndDoc      = 2;

  {Event codes: (outbound)}
  eSetFileName = 3;

{$IFDEF Win32}
type
  TPipeEvent = record
    Event : Byte;
    Data : ShortString;
  end;
{$ENDIF}

type
  CharSet = set of char;
  {$IFDEF AProBCB}
  TPassString = String[255];
  {$ENDIF}

  {$IFDEF AproBCB}
  TApdHwnd = Integer;
  {$ELSE}
  TApdHwnd = HWND;
  {$ENDIF}

  {$IFNDEF Win32}
  {Use the same type names in Delphi 1.0 and Delphi32}
  AnsiChar = Char;
  PAnsiChar = PChar;
  AnsiString  = string;
  ShortString = string;
  POverlapped = pointer;
  DWORD = LongInt;
  {$ENDIF}

  {Standard event timer record structure used by all timing routines}
  EventTimer = record
    StartTicks : LongInt;  {Tick count when timer was initialized}
    ExpireTicks : LongInt; {Tick count when timer will expire}
  end;

const
  MaxTicks    = 39045157;   {Max ticks, 24.8 days}

  {Clock frequency of 1193180/65536 is reduced to 1675/92. This}
  {allows longint conversions of Ticks values upto TicksPerDay}
  TicksFreq = 1675;
  SecsFreq  = 92;
  MSecsFreq = 92000;

const
  {Compile-time configurations}
  {$IFDEF Win32}
  MaxComHandles = 50;               {Max comm ports open at once}
  {$ELSE}
  MaxComHandles = 10;               {Max comm ports open at once}
  {$ENDIF}
  DispatchBufferSize = 8192;        {Size of each port's dispatch buffer}
  MaxMessageLen = 80;               {All error and status strings less than 80}

  {For skipping line parameter changes}
  DontChangeBaud         = 0;
  DontChangeParity       = SpaceParity + 1;
  DontChangeDatabits     = 9;
  DontChangeStopbits     = TwoStopbits + 1;

  {Modem status trigger options}
  msCTSDelta   = $0010;
  msDSRDelta   = $0020;
  msRingDelta  = $0004;
  msDCDDelta   = $0080;

  {Line status trigger options}
  lsOverrun  = $0001;
  lsParity   = $0002;
  lsFraming  = $0004;
  lsBreak    = $0008;

  {Line and driver errors}
  leNoError    = 0;   {No error, ordinal value matches ecOK}
  leBuffer     = 1;   {Buffer overrun in COMM.DRV}
  leOverrun    = 2;   {UART receiver overrun}
  leParity     = 3;   {UART receiver parity error}
  leFraming    = 4;   {UART receiver framing error}
  leCTSTO      = 5;   {Transmit timeout waiting for CTS}
  leDSRTO      = 6;   {Transmit timeout waiting for DSR}
  leDCDTO      = 7;   {Transmit timeout waiting for RLSD}
  leTxFull     = 8;   {Transmit queue is full}
  leBreak      = 9;   {Break condition received}

  {Status trigger subtypes}
  stNotActive   = 0;  {not active}
  stModem       = 1;  {Trigger on modem status change}
  stLine        = 2;  {Trigger on line status change}
  stOutBuffFree = 3;  {Trigger on outbuff free level}
  stOutBuffUsed = 4;  {Trigger on outbuff used level}
  stOutSent     = 5;  {Trigger on any PutXxx call}

  {Next file method}
  nfNone               = 0;  {No next file method specified}
  nfMask               = 1;  {Use built-in next file mask method}
  nfList               = 2;  {Use built-in next file list method}

  {Action to take if incoming file exists}
  wfcWriteNone          = 0;  {No option set yet}
  wfcWriteFail          = 1;  {Fail the open attempt}
  wfcWriteRename        = 2;  {Rename the incoming file}
  wfcWriteAnyway        = 3;  {Overwrite the existing file}
  wfcWriteResume        = 4;  {Resume an interrupted receive}

  {Ascii CR/LF translation options}
  atNone               = 0;  {No CR/LF translations}
  atStrip              = 1;  {Strip CRs or LFs}
  atAddCRBefore        = 2;  {Add CR before each LF}
  atAddLFAfter         = 3;  {Add LF after each CR}

  {Protocol status start/end flags}
  apFirstCall          = $01; {Indicates the first call to status}
  apLastCall           = $02; {Indicates the last call to status}

  {For specifying log file calls}
  lfReceiveStart       = 0;  {Receive starting}
  lfReceiveOk          = 1;  {File received ok}
  lfReceiveFail        = 2;  {File receive failed}
  lfReceiveSkip        = 3;  {File was rejected by receiver}
  lfTransmitStart      = 4;  {Transmit starting}
  lfTransmitOk         = 5;  {File was transmitted ok}
  lfTransmitFail       = 6;  {File transmit failed}
  lfTransmitSkip       = 7;  {File was skipped, rejected by receiver}

type
  {Convenient types used by protocols}
  TNameCharArray = array[0..fsFileName ] of Char;
  TExtCharArray  = array[0..fsExtension] of Char;
  TPathCharArray = array[0..fsPathName ] of Char;
  TDirCharArray  = array[0..fsDirectory] of Char;
  TChar20Array   = array[0..20] of Char;
  TCharArray = array[0..255] of Char;

  {For generic buffer typecasts}
  PByteBuffer = ^TByteBuffer;
  TByteBuffer = array[1..65535] of Byte;

  {Port characteristic constants}
  TDatabits = 5..DontChangeDatabits;
  TStopbits = 1..DontChangeStopbits;

  {NotifyProc type, same as a window procedure}
  TApdNotifyProc = procedure(Msg, wParam : Cardinal;
                         lParam : Longint);
  TApdNotifyEvent = procedure(Msg, wParam : Cardinal;
                         lParam : Longint) of object;
const
  {Avoid requiring WIN31}
  ev_CTSS   = $0400;           {CTS state}
  ev_DSRS   = $0800;           {DSR state}
  ev_RLSDS  = $1000;           {RLSD state}
  ev_RingTe = $2000;           {Ring trailing edge indicator}

const
  {MSRShadow register from COMM.DRV}
  MsrShadowOfs = 35;           {Offset of MSRShadow from EventWord}

const
  {Modem status bit masks}
  DeltaCTSMask     = $01;      {CTS changed since last read}
  DeltaDSRMask     = $02;      {DSR changed since last read}
  DeltaRIMask      = $04;      {RI changed since last read}
  DeltaDCDMask     = $08;      {DCD changed since last read}
  CTSMask          = $10;      {Clear to send}
  DSRMask          = $20;      {Data set ready}
  RIMask           = $40;      {Ring indicator}
  DCDMask          = $80;      {Data carrier detect}

const
  {Message base}
  apw_First              = $7E00;   {Sets base for all APW messages}

const
  {Custom message types}
  apw_TriggerAvail       = apw_First+1;   {Trigger for any data avail}
  apw_TriggerData        = apw_First+2;   {Trigger data}
  apw_TriggerTimer       = apw_First+3;   {Trigger timer}
  apw_TriggerStatus      = apw_First+4;   {Status change (modem, line, buffer)}
  apw_FromYmodem         = apw_First+5;   {Tells Xmodem it was called from Ymodem}
  apw_PortOpen           = apw_First+8;   {Apro, tell users port open}
  apw_PortClose          = apw_First+9;   {Apro, tell users port closed}
  apw_ClosePending       = apw_First+10;  {Apro, tell ourself that the port was closed}

const
  {Protocol message types}
  apw_ProtocolCancel     = apw_First+20;  {To protocol - chk for protcl abort}
  apw_ProtocolStatus     = apw_First+21;  {From protocol - update status display}
  apw_ProtocolLog        = apw_First+22;  {From protocol - LogFile message}
  apw_ProtocolNextFile   = apw_First+23;  {From protocol - return next file}
  apw_ProtocolAcceptFile = apw_First+24;  {From protocol - accept file}
  apw_ProtocolFinish     = apw_First+25;  {From protocol - protocol is finished}
  apw_ProtocolResume     = apw_First+26;  {From protocol - resume request}
  apw_ProtocolError      = apw_First+27;  {From protocol - error during protocol}

const
  {Modem message types}
  apw_ModemOk            = apw_First+40;  {From modem - got OK response}
  apw_ModemConnect       = apw_First+41;  {From modem - got CONNECT response}
  apw_ModemBusy          = apw_First+42;  {From modem - got BUSY response}
  apw_ModemVoice         = apw_First+43;  {From modem - got VOICE response}
  apw_ModemNoCarrier     = apw_First+44;  {From modem - got NO CARRIER response}
  apw_ModemNoDialTone    = apw_First+45;  {From modem - got NO DIALTONE response}
  apw_ModemError         = apw_First+46;  {From modem - got ERROR response}
  apw_GotLineSpeed       = apw_First+47;  {From modem - got connect speed}
  apw_GotErrCorrection   = apw_First+48;  {From modem - got EC response}
  apw_GotDataCompression = apw_First+49;  {From modem - got compression response}
  apw_CmdTimeout         = apw_First+50;  {From modem - command timed out}
  apw_DialTimeout        = apw_First+51;  {From modem - dial timed out}
  apw_AnswerTimeout      = apw_First+52;  {From modem - answer timed out}
  apw_DialCount          = apw_First+53;  {From modem - dial still in progress}
  apw_AnswerCount        = apw_First+54;  {From modem - answer still in progress}
  apw_ModemRing          = apw_First+55;  {From modem - phone rang}
  apw_ModemIsConnected   = apw_First+56;  {From modem - connection completed}
  apw_ConnectFailed      = apw_First+57;  {From modem - connection failed}
  apw_CommandProcessed   = apw_First+58;  {From modem - finished command}

const
  {Terminal message types}
  apw_TermStart          = apw_First+60;  {To terminal - start}
  apw_TermStop           = apw_First+61;  {To terminal - stop}
  apw_TermSetCom         = apw_First+62;  {To terminal - set com handle}
  apw_TermRelCom         = apw_First+63;  {To terminal - release com handle}
  apw_TermSetEmuPtr      = apw_First+64;  {To terminal - set emulator pointer}
  apw_TermSetEmuProc     = apw_First+65;  {To terminal - set emulator proc}
  apw_TermClear          = apw_First+66;  {To terminal - clear window}
  apw_TermBuffer         = apw_First+67;  {To terminal - alloc new buffers}
  apw_TermColors         = apw_First+68;  {To terminal - set new colors}
  apw_TermToggleScroll   = apw_First+69;  {To terminal - toggle scrollback}
  apw_TermCapture        = apw_First+70;  {To terminal - set capture mode}
  apw_TermStuff          = apw_First+71;  {To terminal - stuff data}
  apw_TermPaint          = apw_First+72;  {To terminal - update screen}
  apw_TermSetWndProc     = apw_First+73;  {To terminal - set window proc}
  apw_TermColorsH        = apw_First+74;  {To terminal - set highlight colors}
  apw_TermSave           = apw_First+75;  {To terminal - save/restore}
  apw_TermColorMap       = apw_First+76;  {To terminal - get/set color map}
  apw_TermForceSize      = apw_First+77;  {To terminal - force new size}
  apw_TermFontSize       = apw_First+78;  {To terminal - get font size}

const
  apw_TermStatus         = apw_First+80;  {From terminal - show status}
  apw_TermBPlusStart     = apw_First+81;  {From terminal - B+ is starting}
  apw_TermError          = apw_First+82;  {From terminal - error}
  apw_CursorPosReport    = apw_First+83;  {From terminal - Cursor Pos Report}

const
  apw_FaxCvtStatus       = apw_First+90;  {From fax converter - show status}
  apw_FaxUnpStatus       = apw_First+91;  {From fax unpacker - show status}
  apw_FaxOutput          = apw_First+92;  {From fax unpacker - output line}

const
  apw_ViewSetFile        = apw_First+100; {To fax viewer - change file name}
  apw_ViewSetFG          = apw_First+101; {To fax viewer - set foreground color}
  apw_ViewSetBG          = apw_First+102; {To fax viewer - set background color}
  apw_ViewSetScale       = apw_First+103; {To fax viewer - set scale factors}
  apw_ViewSetScroll      = apw_First+104; {To fax viewer - set scroll increments}
  apw_ViewSelectAll      = apw_First+105; {To fax viewer - select entire image}
  apw_ViewSelect         = apw_First+106; {To fax viewer - select image rect}
  apw_ViewCopy           = apw_First+107; {To fax viewer - copy data to cboard}
  apw_ViewSetWndProc     = apw_First+108; {To fax viewer - set window procedure}
  apw_ViewSetWhitespace  = apw_First+109; {To fax viewer - set whitespace comp}
  apw_ViewGetBitmap      = apw_First+110; {To fax viewer - get memory bmp}
  apw_ViewGetNumPages    = apw_First+111; {To fax viewer - get num pages}
  apw_ViewStartUpdate    = apw_First+112; {To fax viewer - start scale update}
  apw_ViewEndUpdate      = apw_First+113; {To fax viewer - end scale upate}
  apw_ViewGotoPage       = apw_First+114; {To fax viewer - go to a page}
  apw_ViewGetCurPage     = apw_First+115; {To fax viewer - get current page #}
  apw_ViewSetDesignMode  = apw_First+116; {To fax viewer - indicate in design}
  apw_ViewSetRotation    = apw_First+117; {To fax viewer - set rotation}
  apw_ViewSetAutoScale   = apw_First+118; {To fax viewer - auto scaling}
  apw_ViewNotifyPage     = apw_First+119; {To fax viewer - notify of page chg}
  apw_ViewGetPageDim     = apw_First+120; {To fax viewer - get pg dimensions}
  apw_ViewSetLoadWholeFax= apw_First+121; {To fax viewer - set load whole fax}
  apw_ViewSetBusyCursor  = apw_First+122; {To fax viewer - set cursor for busy}
  apw_ViewerError        = apw_First+123; {Fax viewer error report}
  apw_ViewGetPageFlags   = apw_First+124; {To fax viewer - get pg flags}
  apw_ViewGetFileName    = apw_First+125; {To fax viewer - get file name}

const
  apw_TermBlinkTimeChange      = apw_First+130; {set new blink time}
  apw_TermPersistentMarkChange = apw_First+131; {set persistent blocks}
  apw_TermSetKeyEmuPtr         = apw_First+132; {set Key Emulator pointer }
  apw_TermSetKeyEmuProc        = apw_First+133; {set Key Emulator proc }
  apw_TermSetHalfDuplex        = apw_First+134; {set Duplex mode}
  apw_TermGetBuffPtr           = apw_First+135; {get a pointer to term buffer}
  apw_TermGetClientLine        = apw_First+136; {get the first client line in buffer}

const
  apw_PrintDriverJobCreated    = apw_First+140; {printer driver created fax job}
  apw_BeginDoc                 = apw_First+141; {printer driver starts printing}
  apw_EndDoc                   = apw_First+142; {printer driver has finished printing}
  apw_AddPrim                  = apw_First+143; {internal FaxSrvx sample message}

const
  apw_FaxCancel          = apw_First+160; {To fax - cancel the session}
  apw_FaxNextfile        = apw_First+161; {From fax - return next fax to send}
  apw_FaxStatus          = apw_First+162; {From fax - show the fax status}
  apw_FaxLog             = apw_First+163; {From fax - log the fax start/stop}
  apw_FaxName            = apw_First+164; {From fax - name the incoming fax}
  apw_FaxAccept          = apw_First+165; {From fax - accept this fax?}
  apw_FaxError           = apw_First+166; {From fax - session had error}
  apw_FaxFinish          = apw_First+167; {From fax - session finished}

const
  apw_TapiWaveMessage    = apw_First+180; {Tapi wave event message}

const
  {Window class names}
  DispatcherClassName      = 'awDispatch';
  ProtocolClassName        = 'awProtocol';
  TerminalClassName        = 'awTerminal';
  MessageHandlerClassName  = 'awMsgHandler';
  FaxViewerClassName       = 'awViewer';
  FaxViewerClassNameDesign = 'dcViewer';
  TerminalClassNameDesign  = 'dcTerminal';
  FaxHandlerClassName      = 'awFaxHandler';

const
  {Error groups}
  egDos                  =  -0;     {DOS, DOS critical and file I/O}
  egGeneral              =  -1;     {General errors}
  egOpenComm             =  -2;     {OpenComm errors}
  egSerialIO             =  -3;     {Errors during serial I/O processing}
  egModem                =  -4;     {Errors during modem processing}
  egTrigger              =  -5;     {Error setting up triggers}
  egProtocol             =  -6;     {Errors that apply to one or more protocols}
  egINI                  =  -7;     {INI database errors}
  egFax                  =  -8;     {FAX errors}
  egAdWinsock            =   9;     {APro specific Winsock errors}
  egWinsock              =  10;     {Winsock errors}
  egWinsockEx            =  11;     {Additional Winsock errors}
  egTapi                 = -13;     {TAPI errors}

const
  { Below are all error codes used by APRO -- resource IDs are Abs(ErrorCode) }
  { The corresponding strings can be found in APW.STR.  If you are adding     }
  { strings, it's best to go there first to 'stake a claim' on an appropriate }
  { range of IDs -- since constants for some status strings are found in the  }
  { applicable component's unit instead of here...                            }

  {No error}
  ecOK                     = 0;         {Okay}

const
  {egDOS}
  ecFileNotFound           = -2;       {File not found}
  ecPathNotFound           = -3;       {Path not found}
  ecTooManyFiles           = -4;       {Too many open files}
  ecAccessDenied           = -5;       {File access denied}
  ecInvalidHandle          = -6;       {Invalid file handle}
  ecOutOfMemory            = -8;       {Insufficient memory}
  ecInvalidDrive           = -15;      {Invalid drive}
  ecNoMoreFiles            = -18;      {No more files}
  ecDiskRead               = -100;     {Attempt to read beyond end of file}
  ecDiskFull               = -101;     {Disk is full}
  ecNotAssigned            = -102;     {File not Assign-ed}
  ecNotOpen                = -103;     {File not open}
  ecNotOpenInput           = -104;     {File not open for input}
  ecNotOpenOutput          = -105;     {File not open for output}
  ecWriteProtected         = -150;     {Disk is write-protected}
  ecUnknownUnit            = -151;     {Unknown disk unit}
  ecDriveNotReady          = -152;     {Drive is not ready}
  ecUnknownCommand         = -153;     {Unknown command}
  ecCrcError               = -154;     {Data error}
  ecBadStructLen           = -155;     {Bad request structure length}
  ecSeekError              = -156;     {Seek error}
  ecUnknownMedia           = -157;     {Unknown media type}
  ecSectorNotFound         = -158;     {Disk sector not found}
  ecOutOfPaper             = -159;     {Printer is out of paper}
  ecDeviceWrite            = -160;     {Device write error}
  ecDeviceRead             = -161;     {Device read error}
  ecHardwareFailure        = -162;     {General failure}

const
  {egGeneral}
  ecBadHandle              = -1001;    {Bad handle passed to com function}
  ecBadArgument            = -1002;    {Bad argument passed to function}
  ecGotQuitMsg             = -1003;    {Yielding routine got WM_QUIT message}
  ecBufferTooBig           = -1004;    {Terminal buffer size too big}
  ecPortNotAssigned        = -1005;    {ComPort component not assigned}
  ecInternal               = -1006;    {Internal INIDB errors}
  ecModemNotAssigned       = -1007;    {Modem component not assigned}
  ecPhonebookNotAssigned   = -1008;    {Phonebook component not assgnd}
  ecCannotUseWithWinSock   = -1009;    {Component not compatible with WinSock}

const
  {egOpenComm}
  ecBadId                  = -2001;    {ie_BadId - bad or unsupported ID}
  ecBaudRate               = -2002;    {ie_Baudrate - unsupported baud rate}
  ecByteSize               = -2003;    {ie_Bytesize - invalid byte size}
  ecDefault                = -2004;    {ie_Default - error in default parameters}
  ecHardware               = -2005;    {ie_Hardware - hardware not present}
  ecMemory                 = -2006;    {ie_Memory - unable to allocate queues}
  ecCommNotOpen            = -2007;    {ie_NOpen - device not open}
  ecAlreadyOpen            = -2008;    {ie_Open - device already open}
  ecNoHandles              = -2009;    {No more handles, can't open port}
  ecNoTimers               = -2010;    {No timers available}
  ecNoPortSelected         = -2011;    {No port selected (attempt to open com0)}
  ecNotOpenedByTapi        = -2012;    {Comport was not opened by Tapi}

const
  {egSerialIO}
  ecNullApi                = -3001;    {No device layer specified}
  ecNotSupported           = -3002;    {Function not supported by driver}
  ecRegisterHandlerFailed  = -3003;    {EnableCommNotification failed}
  ecPutBlockFail           = -3004;    {Failed to put entire block}
  ecGetBlockFail           = -3005;    {Failed to get entire block}
  ecOutputBufferTooSmall   = -3006;    {Output buffer too small for block}
  ecBufferIsEmpty          = -3007;    {Buffer is empty}
  ecTracingNotEnabled      = -3008;    {Tracing not enabled}
  ecLoggingNotEnabled      = -3009;    {Logging not enabled}
  ecBaseAddressNotSet      = -3010;    {Base addr not found, RS485 mode}

const
  {Modem}
  ecModemNotStarted        = -4001;    {StartModem has not been called}
  ecModemBusy              = -4002;    {Modem is busy elsewhere}
  ecModemNotDialing        = -4003;    {Modem is not currently dialing}
  ecNotDialing             = -4004;    {TModemDialer is not dialing}
  ecAlreadyDialing         = -4005;    {TModemdialer is already dialing}
  ecModemNotResponding     = -4006;    {No response from modem}
  ecModemRejectedCommand   = -4007;    {Bad command sent to modem}
  ecModemStatusMismatch    = -4008;    {Wrong modem status requested}

  { Protocols }
  { If strings are added -- apStatusMsg needs to be changed in AWABSPCL.PAS }

const
  psOK                 = 4700;   {Protocol is ok}
  psProtocolHandshake  = 4701;   {Protocol handshaking in progress}
  psInvalidDate        = 4702;   {Bad date/time stamp received and ignored}
  psFileRejected       = 4703;   {Incoming file was rejected}
  psFileRenamed        = 4704;   {Incoming file was renamed}
  psSkipFile           = 4705;   {Incoming file was skipped}
  psFileDoesntExist    = 4706;   {Incoming file doesn't exist locally, skipped}
  psCantWriteFile      = 4707;   {Incoming file skipped due to Zmodem options}
  psTimeout            = 4708;   {Timed out waiting for something}
  psBlockCheckError    = 4709;   {Bad checksum or CRC}
  psLongPacket         = 4710;   {Block too long}
  psDuplicateBlock     = 4711;   {Duplicate block received and ignored}
  psProtocolError      = 4712;   {Error in protocol}
  psCancelRequested    = 4713;   {Cancel requested}
  psEndFile            = 4714;   {At end of file}
  psResumeBad          = 4715;   {B+ host refused resume request}
  psSequenceError      = 4716;   {Block was out of sequence}
  psAbortNoCarrier     = 4717;   {Aborting on carrier loss}

const
  {Specific to certain protocols}
  psGotCrcE            = 4718;   {Got CrcE packet (Zmodem)}
  psGotCrcG            = 4719;   {Got CrcG packet (Zmodem)}
  psGotCrcW            = 4720;   {Got CrcW packet (Zmodem)}
  psGotCrcQ            = 4721;   {Got CrcQ packet (Zmodem)}
  psTryResume          = 4722;   {B+ is trying to resume a download}
  psHostResume         = 4723;   {B+ host is resuming}
  psWaitAck            = 4724;   {Waiting for B+ ack (internal)}

const
  {Internal}
  psNoHeader           = 4725;   {Protocol is waiting for header (internal)}
  psGotHeader          = 4726;   {Protocol has header (internal)}
  psGotData            = 4727;   {Protocol has data packet (internal)}
  psNoData             = 4728;   {Protocol doesn't have data packet yet (internal)}

  { Constants for fax strings }
  { If strings are added -- afStatusMsg needs to be changed in AWABSFAX.PAS }

const
  {Fax progress codes, sending}
  fpInitModem          = 4801;   {Initializing modem for fax processing}
  fpDialing            = 4802;   {Dialing}
  fpBusyWait           = 4803;   {Busy, FaxTransmit is waiting}
  fpSendPage           = 4804;   {Sending document page data}
  fpSendPageStatus     = 4805;   {Send EOP}
  fpPageError          = 4806;   {Error sending page}
  fpPageOK             = 4807;   {Page accepted by remote}
  fpConnecting         = 4808;   {Send call handoff connecting}

const
  {Fax progress codes, receiving}
  fpWaiting            = 4820;   {Waiting for incoming call}
  fpNoConnect          = 4821;   {No connect on this call}
  fpAnswer             = 4822;   {Answering incoming call}
  fpIncoming           = 4823;   {Incoming call validated as fax}
  fpGetPage            = 4824;   {Getting page data}
  fpGetPageResult      = 4825;   {Getting end-of-page signal}
  fpCheckMorePages     = 4826;   {getting end-of-document status}
  fpGetHangup          = 4827;   {Get hangup command}
  fpGotHangup          = 4828;   {Got Class 2 FHNG code}

const
  {Fax progress codes, common}
  fpSessionParams      = 4840;   {Getting connection params}
  fpGotRemoteID        = 4841;   {got called-station ID}
  fpCancel             = 4842;   {User abort}
  fpFinished           = 4843;   {Finished with this fax}

const
  {Trigger errors}
  ecNoMoreTriggers         = -5001;    {No more trigger slots}
  ecTriggerTooLong         = -5002;    {Data trigger too long}
  ecBadTriggerHandle       = -5003;    {Bad trigger handle}

const
  {Packet errors}
  ecStartStringEmpty       = -5501;    {Start string is empty}
  ecPacketTooSmall         = -5502;    {Packet size cannot be smaller than start string}
  ecNoEndCharCount         = -5503;    {CharCount packets must have an end-condition}
  ecEmptyEndString         = -5504;    {End string is empty}
  ecZeroSizePacket         = -5505;    {Packet size cannot be zero}
  ecPacketTooLong          = -5506;    {Packet too long}

const
  {Protocol errors}
  ecBadFileList            = -6001;    {Bad format in file list}
  ecNoSearchMask           = -6002;    {No search mask specified during transmit}
  ecNoMatchingFiles        = -6003;    {No files matched search mask}
  ecDirNotFound            = -6004;    {Directory in search mask doesn't exist}
  ecCancelRequested        = -6005;    {Cancel requested}
  ecTimeout                = -6006;    {Fatal time out}
  ecProtocolError          = -6007;    {Unrecoverable event during protocol}
  ecTooManyErrors          = -6008;    {Too many errors during protocol}
  ecSequenceError          = -6009;    {Block sequence error in Xmodem}
  ecNoFilename             = -6010;    {No filename specified in protocol receive}
  ecFileRejected           = -6011;    {File was rejected}
  ecCantWriteFile          = -6012;    {Cant write file}
  ecTableFull              = -6013;    {Kermit window table is full, fatal error}
  ecAbortNoCarrier         = -6014;    {Aborting due to carrier loss}
  ecBadProtocolFunction    = -6015;    {Function not support by protocol}

const
  {INI database}
  ecKeyTooLong             = -7001;    {Key string too long}
  ecDataTooLarge           = -7002;    {Data string too long}
  ecNoFieldsDefined        = -7003;    {No fields defined in database}
  ecIniWrite               = -7004;    {Generic INI file write error}
  ecIniRead                = -7005;    {Generic INI file read error}
  ecNoIndexKey             = -7006;    {No index defined for database}
  ecRecordExists           = -7007;    {Record already exists}
  ecRecordNotFound         = -7008;    {Record not found in database}
  ecMustHaveIdxVal         = -7009;    {Invalid index key name}
  ecDatabaseFull           = -7010;    {Maximum database records (999) reached}
  ecDatabaseEmpty          = -7011;    {No records in database}
  ecDatabaseNotPrepared    = -7012;    {iPrepareIniDatabase not called}
  ecBadFieldList           = -7013;    {Bad field list in INIDB}
  ecBadFieldForIndex       = -7014;    {Bad field for index in INIDB}

const
  ecFaxBadFormat           = -8001;    {File is not an APF file}
  ecBadGraphicsFormat      = -8002;    {Unsupported graphics file format}
  ecConvertAbort           = -8003;    {User aborted fax conversion}
  ecUnpackAbort            = -8004;    {User aborted fax unpack}
  ecCantMakeBitmap         = -8005;    {CreateBitmapIndirect API failure}
  ecNoImageLoaded          = -8050;    {no image loaded into viewer}
  ecNoImageBlockMarked     = -8051;    {no block of image marked}
  ecFontFileNotFound       = -8052;    {APFAX.FNT not found, or resource bad}
  ecInvalidPageNumber      = -8053;    {Invalid page number specified for fax}
  ecBmpTooBig              = -8054;    {BMP size exceeds Windows' maxheight of 32767}
  ecEnhFontTooBig          = -8055;    {Font selected for enh text converter too large}

const
  ecFaxBadMachine          = -8060;    {Fax incompatible with remote fax}
  ecFaxBadModemResult      = -8061;    {Bad response from modem}
  ecFaxTrainError          = -8062;    {Modems failed to train}
  ecFaxInitError           = -8063;    {Error while initializing modem}
  ecFaxBusy                = -8064;    {Called fax number was busy}
  ecFaxVoiceCall           = -8065;    {Called fax number answered with voice}
  ecFaxDataCall            = -8066;    {Incoming data call}
  ecFaxNoDialTone          = -8067;    {No dial tone}
  ecFaxNoCarrier           = -8068;    {Failed to connect to remote fax}
  ecFaxSessionError        = -8069;    {Fax failed in mid-session}
  ecFaxPageError           = -8070;    {Fax failed at page end}
  ecFaxGDIPrintError       = -8071;    {NextBand GDI error in fax print driver}
  ecFaxMixedResolution     = -8072;    {Multiple resolutions in one session}
  ecFaxConverterInitFail   = -8073;    {Initialization of fax converter failed}
  ecNoAnswer               = -8074;    {Remote fax did not answer}
  ecAlreadyMonitored       = -8075;    {MonitorDir already being used}

const
  ecUniAlreadyInstalled    = -8080;    {Unidrv support files already installed}
  ecUniCannotGetSysDir     = -8081;    {Cannot determine windows system dir}
  ecUniCannotGetWinDir     = -8082;    {Cannot determine windows dir}
  ecUniUnknownLayout       = -8083;    {Cannot determine setup file layout}
  ecUniCannotParseInfFile  = -8084;    {Cannot find Unidrv files in setup file}
  ecUniCannotInstallFile   = -8085;    {Cannot install Unidrv files to system dir}
  ecNotNTDriver            = -8086;    {Printer driver not NT compatible}
  ecDrvCopyError           = -8087;    {Error copying printer driver}
  ecCannotAddPrinter       = -8088;    {32-bit AddPrinter call failed}
  ecDrvBadResources        = -8089;    {Bad/missing resources in driver}
  ecDrvDriverNotFound      = -8090;    {Driver file not found}
  ecUniCannotGetPrinterDriverDir
                           = -8091;    {Cannot determine Win NT printer driver dir}
  ecInstallDriverFailed    = -8092;    {AddPrinterDriver API failed}

  { The string resource range 13500 - 13800 is used for TAPI }
  { status messages, which do not require constants here     }

const
  {Adjusted TAPI error codes}
  ecAllocated              = -13801;
  ecBadDeviceID            = -13802;
  ecBearerModeUnavail      = -13803;
  ecCallUnavail            = -13805;
  ecCompletionOverrun      = -13806;
  ecConferenceFull         = -13807;
  ecDialBilling            = -13808;
  ecDialDialtone           = -13809;
  ecDialPrompt             = -13810;
  ecDialQuiet              = -13811;
  ecIncompatibleApiVersion = -13812;
  ecIncompatibleExtVersion = -13813;
  ecIniFileCorrupt         = -13814;
  ecInUse                  = -13815;
  ecInvalAddress           = -13816;
  ecInvalAddressID         = -13817;
  ecInvalAddressMode       = -13818;
  ecInvalAddressState      = -13819;
  ecInvalAppHandle         = -13820;
  ecInvalAppName           = -13821;
  ecInvalBearerMode        = -13822;
  ecInvalCallComplMode     = -13823;
  ecInvalCallHandle        = -13824;
  ecInvalCallParams        = -13825;
  ecInvalCallPrivilege     = -13826;
  ecInvalCallSelect        = -13827;
  ecInvalCallState         = -13828;
  ecInvalCallStatelist     = -13829;
  ecInvalCard              = -13830;
  ecInvalCompletionID      = -13831;
  ecInvalConfCallHandle    = -13832;
  ecInvalConsultCallHandle = -13833;
  ecInvalCountryCode       = -13834;
  ecInvalDeviceClass       = -13835;
  ecInvalDeviceHandle      = -13836;
  ecInvalDialParams        = -13837;
  ecInvalDigitList         = -13838;
  ecInvalDigitMode         = -13839;
  ecInvalDigits            = -13840;
  ecInvalExtVersion        = -13841;
  ecInvalGroupID           = -13842;
  ecInvalLineHandle        = -13843;
  ecInvalLineState         = -13844;
  ecInvalLocation          = -13845;
  ecInvalMediaList         = -13846;
  ecInvalMediaMode         = -13847;
  ecInvalMessageID         = -13848;
  ecInvalParam             = -13850;
  ecInvalParkID            = -13851;
  ecInvalParkMode          = -13852;
  ecInvalPointer           = -13853;
  ecInvalPrivSelect        = -13854;
  ecInvalRate              = -13855;
  ecInvalRequestMode       = -13856;
  ecInvalTerminalID        = -13857;
  ecInvalTerminalMode      = -13858;
  ecInvalTimeout           = -13859;
  ecInvalTone              = -13860;
  ecInvalToneList          = -13861;
  ecInvalToneMode          = -13862;
  ecInvalTransferMode      = -13863;
  ecLineMapperFailed       = -13864;
  ecNoConference           = -13865;
  ecNoDevice               = -13866;
  ecNoDriver               = -13867;
  ecNoMem                  = -13868;
  ecNoRequest              = -13869;
  ecNotOwner               = -13870;
  ecNotRegistered          = -13871;
  ecOperationFailed        = -13872;
  ecOperationUnavail       = -13873;
  ecRateUnavail            = -13874;
  ecResourceUnavail        = -13875;
  ecRequestOverrun         = -13876;
  ecStructureTooSmall      = -13877;
  ecTargetNotFound         = -13878;
  ecTargetSelf             = -13879;
  ecUninitialized          = -13880;
  ecUserUserInfoTooBig     = -13881;
  ecReinit                 = -13882;
  ecAddressBlocked         = -13883;
  ecBillingRejected        = -13884;
  ecInvalFeature           = -13885;
  ecNoMultipleInstance     = -13886;

const
  {Apro encounters a few of its own TAPI errors, place these error
   codes after the native TAPI error codes, but leave a little bit
   of room for expansion of the TAPI error codes.}
  ecTapiBusy               = -13928;
  ecTapiNotSet             = -13929;
  ecTapiNoSelect           = -13930;
  ecTapiLoadFail           = -13931;
  ecTapiGetAddrFail        = -13932;
  ecTapi16Disabled         = -13933;
  ecTapiUnexpected         = -13934;
  ecTapiVoiceNotSupported  = -13935;
  ecTapiWaveFail           = -13936;
  ecTapiCIDBlocked         = -13937;
  ecTapiCIDOutOfArea       = -13938;
  ecTapiWaveFormatError    = -13939;
  ecTapiWaveReadError      = -13940;
  ecTapiWaveBadFormat      = -13941;
  ecTapiTranslateFail      = -13942;
  ecTapiWaveDeviceInUse    = -13943;
  ecTapiWaveFileExists     = -13944;
  ecTapiWaveNoData         = -13945;

  {RAS error codes}
  ecRasLoadFail            = -13980;

const
  {Convenient character constants (and aliases)}
  cNul = #0;
  cSoh = #1;
  cStx = #2;
  cEtx = #3;
  cEot = #4;
  cEnq = #5;
  cAck = #6;
  cBel = #7;
  cBS  = #8;
  cTab = #9;
  cLF  = #10;
  cVT  = #11;
  cFF  = #12;
  cCR  = #13;
  cSO  = #14;
  cSI  = #15;
  cDle = #16;
  cDC1 = #17;       cXon  = #17;
  cDC2 = #18;
  cDC3 = #19;       cXoff = #19;
  cDC4 = #20;
  cNak = #21;
  cSyn = #22;
  cEtb = #23;
  cCan = #24;
  cEM  = #25;
  cSub = #26;
  cEsc = #27;
  cFS  = #28;
  cGS  = #29;
  cRS  = #30;
  cUS  = #31;

type
  {Protocol status information record}
  TProtocolInfo = record
    piProtocolType     : Cardinal;
    piBlockErrors      : Cardinal;
    piTotalErrors      : Cardinal;
    piBlockSize        : Cardinal;
    piBlockNum         : Cardinal;
    piFileSize         : LongInt;
    piBytesTransferred : LongInt;
    piBytesRemaining   : LongInt;
    piInitFilePos      : LongInt;
    piElapsedTicks     : LongInt;
    piFlags            : LongInt;
    piBlockCheck       : Cardinal;
    piFileName         : TPathCharArray;
    piError            : Integer;
    piStatus           : Cardinal;
  end;

const
  {Port options}
  {$IFNDEF Win32}
  poUseMSRShadow   = $01;   {Use the MSR shadow register for modem status}
  {$ENDIF}
  poUseEventWord   = $04;   {Set to use the event word}

  {Hardware flow control options}
  hfUseDTR         = $01;   {Use DTR for receive flow control}
  hfUseRTS         = $02;   {Use RTS for receive flow control}
  hfRequireDSR     = $04;   {Require DSR before transmitting}
  hfRequireCTS     = $08;   {Require CTS before transmitting}

  {Software flow control options}
  sfTransmitFlow   = $01;   {Honor received Xon/Xoffs}
  sfReceiveFlow    = $02;   {Send Xon/Xoff as required}

  {$IFDEF Win32}
  {Define bits for TDCB Flags field}
  dcb_Binary                = $0001;
  dcb_Parity                = $0002;
  dcb_OutxCTSFlow           = $0004;
  dcb_OutxDSRFlow           = $0008;
  dcb_DTRBit1               = $0010;
  dcb_DTRBit2               = $0020;
  dcb_DsrSensitivity        = $0040;
  dcb_TxContinueOnXoff      = $0080;
  dcb_OutX                  = $0100;
  dcb_InX                   = $0200;
  dcb_ErrorChar             = $0400;
  dcb_Null                  = $0800;
  dcb_RTSBit1               = $1000;
  dcb_RTSBit2               = $2000;
  dcb_AbortOnError          = $4000;

  dcb_DTR_CONTROL_ENABLE    = dcb_DTRBit1;
  dcb_DTR_CONTROL_HANDSHAKE = dcb_DTRBit2;
  dcb_RTS_CONTROL_ENABLE    = dcb_RTSBit1;
  dcb_RTS_CONTROL_HANDSHAKE = dcb_RTSBit2;
  dcb_RTS_CONTROL_TOGGLE    = (dcb_RTSBit1 + dcb_RTSBit2);
  {$ENDIF}

  {For reporting flow states, note: no receive hardware flow status is provided}
  fsOff      = 1;  {No flow control is in use}
  fsOn       = 2;  {Flow control is but not transmit blocked}
  fsDsrHold  = 3;  {Flow control is on and transmit blocked by low DSR}
  fsCtsHold  = 4;  {Flow control is on and transmit blocked by low CTS}
  fsDcdHold  = 5;  {Flow control is on and transmit blocked by low DCD}
  fsXOutHold = 6;  {Flow control is on and transmit blocked by Xoff}
  fsXInHold  = 7;  {Flow control is on and receive blocked by Xoff}
  fsXBothHold= 8;  {Flow control is on and both are blocked by Xoff}

const
  {Emulator commands}
  eNone            = 0;       {No command, ignore this char}
  eChar            = 1;       {No command, process the char}
  eGotoXY          = 2; {X}   {Absolute goto cursor position call}
  eUp              = 3; {X}   {Cursor up}
  eDown            = 4; {X}   {Cursor down}
  eRight           = 5; {X}   {Cursor right}
  eLeft            = 6; {X}   {Cursor left}
  eClearBelow      = 7; {R}   {Clear screen below cursor}
  eClearAbove      = 8; {R}   {Clear screen above cursor}
  eClearScreen     = 9; {R}   {Clear entire screen}
  eClearEndofLine  = 10;{R}   {Clear from cursor to end of line}
  eClearStartOfLine= 11;{R}   {Clear from cursor to the start of line}
  eClearLine       = 12;{R}   {Clear entire line that cursor is on}
  eSetMode         = 13;{X}   {Set video mode}
  eSetBackground   = 14;      {Set background attribute}
  eSetForeground   = 15;      {Set foreground attribute}
  eSetAttribute    = 16;{X}   {Set video attribute (foreground and background)}
  eSaveCursorPos   = 17;      {Save cursor position}
  eRestoreCursorPos= 18;      {Restore cursor position}
  eDeviceStatusReport = 19;{X}{Report device status or cursor position}
  eString          = 20;      {Pascal style string}
  eHT              = 21;      {Horizontal Tab Character}
  eError           = 255;     {indicates a parser error}

  eAPC  { } = 30;      {Application programming command}
  eCBT  {X} = 31;      {Cursor backward tabulation}
  eCCH  { } = 32;      {Cancel character}
  eCHA  {X} = 33;      {Cursor horizontal absolute}
  eCHT  {X} = 34;      {Cursor horizontal tabulation}
  eCNL  {X} = 35;      {Cursor next line}
  eCPL  {X} = 36;      {Cursor preceding line}
  eCPR  {X} = 37;      {Cursor position report}
  eCRM  {.} = 38;      {Control representation mode}
  eCTC  {X} = 39;      {Cursor tabulation control}
  eCUB  {X} = eLeft;   {Cursor backward}
  eCUD  {X} = eDown;   {Cursor down}
  eCUF  {X} = eRight;  {Cursor forward}
  eCUP  {X} = eGotoXY; {Cursor position}
  eCUU  {X} = eUp;     {Cursor up}
  eCVT  {X} = 40;      {Cursor vertical tabulation}
  eDA   {X} = 41;      {Device attributes}
  eDAQ  { } = 42;      {Define area qualification}
  eDCH  {X} = 43;      {Delete character}
  eDCS  { } = 44;      {Device control string}
  eDL   {X} = 45;      {Delete line}
  eDMI  { } = 46;      {Disable manual input}
  eDSR  {X} = eDeviceStatusReport;{Device status report}
  eEA   { } = 47;      {Erase in area}
  eEBM  { } = 48;      {Editing boundry mode}
  eECH  {X} = 49;      {Erase character}
  eED   {X} = 50;      {Erase in Display}
  eEF   { } = 51;      {Erase in field}
  eEL   {X} = 52;      {Erase in line}
  eEMI  { } = 53;      {Enable manual input}
  eEPA  { } = 54;      {End of protected mode}
  eERM  { } = 55;      {Erasure mode}
  eESA  { } = 56;      {End of selected area}
  eFEAM { } = 57;      {Format effector action mode}
  eFETM { } = 58;      {Format effector transfer mode}
  eFNT  { } = 59;      {Font selection}
  eGATM { } = 60;      {Guarded area transfer mode}
  eGSM  { } = 61;      {Graphics size modification}
  eGSS  { } = 62;      {Graphics size selection}
  eHEM  { } = 63;      {Horizontal editing mode}
  eHPA  {X} = eCHA;    {Horizontal position absolute}
  eHPR  {X} = eCUF;    {Horizontal position relative}
  eHTJ  {X} = 64;      {Horizontal tab with justification}
  eHTS  {X} = 65;      {Horizontal tabulation set}
  eHVP  {X} = eCUP;    {Horizontal and vertical position}
  eICH  {X} = 66;      {Insert character}
  eIL   {X} = 67;      {Insert line}
  eIND  {X} = eCUD;    {Index}
  eINT  { } = 68;      {Interrupt}
  eIRM  {.} = 69;      {Inseration-Replacement mode}
  eJFY  { } = 70;      {Justify}
  eKAM  {.} = 71;      {Keyboard action mode}
  eLNM  {.} = 72;      {Line feed new line mode}
  eMATM { } = 73;      {Multiple area transfer mode}
  eMC   {.} = 74;      {Media copy}
  eMW   {.} = 75;      {Message waiting}
  eNEL  {X} = 76;      {Next line}
  eNP   {.} = 77;      {Next page}
  eOSC  { } = 78;      {Operating system command}
  ePLD  { } = 79;      {Partial line down}
  ePLU  { } = 80;      {Partial line up}
  ePM   { } = 81;      {Privacy message}
  ePP   {.} = 82;      {Preceding page}
  ePU1  { } = 83;      {Private use 1}
  ePU2  { } = 84;      {Private use 2}
  ePUM  { } = 85;      {Positioning unit mode}
  eQUAD { } = 86;      {Quad}
  eREP  { } = 87;      {Repeat}
  eRI   {X} = 88;      {Reverse index}
  eRIS  {.} = 89;      {Reset to initial state}
  eRM   {.} = 90;      {Reset mode}
  eSATM { } = 91;      {Selected area transfer mode}
  eSD   { } = 92;      {Scroll down}
  eSEM  { } = 93;      {selected editing extent mode}
  eSGR  {X} = eSetAttribute;{Select graphics rendition}
  eSL   { } = 94;      {Scroll left}
  eSM   {.} = eSetMode;{Set Mode}
  eSPA  { } = 95;      {Start of protected area}
  eSPI  { } = 96;      {Spacing increment}
  eSR   { } = 97;      {Scroll right}
  eSRM  { } = 98;      {Send-Receive mode}
  eSRTM { } = 99;      {Status report transfer mode}
  eSS2  { } = 100;     {Single shift 2}
  eSS3  { } = 101;     {Single shift 3}
  eSSA  { } = 102;     {Start of selected area}
  eST   { } = 103;     {String terminator}
  eSTS  { } = 104;     {Set transmit state}
  eSU   { } = 105;     {Scroll up}
  eTBC  {X} = 106;     {Tabulation clear}
  eTSM  { } = 107;     {Tabulation stop mode}
  eTSS  { } = 108;     {Thin space specification}
  eTTM  { } = 109;     {Transfer termination mode}
  eVEM  { } = 110;     {Vertical editing mode}
  eVPA  {X} = 111;     {Vertical position absolute}
  eVPR  {X} = eCUD;    {Vertical position relative}
  eVTS  {X} = 112;     {vertical tabulation set}
  eDECSTBM  = 113;     {dec private-set Top/Bottom margin}

                       {New for version 3.0}
  eENQ  {X} = 114;     {enquiry request}
  eBEL  {X} = 115;     {sound bell}
  eBS   {X} = 116;     {backspace}
  eLF   {X} = 117;     {line feed command}
  eCR   {X} = 118;     {carriage return}
  eSO   {X} = 119;     {invoke G1 charset}
  eSI   {X} = 120;     {invoke G0 charset}
  eIND2 {X} = 121;     {corrected eIND (<> eCUD, eDown) new term only}
  eDECALN   = 122;     {DEC PRIVATE-screen alignment display}
  eDECDHL   = 123;     {DEC PRIVATE-Double height line}
  eDECDWL   = 124;     {DEC PRIVATE-Double width line}
  eDECLL    = 125;     {DEC PRIVATE-load LEDs}
  eDECREQTPARM = 126;  {DEC PRIVATE-request terminal parameters}
  eDECSWL   = 127;     {DEC PRIVATE-single width line}
  eDECTST   = 128;     {DEC PRIVATE-Invoke confidence test}
  eDECSCS   = 129;     {DEC PRIVATE-select charset}

  {Extended attributes}
  eattrBlink      = $01;
  eattrInverse    = $02;
  eattrIntense    = $04;
  eattrInvisible  = $08;
  eattrUnderline  = $10;

  {ANSI color constants}
  emBlack       = 0;
  emRed         = 1;
  emGreen       = 2;
  emYellow      = 3;
  emBlue        = 4;
  emMagenta     = 5;
  emCyan        = 6;
  emWhite       = 7;
  emBlackBold   = 8;
  emRedBold     = 9;
  emGreenBold   = 10;
  emYellowBold  = 11;
  emBlueBold    = 12;
  emMagentaBold = 13;
  emCyanBold    = 14;
  emWhiteBold   = 15;

  {AnsiEmulator option flags}
  teMapVT100           = $0001;

  {Misc}
  MaxParams   = 5;       {Maximum parameters for our interpreter}
  MaxQueue    = 20;      {Maximum characters in queue}
  MaxOther    = 11;      {Maximum other data}
  MaxParamLength = 5;    {Maximum parameter length for interpreter}
  KeyMappingLen = 20;   {Maximum length of a keymapping}

type
  {AnsiEmulator's parser states}
  TAnsiParser = (GotNone, GotEscape, GotBracket, GotSemiColon, GotParam,
                 GotCommand, GotControlSeqIntro, GotLeftBrace, GotRightBrace,
                 GotSpace, GotQuestionMark, GotQuestionParam);

  {Array used for internal queue}
  TQueue = Array[1..MaxQueue] of Char;

  {Emulator for PC ANSI codes}
  PAnsiEmulator = ^TAnsiEmulator;
  TAnsiEmulator = record
    emuType        : Cardinal;       { Emulator Type }
    emuFlags       : Cardinal;
    emuFirst       : Bool;           {True if first time thru}
    emuAttr        : Byte;
    emuIndex       : Cardinal;       {Index into rcvd byte array}
    emuParamIndex  : Cardinal;       {Parameter index}
    emuQueue       : TQueue;         {Queue of recvd bytes}
    emuParamStr    : array[1..MaxParams] of string[MaxParamLength];
    emuParamInt    : array[1..MaxParams] of Integer;
    emuParserState : TAnsiParser;    {Current state}
    emuOther       : Pointer;
  end;

const
  {Terminal window Cardinal}
  gwl_Terminal = 0;

  {Terminal options}
  tws_WantTab        = $0001; {Process tabs internally}
  tws_IntHeight      = $0002; {Integral height}
  tws_IntWidth       = $0004; {Integral width}
  tws_AutoHScroll    = $0008; {Add/remove horiz scroll automatically}
  tws_AutoVScroll    = $0010; {Add/remove vert scroll automatically}

type
  {For general typecasting}
  LH = record
    L,H : Word;
  end;

const
  MaxDBRecs    = 999;         {Maximum number of database records}
  MaxNameLen   = 21;          {Maximum length of a profile string key}
  MaxIndexLen  = 31;          {Maximum length of an index string}
  NonValue     = '#';         {Value of DB fields SPECIFICALLY left blank}
  dbIndex      = 'Index';     {Item index section heading}
  dbDefaults   = 'Defaults';  {Default value section heading}
  dbNumEntries = '_Entries';  {Number of entries key name}
  dbBogus      = 'None';      {Bogus key name for creating sections}

type
  PIniDatabaseKey = ^TIniDatabaseKey;
  TIniDatabaseKey = record
    KeyName  : PChar;
    DataSize : Cardinal;
    StrType  : Bool;
    Index    : Bool;
    Next     : PIniDatabaseKey;
  end;

  PIniDatabase = ^TIniDatabase;
  TIniDatabase = record
    FName          : PChar;
    DictionaryHead : PIniDatabaseKey;
    DictionaryTail : PIniDatabaseKey;
    NumRecords     : Integer;
    RecordSize     : Cardinal;
    DefaultRecord  : Pointer;
    Prepared       : Bool;
  end;

const
  MaxTags      = 5;     {Maximum number of err corr or data comp tags}
  TagSepChar   = ',';   {Character that separates tags in a profile string}

const
  ModemNameLen = 31;    {Length of a modem name string}
  CmdLen       = 41;    {Maximum length of a modem command}
  RspLen       = 21;    {Maximum length of a modem response}
  TagLen       = 21;    {Maximum length of a tag string}
  TagProfLen   = 105;   {Maximum length of a tag profile string}
  BoolLen      = 5;     {Maximum length of a boolean string}
  BaudLen      = 7;     {Maximum length of a baud rate string}
  ConfigLen    = 255;   {Maximum length of a configuration string}

type
  {where these same variables are declared as Strings.}
  TModemNameZ     = array[0..ModemNameLen] of Char;
  TCmdStringZ     = array[0..CmdLen] of Char;
  TRspStringZ     = array[0..RspLen] of Char;
  TTagStringZ     = array[0..TagLen] of Char;
  TTagProfStringZ = array[0..TagProfLen] of Char;
  TConfigStringZ  = array[0..ConfigLen] of Char;
  TBoolStrZ       = array[0..BoolLen] of Char;
  TBaudStrZ       = array[0..BaudLen] of Char;

  TTagArrayZ = array[1..MaxTags] of TTagStringZ;

  PModemBaseData = ^TModemBaseData;
  TModemBaseData = record
    Name          : TModemNameZ;
    InitCmd       : TCmdStringZ;
    DialCmd       : TCmdStringZ;
    DialTerm      : TCmdStringZ;
    DialCancel    : TCmdStringZ;
    HangupCmd     : TCmdStringZ;
    ConfigCmd     : TConfigStringZ;
    AnswerCmd     : TCmdStringZ;
    OkMsg         : TRspStringZ;
    ConnectMsg    : TRspStringZ;
    BusyMsg       : TRspStringZ;
    VoiceMsg      : TRspStringZ;
    NoCarrierMsg  : TRspStringZ;
    NoDialToneMsg : TRspStringZ;
    ErrorMsg      : TRspStringZ;
    RingMsg       : TRspStringZ;
  end;

  PModemData = ^TModemData;
  TModemData = record
    Data        : TModemBaseData;
    NumErrors   : Cardinal;
    Errors      : TTagArrayZ;
    NumComps    : Cardinal;
    Compression : TTagArrayZ;
    LockDTE     : Bool;
    DefBaud     : LongInt;
  end;

  PModemXFer = ^TModemXFer;
  TModemXFer = record
    Data     : TModemBaseData;
    Errors   : TTagProfStringZ;
    Compress : TTagProfStringZ;
    LockDTE  : TBoolStrZ;
    DefBaud  : TBaudStrZ;
  end;

  PModemDatabase = ^TModemDatabase;
  TModemDatabase = record
    DB : PIniDatabase;
  end;


const
  {keyboard shift state masks}
  ksControl = $02;
  ksAlt     = $04;
  ksShift   = $08;

  {keyboard toggle state masks}
  tsCapital = $02;
  tsNumlock = $04;
  tsScroll  = $08;

  {keybard INI file constants}
  KeyMapNameLen  = 30;    {Length of a KeyMap name string}
  MaxKeyMaps     = 100;   {Maximum possible key mapping per type}

  KeyIndexName    = 'EMULATOR';
  KeyIndexMaxLen  = 120;

type
  TKeyMapName    = array[0..KeyMapNameLen] of Char;
  TKeyMapping    = array[0..KeyMappingLen] of char;
  TKeyMappingStr = string[KeyMappingLen];


  PKeyMapXFerRec = ^TKeyMapXFerRec;
  TKeyMapXFerRec = record
    Name : TKeyMapName;
    Keys : array[1..MaxKeyMaps] of TKeyMapping;
  end;

  PVKeyMapRec = ^TVKeyMapRec;
  TVKEyMapRec = record
    KeyCode   : Cardinal;
    ShiftState: Cardinal;
    Mapping   : TKeyMappingStr;
  end;

  PKeyEmulator = ^TKeyEmulator;
  TKeyEmulator = record
    kbKeyFileName : PChar;                            { current file name }
    kbKeyName     : TKeyMapName;                      { current key index name }
    kbProcessAll  : Bool;
    kbProcessExt  : Bool;
    kbKeyNameList : array[0..KeyIndexMaxLen] of char;
    kbKeyMap      : array[1..MaxKeyMaps] of TVKeyMapRec;
    kbKeyDataBase : PIniDataBase;          { pointer to the INI data base file }
  end;

const
  {---- Option codes for protocols ----}
  apIncludeDirectory   = $0001;   {Set to include directory in file names}
  apHonorDirectory     = $0002;   {Set to honor directory in file names}
  apRTSLowForWrite     = $0004;   {Set to lower RTS during disk writes}
  apAbortNoCarrier     = $0008;   {Set to abort protocol on DCD loss}
  apKermitLongPackets  = $0010;   {Set to support long packets}
  apKermitSWC          = $0020;   {Set to support SWC}
  apZmodem8K           = $0040;   {Set to support 8K blocks}
  apBP2KTransmit       = $0080;   {Set to support 2K transmit blocks}
  apAsciiSuppressCtrlZ = $0100;   {Set to stop transmitting on ^Z}

  {---- Default options for protocols ----}
  DefProtocolOptions = 0;
  BadProtocolOptions = apKermitLongPackets+apKermitSWC+apZmodem8K;

  {Block check codes}
  bcNone      = 0;        {No block checking}
  bcChecksum1 = 1;        {Basic checksum}
  bcChecksum2 = 2;        {Two byte checksum}
  bcCrc16     = 3;        {16 bit Crc}
  bcCrc32     = 4;        {32 bit Crc}
  bcCrcK      = 5;        {Kermit style Crc}

  {Convenient blockcheck string constants}
  bcsNone      = 'No check';
  bcsChecksum1 = 'Checksum';
  bcsChecksum2 = 'Checksum2';
  bcsCrc16     = 'Crc16';
  bcsCrc32     = 'Crc32';
  bcsCrck      = 'CrcKermit';

  {Constants for supported protocol types}
  NoProtocol  = 0;
  Xmodem      = 1;
  XmodemCRC   = 2;
  Xmodem1K    = 3;
  Xmodem1KG   = 4;
  Ymodem      = 5;
  YmodemG     = 6;
  Zmodem      = 7;
  Zmodem8K    = 8;
  Kermit      = 9;
  Ascii       = 10;
  BPlus       = 11;

  {Zmodem attention string length}
  MaxAttentionLen = 32;

  {Zmodem file management options}
  zfWriteNewerLonger = 1;          {Transfer if new, newer or longer}
  zfWriteCrc         = 2;          {Not supported, same as WriteNewer}
  zfWriteAppend      = 3;          {Transfer if new, append if exists}
  zfWriteClobber     = 4;          {Transfer regardless}
  zfWriteNewer       = 5;          {Transfer if new or newer}
  zfWriteDifferent   = 6;          {Transfer if new or diff dates/lens}
  zfWriteProtect     = 7;          {Transfer only if new}

  {Convenient protocol string constants}
  ProtocolString : array[NoProtocol..BPlus] of array[0..9] of Char= (
    'None', 'Xmodem', 'XmodemCRC', 'Xmodem1K', 'Xmodem1KG',
    'Ymodem', 'YmodemG', 'Zmodem', 'Zmodem8K', 'Kermit', 'Ascii', 'B+');

type
  {For holding lists of files to transmit}
  PFileList = ^TFileList;
  TFileList = array[0..65535-1] of Char;

{Fax conversion}

const
  rw1728 = 1;                     {standard width}
  rw2048 = 2;                     {extra wide}

  {Fax pixel widths}
  StandardWidth  = 1728;          {Standard width in pixels}
  WideWidth      = 2048;          {Allowed higher resolution}

  {Option flags for FAX page header}
  ffHighRes     = $0001;          {Image stored in high-res mode}
  ffHighWidth   = $0002;          {Image uses option high-width mode}
  ffLengthWords = $0004;          {Set if raster lines include length Cardinal}

  {Options for fax conversion}
  fcDoubleWidth = $0001;          {Double the horizontal width in std res}
  fcHalfHeight  = $0002;          {Halve the vertical height in std res}
  fcCenterImage = $0004;          {Center graphics images horizontally}
  fcYield       = $0008;          {Have the converter yield while converting}
  fcYieldOften  = $0010;          {Increases the number of yields}

  {Flags passed to status function}
  csStarting    = $0001;
  csEnding      = $0002;

  {Font handles, same value as bytes-per-char}
  SmallFont    = 16;
  StandardFont = 48;

  {Maximum number of tree records}
  MaxTreeRec = 306;

  {Max size of decompress buffer}
  MaxData = 4096;

  {Text conversion limits}
  MaxLineLen = 144;

  {encoding/decoding table limits}
  MaxCodeTable   = 63;
  MaxMUCodeTable = 39;

  {default extensions}
  DefTextExt = 'TXT';
  DefTiffExt = 'TIF';
  DefPcxExt  = 'PCX';
  DefDcxExt  = 'DCX';
  DefBmpExt  = 'BMP';
  DefApfExt  = 'APF';

type
  {Compression code tables}
  TCodeRec = record
    Code : Word;
    Sig  : Word;
  end;

  TTermCodeArray   = array[0..MaxCodeTable] of TCodeRec;
  TMakeUpCodeArray = array[0..MaxMUCodeTable] of TCodeRec;

  {generic byte array}
  {$IFNDEF Win32}
  PByteArray = ^TByteArray;
  TByteArray = array[0..$FFF0] of Byte;
  {$ENDIF}

  PBufferedOutputFile = ^TBufferedOutputFile;
  TBufferedOutputFile = record
    BufPos  : Word;
    Buffer  : PByteArray;
    OutFile : File;
  end;

  {For storing station IDs}
  Str20 = String[20];

  {Stores information about our fonts}
  TFontRecord = record
    Bytes  : Byte;  {# of bytes per char in font}
    PWidth : Byte;  {width of font in pixels}
    Width  : Byte;  {width of font in bytes (e.g. 16-pixel-wide = 2)}
    Height : Byte;  {height of font in raster lines}
  end;

  {Fax file signature array}
  TSigArray = Array[0..5] of Char;

const
  {Default fax file signature}
  DefAPFSig : TSigArray = 'APF10'#26;

type
  {APRO fax file header record}
  TFaxHeaderRec = packed record
    Signature  : TSigArray;              {APRO FAX signature}
    FDateTime  : LongInt;                {Date and time in DOS format}
    SenderID   : Str20;                  {Station ID of sender}
    Filler     : Byte;                   {Alignment byte, unused}
    PageCount  : Word;                   {Number of pages in this file}
    PageOfs    : LongInt;                {Offset in file of first page}
    Padding    : Array[39..64] of Byte;  {Expansion room}
  end;

  {APRO fax page header record}
  TPageHeaderRec = packed record
    ImgLength : LongInt;                 {Bytes of image data in this page}
    ImgFlags  : Word;                    {Image flags for width, res, etc}
    Padding   : Array[7..16] of Byte;    {Expansion room}
  end;

  {APRO fax server job header}
  TFaxJobHeaderRec = packed record
    ID       : LongInt;          {APRO fax job signature}
    Status   : Byte;             {0=none sent, 1=some sent, 2=all sent, 3=paused}
    JobName  : Str20;            {Friendly name of fax job}
    Sender   : String[40];       {Name of sender (same as HeaderSender)}
    SchedDT  : TDateTime;        {TDateTime the first job should be sent}
    NumJobs  : Byte;             {Number of FaxJobInfoRecs for this job}
    NextJob  : Byte;             {The index of the next FaxJobInfo to send}
    CoverOfs : LongInt;          {Offset in file of text CoverFile data}
    FaxHdrOfs: LongInt;          {Offset in file of TFaxHeaderRec}
    Padding  : Array[86..128] of Byte; {Expansion room}
  end;

  {APRO fax server job recipient record }
  TFaxRecipientRec = packed record
    Status         : Byte;             {0=not sent, 1=sending, 2=sent, 3=paused}
    JobID          : Byte;             {Unique ID for this job}
    SchedDT        : TDateTime;        {TDateTime this job should be sent}
    AttemptNum     : Byte;             {Retry number for this recipient}
    LastResult     : Word;             {Last ErrorCode for this fax}
    PhoneNumber    : String[50];       {Phone number to dial for this job}
    HeaderLine     : String[100];      {Header line}
    HeaderRecipient: String[30];       {Recipient's name}
    HeaderTitle    : String[30];       {Title of fax}
    Padding        : Array[228..256] of Byte;{Expansion room}
  end;

  {Pcx header}
  TPcxPalArray  = Array[0..47] of Byte;
  TPcxHeaderRec = packed record
    Mfgr      : Byte;
    Ver       : Byte;
    Encoding  : Byte;
    BitsPixel : Byte;
    XMin      : Word;
    YMin      : Word;
    XMax      : Word;
    YMax      : Word;
    HRes      : Word;
    VRes      : Word;
    Palette   : TPcxPalArray;
    Reserved  : Byte;
    Planes    : Byte;
    BytesLine : Word;
    PalType   : Word;
    Filler    : Array[1..58] of Byte;  {pad to 128 bytes}
  end;

  TDcxOfsArray = array[1..1024] of LongInt;

  PDcxHeaderRec = ^TDcxHeaderRec;
  TDcxHeaderRec = packed record
    ID      : LongInt;
    Offsets : TDcxOfsArray;
  end;

  TTreeRec = record
    Next0 : Integer;
    Next1 : Integer;
  end;
  TTreeArray = array[0..MaxTreeRec] of TTreeRec;
  PTreeArray = ^TTreeArray;

  {$IFNDEF DrvInst}
  PAbsFaxCvt = ^TAbsFaxCvt;

  {callback function to open a converter input file}
  TOpenFileCallback = function(Cvt : PAbsFaxCvt; FileName : PChar) : Integer;

  {callback function to close a converter input file}
  TCloseFileCallback = procedure(Cvt : PAbsFaxCvt);

  {callback function converters use to get input raster}
  TGetLineCallback = function(Cvt : PAbsFaxCvt; var Data; var Len : Integer;
                              var EndOfPage, MorePages : Bool) : Integer;

  {callback function converters use to output data}
  TPutLineCallback = function(Cvt : PAbsFaxCvt; var Data; Len : Integer;
                              EndOfPage, MorePages : Bool) : Integer;


  {callback function for status information}
  TCvtStatusCallback = function(Cvt : PAbsFaxCvt; StatFlags : Word;
                                BytesRead, BytesToRead : LongInt) : Bool;

  {base converter data}
  TAbsFaxCvt = record
    UseHighRes  : Bool;               {TRUE if for high-res mode}
    DoubleWidth : Bool;               {TRUE do double each pixel}
    HalfHeight  : Bool;               {TRUE to discard each raster line}
    Flags       : Cardinal;           {Options flags}
    ByteOfs     : Cardinal;           {Byte offset in buffer}
    BitOfs      : Cardinal;           {Bit offset in buffer}
    ResWidth    : Cardinal;           {Width of current resolution in pels}
    LeftMargin  : Cardinal;           {Left margin in pels}
    TopMargin   : Cardinal;           {Top margin in pels}
    CurrPage    : Cardinal;           {Current page being processed}
    CurrLine    : Cardinal;           {Number of text/raster lines cvted}
    LastPage    : Cardinal;           {Last page number used in file cvt}
    CurPagePos  : LongInt;            {file offset of current page}
    CenterOfs   : Cardinal;           {Offset of center of bitmap}
    UserData    : Pointer;            {Data needed by higher level cvters}
    OtherData   : Pointer;            {Other, miscellaneous data}
    BytesRead   : LongInt;
    BytesToRead : LongInt;
    DataLine    : PByteArray;         {Buffered line of compressed data}
    TmpBuffer   : PByteArray;         {Temp compression buffer}
    GetLine     : TGetLineCallback;   {Callback function to get a raster line}
    OpenCall    : TOpenFileCallback;  {To open the input file, if any}
    CloseCall   : TCloseFileCallback; {To close the input file, if any}
    StatusFunc  : TCvtStatusCallback; {Callback for status display}
    StatusWnd   : HWnd;               {Handle of window receiving status msgs}
    DefExt      : array[0..3] of Char;
    InFileName  : array[0..255] of Char;
    OutFileName : array[0..255] of Char;
    StationID   : array[0..20] of Char;
    MainHeader  : TFaxHeaderRec;      {main header of fax output file}
    PageHeader  : TPageHeaderRec;     {header for current output page}
    OutFile     : PBufferedOutputFile;{Output file}
    {$IFNDEF PrnDrv}
    InBitmap    : Graphics.TBitmap;
    {$ENDIF}
  end;

  {$IFNDEF PrnDrv}

const
  LineBufferSize = 4096;
type
  TLineReader = class
    protected
      Buffer : array[0..LineBufferSize] of char;
      fEOLF : Boolean;
      ReadPtr : PChar;
      fStream : TStream;
      fBytesRead : LongInt;
      fFileSize : LongInt;
      procedure ReadPage;
    public
      property BytesRead : LongInt read fBytesRead;
      constructor Create(Stream : TStream);
      destructor Destroy; override;
      property EOLF : Boolean read fEOLF;
      property FileSize : LongInt read fFileSize;
      function NextLine : string;
  end;

type
  TAdStr = class
  private
    FMaxLen: Integer;
    FLen: Integer;
    FString: PChar;
    FCur: PChar;

  protected
    procedure SetLen(NewLen: Integer);
    function GetLen: Integer;

    procedure SetMaxLen(NewMaxLen: Integer);
    function GetMaxLen: Integer;

    function GetBuffLen: Integer;

    procedure SetChar(Index: Cardinal; Value: Char);
    function GetChar(Index: Cardinal): Char;

    function GetCurChar: Char;

  public
    constructor Create(AMaxLen: Cardinal);
    destructor Destroy; override;
    procedure Assign(Source: TAdStr);

    property Len: Integer
      read GetLen write SetLen;
    property MaxLen: Integer
      read GetMaxLen write SetMaxLen;
    property BuffLen: Integer
      read GetBuffLen;
    property Chars[Index: Cardinal]: Char
      read GetChar write SetChar; default;
    property CurChar: Char
      read GetCurChar;
    property Str: PChar
      read FString;
    property Cur: PChar
      read FCur;

    procedure First;
    procedure GotoPos(Index: Cardinal);
    procedure Last;
    procedure MoveBy(IndexBy: LongInt);
    procedure Next;
    procedure Prev;

    procedure Append(const Text: string);
    procedure AppendTAdStr(TS: TAdStr);
    procedure AppendBuff(Buff: PChar);
    procedure Clear;
    function Copy(Index, SegLen: Integer): string;
    procedure Delete(Index, SegLen: Integer);
    procedure Insert(const Text: string; Index: Integer);
    function Pos(const SubStr: string): Cardinal;
    function PosIdx(const SubStr: string; Index: Integer): Cardinal;
    procedure Prepend(const Text: string);
    procedure Resize(NewLen: Integer);
  end;

  TAdStrCur = class
  private
  public
  end;

  {text converter data}
  PTextFaxData = ^TTextFaxData;
  TTextFaxData = record
    IsExtended : Boolean;                      {Using extended text option?}
    ReadBuffer : PByteArray;                   {Input buffer}
    TabStop    : Cardinal;                     {Number of spaces per tab character}
    LineCount  : Cardinal;                     {Number of text lines between page}
    InFile     : TLineReader;                  {Input file}
    OnLine     : DWORD;                        {Number of current input line}
    CurRow     : Cardinal;                     {Current raster row of CurStr}
    CurStr       : array[0..255] of char;
    Pending      : string;
    FFPending  : Boolean;                      {TRUE if formfeed pending}
    FontRec    : TFontRecord;                  {Holds current font info}
    case Integer of
      0: (FontLoaded : Bool;                   {False until font loaded}
          FontPtr    : PByteArray);            {Pointer to the loaded font table}
      1: (Bitmap     : Graphics.TBitmap;       {Memory bitmap for rendering text}
          LineBytes  : Cardinal;               {Bytes per raster line}
          Offset     : Cardinal;               {Current offset in the bitmap}
          ImageSize  : LongInt;                {Size of image structure}
          ImageData  : Pointer);               {Image data}
  end;
  {$ENDIF}

  {TIFF strip information}
  PStripRecord = ^TStripRecord;
  TStripRecord = packed record
    Offset : LongInt;
    Length : LongInt;
  end;

  PStripInfo = ^TStripInfo;
  TStripInfo = array[1..(65521 div SizeOf(TStripRecord))] of TStripRecord;

  {TIFF converter data}
  PTiffFaxData = ^TTiffFaxData;
  TTiffFaxData = record
    Intel       : Bool;                {TRUE if file is in Intel byte order}
    LastBitMask : Word;                {Last decode bit mask}
    CurrRBSize  : Cardinal;            {Amount of data in read buffer}
    CurrRBOfs   : Cardinal;            {Current offset in ReadBuffer}
    OnStrip     : Cardinal;            {Current strip being processed}
    OnRaster    : Cardinal;            {Current raster line being processed}
    Version     : Word;                {Version number from file preable}
    SubFile     : Word;                {TIFF tag field values for image:}
    ImgWidth    : Word;                {image width}
    ImgLen      : Word;                {length of image}
    ImgBytes    : Word;                {bytes per raster line}
    NumLines    : Word;                {image length (height)}
    CompMethod  : Word;                {compression type}
    PhotoMet    : Word;                {photometric conversion type}
    RowStrip    : DWORD;               {raster lines per image strip}
    StripOfs    : LongInt;             {offset in file to first strip}
    StripCnt    : DWORD;               {number of strips}
    StripInfo   : PStripInfo;          {strip offsets/lengths}
    ByteCntOfs  : LongInt;             {offset to byte count list}
    ImgStart    : LongInt;             {start of image data in file}
    ReadBuffer  : PByteArray;          {buffer for reads}
    InFile      : File;                {input file}
  end;

  PDcxFaxData = ^TDcxFaxData;
  TDcxFaxData = record
    DcxHeader : TDcxHeaderRec;         {Offsets to DCX pages}
    DcxPgSz   : TDcxOfsArray;          {Number of bytes per PCX image}
    DcxNumPag : Cardinal;              {Number of pages (PCX images) in file}
    OnPage    : Cardinal;              {Current page being converted}
  end;

  PPcxFaxData = ^TPcxFaxData;
  TPcxFaxData = record
    CurrRBSize   : Cardinal;           {Read buffer size}
    CurrRBOfs    : Cardinal;           {Offset into read buffer}
    ActBytesLine : Cardinal;           {Actual number of bytes per line}
    ReadBuffer   : PByteArray;         {Read buffer}
    PcxHeader    : TPcxHeaderRec;      {Header from PCX image}
    PcxBytes     : DWORD;              {Number of bytes in PCX image}
    InFile       : File;               {Input file}
    PcxWidth     : Word;               {Width of raster line in pixels}
    DcxData      : PDcxFaxData;        {Optional DCX conversion data}
  end;

const
  DMSize = 32;
{$IFNDEF PrnDrv}
type
  PBitmapFaxData = ^TBitmapFaxData;
  TBitmapFaxData = record
    BmpHandle       : HBitmap;
    DataBitmap      : Graphics.TBitmap;
    BytesPerLine    : Cardinal;
    Width           : Cardinal;
    NumLines        : Cardinal;
    OnLine          : Cardinal;
    Offset          : LongInt;
    BitmapBufHandle : THandle;
    BitmapBuf       : Pointer;
    NeedsDithering  : Boolean;
    DM              : array[0..Pred(DMSize),0..Pred(DMSize)] of Integer;
  end;
{$ENDIF}
{$ENDIF} {DrvInst}

{Fax unpacking}

{options passed to unpacker callback}
const
  upStarting = $0001;
  upEnding   = $0002;

{flags passed to unpacker status}
const
  usStarting = $0001;
  usEnding   = $0002;

const
  {unpacker options}
  ufYield            = $0001;
  ufAutoDoubleHeight = $0002;
  ufAutoHalfWidth    = $0004;
  ufAbort            = $0008;

  DefUnpackOptions = ufYield or ufAutoDoubleHeight;
  BadUnpackOptions = Cardinal(0);

  {const number of raster lines per allocated page}
  {$IFDEF Win32}
  RasterBufferPageSize = Cardinal(1024);
  {$ELSE}
  RasterBufferPageSize = 256;
  {$ENDIF}

type
  {settings for horizontal and vertical scaling}
  PScaleSettings = ^TScaleSettings;
  TScaleSettings = record
    HMult : Cardinal;
    HDiv  : Cardinal;
    VMult : Cardinal;
    VDiv  : Cardinal;
  end;

  PUnpackFax = ^TUnpackFax;

  {callback for outputting unpacked data}
  TUnpackLineCallback = function(Unpack : PUnpackFax; plFlags : Word; var Data; Len, PageNum : Cardinal) : Integer;

  {callback for outputting status information}
  TUnpackStatusCallback = procedure(Unpack : PUnpackFax; FaxFile : PChar; PageNum : Cardinal;
                                    BytesUnpacked, BytesToUnpack : LongInt);

  {memory bitmap descriptor}
  PMemoryBitmapDesc = ^TMemoryBitmapDesc;
  TMemoryBitmapDesc = record
    Width  : Cardinal;
    Height : Cardinal;
    Bitmap : HBitmap;
  end;

  TUnpackFax = record
    {basic unpacker data}
    CurCode    : Cardinal;
    CurSig     : Cardinal;
    LineOfs    : Cardinal;            {Current offset in line}
    LineBit    : Cardinal;            {Current offset in byte}
    CurrPage   : Cardinal;            {Current page}
    CurrLine   : Cardinal;            {Current line}
    Flags      : Cardinal;            {Option flags}
    BadCodes   : Cardinal;            {Number of bad codes unpacked}
    WSFrom     : Cardinal;            {Whitespace comp - size of run to comp}
    WSTo       : Cardinal;            {Number of lines to compress to}
    WhiteCount : Cardinal;            {Count of white lines unpacked}
    TreeLast   : Integer;
    TreeNext   : Integer;
    Match      : Integer;
    ImgBytes   : LongInt;
    ImgRead    : LongInt;
    WhiteTree  : PTreeArray;          {Tree of white runlength codes}
    BlackTree  : PTreeArray;          {Tree of black runlength codes}
    LineBuffer : PByteArray;          {Buffer for decompression}
    TmpBuffer  : PByteArray;
    FileBuffer : PByteArray;          {File I/O buffer}
    FaxHeader  : TFaxHeaderRec;
    PageHeader : TPageHeaderRec;
    OutputLine : TUnpackLineCallback; {Output a decompressed raster line}
    Status     : TUnpackStatusCallback;
    UserData   : Pointer;             {Data needed by higher level unpackers}

    {scaling data}
    Height     : Cardinal;            {height of bitmap}
    Width      : Cardinal;            {width of bitmap}
    Handle     : THandle;             {handle to memory block}
    Pages      : Cardinal;            {pages allocate in handle}
    MaxWid     : Cardinal;            {maximum width of line}
    Lines      : Pointer;             {raster lines}
    Scale      : TScaleSettings;      {scale settings}
    MemBmp     : TMemoryBitmapDesc;   {memory bitmap}
    SaveHook   : TUnpackLineCallback; {saved output line hook}
    ToBuffer   : Bool;                {unpack to memory buffer?}
    Inverted   : Bool;                {TRUE if bitmap data should be inverted}
  end;

  {data for unpacking to PCX file}
  PUnpackToPcxData = ^TUnpackToPcxData;
  TUnpackToPcxData = record
    PBOfs       : Cardinal;
    Lines       : Cardinal;
    LastPage    : Cardinal;
    PCXOfs      : LongInt;
    FileOpen    : Bool;
    DcxUnpack   : Bool;
    OutFile     : File;
    OutName     : array[0..255] of Char;
    PackBuffer  : array[0..511] of Byte;
    DcxHead     : TDcxHeaderRec;
  end;

{image converters}
const
  DCXHeaderID = 987654321;

{Fax viewer}

const
  {fax viewer window Cardinal}
  gwl_Viewer = 0;

const
  {special styles}
  vws_DragDrop  = $0001;

  {default colors}
  DefViewerBG = $FFFFFF;
  DefViewerFG = $000000;

  {default scrolling parameters}
  DefVScrollInc = 8;
  DefHScrollInc = 8;

{Abstract fax send/receive}
const
  {Constants used to initialize object fields}
  DefConnectAttempts : Cardinal = 1;   {Default one connect attempt}
  DefMaxRetries : Integer       = 2;   {Max times to retry sending a page}
  DefStatusTimeout : Integer    = 1;   {Seconds between status updates}

  {Constants used directly}
  DefNormalInit                = 'ATE0Q0V1X4S0=0S2=43';
  DefBlindInit                 = 'ATE0Q0V1X3S0=0S2=43';
  DefNoDetectBusyInit          = 'ATE0Q0V1X2S0=0S2=43';
  DefX1Init                    = 'ATE0Q0V1X1S0=0S2=43';
  DefInit                      = DefNormalInit;
  DefStatusBytes : Cardinal        = 10000;   {Force periodic exit}
  MaxBadPercent : Cardinal         = 10;      {Error if this % bad training}
  FlushWait : Cardinal             = 500;     {Msec before/after DTR drop}
  FrameWait : Cardinal             = 20;      {Msec delay before HDLC frame}

  {Fax send/receive options}
  afAbortNoConnect      = $0001;   {Abort if no connect}
  afExitOnError         = $0002;   {Exit FaxTransmit/Receive on error}
  afCASSubmitUseControl = $0004;   {SubmitSingleFile uses control file}
  afSoftwareFlow        = $0008;   {Use software flow control in C1/2}

  DefFaxOptions : Cardinal = 0;
  BadFaxOptions = Cardinal(0);

  {Fax types (for specifying different send/receive state machines}
  ftNone              = 0;   {None specified}
  ftClass12           = 1;   {Class 1/2/2.0}

type
  {.Z+}
  ClassType = (ctUnknown, ctDetect, ctClass1, ctClass2, ctClass2_0);
  {.Z-}

  {Logging codes}
  TLogFaxCode = (
    lfaxNone,
    lfaxTransmitStart,
    lfaxTransmitOk,
    lfaxTransmitFail,
    lfaxReceiveStart,
    lfaxReceiveOk,
    lfaxReceiveSkip,
    lfaxReceiveFail);
  {Logging codes for TApdFaxServer}
  TFaxServerLogCode = (
    fslNone,
    fslPollingEnabled,
    fslPollingDisabled,
    fslMonitoringEnabled,
    fslMonitoringDisabled);

  {General fax states}
  FaxStateType = (
    faxReady,           {State machine ready immediately}
    faxWaiting,         {State machine waiting}
    faxCritical,        {State machine in critical state}
    faxFinished);       {State machine is finished}

type
  {.Z+}
  {A list of files/numbers to fax}
  TFaxNumber = String[40];
  PFaxEntry = ^TFaxEntry;
  TFaxEntry = record
    fNumber : TFaxNumber;
    fFName  : ShortString;
    fCover  : ShortString;
    fNext   : PFaxEntry;
  end;
  {.Z-}

  {A general (Pascal and C++) structure for returning the next fax to send}
  PSendFax = ^TSendFax;
  TSendFax = record
    sfNumber : array[0..40] of Char;
    sfFName  : array[0..255] of Char;
    sfCover  : array[0..255] of Char;
  end;

const
  {Trigger constants}
  MaxTrigData = 21;                 {Max length of data trigger (should be odd)}
  MaxDataPointers = 3;              {Max number of data pointers}
  TimerFreq = 50;                   {Dispatcher timer interval in millisecs}

  {Data pointer constants}
  dpProtocol = 1;
  dpFax      = 2;
  dpModem    = 3;

  {Tracing constants}
  MaxTraceCol = 78;                 {Wrap trace reports at this column}
  {$IFDEF Win32}
  HighestTrace = 4000000;           {Largest acceptable trace buffer size}
  {$ELSE}
  HighestTrace = 32760;             {Largest acceptable trace buffer size}
  {$ENDIF}

  {Logging constants}
  {$IFDEF Win32}
  MaxDLogQueueSize = 16000000;      {Largest acceptable log queue}
  {$ELSE}
  MaxDLogQueueSize = 65520;         {Largest acceptable log queue}
  {$ENDIF}

type
  {Types of dispatch entries}
  TDispatchType = (
     dtNone, dtDispatch, dtTrigger, dtError, dtThread,
     dtTriggerAlloc, dtTriggerDispose, dtTriggerHandlerAlloc,
     dtTriggerHandlerDispose, dtTriggerDataChange, dtTelnet, dtFax,
     dtXModem, dtYModem, dtZModem, dtKermit, dtAscii, dtBPlus,
     dtPacket, dtUser);
  TDispatchSubType =
    (dstNone,
     dstReadCom, dstWriteCom, dstLineStatus, dstModemStatus,
     dstAvail, dstTimer, dstData, dstStatus,
     dstThreadStart, dstThreadExit, dstThreadSleep, dstThreadWake,
     dstDataTrigger, dstTimerTrigger, dstStatusTrigger, dstAvailTrigger,
     dstWndHandler, dstProcHandler, dstEventHandler,
     dstSWill, dstSWont, dstSDo, dstSDont, dstRWill, dstRWont,
     dstRDo, dstRDont, dstCommand, dstSTerm,
     dsttfNone, dsttfGetEntry, dsttfInit, dsttf1Init1, dsttf2Init1,
     dsttf2Init1A, dsttf2Init1B, dsttf2Init2, dsttf2Init3, dsttfDial,
     dsttfRetryWait, dsttf1Connect, dsttf1SendTSI, dsttf1TSIResponse,
     dsttf1DCSResponse, dsttf1TrainStart, dsttf1TrainFinish,
     dsttf1WaitCFR, dsttf1WaitPageConnect, dsttf2Connect,
     dsttf2GetParams, dsttfWaitXon, dsttfWaitFreeHeader,
     dsttfSendPageHeader, dsttfOpenCover, dsttfSendCover,
     dsttfPrepPage,  dsttfSendPage, dsttfDrainPage, dsttf1PageEnd,
     dsttf1PrepareEOP, dsttf1SendEOP, dsttf1WaitMPS, dsttf1WaitEOP,
     dsttf1WaitMCF, dsttf1SendDCN, dsttf1Hangup, dsttf1WaitHangup,
     dsttf2SendEOP, dsttf2WaitFPTS, dsttf2WaitFET, dsttf2WaitPageOK,
     dsttf2SendNewParams, dsttf2NextPage, dsttf20CheckPage,
     dsttfClose, dsttfCompleteOK, dsttfAbort, dsttfDone, dstrfNone,
     dstrfInit, dstrf1Init1, dstrf2Init1, dstrf2Init1A, dstrf2Init1B,
     dstrf2Init2, dstrf2Init3, dstrfWaiting, dstrfAnswer,
     dstrf1SendCSI, dstrf1SendDIS, dstrf1CollectFrames,
     dstrf1CollectRetry1, dstrf1CollectRetry2, dstrf1StartTrain,
     dstrf1CollectTrain, dstrf1Timeout, dstrf1Retrain,
     dstrf1FinishTrain, dstrf1SendCFR, dstrf1WaitPageConnect,
     dstrf2ValidConnect, dstrf2GetSenderID, dstrf2GetConnect,
     dstrfStartPage, dstrfGetPageData, dstrf1FinishPage,
     dstrf1WaitEOP, dstrf1WritePage, dstrf1SendMCF, dstrf1WaitDCN,
     dstrf1WaitHangup, dstrf2GetPageResult, dstrf2GetFHNG,
     dstrfComplete, dstrfAbort, dstrfDone,
     dsttxInitial, dsttxHandshake, dsttxGetBlock, dsttxWaitFreeSpace,
     dsttxSendBlock, dsttxDraining, dsttxReplyPending,
     dsttxEndDrain, dsttxFirstEndOfTransmit, dsttxRestEndOfTransmit,
     dsttxEotReply, dsttxFinished, dsttxDone,
     dstrxInitial, dstrxWaitForHSReply, dstrxWaitForBlockStart,
     dstrxCollectBlock, dstrxProcessBlock,  dstrxFinishedSkip,
     dstrxFinished, dstrxDone,
     dsttyInitial, dsttyHandshake, dsttyGetFileName, dsttySendFileName,
     dsttyDraining, dsttyReplyPending, dsttyPrepXmodem,
     dsttySendXmodem, dsttyFinished, dsttyFinishDrain, dsttyDone,
     dstryInitial, dstryDelay, dstryWaitForHSReply,
     dstryWaitForBlockStart, dstryCollectBlock, dstryProcessBlock,
     dstryOpenFile, dstryPrepXmodem, dstryReceiveXmodem, dstryFinished,
     dstryDone, dsttzInitial, dsttzHandshake, dsttzGetFile,
     dsttzSendFile, dsttzCheckFile, dsttzStartData, dsttzEscapeData,
     dsttzSendData, dsttzWaitAck, dsttzSendEof, dsttzDrainEof,
     dsttzCheckEof, dsttzSendFinish, dsttzCheckFinish, dsttzError,
     dsttzCleanup, dsttzDone, dstrzRqstFile, dstrzDelay, dstrzWaitFile,
     dstrzCollectFile, dstrzSendInit, dstrzSendBlockPrep,
     dstrzSendBlock, dstrzSync, dstrzStartFile, dstrzStartData,
     dstrzCollectData, dstrzGotData, dstrzWaitEof, dstrzEndOfFile,
     dstrzSendFinish, dstrzCollectFinish, dstrzError, dstrzWaitCancel,
     dstrzCleanup, dstrzDone,
     dsttkInit, dsttkInitReply, dsttkCollectInit, dsttkOpenFile,
     dsttkSendFile, dsttkFileReply, dsttkCollectFile, dsttkCheckTable,
     dsttkSendData, dsttkBlockReply, dsttkCollectBlock, dsttkSendEof,
     dsttkEofReply, dsttkCollectEof, dsttkSendBreak, dsttkBreakReply,
     dsttkCollectBreak, dsttkComplete, dsttkWaitCancel, dsttkError,
     dsttkDone, dstrkInit, dstrkGetInit, dstrkCollectInit,
     dstrkGetFile, dstrkCollectFile, dstrkGetData, dstrkCollectData,
     dstrkComplete, dstrkWaitCancel, dstrkError, dstrkDone,
     dsttaInitial, dsttaGetBlock, dsttaWaitFreeSpace, dsttaSendBlock,
     dsttaSendDelay, dsttaFinishDrain, dsttaFinished, dsttaDone,
     dstraInitial, dstraCollectBlock, dstraProcessBlock,
     dstraFinished, dstraDone, dstEnable, dstDisable, dstStringPacket,
     dstSizePacket, dstPacketTimeout, dstStartStr, dstEndStr,
     dstIdle, dstWaiting, dstCollecting
     );

  {For holding trace entries}
  TTraceRecord = record
    EventType : Char;
    C : Char;
  end;
  PTraceQueue = ^TTraceQueue;
  TTraceQueue = array[0..HighestTrace] of TTraceRecord;

  {Holds one dispatcher entry}
  PDispatchRecord = ^TDispatchRecord;
  TDispatchRecord = record
    drType     : TDispatchType;
    drSubType  : TDispatchSubType;
    drTime     : DWORD;
    drData     : Cardinal;
    drMoreData : Cardinal;
  end;

  {Circular dispatch buffer}
  PDispatchQueue = ^TDispatchQueue;
  TDispatchQueue = array[0..MaxDLogQueueSize] of Byte;

  {DispatchBuffer type}
  PDBuffer = ^TDBuffer;
  TDBuffer = array[0..65527] of Char;

  {$IFDEF Win32}
  {Output buffer type}
  POBuffer = ^TOBuffer;
  TOBuffer = array[0..pred(High(Integer))] of Char;
  {$ENDIF}

  {$IFNDEF PrnDrv}

  {For storing com name}
  TComName = array[0..5] of Char;

  {Trigger types}
  TTriggerType = (ttNone, ttAvail, ttTimer, ttData, ttStatus);

  {Timer trigger record}
  PTimerTrigger = ^TTimerTrigger;
  TTimerTrigger = record
    tHandle : Cardinal;
    tET     : EventTimer;
    tTicks  : LongInt;
    tValid  : Bool;
    tActive : Bool;
  end;

  {Data trigger match array}
  TCheckIndex = array[0..MaxTrigData] of Cardinal;

  {Data trigger record}
  PDataTrigger = ^TDataTrigger;
  TDataTrigger = record
    tHandle     : Cardinal;
    tLen        : Cardinal;
    tChkIndex   : TCheckIndex;
    tMatched    : Bool;
    tIgnoreCase : Bool;
    tData       : array[0..MaxTrigData] of Char;
  end;

  {Status trigger record}
  PStatusTrigger = ^TStatusTrigger;
  TStatusTrigger = record
    tHandle    : Cardinal;
    tSType     : Cardinal;
    tValue     : Word;
    tSActive   : Boolean;
    StatusHit  : Boolean;
  end;

  {Trigger save record}
  TTriggerSave = record
    tsLenTrigger     : Cardinal;
    tsTimerTriggers  : Tlist;
    tsDataTriggers   : TList;
    tsStatusTriggers : TList;
  end;

  {Trigger handler records}
  PWndTriggerHandler = ^TWndTriggerHandler;
  TWndTriggerHandler = record
    thWnd     : TApdHwnd;           {Window that gets messages}
    thDeleted : Boolean;
  end;
  PProcTriggerHandler = ^TProcTriggerHandler;
  TProcTriggerHandler = record
    thNotify  : TApdNotifyProc;     {Address of notification proc}
    thDeleted : Boolean;
  end;
  PEventTriggerHandler = ^TEventTriggerHandler;
  TEventTriggerHandler = record
    thNotify  : TApdNotifyEvent;    {Address of notification event}
    thDeleted : Boolean;
    thSync : Boolean;
  end;
  {Data pointers for various purposes}
  TDataPointerArray = array[1..MaxDataPointers] of Pointer;
    {indexes in use internally (each component must use unique index) :
      1 : protocol component
      2 : fax component
      3 : legacy modem component
    }
  {$ENDIF}

{$IFDEF Win32}
procedure SetFlag(var Flags : Cardinal; FlagMask : Cardinal);
{$ELSE}
procedure SetFlag(var Flags : Cardinal; FlagMask : Cardinal);
  {-Set bit(s) in the parameter Flags. The bits to set are specified in
  FlagMask.}
  inline(
    $58/                     {pop ax        ;FlagMask into AX}
    $5F/                     {pop di}
    $07/                     {pop es        ;ES:DI => Flags}
    $26/$09/$05);            {or es:[di],ax ;Flags := Flags or FlagMask}
{$ENDIF}

{$IFDEF Win32}
procedure ClearFlag(var Flags : Cardinal; FlagMask : Cardinal);
{$ELSE}
procedure ClearFlag(var Flags : Cardinal; FlagMask : Cardinal);
  {-Clear bit(s) in the parameter Flags. The bits to clear are specified in
  Flagmask.}
  inline(
    $58/                     {pop ax         ;FlagMask into AX}
    $5F/                     {pop di}
    $07/                     {pop es         ;ES:DI => Flags}
    $F7/$D0/                 {not ax         ;FlagMask := not FlagMask}
    $26/$21/$05);            {and es:[di],ax ;Flags := Flags and not FlagMask}
{$ENDIF}

{$IFDEF Win32}
function FlagIsSet(Flags : Cardinal; FlagMask : Cardinal) : Bool;
{$ELSE}
function FlagIsSet(Flags, FlagMask : Cardinal) : Bool;
  {-Return True if the bit specified by FlagMask is set in Flags.}
  inline(
    $5A/                     {pop dx    ;FlagMask into DX}
    $58/                     {pop ax    ;Flags into AX}
    $21/$D0/                 {and ax,dx ;Mask out everything not in FlagMask}
    $74/$03/                 {jz  Exit}
    $B8/$01/$00);            {mov ax,1  ;AX = Ord(True)}
                              {Exit:}
{$ENDIF}

{$IFDEF Win32}
procedure SetByteFlag(var Flags : Byte; FlagMask : Byte);
{$ELSE}
procedure SetByteFlag(var Flags : Byte; FlagMask : Byte);
  {-Set bit(s) in the parameter Flags. The bits to set are specified in
  FlagMask.}
  inline(
    $58/                     {pop ax        ;FlagMask into AL}
    $5F/                     {pop di}
    $07/                     {pop es        ;ES:DI => Flags}
    $26/$08/$05);            {or es:[di],al ;Flags := Flags or FlagMask}
{$ENDIF}

{$IFDEF Win32}
procedure ClearByteFlag(var Flags : Byte; FlagMask : Byte);
{$ELSE}
procedure ClearByteFlag(var Flags : Byte; FlagMask : Byte);
  {-Clear bit(s) in the parameter Flags. The bits to clear are specified in
  FlagMask.}
  inline(
    $58/                     {pop ax         ;FlagMask into AL}
    $5F/                     {pop di}
    $07/                     {pop es         ;ES:DI => Flags}
    $F6/$D0/                 {not al         ;AL := not AL}
    $26/$20/$05);            {and es:[di],al ;Flags := Flags and not FlagMask}
{$ENDIF}

{$IFDEF Win32}
function ByteFlagIsSet(Flags : Byte; FlagMask : Byte) : Bool;
{$ELSE}
function ByteFlagIsSet(Flags, FlagMask : Byte) : Bool;
  {-Return True if the bit specified by FlagMask is set in the Flags
  parameter.}
  Inline(
    $5A/                   {pop dx    ;FlagMask into DL}
    $58/                   {pop ax    ;Flags into AL}
    $30/$E4/               {xor ah,ah ;Zero out AH}
    $20/$D0/               {and al,dl ;Mask out everything not in FlagMask}
    $74/$02/               {jz  Exit}
    $B0/$01);              {mov al,1  ;AX = Ord(True)}
                            {Exit:}
{$ENDIF}

{$IFDEF Win32}
function MinWord(A, B : Cardinal) : Cardinal;
{$ELSE}
function MinWord(A, B : Cardinal) : Cardinal;
  {-Return the smaller of A and B.}
  inline(
    $58/                     {pop ax}
    $5B/                     {pop bx}
    $39/$C3/                 {cmp bx,ax}
    $73/$02/                 {jae done}
    $89/$D8);                {mov ax,bx}
                             {done:}
{$ENDIF}

{$IFDEF Win32}
function AddWordToPtr(P : Pointer; W : Cardinal) : Pointer;
{$ELSE}
function AddWordToPtr(P : Pointer; W : Cardinal) : Pointer;
  {-Add a Cardinal to a pointer.}
  inline(
    $5B/                     {pop bx     ;bx = W}
    $58/                     {pop ax     ;ax = Ofs(P^)}
    $5A/                     {pop dx     ;dx = Seg(P^)}
    $01/$D8);                {add ax,bx  ;ax = Ofs(P^)+W}
{$ENDIF}

type
  QPCCast = record
    LowPart: DWORD;
    HighPart: DWORD;
  end;
const
  QPFreq : DWORD = 0;
function AdTimeGetTime : DWord;

function Ticks2Secs(Ticks : LongInt) : LongInt;
function Secs2Ticks(Secs : LongInt) : LongInt;
function MSecs2Ticks(MSecs : LongInt) : LongInt;
procedure NewTimer(var ET : EventTimer; Ticks : LongInt);
procedure NewTimerSecs(var ET : EventTimer; Secs : LongInt);
function TimerExpired(ET : EventTimer) : Bool;
function ElapsedTime(ET : EventTimer) : LongInt;
function ElapsedTimeInSecs(ET : EventTimer) : LongInt;
function RemainingTime(ET : EventTimer) : LongInt;
function RemainingTimeInSecs(ET : EventTimer) : LongInt;
function DelayTicks(Ticks: LongInt; Yield : Bool) : Longint;
{$IFNDEF PrnDrv}
function Long2StrZ(Dest : PChar; L : LongInt) : PChar;
function Str2LongZ(S : PChar; var I : LongInt) : Bool;
{$ENDIF}
function JustPathnameZ(Dest : PChar; PathName : PChar) : PChar;
function JustFilenameZ(Dest : PChar; PathName : PChar) : PChar;
{$IFNDEF PrnDrv}
function JustExtensionZ(Dest : PChar; Name : PChar) : PChar;
{$ENDIF}
function StrStCopy(Dest : PChar; S : PChar; Pos, Count : Cardinal) : PChar;
function AddBackSlashZ(Dest : PChar; DirName : PChar) : PChar;
{$IFNDEF PrnDrv}
function ExistFileZ(FName : PChar) : Bool;
{$ENDIF}
function ForceExtensionZ(Dest : PChar; Name, Ext : PChar) : PChar;
function DefaultExtensionZ(Dest : PChar; Name, Ext : PChar) : PChar;
function GetPtr(P : Pointer; O : LongInt) : Pointer;
procedure NotBuffer(var Buf; Len : Cardinal);

{$IFNDEF Win32}
function Trim(const S : string) : string;
{$ENDIF}

function DelayMS(MS : Cardinal) : Cardinal;

function SafeYield : LongInt;

{$IFNDEF Win32}
function TrimRight(const S : String) : String;
  {-Return a String with trailing white space removed}
{$ENDIF}

{$IFNDEF PrnDrv}
function JustName(PathName : String) : String;
  {-Return just the name (no extension, no path) of a pathname}

function AddBackSlash(const DirName : String) : String;
  {-Add a default backslash to a directory name}

type
  TApdBaseComponent = class(TComponent)
  protected
    function GetVersion : string;
    procedure SetVersion(const Value : string);
  published
    property Version : string
      read GetVersion
      write SetVersion
      stored False;
  end;

  TApdBaseWinControl = class(TWinControl)
  protected
    function GetVersion : string;
    procedure SetVersion(const Value : string);
  published
    property Version : string
      read GetVersion
      write SetVersion
      stored False;
  end;

{$ENDIF}


implementation

{$IFNDEF PrnDrv}
{$IFNDEF DrvInst}
constructor TLineReader.Create(Stream : TStream);
begin
  fStream := Stream;
  fFileSize := fStream.Size;
  fBytesRead := 0;
  ReadPage;
end;

destructor TLineReader.Destroy;
begin
  fStream.Free;
  inherited Destroy;
end;

function TLineReader.NextLine : string;
var
  EOL : PChar;
  Done : Boolean;
begin
  Result := '';
  repeat
    Done := True;
    EOL := StrScan(ReadPtr,#13);
    if EOL <> nil then begin
      EOL^ := #0;
      Result := Result + StrPas(ReadPtr);
      ReadPtr := EOL;
      inc(ReadPtr);
      if ReadPtr^ = #10 then inc(ReadPtr);
    end else begin
      Result := Result + StrPas(ReadPtr);
      ReadPage;
      Done := EOLF;
    end;
  until Done;
end;

procedure TLineReader.ReadPage;
var
  BytesRead : Integer;
begin
  BytesRead := fStream.Read(Buffer,LineBufferSize);
  inc(fBytesRead,BytesRead);
  fEOLF := BytesRead = 0;
  ReadPtr := @Buffer[0];
  if ReadPtr^ = #10 then inc(ReadPtr);
  if not fEOLF then
    if Buffer[BytesRead-1] = #$1A then
      Buffer[BytesRead-1] := #0
    else
      Buffer[BytesRead] := #0;
end;

{ TAdStr }

constructor TAdStr.Create(AMaxLen: Cardinal);
begin
  inherited Create;
  FMaxLen := 0;
  FLen := 0;
  FString := nil;
  SetMaxLen(AMaxLen);
end;

destructor TAdStr.Destroy;
begin
  if Assigned(FString) then
    FreeMem(FString, FMaxLen + 1);
  inherited Destroy;
end;

procedure TAdStr.Append(const Text: string);
var
  NewLen: Integer;
  Buff: PChar;
begin
  if Text = '' then Exit;         { nothing to append }

  NewLen := Length(Text) + FLen;
  if NewLen > FMaxLen then         { if new text will be longer than allocated }
    Resize(NewLen);              { reallocate }

  Buff := StrAlloc(Length(Text) + 1);
  StrPCopy(Buff,Text);
  StrCat(FString, Buff);
  StrDispose(Buff);
  FLen := StrLen(FString);
end;

procedure TAdStr.AppendBuff(Buff: PChar);
var
  BuffLen: Integer;
begin
  BuffLen := StrLen(Buff);
  if BuffLen = 0 then Exit;

  if BuffLen + FLen > FMaxLen then
    Resize(BuffLen + FLen);

  StrCat(FString, Buff);
  FLen := StrLen(FString);
end;

procedure TAdStr.AppendTAdStr(TS: TAdStr);
begin
  AppendBuff(TS.Str);
end;

procedure TAdStr.Assign(Source: TAdStr);
begin
  if not Assigned(Source) then Exit;

  if Source.MaxLen <> MaxLen then
    Resize(Source.MaxLen);

  FMaxLen := Source.MaxLen;

  StrCopy(FString, Source.Str);
  FLen    := StrLen(FString);

  GotoPos(Source.Cur - Source.Str);
end;

procedure TAdStr.Clear;
begin
  FString[0] := #0;
  FLen := 0;
  FCur := FString;
end;

function TAdStr.Copy(Index, SegLen: Integer): string;
var
  P:PChar;
  NewLen: Integer;
begin
  if (Index = 0) or (SegLen = 0) or (Index > FLen) then begin
    Result := '';
    Exit;
  end;

  NewLen := SegLen;
  if Index + (SegLen - 1) > FLen then  { requested segment runs past end of string }
    NewLen := FLen - Index;  { just return up to end of string }

{$ifndef WIN32 }
  if NewLen > 255 then  { old Pascal strings can contain no more than 255 chars }
    NewLen := 255;
{$endif }
  GotoPos(Index);

  P := StrAlloc(NewLen + 1);
  StrLCopy(P, FCur, NewLen);
  Result := StrPas(P);
  StrDispose(P);
end;

procedure TAdStr.Delete(Index, SegLen: Integer);
var
  Src: PChar;
  SrcLen: Cardinal;
begin
  if (Index = 0) or (SegLen = 0) or (Index > FLen) then Exit;

  GotoPos(Index);             { locate starting point }
  if Index + (SegLen - 1) > FLen then  { delete rest of string }
    FCur[0] := #0
  else begin                  { remove chunk }
    Src := FCur + SegLen;     { find start of remain post chunk string }
    SrcLen := StrLen(Src);
    StrLCopy(FCur, Src, SrcLen);
  end;
  FLen := StrLen(FString);
end;

procedure TAdStr.First;
begin
  FCur := FString;
end;

function TAdStr.GetBuffLen: Integer;
begin
  Result := FMaxLen + 1;
end;

function TAdStr.GetChar(Index: Cardinal): Char;
begin
  Result := FString[Index];
end;

function TAdStr.GetCurChar: Char;
begin
  Result := FCur[0];
end;

function TAdStr.GetLen: Integer;
begin
  Result := FLen;
end;

function TAdStr.GetMaxLen: Integer;
begin
  Result := FMaxLen;
end;

procedure TAdStr.GotoPos(Index: Cardinal);
begin
  FCur := FString;
  Inc(FCur, Index-1);
end;

procedure TAdStr.Insert(const Text: string; Index: Integer);
var
  Buff: PChar;
  NewLen: Integer;
begin
  if (Index = 0) or (Index > FLen) or (Text = '') then Exit;

  NewLen := Length(Text) + FLen;
  if NewLen > FMaxLen then         { if new text will be longer than allocated }
    Resize(NewLen);              { reallocate }

  GotoPos(Index);                  { find insertion point }
  Buff := StrNew(FCur);            { make copy of rest of string }
  StrPCopy(FCur, Text);            { append Text at insertion point }
  StrCat(FString, Buff);           { add rest of string back on }
  StrDispose(Buff);
  FLen := StrLen(FString);
end;

procedure TAdStr.Last;
begin
  FCur := StrEnd(FString) - 1;
end;

procedure TAdStr.Resize(NewLen: Integer);
var
  Temp: PChar;
  TempLen: Cardinal;
begin
  Temp := StrNew(FString);
  if (NewLen - 1) < FLen then
    TempLen := NewLen - 1
  else
    TempLen := FLen;
  SetMaxLen(NewLen);
  StrLCopy(FString, Temp, TempLen);
  StrDispose(Temp);
  FLen := StrLen(FString)
end;

procedure TAdStr.MoveBy(IndexBy: LongInt);
begin
  if IndexBy < 0 then
    Dec(FCur, IndexBy)
  else
  if IndexBy > 0 then
    Inc(FCur, IndexBy)
  else
    {no change};
end;

procedure TAdStr.Next;
begin
  Inc(FCur, 1);
end;

function TAdStr.Pos(const SubStr: string): Cardinal;
var
  Buff: PChar;
begin
  Buff := StrAlloc(Length(SubStr) + 1);
  StrPCopy(Buff,SubStr);
  FCur := StrPos(FString, Buff);
  StrDispose(Buff);

  if FCur = nil then
    Result := 0
  else
    Result := FCur - FString + 1;
end;

function TAdStr.PosIdx(const SubStr: string; Index: Integer): Cardinal;
var
  Buff: PChar;
begin
  if (Index = 0) or (Index > FLen) then begin
    Result := 0 ;
    Exit ;
  end;

  GetMem(Buff, Length(SubStr) + 5);
  GotoPos(Index);
  FCur := StrPos(FCur, StrPCopy(Buff,SubStr));
  StrDispose(Buff);

  if FCur = nil then
    Result := 0
  else
    Result := FCur - FString + 1;
end;

procedure TAdStr.Prepend(const Text: string);
begin
  Insert(Text,1);
end;

procedure TAdStr.Prev;
begin
  Dec(FCur,1);
end;

procedure TAdStr.SetChar(Index: Cardinal; Value: Char);
begin
  if FString[Index] <> Value then
    FString[Index] := Value;
end;

procedure TAdStr.SetLen(NewLen: Integer);
begin
  if NewLen <= FLen then
    FString[NewLen] := #0;
end;

procedure TAdStr.SetMaxLen(NewMaxLen: Integer);
begin
  if FMaxLen <> NewMaxLen then begin
    if Assigned(FString) then
      FreeMem(FString, FMaxLen + 5);
    FMaxLen := NewMaxLen;
    if FMaxLen = 0 then
      FString := nil
    else
      GetMem(FString, FMaxLen + 5);
  end;

  if Assigned(FString) then
    FString[0] := #0;
  FLen := 0;
end;

{$ENDIF}
{$ENDIF}

{$IFDEF Win32}
function MinWord(A, B : Cardinal) : Cardinal;
begin
  if A < B then
    Result := A
  else
    Result := B;
end;

function FlagIsSet(Flags : Cardinal; FlagMask : Cardinal) : Bool;
begin
  FlagIsSet := (Flags and FlagMask) <> 0;
end;

procedure ClearFlag(var Flags : Cardinal; FlagMask : Cardinal);
begin
  Flags := Flags and not FlagMask;
end;

procedure SetFlag(var Flags : Cardinal; FlagMask : Cardinal);
begin
  Flags := Flags or FlagMask;
end;

function ByteFlagIsSet(Flags : Byte; FlagMask : Byte) : Bool;
begin
  ByteFlagIsSet := (Flags and FlagMask) <> 0;
end;

procedure ClearByteFlag(var Flags : Byte; FlagMask : Byte);
begin
  Flags := Flags and not FlagMask;
end;

procedure SetByteFlag(var Flags : Byte; FlagMask : Byte);
begin
  Flags := Flags or FlagMask;
end;

function AddWordToPtr(P : Pointer; W : Cardinal) : Pointer; assembler;
asm
  add   eax,edx
end;
{$ENDIF}

const
  DosDelimSet : set of Char = ['\', ':', #0];

  {$IFDEF Win32}
  MaxPCharLen = $7FFFFFFF;
  {$ELSE}
  MaxPCharLen = $FFFF;
  {$ENDIF}

  function SafeYield : LongInt;
    {-Allow other processes a chance to run}
  var
    Msg : TMsg;
  begin
    SafeYield := 0;
    if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin
      if Msg.Message = wm_Quit then
        {Re-post quit message so main message loop will terminate}
        PostQuitMessage(Msg.WParam)
      else begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
      {Return message so caller can act on message if necessary}
      SafeYield := MAKELONG(Msg.Message, Msg.hwnd);
    end;
  end;

  { Centralized timer method -- will use QueryPerformaceCounter }
  { if avail, return is the number of ms since the system started }
  function AdTimeGetTime : DWord;
  {$IFDEF Win32}
  var
    Count : TLargeInteger;
  {$ENDIF}
  begin
    {$IFDEF Win32}
    if QPFreq <> 0 then begin
      QueryPerformanceCounter(Count);
      asm
        xor edx, edx
        mov eax, QPCCast(Count).HighPart
        div QPFreq
        mov eax, QPCCast(Count).LowPart
        div QPFreq
        mov Result, eax
      end;
    end else
    {$ENDIF}
      Result := timeGetTime;
  end;

  function Ticks2Secs(Ticks : LongInt) : LongInt;
    {-Returns seconds value for Ticks Ticks}
  begin
    Ticks2Secs := ((Ticks + 9) * SecsFreq) div TicksFreq;
  end;

  function Secs2Ticks(Secs : LongInt) : LongInt;
    {-Returns Ticks value for Secs seconds}
  begin
    Secs2Ticks := (Secs * TicksFreq) div SecsFreq;
  end;

  function MSecs2Ticks(MSecs : LongInt) : LongInt;
    {-Returns Ticks value for msecs}
  begin
    Result := (MSecs * TicksFreq) div MSecsFreq;
  end;

  procedure NewTimer(var ET : EventTimer; Ticks : LongInt);
    {-Returns a set EventTimer that will expire in Ticks}
  begin
    {Max acceptable value is MaxTicks}
    if Ticks > MaxTicks then
      Ticks := MaxTicks;

    with ET do begin
      StartTicks := AdTimeGetTime div 55;
      ExpireTicks := StartTicks + Ticks;
    end;
  end;

  procedure NewTimerSecs(var ET : EventTimer; Secs : LongInt);
    {-Returns a set EventTimer}
  begin
    NewTimer(ET, Secs2Ticks(Secs));
  end;

  function TimerExpired(ET : EventTimer) : Bool;
    {-Returns True if ET has expired}
  var
    CurTicks : LongInt;
  begin
    with ET do begin
      {Get current Ticks; assume timer has expired}
      CurTicks := AdTimeGetTime div 55;
      TimerExpired := True;
      {Check normal expiration}
      if CurTicks > ExpireTicks then
        Exit;
      {Check wrapped CurTicks}
      if (CurTicks < StartTicks) and
         ((CurTicks + MaxTicks) > ExpireTicks) then
        Exit;

      {If we get here, timer hasn't expired yet}
      TimerExpired := False;
    end;
  end;

  function ElapsedTime(ET : EventTimer) : LongInt;
    {-Returns elapsed time, in Ticks, for this timer}
  var
    CurTicks : LongInt;
  begin
    with ET do begin
      CurTicks := AdTimeGetTime div 55;
      if CurTicks >= StartTicks then
        {No wrap yet}
        ElapsedTime := CurTicks - StartTicks
      else
        {Got a wrap, account for it}
        ElapsedTime := (MaxTicks - StartTicks) + CurTicks;
    end;
  end;

  function ElapsedTimeInSecs(ET : EventTimer) : LongInt;
    {-Returns elapsed time, in seconds, for this timer}
  begin
    ElapsedTimeInSecs := Ticks2Secs(ElapsedTime(ET));
  end;

  function RemainingTime(ET : EventTimer) : LongInt;
    {-Returns remaining time, in Ticks, for this timer}
  var
    CurTicks : LongInt;
    RemainingTicks : LongInt;
  begin
    with ET do begin
      CurTicks := AdTimeGetTime div 55;
      if CurTicks >= StartTicks then
        {No wrap yet}
        RemainingTicks := ExpireTicks - CurTicks
      else
        {Got a wrap, account for it}
        RemainingTicks := (ExpireTicks - MaxTicks) - CurTicks;
    end;
    if RemainingTicks < 0 then
      RemainingTime := 0
    else
      RemainingTime := RemainingTicks;
  end;

  function RemainingTimeInSecs(ET : EventTimer) : LongInt;
    {-Returns remaining time, in seconds, for this timer}
  begin
    RemainingTimeInSecs := Ticks2Secs(RemainingTime(ET));
  end;

  function DelayTicks(Ticks : LongInt; Yield : Bool) : LongInt;
    {-Delay for Ticks ticks}
  var
    ET : EventTimer;
    Res : LongInt;
  begin
    if Ticks <= 0 then begin
      DelayTicks := 0;
      Exit;
    end else if Ticks > MaxTicks then
      Ticks := MaxTicks;

    Res := 0;
    NewTimer(ET, Ticks);
    repeat
      if Yield then
        Res := SafeYield;
    until (Res = wm_Quit) or TimerExpired(ET);
    DelayTicks := Res;
  end;

  {$IFNDEF PrnDrv}
  function Long2StrZ(Dest : PChar; L : LongInt) : PChar;
    {-Convert a long/Cardinal/integer/byte/shortint to a string}
  var
    S : string;
  begin
    Str(L, S);
    Result := StrPCopy(Dest, S);
  end;
  {$ENDIF}

const
  MaxLen  = 255;
  ExtLen = 3;

type
  TSmallArray = Array[0..MaxLen-1] of Char;

  {$IFNDEF PrnDrv}
  function Str2LongZ(S : PChar; var I : LongInt) : Bool;
    {-Convert a string to a longint, returning true if successful}
  var
    Err : Integer;
  begin
    Val(StrPas(S),I,Err);
    Result := Err = 0;
  end;
  {$ENDIF}

  function JustPathnameZ(Dest : PChar; PathName : PChar) : PChar;
    {-Return just the drive:directory portion of a pathname}
  var
    I : Integer;

  begin
    I := StrLen(PathName);
    repeat
      Dec(I);
    until (I = -1) or (PathName[I] in DosDelimSet);

    if I = -1 then
      {Had no drive or directory name}
      Dest[0] := #0
    else if I = 0 then begin
      {Either the root directory of default drive or invalid pathname}
      Dest[0] := PathName[0];
      Dest[1] := #0;
    end else if (PathName[I] = '\') then begin
      if PathName[Pred(I)] = ':' then
        {Root directory of a drive, leave trailing backslash}
        Dest := StrStCopy(Dest, PathName, 0, Succ(I))
      else
        {Subdirectory, remove the trailing backslash}
        Dest := StrStCopy(Dest, PathName, 0, I);
    end else
      {Either the default directory of a drive or invalid pathname}
      Dest:= StrStCopy(Dest, PathName, 0, Succ(I));
    Result := Dest;
  end;

  function JustFilenameZ(Dest : PChar; PathName : PChar) : PChar;
    {-Return just the filename of a pathname}
  var
    I : Cardinal;
  begin
    I := StrLen(PathName);
    while (I > 0) and (not (PathName[I-1] in DosDelimSet)) do
      Dec(I);
    Dest := StrStCopy(Dest, PathName, I, MaxLen);
    Result := Dest;
  end;

  {$IFNDEF PrnDrv}
  function JustExtensionZ(Dest : PChar; Name : PChar) : PChar;
  var
    X : string[4];
  begin
    X := ExtractFileExt(StrPas(Name));
    if X = '' then
      Dest := #0
    else
      StrPCopy(Dest,copy(X,2,255));
    Result := Dest;
  end;
  {$ENDIF}

  function StrStCopy(Dest : PChar; S : PChar; Pos, Count : Cardinal) : PChar;
  var
    Len : Cardinal;

  begin
    Len := StrLen(S);
    if Pos < Len then begin
      if (Len-Pos) < Count then
        Count := Len-Pos;
      Move(S[Pos], Dest^, Count);
      Dest[Count] := #0;
    end else
      Dest[0] := #0;
    StrStCopy := Dest;
  end;

  function AddBackSlashZ(Dest : PChar; DirName : PChar) : PChar;
    {-Add a default backslash to a directory name}
  var
    L : Cardinal;
  begin
    Result := Dest;
    StrCopy(Dest, DirName);
    L := StrLen(DirName);
    if (L > 0) and not(DirName[L-1] in DosDelimSet) then begin
      Dest[L] := '\';
      Dest[L+1] := #0;
    end;
  end;

  {$IFNDEF PrnDrv}
  function ExistFileZ(FName : PChar) : Bool;
  begin
    Result := FileExists(StrPas(FName));
  end;
  {$ENDIF}

  function ForceExtensionZ(Dest : PChar; Name, Ext : PChar) : PChar;
  begin
    Result := StrPCopy(Dest,ChangeFileExt(StrPas(Name),'.'+StrPas(Ext)));
  end;

  function DefaultExtensionZ(Dest : PChar; Name, Ext : PChar) : PChar;
  var
    S : string;
  begin
    S := StrPas(Name);
    if ExtractFileExt(S) = '' then
      S := ChangeFileExt(S,'.'+StrPas(Ext));
    Result := StrPCopy(Dest,S);
  end;

  {$IFNDEF Win32}
  function GetPtr(P : Pointer; O : LongInt) : Pointer; assembler;
    {-Return a pointer to an offset in a huge memory block}
  asm
    mov   dx,Cardinal ptr [O+2]
    shl   dx,3
    add   dx,Cardinal ptr [P+2]
    mov   ax,Cardinal ptr [O]
    add   ax,Cardinal ptr [P]
  end;
  {$ELSE}
  function GetPtr(P : Pointer; O : LongInt) : Pointer; assembler; register;
  asm
    add   eax,edx   {eax = P; edx = Offset}
  end;
  {$ENDIF}

  {$IFNDEF Win32}
  procedure NotBuffer(var Buf; Len : Cardinal); assembler;
  asm
    push  ds
    lds   si,Buf                {DS:SI->Buf}
    xor   ax,ax                 {AX=0}
    mov   cx,Len                {CX = Length of buffer}
    shr   cx,1                  {CX = CX / 2}
    adc   ax,ax                 {AX = remainder from division}
    jcxz  @2                    {Jump if there are no words to NOT}
@1: not   Cardinal ptr [si]     {NOT next Cardinal of buffer}
    inc   si                    {SI += 2}
    inc   si
    loop  @1

@2: or    ax,ax                 {jump if no more data}
    jz    @3
    not   byte ptr [si]         {NOT last byte of buffer}

@3: pop   ds
  end;
  {$ELSE}
  procedure NotBuffer(var Buf; Len : Cardinal); assembler; register;
  asm
    {eax is the pointer to the buffer}
    {edx is the length of the buffer}
    xor   ecx,ecx
    shr   edx,1
    rcl   ecx,1
    shr   edx,1
    rcl   ecx,1

    or    edx,edx
    jz    @2

@1: not   dword ptr [eax]
    add   eax,4
    dec   edx
    jnz   @1

@2: or    ecx,ecx
    jz    @4

@3: not   byte ptr [eax]
    inc   eax
    dec   ecx
    jnz   @3

@4:
  end;
  {$ENDIF}

  {$IFNDEF Win32}
  function Trim(const S : string) : string;
    {-Remove leading and trailing whitespace from a string}
  begin
    Result := S;
    while (Length(Result) > 0) and (Result[Length(Result)] <= ' ') do
      Dec(Result[0]);
    while (Length(Result) > 0) and (Result[1] <= ' ') do
      Delete(Result, 1, 1);
  end;
  {$ENDIF}

  function DelayMS(MS : Cardinal) : Cardinal;
  var
    CDelay: Cardinal;
    CTime: LongInt;
    LTime: LongInt;
  begin
    {Always return the delayed MS value}
    DelayMS := MS;

    {Get starting time}
    LTime := AdTimeGetTime;

    {Delay for MS milliseconds}
    CDelay := 0;
    while CDelay < MS do begin
      CTime := AdTimeGetTime;
      Inc(CDelay, CTime - LTime);
      LTime := CTime;
    end;
  end;

  {$IFNDEF Win32}
  function TrimRight(const S : String) : String;
    {-Return a String with trailing white space removed}
  var
    SLen : Byte absolute Result;

  begin
    Result := S;
    while (SLen > 0) and (Result[SLen] <= ' ') do
      Dec(SLen);
  end;
  {$ENDIF}

{$IFNDEF PrnDrv}
  function JustName(PathName : string) : string;
    {-Return just the name (no extension, no path) of a pathname}
  var
    DotPos : Byte;
  begin
    PathName := ExtractFileName(PathName);
    DotPos := Pos('.', PathName);
    if DotPos > 0 then
      PathName := Copy(PathName, 1, DotPos-1);
    Result := PathName;
  end;

  function AddBackSlash(const DirName : String) : String;
    {-Add a default backslash to a directory name}
  begin
    Result := DirName;
    if DirName = '' then Exit;
    if not(DirName[Length(DirName)] in DosDelimSet) then
      Result := DirName+'\';
  end;

function TApdBaseComponent.GetVersion : string;
begin
  Result := ApVersionStr;
end;

procedure TApdBaseComponent.SetVersion(const Value : string);
begin
end;

function TApdBaseWinControl.GetVersion : string;
begin
  Result := ApVersionStr;
end;

procedure TApdBaseWinControl.SetVersion(const Value : string);
begin
end;

{$ENDIF}
{$IFDEF Win32}
var
  Freq : TLargeInteger;
initialization
  QueryPerformanceFrequency(Freq);
  { Our assumption that HighPart is zero should be good for }
  { a long time but we'll do this safety check just in case }
  if (QPCCast(Freq).HighPart <> 0) or
     (QPCCast(Freq).LowPart = 0) then Exit;

  QPFreq := QPCCast(Freq).LowPart div 1000;
  if (QPCCast(Freq).LowPart mod 1000) > 500 then Inc(QPFreq);
{$ENDIF}

end.

