home *** CD-ROM | disk | FTP | other *** search
- program Menu;
- {$C-,V-}
- type
- MaxStr = String[255];
- Str80 = String[80];
- Str2 = String[2];
-
- var
- Ok : boolean;
- SwitchChar : char;
- NormalCursor : integer;
- NoCursor : integer;
-
- {*Include File ATTKBD.CON ***** START *****}
-
- { ***************************************************************** }
- { ATT PC Keyboard definitions }
- { ***************************************************************** }
-
- const
- RETURN_Key = #$0D;
- BACKSPACE_Key = #$08;
- ESCAPE_Key = #$1B;
- BEEP_Key = #$07;
- PREAMBLE_Key = #$00;
- PREAMBLE_Byte = $00;
- UP_Key = #$48;
- DOWN_Key = #$50;
- RIGHT_Key = #$4D;
- LEFT_Key = #$4B;
- HOME_Key = #$47;
- INSERT_Key = #$52;
- DELETE_Key = #$53;
- PageDwn_Key = #$51;
- PageUp_Key = #$49;
- END_Key = #$4F;
- TAB_Key = #$09;
- BACKTAB_Key = #$0F;
-
- CTRL_LEFT_Key = #$73;
- CTRL_RIGHT_Key = #$74;
- CTRL_END_Key = #$75;
- CTRL_PageDwn_Key = #$76;
- CTRL_HOME_Key = #$77;
- CTRL_PageUp_Key = #$84;
-
- SFKey01 = #$3B;
- SFKey02 = #$3C;
- SFKey03 = #$3D;
- SFKey04 = #$3E;
- SFKey05 = #$3F;
- SFKey06 = #$40;
- SFKey07 = #$41;
- SFKey08 = #$42;
- SFKey09 = #$43;
- SFKey10 = #$44;
-
- Shift_SFKey01 = #$54;
- Shift_SFKey02 = #$55;
- Shift_SFKey03 = #$56;
- Shift_SFKey04 = #$57;
- Shift_SFKey05 = #$58;
- Shift_SFKey06 = #$59;
- Shift_SFKey07 = #$5A;
- Shift_SFKey08 = #$5B;
- Shift_SFKey09 = #$5C;
- Shift_SFKey10 = #$5D;
-
- Alt_SFKey01 = #$68;
- Alt_SFKey02 = #$69;
- Alt_SFKey03 = #$6A;
- Alt_SFKey04 = #$6B;
- Alt_SFKey05 = #$6C;
- Alt_SFKey06 = #$6D;
- Alt_SFKey07 = #$6E;
- Alt_SFKey08 = #$6F;
- Alt_SFKey09 = #$70;
- Alt_SFKey10 = #$71;
-
- { ***************************************************************** }
-
-
- {*Include File End ATTKBD.CON ***** END *****}
- {*Include File CURSOR.INC ***** START *****}
- { Set Cursor Size : subfunction 01h of Intr 10h.
- The Documentation in the ATT Systems Programmers Guide did not
- describe what the actual call does, but after experimenting the
- meaning of start and end line is now clear.
- The cursor size in the ATT is saved at 0040:0060; and is lines 6 - 7.
-
- }
-
- procedure CursorSize(NewCursor : Integer);
- { This procedure call the BIOS throught interrupt 10H to set
- the top and bottom line of the cursor. Scan Lines are
- hardware dependent so you will have to experiment to find
- what works on your system. }
-
- type
- Register = record case boolean of
- true : (ax,bx,cx,dx,bp,si,di,ds,es,flags : integer);
- false: (al,ah,bl,bh,cl,ch,dl,dh : byte);
- end;
- var
- Regs : Register;
-
- begin
- With Regs do
- begin
- ah := $01; {ah = 1 means set cursor type}
- bx := $0; {bx = page number, zero for us}
- cx := NewCursor; {ch bits 4 to 0 = start line for cursor}
- {cl bits 4 to 0 = end line for cursor}
- cl := (cl and $1F); {mask off all but low order 5 bits}
- ch := (ch and $1F); {do the same for ch, in case of programmer}
- {error. Can this happen? naw not a chance}
- intr($10,Regs); {set cursor}
- end;
- end;
-
-
- {*Include File End CURSOR.INC ***** END *****}
- {*Include File SCAN.INC ***** START *****}
- function Read_Char(var extend : boolean): char;
- type
- Register = record case boolean of
- true : (ax,bx,cx,dx,bp,si,di,ds,es,flags : integer);
- false: (al,ah,bl,bh,cl,ch,dl,dh : byte);
- end;
- var
- Regs : Register;
- begin
- with Regs do
- begin
- ah := $07;
- MsDos(Regs);
- if al = PREAMBLE_Byte then
- begin
- extend := true;
- MsDos(Regs);
- end
- else
- extend := false;
- Read_Char:=Chr(al);
- end;
- end;
-
- {*Include File End SCAN.INC ***** END *****}
- {*Include File INPUTUTI.INC ***** START *****}
- type
- AnyStr = String[255];
- CharSet = Set Of Char;
-
-
- { UpcaseStr converts a string to upper case }
-
- function UpcaseStr(S : Str80) : Str80;
- var
- P : Integer;
- begin
- for P := 1 to Length(S) do
- S[P] := Upcase(S[P]);
- UpcaseStr := S;
- end;
-
- { ConstStr returns a string with N characters of value C }
-
- function ConstStr(C : Char; N : Integer) : Str80;
- var
- S : string[80];
- begin
- if N < 0 then
- N := 0;
- S[0] := Chr(N);
- FillChar(S[1],N,C);
- ConstStr := S;
- end;
-
- { Beep sounds the terminal bell or beeper }
-
- procedure Beep;
- begin
- Write(BEEP_Key);
- end;
-
-
- procedure InputStr(var S : AnyStr;
- L,X,Y : Integer;
- Term : CharSet;
- var TC : Char );
- var
- P : Integer;
- Ch : Char;
- Special : boolean;
- InsertMode : boolean;
- begin
- NormVideo;
- If Length(S)>L then
- S:=Copy(S,1,L);
- GotoXY(X,Y); Write(S,ConstStr('_',L - Length(S)));
- InsertMode:=true;
- P := 0;
- repeat
- GotoXY(X + P,Y); Ch:=Read_Char(Special);
- If Not Special then
- begin
- case Ch of
- #32..#126 : if P < L then
- begin
- case InsertMode of
- true : begin
- if Length(S) = L then
- Delete(S,L,1);
- P:=P+1;
- Insert(Ch,S,P);
- Write(Copy(S,P,L));
- If P=L then P:=P-1;
- end;
- false : begin
- P:=P+1;
- if P <= Length(S) then
- Delete(S,P,1);
- Insert(Ch,S,P);
- Write(Copy(S,P,L));
- If P=L then P:=P-1;
- end;
- end; { case Insert Mode }
- end;
-
- BACKSPACE_Key : if P > 0 then
- begin
- Delete(S,P,1);
- Write(BACKSPACE_Key,Copy(S,P,L),'_':1);
- P := P - 1;
- end
- else Beep;
- else
- if not (Ch in Term) then Beep;
- end; { of case }
- end
- else
- begin
- case Ch of
- LEFT_Key : if P > 0 then
- P := P - 1
- else Beep;
- RIGHT_Key : if P < Length(S) then
- P := P + 1
- else Beep;
- INSERT_Key : InsertMode:=not InsertMode;
- HOME_Key : P := 0;
- END_Key : P := Length(S);
- DELETE_Key : if P < Length(S) then
- begin
- Delete(S,P+1,1);
- Write(Copy(S,P + 1,L),'_':1);
- end;
- CTRL_END_Key : begin
- Write(ConstStr('_',Length(S) - P));
- Delete(S,P+1,L);
- end;
- else
- Beep;
- end; {of case}
- end;
- until Ch in Term;
- P := Length(S);
- GotoXY(X + P ,Y);
- If L>P then Write(ConstStr('_',L - P));
- TC := Ch;
- LowVideo;
- end;
-
-
- procedure Select( Prompt : Str80;
- Term : CharSet;
- var TC : Char );
- var
- Ch : Char;
- Special : boolean;
- begin
- GotoXY(1,23); Write(Prompt,'? ' ); ClrEol;
- repeat
- Ch:=Read_Char(Special);
- TC := Upcase(Ch);
- if not (TC in Term) then
- Beep;
- until TC in Term;
- case Ch of
- #32..#126 : Write(TC);
- end;
- end;
-
- procedure ClearLines(F,L:integer);
- var
- I : integer;
- begin
- For I:=F to L do
- begin
- GotoXY(1,I);ClrEol;
- end;
- end;
-
-
- {*Include File End INPUTUTI.INC ***** END *****}
- {*Include File MESSAGE.INC ***** START *****}
- procedure Message(S:Str80);
- begin
- GotoXY(1,25);ClrEol;
- If Length(S)>0 then
- begin
- NormVideo;
- Write('ERROR: ',S);
- LowVideo;
- Beep;
- end;
- end;
- {*Include File End MESSAGE.INC ***** END *****}
- {*Include File BIOSDATE.INC ***** START *****}
- type
- Bios = Record
- AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags:Integer;
- end;
-
- BiosB = Record
- AL,AH,BL,BH,CL,CH,DL,DH:Byte;
- end;
-
-
- procedure GetDate(var Year,Month,Day:Integer);
- var
- Reg : Bios;
- RegB : BiosB absolute Reg;
-
- begin
- RegB.AH:=$2A;
- MsDos(Reg);
- Year:=Reg.CX;
- Month:=RegB.DH;
- Day:=RegB.DL;
- end;
-
- Procedure GetTime(var Hrs,Min,Sec,HSec:Integer);
- var
- Reg : Bios;
- RegB : BiosB absolute Reg;
-
- begin
- RegB.AH:=$2C;
- MsDos(Reg);
- Hrs:=RegB.CH;
- Min:=RegB.CL;
- Sec:=RegB.DH;
- HSec:=RegB.DL;
- end;
-
-
- {*Include File End BIOSDATE.INC ***** END *****}
- {*Include File GETSWITC.INC ***** START *****}
- { **************************************************************************
- WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING !
- -----------------------------------------------------------------------
-
- This function call is defined in the Program Development Guide on the
- WANG system. This function returns the switch character used by
- COMMAND.COM. On the WANG system this is '-', to try to make this
- program generic I used this call. In the IBM DOS Technical Ref 2.10
- this call was documented only by the line 'USED INTERNALLY'. If this
- does not work change this function to return your switch char which
- is probably '/' if you are on an IBM/IBM clone.
-
- }
-
- function GetDOSswitch:char;
- type
- DosRegs = record case integer of
- 1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: integer);
- 2 : (AL,AH,BL,BH,CL,CH,DL,DH: byte);
- end;
- var
- Regs : DosRegs;
- begin
- with Regs do
- begin
- AH:=$37;
- AL:=0;
- end;
- MsDos(Regs);
- with Regs do
- GetDOSswitch:=Chr(DL);
- end;
-
-
- {*Include File End GETSWITC.INC ***** END *****}
- {*Include File FILLZERO.INC ***** START *****}
- procedure FillZero(var S:MaxStr);
- var
- I : integer;
- begin
- for I:=1 to Length(S) do
- If S[I]=' ' then
- S[I]:='0';
- end;
-
- {*Include File End FILLZERO.INC ***** END *****}
- {*Include File SPFUN.INC ***** START *****}
- { these routines use the MSDOS functions to get the date and time. The
- data is then converted into printable format. }
-
- function CurrentDate:Str80;
- var
- Month,
- Day,
- Year : Integer;
- S,T : MaxStr;
-
- begin
- GetDate(Year,Month,Day);
- Str(Month:2,S);
- FillZero(S);
- T:=S+'/';
- Str(Day:2,S);
- FillZero(S);
- T:=T+S+'/';
- Str(Year,S);
- T:=T+S;
- CurrentDate:=T;
- end;
-
- function Time:Str80;
- var
- Hrs,
- Min,
- Sec,
- HSec : Integer;
- S,T : MaxStr;
-
- begin
- GetTime(Hrs,Min,Sec,HSec);
- If Hrs>12 then Str(Hrs-12:2,S)
- Else Str(Hrs:2,S);
- FillZero(S);
- T:=S+':';
- Str(Min:2,S);
- FillZero(S);
- T:=T+S+':';
- Str(Sec:2,S);
- FillZero(S);
- T:=T+S;
- If (Hrs=12) and (Min=0) then T:=T+' M' Else
- If Hrs<12 then T:=T+' AM' Else
- T:=T+' PM';
- Time:=T;
- end;
-
- {*Include File End SPFUN.INC ***** END *****}
- {*Include File EXEC.INC ***** START *****}
- { EXEC.PAS version 1.3
-
- This file contains 2 functions for Turbo Pascal that allow you to run other
- programs from within a Turbo program. The first function, SubProcess,
- actually calls up a different program using MS-DOS call 4BH, EXEC. The
- second function, GetComSpec, returns the path name of the command
- interpreter, which is necessary to do certain operations. There is also a
- main program that allows you to test the functions.
-
- Revision history
- ----------------
- Version 1.3 works with MS-DOS 2.0 and up, TURBO PASCAL version 1.0 and up.
- Version 1.2 had a subtle but dangerous bug: I set a variable that was
- addressed relative to BP, using a destroyed BP!
- Version 1.1 didn't work with Turbo 2.0 because I used Turbo 3.0 features
- Version 1.0 only worked with DOS 3.0 due to a subtle bug in DOS 2.x
-
- - Bela Lubkin
- Borland International Technical Support
- CompuServe 71016,1573
- }
-
- Type
- Str66=String[66];
- Str255=String[255];
-
- Function SubProcess(CommandLine: Str255): Integer;
- { Pass this function a string of the form
- 'D:\FULL\PATH\NAME\OF\FILE.TYP parameter1 parameter2 ...'
-
- For example,
- 'C:\SYSTEM\CHKDSK.COM'
- 'A:\WS.COM DOCUMENT.1'
- 'C:\DOS\LINK.EXE TEST;'
- 'C:\COMMAND.COM /C COPY *.* B:\BACKUP >FILESCOP.IED'
-
- The third example shows several things. To do any of the following, you
- must invoke the command processor and let it do the work: redirection;
- piping; path searching; searching for the extension of a program (.COM,
- .EXE, or .BAT); batch files; and internal DOS commands. The name of the
- command processor file is stored in the DOS environment. The function
- GetComSpec in this file returns the path name of the command processor.
- Also note that you must use the /C parameter or COMMAND will not work
- correctly. You can also call COMMAND with no parameters. This will allow
- the user to use the DOS prompt to run anything (as long as there is enough
- memory). To get back to your program, he can type the command EXIT.
-
- Actual example:
- I:=SubProcess(GetComSpec+' /C COPY *.* B:\BACKUP >FILESCOP.IED');
-
- The value returned is the result returned by DOS after the EXEC call. The
- most common values are:
-
- 0: Success
- 1: Invalid function (should never happen with this routine)
- 2: File/path not found
- 8: Not enough memory to load program
- 10: Bad environment (greater than 32K)
- 11: Illegal .EXE file format
-
- If you get any other result, consult an MS-DOS Technical Reference manual.
-
- VERY IMPORTANT NOTE: you MUST use the Options menu of Turbo Pascal to
- restrict the amount of free dynamic memory used by your program. Only the
- memory that is not used by the heap is available for use by other
- programs. }
-
- Const
- SSSave: Integer=0;
- SPSave: Integer=0;
-
- Var
- Regs: Record Case Integer Of
- 1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: Integer);
- 2: (AL,AH,BL,BH,CL,CH,DL,DH: Byte);
- End;
- FCB1,FCB2: Array [0..36] Of Byte;
- PathName: Str66;
- CommandTail: Str255;
- ParmTable: Record
- EnvSeg: Integer;
- ComLin: ^Integer;
- FCB1Pr: ^Integer;
- FCB2Pr: ^Integer;
- End;
- I,RegsFlags: Integer;
-
- Begin
- If Pos(' ',CommandLine)=0 Then
- Begin
- PathName:=CommandLine+#0;
- CommandTail:=^M;
- End
- Else
- Begin
- PathName:=Copy(CommandLine,1,Pos(' ',CommandLine)-1)+#0;
- CommandTail:=Copy(CommandLine,Pos(' ',CommandLine),255)+^M;
- End;
- CommandTail[0]:=Pred(CommandTail[0]);
- With Regs Do
- Begin
- FillChar(FCB1,Sizeof(FCB1),0);
- AX:=$2901;
- DS:=Seg(CommandTail[1]);
- SI:=Ofs(CommandTail[1]);
- ES:=Seg(FCB1);
- DI:=Ofs(FCB1);
- MsDos(Regs); { Create FCB 1 }
- FillChar(FCB2,Sizeof(FCB2),0);
- AX:=$2901;
- ES:=Seg(FCB2);
- DI:=Ofs(FCB2);
- MsDos(Regs); { Create FCB 2 }
- (* ES:=CSeg;
- BX:=SSeg-CSeg+MemW[CSeg:MemW[CSeg:$0101]+$112];
- AH:=$4A;
- MsDos(Regs); { Deallocate unused memory } *)
- With ParmTable Do
- Begin
- EnvSeg:=MemW[CSeg:$002C];
- ComLin:=Addr(CommandTail);
- FCB1Pr:=Addr(FCB1);
- FCB2Pr:=Addr(FCB2);
- End;
- InLine($8D/$96/ PathName /$42/ { <DX>:=Ofs(PathName[1]); }
- $8D/$9E/ ParmTable / { <BX>:=Ofs(ParmTable); }
- $B8/$00/$4B/ { <AX>:=$4B00; }
- $1E/$55/ { Save <DS>, <BP> }
- $16/$1F/ { <DS>:=Seg(PathName[1]); }
- $16/$07/ { <ES>:=Seg(ParmTable); }
- $2E/$8C/$16/ SSSave / { Save <SS> in SSSave }
- $2E/$89/$26/ SPSave / { Save <SP> in SPSave }
- $FA/ { Disable interrupts }
- $CD/$21/ { Call MS-DOS }
- $FA/ { Disable interrupts }
- $2E/$8B/$26/ SPSave / { Restore <SP> }
- $2E/$8E/$16/ SSSave / { Restore <SS> }
- $FB/ { Enable interrupts }
- $5D/$1F/ { Restore <BP>,<DS> }
- $9C/$8F/$86/ RegsFlags / { Flags:=<CPU flags> }
- $89/$86/ Regs ); { Regs.AX:=<AX>; }
- { The messing around with SS and SP is necessary because under DOS 2.x,
- after returning from an EXEC call, ALL registers are destroyed except
- CS and IP! I wish I'd known that before I released this package the
- first time... }
- If (RegsFlags And 1)<>0 Then SubProcess:=AX
- Else SubProcess:=0;
- End;
- End;
-
- Function GetComSpec: Str66;
- Type
- Env=Array [0..32767] Of Char;
- Var
- EPtr: ^Env;
- EStr: Str255;
- Done: Boolean;
- I: Integer;
-
- Begin
- EPtr:=Ptr(MemW[CSeg:$002C],0);
- I:=0;
- Done:=False;
- EStr:='';
- Repeat
- If EPtr^[I]=#0 Then
- Begin
- If EPtr^[I+1]=#0 Then Done:=True;
- If Copy(EStr,1,8)='COMSPEC=' Then
- Begin
- GetComSpec:=Copy(EStr,9,100);
- Done:=True;
- End;
- EStr:='';
- End
- Else EStr:=EStr+EPtr^[I];
- I:=I+1;
- Until Done;
- End;
-
-
- {*Include File End EXEC.INC ***** END *****}
- {*Include File CURDRIVE.INC ***** START *****}
- procedure CurrentDrive(var S:Str2);
- type
- DosRegs = record case integer of
- 1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: integer);
- 2 : (AL,AH,BL,BH,CL,CH,DL,DH: byte);
- end;
- var
- Regs : DosRegs;
- begin
- Regs.AH:=$19; { Current Disk function code }
- MsDos(Regs); { do it , close your eyes }
- S:=Chr(Ord('A')+Regs.AL)+':';
- { Generate drive designation }
- end;
-
-
- {*Include File End CURDRIVE.INC ***** END *****}
- {*Include File MENUTYPE.INC ***** START *****}
- type
- bytechar = record case boolean of
- true : (c:char);
- false: (b:byte);
- end;
- MenuPointer = ^MenuBuffer;
- MenuBuffer = record
- Buf : Array [1..5,0..255] of bytechar;
- end;
- HelpPointer = ^HelpBuffer;
- HelpBuffer = record
- Buf : Array [1..187,0..255] of bytechar;
- end;
-
- ByteFile = file;
-
- const
- Special : set of char = [#$09,#$08,#$0D,#$20,ESCAPE_Key];
-
- var
- HBuffer : HelpBuffer;
- MBuffer : MenuBuffer;
- FilVar : ByteFile;
-
- {*Include File End MENUTYPE.INC ***** END *****}
- {*Include File HANDLE.INC ***** START *****}
- { The Following functions were written to take care of the ReadBlock
- bug in Turbo V3.0. The FileHandle function returns the MSDOS file
- handle to be used in reading from a file. The DosBlockRead function
- will attempt to read Recs number of bytes from a file with handle
- FileH. If no error occurs then the number of bytes read will be
- return in Result, otherwise Result will be -1.
-
- Gary W. Miller
- 70127,3674 Compuserve
-
- }
-
- function FileHandle(var FilVar):integer;
- var
- H : integer absolute FilVar;
- begin
- FileHandle:=H;
- end;
-
-
- procedure DosBlockRead(FileH:integer;var Buffer;Recs:integer;var Result:integer);
- type
- DosRegs = record case integer of
- 1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: integer);
- 2 : (AL,AH,BL,BH,CL,CH,DL,DH: byte);
- end;
- var
- Regs : DosRegs;
- begin
- with Regs do
- begin
- DS:=Seg(Buffer); { location of Buffer segment }
- DX:=Ofs(Buffer); { offset }
- CX:=Recs; { number of bytes to read }
- AH:=$3f; { Read File or Device Code }
- BX:=FileH; { Pass file handle }
- end;
- MsDos(Regs); { do it , close your eyes }
- with Regs do
- begin
- If (Flags and 1)<>0 then
- Result:=-1 { crap, we blew it }
- else
- Result:=AX; { tell me what you read }
- end;
- end;
-
-
- procedure DosBlockWrite(FileH:integer;var Buffer;Recs:integer;var Result:integer);
- type
- DosRegs = record case integer of
- 1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: integer);
- 2 : (AL,AH,BL,BH,CL,CH,DL,DH: byte);
- end;
- var
- Regs : DosRegs;
- begin
- with Regs do
- begin
- DS:=Seg(Buffer); { location of Buffer segment }
- DX:=Ofs(Buffer); { offset }
- CX:=Recs; { number of bytes to write }
- AH:=$40; { Write File or Device Code }
- BX:=FileH; { Pass file handle }
- end;
- MsDos(Regs); { do it , close your eyes }
- with Regs do
- begin
- If (Flags and 1)<>0 then
- Result:=-1 { crap, we blew it }
- else
- Result:=AX; { tell me what you wrote }
- end;
- end;
-
-
- {*Include File End HANDLE.INC ***** END *****}
- {*Include File CHGDIR.INC ***** START *****}
- { This procedure changes the current logged directory or drive based
- on the string passed. To change the logged drive pass this function
- the drive you wish to change to. To change directory pass the complete
- path name of the directory to change to. If any error occurs while
- making the change an error flag will be returned. }
-
- procedure ChangeDir(S:AnyStr;var Ok:boolean);
- begin
- {$I-}
- ChDir(S);
- {$I+}
- Ok:=(IOresult=0);
- end;
-
- { This procedure makes the rather rash assumtion that what ever path you
- pass it exists. If it does not exist then the function will return
- without doing anything. }
-
- procedure ReturnToPath(S:AnyStr);
- var
- Ok : boolean;
-
- begin
- ChangeDir(S,Ok);
- end;
-
- {*Include File End CHGDIR.INC ***** END *****}
-
- {*Include File MENUPROC.INC ***** START *****}
- procedure Display(var Buffer);
- type
- LineRec = record
- y : byte;
- x : byte;
- txt : String[255];
- end;
-
- var
- MenuLine : LineRec absolute Buffer;
- i : integer;
- flag : boolean;
- begin
- with MenuLine do
- begin
- if x = $ff then
- begin
- i:=1;
- while txt[i]<>#03 do
- i:=i+1;
- x:=40-((i) shr 1);
- end;
- GotoXY(x,y+1);
- If txt[0]=Chr(2) then
- begin
- i:=1;
- flag:=true;
- while txt[i]<>#03 do
- begin
- if flag and (txt[i]>#$20) then
- flag:=false;
- i:=i+1;
- end;
- If not flag then
- txt[0]:=Chr(i-1)
- else
- txt[0]:=Chr(0);
- end;
- If length(txt)>0 then
- write(txt);
- end;
- end;
-
- procedure Entry(i:integer;var b,o:byte;var buffer);
- type
- OffRec = record
- offset : byte;
- blk : byte;
- end;
- OffTable = Array [0..52] of OffRec;
- var
- table : Offtable absolute buffer;
- begin
- with table[i] do
- begin
- b:=blk;
- o:=offset;
- end;
- end;
-
- procedure RunInfo(var Buffer ;
- var Fname : Str80;
- var Path : Str80;
- var Drive : Str80;
- var ParmStr: Str80;
- var flag : byte;
- var help : byte);
- type
- RunRec = record
- pflag : byte;
- phelp : byte;
- junk : byte;
- pdisk : byte;
- ptxt : Array [1..255] of char;
- end;
- var
- prec : RunRec absolute Buffer;
- f,t : integer;
- k,p : integer;
- i : integer;
- begin
- with prec do
- begin
- flag:=pflag;
- help:=phelp;
- if pdisk=0 then
- Fname:=''
- else
- Fname:=Chr($40+pdisk)+':';
- Drive:=Fname;
- Path:='';
- f:=Length(Path);
- k:=1;
- if (ptxt[k]='/') or (ptxt[k]='\') then
- begin
- repeat
- f:=f+1;
- Path[f]:=ptxt[k];
- k:=k+1;
- Until ptxt[k]=#$20;
- k:=k+1;
- Path[0]:=Chr(f-1);
- end;
- f:=length(fname);
- p:=k+7;
- t:=0;
- for i:=k to k+10 do
- begin
- if ptxt[i]<>#$20 then
- begin
- if (i>=p) and (t=0) then
- begin
- t:=1;
- f:=f+1;
- fname[f]:='.';
- end;
- f:=f+1;
- fname[f]:=ptxt[i];
- end;
- end;
- fname[0]:=chr(f);
- ParmStr:='';
- k:=0;
- i:=i+1;
- while ptxt[i] <> #$03 do
- begin
- k:=k+1;
- ParmStr[k]:=ptxt[i];
- i:=i+1;
- end;
- ParmStr[0]:=chr(k);
- end;
- end;
-
-
- {*Include File End MENUPROC.INC ***** END *****}
- {*Include File DISPHELP.INC ***** START *****}
- procedure DisplayHelp(i:byte;var HBuffer:HelpBuffer);
- var
- k,l : integer;
- b,o : byte;
- t : char;
- begin
- ClrScr;
- LowVideo;
- l:=1+(i-1)*22;
- for k:=l to l+21 do
- begin
- Entry(k,b,o,HBuffer);
- Display(HBuffer.Buf[b,o]);
- end;
- NormVideo;
- GotoXY(1,24);write('Press Any Key to Return');
- LowVideo;
- Read(Kbd,t);
- ClrScr;
- end;
- {*Include File End DISPHELP.INC ***** END *****}
- {*Include File DISPMENU.INC ***** START *****}
- procedure DisplayMenu(UserSel:integer;var MBuffer:MenuBuffer);
- var
- k : integer;
- l : integer;
- b,o : byte;
- begin
- ClrScr;
- NormVideo;
- GotoXY(5,5);Write('Select and then Proceed:');
- LowVideo;
- For k:=1 to 3 do
- begin
- Entry(k,b,o,MBuffer);
- Display(MBuffer.Buf[b,o]);
- end;
- Entry(0,b,o,MBuffer);
- l:=MBuffer.Buf[b,o+1].b-1;
- For k:=0 to l do
- begin
- If k = UserSel then
- NormVideo
- else
- LowVideo;
- Entry(k+4,b,o,MBuffer);
- Display(MBuffer.Buf[b,o]);
- LowVideo;
- end;
- GotoXY(50,21);write('RETURN - Proceed');
- GotoXY(50,22);write('TAB - Help');
- GotoXY(50,23);write('SPACE - Select');
- GotoXY(50,24);write('ESCAPE - Previous Menu');
- end;
-
- procedure HighLight(var Old:byte;New:byte;MBuffer:MenuBuffer);
- var
- b,o : byte;
- begin
- LowVideo;
- Entry(Old+4,b,o,MBuffer);
- Display(MBuffer.Buf[b,o]);
- NormVideo;
- Old:=New;
- Entry(Old+4,b,o,MBuffer);
- Display(MBuffer.Buf[b,o]);
- LowVideo;
- end;
-
- procedure ReadMenu(var Fname:Str80;var Good:boolean);
- var
- k : integer;
- FilVar : ByteFile;
- Result : integer;
- begin
- Assign(FilVar,Fname);
- {$I-} Reset(FilVar); {$I+}
- Good:=(IOresult=0);
- If Good then
- begin
- k:=1;
- repeat
- with MBuffer do
- DosBlockRead(FileHandle(FilVar),Buf[k],4096,Result);
- k:=k+16;
- Until Result=0;
- Close(FilVar);
- end;
- end;
-
- procedure ReadHelp(var Fname:Str80;var Good:boolean);
- var
- k : integer;
- FilVar : ByteFile;
- Result : integer;
- begin
- Assign(FilVar,Fname);
- {$I-} Reset(FilVar); {$I+}
- Good:=(IOresult=0);
- If Good then
- begin
- k:=1;
- repeat
- with HBuffer do
- DosBlockRead(FileHandle(FilVar),Buf[k],4096,Result);
- k:=k+16;
- Until Result=0;
- Close(FilVar);
- end;
- end;
-
- procedure Menu(Fname,Path,Drive:Str80;var Ok:boolean);
- var
- OkDir,
- HelpCheck,
- MenuOk,
- HelpAvailable : boolean;
- UserSel : byte;
- t,TC : char;
- CDrive : Str2;
- CurrentDir : String[80];
- l : byte;
- FirstLetter : String[24];
- b,o : byte;
- k : byte;
- HFname,
- Rname,
- Rpath,
- Rdrive,
- Rparm : Str80;
- Rflag,
- Rhelp : byte;
- R : integer;
- begin
- Ok:=true;
- GetDir(0,CurrentDir);
- CurrentDrive(CDrive);
- If Length(Drive) > 0 then
- ChangeDir(Drive,Ok)
- else
- Drive:=CDrive;
- If (Length(Path)>0) and Ok then
- ChangeDir(Path,Ok)
- else
- Path:=CurrentDir;
- If Ok then ReadMenu(Fname,Ok);
- HFname:=Copy(Fname,1,Pos('.',Fname))+'hlp';
- HelpCheck:=false;
- If Ok then
- begin
- Entry(0,b,o,MBuffer);
- l:=MBuffer.Buf[b,o+1].b;
- for k:=4 to l+3 do
- begin
- Entry(k,b,o,MBuffer);
- FirstLetter[k-3]:=MBuffer.Buf[b,o+3].c;
- end;
- FirstLetter[0]:=chr(l);
- UserSel:=0;
- DisplayMenu(UserSel,MBuffer);
- t:=#0;
- repeat
- If KeyPressed then
- begin
- Read(Kbd,t);
- t:=UpCase(t);
- Message('');
- If (t in Special) then
- case t of
- RETURN_Key :begin
- Entry(UserSel+4+l,b,o,MBuffer);
- RunInfo(MBuffer.Buf[b,o],Rname,Rpath,Rdrive,Rparm,Rflag,Rhelp);
- if Rflag=0 then
- begin
- Menu(Rname,Rpath,Rdrive,MenuOk);
- If MenuOk then
- begin
- ReadHelp(HFname,HelpAvailable);
- ReadMenu(Fname,Ok);
- DisplayMenu(UserSel,MBuffer);
- end
- else
- Message('Unable to access Menu '+Rname);
- end
- else
- If (Rflag=1) or (Rflag=3) then
- begin
- OkDir:=true;
- If Length(Rdrive)>0 then
- ChangeDir(Rdrive,OkDir);
- If (Length(Rpath)>0) and OkDir then
- ChangeDir(Rpath,OkDir);
- ClrScr;
- CursorSize(NormalCursor);
- If OkDir then
- R:=Subprocess(Rname+' '+Rparm)
- else
- R:=1;
- CursorSize(NoCursor);
- If (R=0) and (Rflag=3) then
- begin
- NormVideo;GotoXY(1,25);ClrEol;
- write('Press any Key to Return to Menu');
- Read(Kbd,t);
- LowVideo;
- end;
- ReturnToPath(Drive+Path);
- DisplayMenu(UserSel,MBuffer);
- If R<>0 then
- begin
- If OkDir then
- Message('Unable to run '+Rname)
- else
- Message('Unable to find '+Rdrive+Rpath);
- end;
- end
- else
- If Rflag=2 then
- begin
- GotoXY(5,5);ClrEol;LowVideo;
- write('File Spec: ');
- NormVideo;
- CursorSize(NormalCursor);
- Rname:='';
- InputStr(Rname,60,17,5,[RETURN_Key,ESCAPE_Key],TC);
- LowVideo;
- If (Length(Rname) > 0) and (TC = RETURN_Key) then
- begin
- ClrScr;
- R:=Subprocess(GetComSpec+' '+SwitchChar+'C '+Rname);
- CursorSize(NoCursor);
- If (R=0) then
- begin
- NormVideo;GotoXY(1,25);ClrEol;
- write('Press any Key to Return to Menu');
- Read(Kbd,t);
- LowVideo;
- end;
- ReturnToPath(Drive+Path);
- DisplayMenu(UserSel,MBuffer);
- If R<>0 then
- Message('Unable to run '+Rname);
- end
- else
- begin
- CursorSize(NoCursor);
- DisplayMenu(UserSel,MBuffer)
- end;
- end
- else
- If Rflag=4 then
- begin
- CursorSize(NormalCursor);
- ClrScr;
- NormVideo;
- writeln('Type EXIT to return to the Menu');
- LowVideo;
- R:=Subprocess(GetComSpec);
- ReturnToPath(Drive+Path);
- CursorSize(NoCursor);
- If R=0 then
- DisplayMenu(UserSel,MBuffer)
- else
- Message('Unable to run '+Rname);
- end
- else
- If Rflag=5 then
- begin
- OkDir:=true;
- If Length(Rdrive)>0 then
- ChangeDir(Rdrive,OkDir);
- If (Length(Rpath)>0) and OkDir then
- ChangeDir(Rpath,OkDir);
- CursorSize(NormalCursor);
- LowVideo;
- ClrScr;
- if OkDir then
- R:=Subprocess(GetComSpec+' '+SwitchChar+'C '+Rname)
- else
- R:=1;
- CursorSize(NoCursor);
- ReturnToPath(Drive+Path);
- If (R=0) then
- begin
- NormVideo;GotoXY(1,25);ClrEol;
- write('Press any Key to Return to Menu');
- Read(Kbd,t);
- LowVideo;
- end;
- DisplayMenu(UserSel,MBuffer);
- If R<>0 then
- begin
- If OkDir then
- Message('Unable to run '+Rname)
- else
- Message('Unable to find '+Rdrive+Rpath);
- end;
- end
- else
- Beep;
- end;
-
- TAB_Key :begin
- Entry(UserSel+4+l,b,o,MBuffer);
- RunInfo(MBuffer.Buf[b,o],Rname,Rpath,Rdrive,Rparm,Rflag,Rhelp);
- If Rhelp=0 then
- begin
- Beep;
- Message('Help not available');
- end
- else
- begin
- If not HelpCheck then
- ReadHelp(HFname,HelpAvailable);
- HelpCheck:=true;
- If HelpAvailable then
- begin
- DisplayHelp(Rhelp,HBuffer);
- DisplayMenu(UserSel,MBuffer);
- end
- else
- begin
- Beep;
- Message('Help not available');
- end;
- end;
- end;
-
- #$20 :begin
- k:=(UserSel+1) mod l;
- HighLight(UserSel,k,MBuffer);
- end;
-
- BACKSPACE_Key :begin
- if k>0 then
- k:=UserSel-1
- else
- k:=l-1;
- HighLight(UserSel,k,MBuffer);
- end;
- end
- else
- If Pos(t,FirstLetter)<>0 then
- begin
- k:=Pos(t,Copy(FirstLetter,UserSel+2,l));
- If k=0 then
- k:=Pos(t,Copy(FirstLetter,1,UserSel))
- else
- k:=k+UserSel+1;
- if k=0 then
- Beep
- else
- HighLight(UserSel,k-1,MBuffer);
- end
- else
- Beep;
- end;
- GotoXY(1,1);write(Time);
- GotoXY(71,1);write(CurrentDate);
- Until t=ESCAPE_Key;
- end;
- ReturnToPath(CDrive+CurrentDir);
- end;
-
-
-
- {*Include File End DISPMENU.INC ***** END *****}
-
- begin
- NoCursor:=$1f1f;
- NormalCursor:=MemW[$0040:$0060];
- SwitchChar:=GetDOSswitch;
- CursorSize(NoCursor);
- repeat
- Menu('menu.dat','','',Ok);
- Until not Ok;
- CursorSize(NormalCursor);
- end.