home *** CD-ROM | disk | FTP | other *** search
- {$R-,S-,I+,D+,T+,F-,V-,B-,N-,L+ }
- UNIT KTOOLS;{ver 3.0}
-
- INTERFACE
- USES
- Dos,
- Crt;
-
- TYPE
- Colors = 0..15;
- MenuItemType = String[30];
- MenuDescType = String[80];
- ScrType = Array[1..4004] OF Byte;
- SaveScrType = ^ScrType;
- BorderType = Record
- TL,TR,BL,BR,FH,FV : Char;
- End;
- AllFiles=ARRAY[1..500] of String[12];
-
- CONST
- Border1 : BorderType = (TL:'╔';TR:'╗';BL:'╚';BR:'╝';FH:'═';FV:'║');
- Border2 : BorderType = (TL:'╒';TR:'╕';BL:'╘';BR:'╛';FH:'═';FV:'│');
- Border3 : BorderType = (TL:'┌';TR:'┐';BL:'└';BR:'┘';FH:'─';FV:'│');
- Border4 : BorderType = (TL:'░';TR:'░';BL:'░';BR:'░';FH:'░';FV:'░');
- Border5 : BorderType = (TL:'▓';TR:'▓';BL:'▓';BR:'▓';FH:'▓';FV:'▓');
-
- VAR
- ActiveDP : Byte; (* Active Display Page *)
- LineWidth : Integer; (* Line Width of current video mode *)
- VideoMode : Byte; (* Current Video Mode i.e. 0,1,2,3,7 *)
- ErrorCode : Integer; (* Global integer for error traps *)
-
- FUNCTION CurrentVideoMode : Byte;
- (*
- This function returns the current video mode... 0..3 = color, 7 = mono.
- Global variables LineWidth & ActiveDP are set each time this function
- is called.
- *)
-
- PROCEDURE CursorOn;
- (*
- This procedure checks the current video mode and restores a normal cursor.
- *)
-
- PROCEDURE CursorOff;
- (*
- This procedure sets bit five of the cursor control byte, turning the cursor
- off.
- *)
-
- FUNCTION KUCase(S:String):String;
- (*
- This function uses upcase procedure to convert an entire string or line from
- a text file to all uppercase characters.
- *)
-
- FUNCTION KLCase(S:String):String;
- (*
- This function uses CHR & ORD and does just the oppsite of KUCase.
- *)
-
- FUNCTION Color(FG,BG:Colors):Byte;
- (*
- This function returns the color attribute result for the combo FG on BG.
- The blinking bit is removed.
- *)
-
- PROCEDURE KAttr(Row,Col,Rows,Cols:Integer;Attr:Byte);
- (*
- This procedure puts the specified Attribute beginning at Row/Col and goes
- Cols by Rows.
- *)
-
- PROCEDURE KFill(Row,Col,Rows,Cols:Integer;Ch:Char;Attr:Byte);
- (*
- This procedure puts the specified Character beginning at Row/Col and goes
- Cols by Rows.
- *)
-
- PROCEDURE KTrim(VAR S:String);
- (*
- This procedure trims all leading and trailing blanks from a string.
- *)
-
- PROCEDURE KWrite(Row,Col:Integer;Attr:Byte;S:String);
- (*
- This procedure writes at string beginning at Row/Col with text Attr.
- It looks for the actual param on the stack.
- *)
-
- PROCEDURE KWriteV(Row,Col:Integer;Attr:Byte;VAR S:String);
- (*
- This procedure writes at string beginning at Row/Col with text Attr.
- It looks for the param address on the stack.
- *)
-
- PROCEDURE KWriteC(Row:Integer;Attr:Byte;S:String);
- (*
- This procedure writes at string beginning at Row/Col with text Attr.
- The output is centered on the screen between column 1 & 80.
- *)
-
- PROCEDURE KWriteCV(Row:Integer;Attr:Byte;VAR S:String);
- (*
- This procedure writes at string beginning at Row/Col with text Attr.
- The output is centered on the screen between column 1 & 80.
- It looks for the param address on the stack.
- *)
-
-
- FUNCTION ReadPen:Integer;
- (*
- This function reads the current position of the light pen after it has been
- triggered and returns the value in ReadPen as an integer
- *)
-
- FUNCTION PenPosition(Row,Col:Byte):Integer;
- (*
- This function returns an integer value of Row/Col which corresponds to the
- integer value that is returned when a call to ReadPen is made.
- *)
-
- FUNCTION PenRow(Pen_Position:Integer):Byte;
- (*
- This function returns the row pointed to by the integer value Pen_Position.
- *)
-
- FUNCTION PenCol(Pen_Position:Integer):Byte;
- (*
- This function returns the col pointed to by the integer value Pen_Position.
- *)
-
- (*
- NOTE: Uses for the light pen routines;
-
- ReadPen :
- Will return the position selected by the light pen if it has been
- triggered. Otherwise ReadPen returns 0. The integer value contains
- the row position in the Hi byte and the column in the Lo byte.
-
- PenPosition :
- This routine is useful for calculating the integer value for
- a particular screen row and col. The integer value can be
- matched aganist the value returned by ReadPen to determine
- a programs action.
-
- PenRow : This returns the row position and is good for program action based
- on input of a particular screen row instead of an X/Y location.
-
- PenCol : This returns the col position and is good for program action based
- on input of a particular screen column instead of a X/Y location.
-
- *)
-
-
- PROCEDURE KSaveScr(ULRow,ULCol,Rows,Cols : Byte;
- VAR Dest_Variable : SaveScrType);
- (*
- This procedure will start at ULRow/ULCol and store the screen area between
- Rows/Cols to the variable Dest_Variable. The first four bytes of Dest_Variable
- contain 1)ULRow 2)ULCol 3)Rows 4)Cols thus the screen is restored simply by
- calling KRestoreScr(Source_Variable);
- *)
-
- PROCEDURE KRestoreScr(Source_Variable : SaveScrType);
- (*
- This procedure restores to the screen, the contents of Source_Variable. The
- first four bytes point to the area of the screen where Source_Variable is to be
- put. I decided on this way since with other types of screen saving routines
- I was continually having to go back and see what coordinates I used for a given
- screen save.
- -------------------------------------------------------------------------------
- NOTE KSaveScr & KRestoreScr are not as fast as similar inline routines and
- are not meant to be. Rather they display the ability of using easy to use
- BIOS routines interfaced with TP4's built in speed to accomplish the task.
- *)
-
-
- PROCEDURE KBox (ULRow,ULCol,Rows,Cols: Integer;
- FrameAttr,WindowAttr : Byte;
- Border : BorderType;
- ClearWindow : Boolean);
- (*
- This procedure draws a box using 1 of 5 frame types. The fore/background colors
- of the frame must be given as well as a color for the actual window. ClearWindow
- is a flag to clear the window area using WindowAttr with blanks/spaces or leave
- the contents inside the window intact. If the window is not cleared then the
- text attribute of the window is unchanged.
- *)
-
- FUNCTION KVertMenu(Selection_Start : INTEGER; {starting menu selection hilited}
- VAR MenuList; {list of menu items }
- MenuItemTotal, {total number of menu items }
- XStart, {starting column position }
- YStart, {starting row postition }
- XHiliteStart, {hilite starting column number }
- LengthOfHilite, {number of columns to hilite }
- NormalAttr, {normal text attribute for menu }
- HiliteAttr : {attribute of hilited item }
- INTEGER):INTEGER; {function returns integer value }
- (*
- This procedure takes a array of items of menuitemtype and produces a vertical
- menu of those items. On return KVertMenu holds the choice number as integer
- type. - MenuList - is a untyped variable, assigned to in the procedure by turbo's
- absolute statement. If menuitemtotal is greater than your actual number of
- menu items then the extra will show up as garbage plucked from ram most likely.
- Since Menu is declared as VAR we deal directly with the data in memory and not
- a mirror image, however no alteration of the data takes place and any extra
- memory locations read should be left unaltered. None the less, we all know
- that PC-Spooks abound in the strangest places.
- *)
-
- FUNCTION KHorizMenu(Selection_Start:INTEGER; {starting menu selection hilited}
- VAR MenuList, {list of menu items }
- MenuDesc; {description of each item }
- MenuItemTotal, {total number of menu items }
- MenuWindowWidth, {number of columns for menu }
- XStart, {starting column position }
- YStart, {starting row postition }
- NormalAttr, {normal text attribute for menu }
- HiliteAttr, {attribute of hilited item }
- DescAttr: {color for descriptions }
- INTEGER):INTEGER; {function returns integer value }
-
- (*
- This procedure takes a array of items of menuitemtype and produces a horizontal
- menu of those items, accompanied by an optional description of each item.
- On return KHorizMenu holds the choice number as integer type. MenuList - is an
- untyped variable, assigned to in the procedure by turbo's absolute statement.
- If menuitemtotal is greater than your actual number of menu items then the
- extra will show up as garbage plucked from ram most likely. Since Menu is
- declared as VAR we deal directly with the data in memory and not a mirror image
- However no alteration of the data takes place and any extra memory locations
- read should be left unaltered. None the less, we all know that PC-Spooks
- abound in the strangest places.
- *)
-
- PROCEDURE CopyFile(Input_File, {filename.ext of file to copy}
- Output_File {filename.ext of created file}
- :String;
- VAR Return_Code {DOS error return code}
- :Integer;
- EraseInputFile:Boolean);
- (*
- This procedure will copy Input_File to the file name created as OutPut_File.
- This is an actual carbon copy, therefore the filenames cannot be the same.
- Rename a file is supported through DOS. Rename a file automatically removes
- the old file. Therefore if "EraseInputFile" is true we will try and use the
- DOS function to copy the file to its new name. If renaming causes an
- error then the drives are most likely not the same and the procedure resorts
- to the copying routine. If "EraseInputFile" is false then the DOS function
- is bypassed and we simply make a carbon copy of the file.
- *)
-
-
- FUNCTION IntToHex(IntNum:Integer):String;
- (*
- This function takes and integer value as it's arg. and returns a Hexadecimal
- ASCII representation of type string.
- *)
-
-
- FUNCTION Space(Number:Integer):String;
- (*
- This function will return {Number} of spaces long of type string in SPACE.
- *)
-
-
- PROCEDURE DirFill(VAR Path:String; {declared search path}
- VAR Files:AllFiles; {array of all files in the directory}
- VAR Counter:Integer; {total number of files in the dir }
- IncludeDirListings:Boolean);
- (*
- Given the search path in PATH, an array of type ALLFILES is built into variable
- FILES. COUNTER holds the number of valid entries and thus the total number of
- files contained in FILES. If INCLUDEDIRLISTINGS is true then all directories
- within the passed dir path will be included in the array and may be selected
- *)
-
- PROCEDURE SortDir(VAR Files:AllFiles; {array of all files in the directory}
- VAR Counter:Integer); {number of files you want sorted in}
- {FILES up to the total number of files}
- (*
- This procedure will sort on name, the number of files you specify in counter.
- You can sort as many or few as you like remembering that those you don't sort
- will be in the same order as when the procedure was called. i.e. every file
- above COUNTER. Note also that since ALLFILES is an array up to 500, if you
- specify more files be sorted than you actually have, your gonna wind up with
- junk in the (COUNTER-Actual) number of first array positions. Or
- somewhereabouts as PC-Spooks go.
- *)
-
-
- FUNCTION PIKDIR(Path:String;IncludeDir:Boolean):String;
- (*
- The function returns the path/file in PIKDIR. The dirpath should be specified
- in PATH. If INCLUDEDIR is true then you will be able to move thru all avail-
- able directories to choose a file from. If INCLUDEDIR is false then only the
- files found in PATH will be available for selection.
-
- NOTE:PIKDIR will return the complete path+File. It will not return PATH without
- a file. This could be modified without hassel.
- *)
-
-
- IMPLEMENTATION
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION CurrentVideoMode:Byte;
- VAR
- Regs:Registers; {Registers defined in DOS unit}
- BEGIN
- Regs.AH := $F;
- Intr($10,Regs);
- CurrentVideoMode:=Regs.AL; {Assign video mode to function name}
- ActiveDP:=Regs.BH; {Active page returned in register BH}
- LineWidth:=Regs.AH; {Characters per line returned in AH}
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE CursorOn;
- VAR
- Regs:Registers; {Registers defined in DOS unit}
- Mode:Byte;
- BEGIN
- Mode := CurrentVideoMode; {get current video mode}
- IF Mode IN[0..3] THEN
- BEGIN
- Regs.AH := $01; { Restore Color Cursor }
- Regs.CH := $06;
- Regs.CL := $07;
- Intr($10,Regs);
- END
- ELSE
- IF Mode = 7 THEN
- BEGIN
- Regs.AH := $01; { Restore Mono Cursor }
- Regs.CH := $C;
- Regs.CL := $D;
- Intr($10,Regs);
- END
- ELSE
- BEGIN
- Regs.AH := $01; { We're gonna put a cursor }
- Regs.CH := $1; { on the screen no matter what }
- Regs.CL := $D; { one big block if all else fails }
- Intr($10,Regs);
- END;
-
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE CursorOff;
- VAR
- Regs:Registers;
- BEGIN { Set bit 5 of cursor control byte }
- Regs.AH := $01; { which turns cursor off }
- Regs.CH := $20;
- Intr($10,Regs);
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION KUCase(S:String):String;
- VAR
- I: integer;
- BEGIN
- FOR I := 1 TO Length(S) DO S[I] := UpCase(S[I]);
- KUCase := S;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION KLCase(S:String):String;
- VAR
- I: integer;
- BEGIN
- FOR I := 1 TO Length(S) DO
- IF S[I] IN['A'..'Z'] THEN {If character is A-Z }
- S[I]:=CHR(ORD(S[I])+$20);{Add HEX 20 ordinal value for lowercase}
- KLCase := S;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION Color(FG,BG:Colors):Byte;
- BEGIN
- Color := (FG+(BG SHL 4)) MOD 128;{shift BG 4 places left(nibble) and add FG}
- END; {MOD 128 removes the blink}
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KAttr(Row,Col,Rows,Cols:Integer;Attr:Byte);
- VAR
- Ch,X,Y,R,C:Integer;
- Regs:Registers;
- BEGIN
- R:=(Row+(Rows-1));
- C:=(Col+(Cols-1));
- REPEAT
- X:=Col;
- REPEAT
- GOTOxy(x,Row); {BIOS call to read screen character}
- Regs.AH:=$08; {and attribute }
- Regs.BH:=ActiveDP; {Specify active page}
- Intr($10,Regs);
-
- { Regs.AL contains the character read with service 8.}
-
- Regs.AH:=$09; {BIOS call to write Character and}
- {attribute to screen}
- Regs.BH:=ActiveDP; {Specify active page}
- Regs.BL:=Attr; {Specify attribute }
- Regs.CX:=$01; {write it once }
- Intr($10,Regs);
- X:=X+1; {INC X i.e col position}
- UNTIL X>C;
- Row:=Row+1; {INC Row i.e. Row position}
- UNTIL Row > R;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KFill(Row,Col,Rows,Cols:Integer;Ch:Char;Attr:Byte);
- VAR
- R:Integer;
- Regs:Registers;
-
- (**)
-
- BEGIN
- R:=(Row+(Rows-1));
- REPEAT
- GOTOxy(col,Row);
- Regs.AH:=$09;
- Regs.AL:=ORD(Ch);
- Regs.BH:=ActiveDP;
- Regs.BL:=Attr;
- Regs.CX:=cols;
- Intr($10,Regs);
- Row:=Row+1;
- UNTIL Row > R;
- END;
-
- (*
-
- {If you don't want to use the Bios calls, comment them out and open this
- section up and recompile. NOTE: BIOS is slower than write if DirectVideo is
- set to true, however by placing the number of cols to fill in the repeating
- register CX the difference is only slightly noticable.}
-
- S : String;
- SavedTextAttr:Integer;
-
- BEGIN
- S:='';
- FOR X := 1 to Cols DO
- S:=S+Ch;
- R:=(Row+(Rows-1));
- SavedTextAttr:=CRT.TextAttr;
- CRT.TextAttr:=Attr;
- REPEAT
- GOTOxy(Col,Row);
- Write(s);
- Row:=Row+1;
- UNTIL Row > R;
- CRT.TextAttr:=SavedTextAttr
- END;
- *)
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KTrim(VAR s : string);
- VAR
- x,b,e : Integer;
- BEGIN
- For X := 1 to LENGTH(s) DO
- IF s[1]=' ' THEN DELETE(S,1,1); {delete leading spaces}
-
- {This may look wrong to check the entire string, but we look at }
- {S[ 1 ] each time and delete blanks at same until a character appears]
- {From that point on S[1] stays the first character we skipped;}
- {This would work as well
- REPEAT
- IF s[1] = ' ' THEN DELETE(S,1,1);
- UNTIL s[1] <> ' ';
-
- and on lengthy strings would be faster. }
-
- b:=1;
- e:=ORD(s[0]);
- REPEAT
- IF s[e] = ' ' THEN DELETE(S,e,1);
- DEC(e);
- UNTIL s[e] <> ' ';
-
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- (*
- The following procedures are straight forward enough and no BIOS is used
- in the code. TEXTATTR is assigned in the CRT unit and referrenced as
- CRT.TextAttr. This holds the attribute of the current video page and not
- necessarily a certain character pos. Thus we save it and change it before
- we write to the screen with our string. Then we put it back the way we
- found it. Centering Text is simply taking the LineWidth minus the length
- of the string divided by 2, which gives us the starting column for our
- gotoxy(?,Row) statement.
- *)
-
- PROCEDURE KWrite(Row,Col:Integer;Attr:Byte;S:String);
- VAR {S is actual 'Hello World' or variable }
- SavedTextAttr:Integer; {VarParm := 'Hello World' }
- BEGIN
- SavedTextAttr:=CRT.TextAttr;
- CRT.TextAttr:=Attr;
- GotoXY(Col,Row);
- Write(s);
- CRT.TextAttr:=SavedTextAttr
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KWriteV(Row,Col:Integer;Attr:Byte;VAR S:String);
- VAR {S must be a variable, only the address is passed}
- SavedTextAttr:Integer; {to save space on the stack}
- BEGIN
- SavedTextAttr:=CRT.TextAttr; {Save current page text attribute}
- CRT.TextAttr:=Attr; {Assign our attribute value}
- GotoXY(Col,Row); {Move cursor to our strating Pos.}
- Write(s); {Write our string and attribute}
- CRT.TextAttr:=SavedTextAttr; {Restore original text attribute}
-
- {We want to restore the original so that TURBO's write & writeln will
- function with a specified global attribute in CRT.TextAttr and we can
- still write our own with no interference}
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KWriteC(Row:Integer;Attr:Byte;S:String);
- VAR
- X,SavedTextAttr:Integer;
- BEGIN
- SavedTextAttr:=CRT.TextAttr;
- CRT.TextAttr:=Attr;
- X:=(LineWidth-Length(S)) DIV 2; {get cursor pos to write string centered}
- GotoXY(X,Row);
- Write(s);
- CRT.TextAttr:=SavedTextAttr
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KWriteCV(Row:Integer;Attr:Byte;VAR S:String);
- VAR
- X,SavedTextAttr:Integer;
- BEGIN
- SavedTextAttr:=CRT.TextAttr;
- CRT.TextAttr:=Attr;
- X:=(LineWidth-Length(S)) DIV 2;
- GotoXY(X,Row);
- Write(s);
- CRT.TextAttr:=SavedTextAttr
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION ReadPen:Integer;
- VAR Regs : Registers;
- BEGIN
- Regs.AH := 4;
- Intr($10,Regs);
- IF Regs.AH = 1 THEN ReadPen := Regs.DX;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION PenPosition(Row,Col:Byte):Integer;
- BEGIN
- PenPosition := (Row SHL 8)+Col;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION PenRow(Pen_Position:Integer):Byte;
- BEGIN
- PenRow := Hi(Pen_Position);
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION PenCol(Pen_Position:Integer):Byte;
- BEGIN
- PenCol := Lo(Pen_Position);
- END;
- (*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KSaveScr(ULRow,ULCol,Rows,Cols : Byte;
- VAR Dest_Variable : SaveScrType);
- VAR
- Ch,X,Y,R,C,Counter:Integer;
- Regs:Registers;
- BEGIN
- R:=(ULRow+(Rows-1));
- C:=(ULCol+(Cols-1));
- Dest_Variable^[1]:=ULRow; {Store the Ystart,Xstart, number of rows}
- Dest_Variable^[2]:=ULCol; {and number of columns in the first 4 pos}
- Dest_Variable^[3]:=Rows; {of the variable}
- Dest_Variable^[4]:=Cols;
- Counter := 5; {Set counter to first byte of the actual screen information}
- REPEAT
- X:=ULCol;
- REPEAT
- GOTOxy(x,ULRow);
- Regs.AH:=$08; {BIOS function number}
- Regs.BH:=ActiveDP;{active display page}
- Intr($10,Regs); {call the interrupt}
- Dest_Variable^[Counter]:=Regs.AL; {Character Read}
- INC(Counter);
- Dest_Variable^[Counter]:=Regs.AH; {Attribute Read}
- INC(Counter);
- INC(X); {INC X i.e col position}
- UNTIL X>C;
- INC(ULRow); {INC Row i.e. Row position}
- UNTIL ULRow > R;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KRestoreScr(Source_Variable : SaveScrType);
- VAR
- Ch,X,Y,R,C,
- Row,Col,Counter:Integer;
- Regs:Registers;
- BEGIN
- R:=(Source_Variable^[1]+(Source_Variable^[3]-1));
- C:=(Source_Variable^[2]+(Source_Variable^[4]-1));
- Row := Source_Variable^[1];
- Col := Source_Variable^[2];
- Counter := 5;
- REPEAT
- X:=Col;
- REPEAT
- GOTOxy(x,Row); {BIOS call to read screen character}
- Regs.AH:=$09; {BIOS call to write Character and}
- {attribute to screen}
- Regs.AL:=Source_Variable^[Counter]; {Specify Character }
- INC(Counter);
- Regs.BL:=Source_Variable^[Counter]; {Specify Attribute }
- INC(Counter);
- Regs.BH:=ActiveDP; {Specify active page}
- Regs.CX:=$01; {write it once }
- Intr($10,Regs);
- INC(X); {INC X i.e col position}
- UNTIL X>C;
- INC(Row); {INC Row i.e. Row position}
- UNTIL Row > R;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- PROCEDURE KBox (ULRow,ULCol,Rows,Cols: Integer;
- FrameAttr,WindowAttr : Byte;
- Border : BorderType;
- ClearWindow : Boolean);
- VAR
- Y,Wh,Wl,H,L : Integer;
- BEGIN
- IF (Rows>=2) AND (Cols>=2) THEN {box can be no smaller than 2x2}
- BEGIN {which ain't much of a box really}
- L:=Lo(WindMin);H:=Hi(WindMin);
- Wl:=Lo(WindMax);Wh:=Hi(WindMax);
- WindMax:=(25 SHL 8)+Wl; {can go past last row by 1 row }
- WITH Border DO {save ourselves some typing via "WITH (record name) DO}
- BEGIN
- KWrite(ULRow,ULCol,FrameAttr,TL); {top left corner}
- KFill(ULRow,ULCol+1,1,Cols-2,FH,FrameAttr); {fill cols with horiz char}
- KWrite(ULRow,ULCol+Cols-1,FrameAttr,TR); {top right corner}
- FOR Y := ULRow+1 TO ULRow+Rows-2 DO
- BEGIN
- KWrite(Y,ULCol,FrameAttr,FV); {loop thru and put the vertical}
- KWrite(Y,ULCol+Cols-1,FrameAttr,FV); {char on both sides}
- END;
- KWrite(ULRow+Rows-1,ULCol,FrameAttr,BL); {bottom left corner}
- KFill(ULRow+Rows-1,ULCol+1,1,Cols-2,FH,FrameAttr); {fill cols with horiz}
- KWrite(ULRow+Rows-1,ULCol+Cols-1,FrameAttr,BR); {Bottom right corner}
-
- IF ClearWindow THEN {if true then clear out the window}
- KFill (ULRow+1,ULCol+1,Rows-2,Cols-2,' ',WindowAttr);
-
- WindMax:=(Wh SHL 8)+Wl; {restore bottom corner of window }
- Window(L,H,Wl,Wh); {restore original window screen}
- GOTOxy(1,1); {don't leave the cursor hid on line 26}
- END
- END
- END;
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION KVertMenu(Selection_Start : INTEGER; {starting menu selection hilited}
- VAR MenuList; {list of menu items }
- MenuItemTotal, {total number of menu items }
- XStart, {starting column position }
- YStart, {starting row postition }
- XHiliteStart, {hilite starting column number }
- LengthOfHilite, {number of columns to hilite }
- NormalAttr, {normal text attribute for menu }
- HiliteAttr : {attribute of hilited item }
- INTEGER):INTEGER; {function returns integer value }
-
-
- VAR
- Menu : Array[1..2] OF MenuItemType absolute MenuList;
- SelectionMade : Boolean; {understand the use of "absolute" before}
- X,Y : INTEGER; {you use it in earnest, and save yourself}
- Row,Col,Rows,Cols, {many headaches}
- Choice : INTEGER;
- Ch : Char;
-
- BEGIN
- Col := XHiliteStart;
- Rows := 1;
- Cols := LengthOfHilite;
- Choice := Selection_Start;
- FOR y := 0 to MenuItemTotal-1 DO {put up the menu list}
- KWrite(YStart+y,XStart,NormalAttr,Menu[y+1]);
- Row := YStart+Selection_Start-1; {Row Position to hilite first}
- KAttr(Row,Col,Rows,Cols,HiliteAttr);
- SelectionMade := False; {haven't made a selection yet}
-
- REPEAT
- Ch := ReadKey;
- IF Ch = #13 THEN { if ENTER then }
- BEGIN
- KVertMenu := Choice; {assign KVertmenu your choice}
- SelectionMade := True; {selection has been made}
- END
- ELSE
- IF Ch = #27 THEN { if ESC then }
- BEGIN
- KVertMenu := 0; { assign KVertMenu 0 because we have no 0 item }
- EXIT; { test for 0 = (No OPeration) in your program }
- END { it's a way out of indecision on the users part}
- ELSE
- IF Ch = #0 Then { if ch = 0 then we have an extended key }
- Ch := ReadKey; { TP4 docs say we'll never have a ch=0 except }
- CASE Ch OF { for extended keys. no more null spooks }
-
- #72 : BEGIN {UP arrow key}
- KAttr(Row,Col,Rows,Cols,NormalAttr);
- IF Choice = 1 THEN BEGIN
- Choice := MenuItemTotal;
- Row := Ystart+MenuItemTotal-1;
- END
- ELSE
- BEGIN
- Choice := Choice-1;
- Row := Row-1;
- END;
- KAttr(Row,Col,Rows,Cols,HiliteAttr);
- END;
- #80 : BEGIN {DOWN arrow}
- KAttr(Row,Col,Rows,Cols,NormalAttr);
- IF Choice = MenuItemTotal THEN BEGIN
- Choice := 1;
- Row := Ystart;
- END
- ELSE
- BEGIN
- Choice := Choice+1;
- Row := Row+1;
- END;
- KAttr(Row,Col,Rows,Cols,HiliteAttr);
- END;
- END;
- UNTIL SelectionMade;
- END;
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
-
- FUNCTION KHorizMenu(Selection_Start:INTEGER; {starting menu selection hilited}
- VAR MenuList, {list of menu items }
- MenuDesc; {description of each item }
- MenuItemTotal, {total number of menu items }
- MenuWindowWidth, {number of columns for menu }
- XStart, {starting column position }
- YStart, {starting row postition }
- NormalAttr, {normal text attribute for menu }
- HiliteAttr, {attribute of hilited item }
- DescAttr: {color for descriptions }
- INTEGER):INTEGER; {function returns integer value }
-
- VAR
- Menu : Array[1..2] OF MenuItemType absolute MenuList;
- Desc : Array[1..2] OF MenuDescType absolute MenuDesc;
-
- (*
- MenuDescType is defined as String[80], hence your description can be 80
- characters in length. However, it is your responsibility to check that
- your description fits inside your specified -MenuWindowWidth-. This is
- obvious if you should box around your menu and the description is too
- long. MenuWindowWidth defines the confines of the MenuList and not the
- description.
- *)
-
- MPos : Array[1..25] OF Integer; {screen pos for each item}
- PageBreak : Array[1..10,0..1] OF Integer; {start & end item number per page}
-
- SelectionMade : Boolean;
- X,Y,Space,Page,
- Row,Col,
- Choice,TotalX,
- Position,MaxPage : INTEGER;
- Ch : Char;
-
-
- FUNCTION MenuItemLength(A:Integer):Integer; { length of a menu item }
- BEGIN
- MenuItemLength := ORD(Menu[A][0]);
- END;
-
- FUNCTION MenuDescLength(A:Integer):Integer; { Length of a description }
- BEGIN
- MenuDescLength := ORD(Desc[A][0]);
- END;
-
- BEGIN (* KHorizMenu *)
- Row := YStart;
- Col := XStart;
- Space := 3; { distance between items }
- Page := 1; { define 1st page and Max Page though we }
- MaxPage := 1; { may change them shortly }
- TotalX := XStart; { TotalX is an accumulator }
- Position := Selection_Start; { define item position to default }
- SelectionMade := False; { we haven't picked one yet }
- PageBreak[MaxPage][0] := 1; { start with item 1 page 1 }
-
- FOR X := 1 TO MenuItemTotal DO
- BEGIN
- IF ( (TotalX-XStart)+MenuItemLength(X) > MenuWindowWidth ) THEN
- BEGIN { If we exceed our windowwidth }
- PageBreak[MaxPage][1] := X-1; {set current page end }
- INC(MaxPage); {increase page by 1 }
- PageBreak[MaxPage][0] := X; {Set new page begin }
- TotalX := XStart; {reset our accumulator }
- MPos[X] := TotalX; {assign screen position }
- END
- ELSE
- MPos[X] := TotalX; { otherwise assign current totalx to MPos[x]}
-
- IF X = MenuItemTotal THEN { ensure last page break holds our }
- PageBreak[MaxPage][1] := X; { total number of menu items }
-
- IF X = Selection_Start THEN { match up the correct page }
- Page := MaxPage; { to our selection default }
-
- TotalX := TotalX+Space+MenuItemLength(X);
- END;
- (*
- MaxPage is used above as our paging referrence. After this loop is
- completed, each page break is defined as well as the starting position
- for each menu item. The variable PAGE is assigned the current MaxPage
- when X and Selection_Start matchup which lets us display the page
- containing our default selection first.
- *)
-
- WHILE NOT SelectionMade DO
- BEGIN
-
- KFIll(Row,XStart,1,MenuWindowWidth,' ',NormalAttr);{clear item portion of window}
-
- FOR X := PageBreak[Page][0] TO PageBreak[Page][1] DO {loop through page and}
- BEGIN {put up the items }
- KWrite(Row,MPos[x],NormalAttr,Menu[X]);
- END;
-
- KAttr(Row,MPos[Position],1,MenuItemLength(Position),HiLiteAttr);{hilite position}
- KWrite(Row+1,XStart,DescAttr,Desc[Position]); {write the items description}
-
- Choice := Position; {useless exchange but it looked nice and neat}
- Ch := ReadKey; {wait for a keystroke}
- IF Ch = #13 THEN { if ENTER then }
- BEGIN
- KHorizMenu := Choice; {assign KHorizMenu your choice}
- SelectionMade := True; {selection has been made}
- END
- ELSE
- IF Ch = #27 THEN { if ESC then }
- BEGIN
- KHorizMenu := 0; { assign KHorizMenu 0 because we have no 0 item }
- EXIT; { test for (0 = No OPeration) in your program }
- END { it's a way out of indecision on the users part }
- ELSE
- IF Ch = #0 Then { if ch = 0 then we have an extended key }
- Ch := ReadKey; { TP4 docs say we'll never have a ch=0 except }
- { for extended keys. no more null spooks }
- (*
- The key handling routines are easily enough understood by the use of the names
- as variables. More programmers should realize that fact.
- The first action taken in both routines is to clear the hilited item and then
- clear the items description from the screen. Notice that we use the length of
- the description as our COLS referrence, thus we clear only what we put up in
- the current description. No mess no hastle.
- *)
-
- CASE Ch OF
- #75 : BEGIN {left arrow key}
- KAttr(Row,MPos[Position],1,MenuItemLength(Position),NormalAttr);
- KFIll(Row+1,XStart,1,MenuDescLength(Position),' ',DescAttr);
-
- IF (Position = 1) AND (Page = 1) THEN
- BEGIN
- Position := MenuItemTotal;
- Page := MaxPage;
- END
- ELSE
- IF Position = PageBreak[Page][0] THEN
- BEGIN
- DEC(Position);
- DEC(Page);
- END
- ELSE
- DEC(Position);
- END;
-
- #77 : BEGIN {right arrow key}
- KAttr(Row,MPos[Position],1,MenuItemLength(Position),NormalAttr);
- KFIll(Row+1,XStart,1,MenuDescLength(Position),' ',DescAttr);
-
- IF Position = MenuItemTotal THEN
- BEGIN
- Position := 1;
- Page := 1;
- END
- ELSE
- IF Position = PageBreak[Page][1] THEN
- BEGIN
- INC(Position);
- INC(Page);
- END
- ELSE
- INC(Position);
- END;
- END;
- END; {while do}
- END;
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- PROCEDURE SortDir(VAR Files:AllFiles;VAR Counter:Integer);
- VAR
- Flag:Boolean;
- X:Integer;
- Temp:String[12];
-
- BEGIN
- Flag:=False;
- REPEAT
- Flag:=False;
- FOR X:=2 TO Counter DO {we stay one ahead of ourselves so start on 2}
- IF (Files[X][1]='<') AND (Files[X-1][1]<>'<') THEN
- BEGIN {-----------------------------------}
- Flag:=True; { First we sort out all DIRECTORY }
- {swap things} Temp:=Files[X-1]; { entries in the array. ( They will }
- {around here} Files[X-1]:=Files[X]; { occupy the first positions in the }
- Files[X]:=Temp; { array.) processing the file names }
- END { as we go along. Examining the three}
- UNTIL NOT Flag; { sets of IF routines will show that}
- REPEAT { we look for dir/dir, dir/file, & }
- Flag:=False; { then file/file. }
- FOR X:=2 TO Counter DO {-----------------------------------}
- IF (Files[X][1]='<') AND (Files[X-1][1]='<') THEN
- IF Files[X]<Files[X-1] THEN
- BEGIN
- Flag:=True;
- {ditto} Temp:=Files[X-1];
- Files[X-1]:=Files[X];
- Files[X]:=Temp;
- END
- ELSE
- ELSE
- IF (Files[X]<Files[X-1]) AND (Files[X-1][1]<>'<') THEN
- BEGIN
- Flag:=True;
- Temp:=Files[X-1];
- {ditto} Files[X-1]:=Files[X];
- Files[X]:=Temp;
- END;
- UNTIL NOT Flag;
- END;
-
-
- (*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- PROCEDURE DirFill(VAR Path:String;VAR Files:AllFiles;
- VAR Counter:Integer;IncludeDirListings:Boolean);
- VAR
- Attri:Byte;
- SRec:SearchRec; { searchrec is defined in the DOS unit of TP4 }
-
- BEGIN
- Attri:=$3F; { attribute of anyfile at all }
- Counter:=0; { set accumulator to 0 }
- FindFirst(Path,Attri,SRec); { TP4 function of DOS function Find First File}
- IF DosError=0 THEN {no problems then go ahead}
- REPEAT
- IF SRec.Name<>'.' THEN {ignore in first directory listing}
- BEGIN
-
- IF IncludeDirListings THEN
- BEGIN
- INC(Counter); {valid file so increase accumualtor by 1}
- IF SRec.Attr=Directory THEN
- Files[Counter]:='<'+SRec.Name+'>' {notate a directory entry}
- ELSE
- Files[Counter]:=SRec.Name; {add it as a file entry}
- END;
-
- IF NOT IncludeDirListings THEN
- IF SRec.Attr<>Directory THEN
- BEGIN
- INC(Counter); {valid file so increase accumualtor by 1}
- Files[Counter]:=SRec.Name; {add it as a file entry}
- END;
-
- END;
- Attri:=$3F; {reset searchrec attribute to anyfile}
- FindNext(SRec); {TP4 function of DOS function to Find Next File}
- UNTIL DosError<>0; {loop until we're out of files (i.e. DosError:=18)}
- END;
-
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- FUNCTION Space(Number:Integer):String;
-
- VAR
- X:Integer;
- TempSpace:String;
-
- BEGIN
- TempSpace:='';
- FOR X:=1 TO Number DO {make up a string of spaces from}
- TempSpace:=TempSpace+' '; {1 to Number long}
- Space:=TempSpace;
- END;
-
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- PROCEDURE CopyFile (Input_File,Output_File:String;
- VAR Return_Code:integer;EraseInputFile:Boolean);
- CONST
- RecordSize = 128;
- RecordNum = 128;
- TYPE
- CopyBuffer = array[1..RecordSize,1..RecordNum] of byte;
-
- VAR
- DOS_Return_Code : Boolean;
- Regs : Registers;
- FileIn,FileOut : File; {untyped file variables}
- CopyBufrPtr : ^CopyBuffer; {the use of a pointer here keeps our program}
- RecordCount : Integer; {from carrying around such a large buffer}
- {throughout it's duration}
- BEGIN
- KTrim(Input_File);
- KTrim(OutPut_File);
- IF Input_File=OutPut_File THEN {if the file names are exact then we're in}
- BEGIN {trouble}
- Return_Code := 5; {access denied code file already exists}
- ErrorCode := Return_Code;
- EXIT; {bailout before we Bombout}
- END;
- DOS_Return_Code := False; {false so copyfile will work anyway}
- Assign(FileIn,Input_File); {tell TP4 about the input file}
- Assign(FileOut,Output_File); { '' '' '' ' oputput file}
- {$I-}
- Reset(FileIn); {does such a file really exist?}
- {$I+}
- Return_Code := IOresult;
- IF (Return_Code = 0) THEN {if it does then we can proceed}
- BEGIN
- IF EraseInputFile THEN { if we want to erase the input file }
- BEGIN
- Input_File:=Input_File+Chr(0); { then we will try the dos rename }
- OutPut_File:=OutPut_File+Chr(0);{ function first. This will move or }
- Regs.Ah:=$56; { change the files directory and not }
- Regs.DS:=seg(Input_File); { take time copying the actual file }
- Regs.Dx:=ofs(Input_File[1]); { data. }
- Regs.ES:=seg(OutPut_File);
- Regs.DI:=ofs(OutPut_File[1]);
- MsDos(Regs);
- IF Regs.AX = 0 THEN DOS_Return_Code := True
- ELSE DOS_Return_Code := False;{not the same drive}
- END;
-
- IF NOT DOS_Return_Code THEN {dos couldn't do it so we'll copy the data}
- BEGIN {or we want a carbon copy of the file}
- ReWrite(FileOut); {create the output file}
- New(CopyBufrPtr); {initialize our copy buffer}
- REPEAT
- Blockread(FileIn,CopyBufrPtr^,RecordNum,RecordCount);
- {read data in}
- Blockwrite(FileOut,CopyBufrPtr^,RecordCount);
- {write data out}
- UNTIL RecordCount = 0;
- Dispose(CopyBufrPtr); {give up our buffer memory to dos}
- Close(FileIn);
- Close(FileOut);
- IF EraseInputFile THEN {$I-}Erase(filein){$I+};
- ErrorCode := IOresult;
- Return_Code := ErrorCode;
- END; { this is your basic copyfile example with additions and subs }
- END; { better error checking and assorted features could still be }
- END; { to enhance the performance of this routine. }
-
-
- (*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- FUNCTION IntToHex;
- CONST
- HexChars: ARRAY[0..15] of char ='0123456789ABCDEF';
- VAR
- Temp:Byte;
- TempStr:String[2];
- BEGIN
- Temp:=Hi(IntNum); {get and convert hi byte to hex}
- TempStr:=HexChars[Temp shr 4]+HexChars[Temp and $0F];
- Temp:=lo(IntNum); {get and convert lo byte to hex}
- IntToHex:=TempStr+HexChars[Temp shr 4]+HexChars[Temp and $0F];
- END;
-
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- FUNCTION PIKDIR(Path:String;IncludeDir:Boolean):String;
-
- PROCEDURE Hilite(X:Integer);
- VAR
- Xcord,Row:Integer;
- BEGIN
- Xcord:=(Trunc((X-1)/17)*15)+5; {set col position for hiliting }
- Row:=(X-(17*Trunc((X-1)/17)))+4; {set row position for " }
- KAttr(Row,Xcord,1,12,79); {hilite the position}
- END;
-
- PROCEDURE LoLite(X:Integer);
- VAR
- Xcord,Row:Integer;
- BEGIN
- Xcord:=(Trunc((X-1)/17)*15)+5; {set col position for loliting }
- Row:=(X-(17*Trunc((X-1)/17)))+4; {set row position for " }
- KAttr(Row,Xcord,1,12,14); {hilite the position}
- END;
-
- VAR
- One:AllFiles;
- X,Y,N:Integer;
- TempCounter,Start,Counter,Counter2,Total:Integer;
- More,Temp:String;
- MoreD,Done:Boolean;
- Position,OldPosition,Old2Position,Old3Position,
- Old4Position,Old5Position,ULRBox,ULCBox,LRRBox,LRCBox:Integer;
- C:Char;
- Near,Far:Byte;
- SavedTxtAttr:Byte;
- MainScr,BoxScr: SaveScrType;
-
-
- PROCEDURE MakeBox;
- VAR
- X,Y,N:Integer;
- BEGIN
- SavedTxtAttr := TextAttr; {makebox goes thru the process }
- TextAttr := 14; {of determining the box size that}
- IF Counter>17 THEN Y:=Trunc(Counter/17)+1 {we will need to hold all the }
- ELSE Y:=1; {listings, as it writes the }
- Start:=10; {entries on the screen. }
- N:=Y;
- IF Y>5 THEN Y:=5;
- IF Counter>17 THEN Far:=22
- ELSE Far:=Counter+5;
- Near:=(Y*15)+3;
- ULRBox := 4;
- ULCBox := 3;
- LRRBox := Far-3;
- LRCBox := Near-2;
- KSaveScr(ULRBox,ULCBox,LRRBox,LRCBox,BoxScr);
- KBox(ULRBox,ULCBox,LRRBox,LRCBox,29,14,Border2,True);
- Y:=N;
- CursorOff;
- FOR N:=1 TO Y DO
- FOR X:=1 TO 17 DO
- BEGIN
- Total:=Total+1;
- GotoXy(5+((N-1)*15),X+4);
- IF (Total<=Counter) AND (Total<86) THEN Write(One[Total]);
- IF (MoreD) AND ((Counter+85)>=Total) THEN Write(One[Total]);
- END;
- Done:=False;
- TextAttr := SavedTxtAttr;
- Hilite(Position);
- END;
-
-
- BEGIN
- DirFill(Path,One,Counter,IncludeDIR);
- {fill array ONE with listings in PATH}
- SortDir(One,Counter); {sort the array}
- Total:=0;
- MoreD:=False;
- NEW(MainScr);
- KSaveScr(1,1,25,80,MainScr);
- Position:=1;
- OldPosition:=1;
- NEW(BoxScr);
- MakeBox;
- REPEAT
- IF KeyPressed THEN
- BEGIN
- C:=ReadKey;
- IF C=#13 THEN
- BEGIN
- IF MoreD THEN Position:=Position+85;
- IF One[Position][1]<>'<' THEN
- BEGIN
- Temp:='';
- FOR X:=1 TO Length(Path)-3 DO
- Temp:=Temp+Path[X];
- Path:=Temp+One[Position];
- PikDir := Path;
- DONE := True;
- END
- ELSE
- BEGIN
- Temp:='';
- FOR X:=1 TO Length(Path)-4 DO
- Temp:=Temp+Path[X];
- Path:=Temp;
- Temp:='';
- FOR X:=1 TO Length(One[Position]) DO
- IF (One[Position][X]<>'<') AND (One[Position][X]<>'>') THEN Temp:=Temp+One[Position][X];
- IF Temp<>'..' THEN
- BEGIN
- Path:=Path+'\'+Temp+'\*.*';
- Old5Position:=Old4Position;
- Old4Position:=Old3Position;
- Old3Position:=Old2Position;
- Old2Position:=OldPosition;
- OldPosition:=Position;
- Position:=1;
- END
- ELSE
- BEGIN
- X:=Length(Path)+1;
- REPEAT
- X:=X-1;
- UNTIL Path[X]='\';
- Path:=Copy(Path,1,X);
- Path:=Path+'*.*';
- Position:=OldPosition;
- OldPosition:=Old2Position;
- Old2Position:=Old3Position;
- Old3Position:=Old4Position;
- Old4Position:=Old5Position;
- END;
- KRestoreScr(BoxScr);
- DirFill(Path,One,Counter,IncludeDIR);
- SortDir(One,Counter);
- Total:=0;
- MoreD:=False;
- MakeBox;
- END;
- END;
- IF C=#0 THEN
- BEGIN
- Lolite(Position);
- C:=ReadKey;
- IF C=#68 THEN Done:=True;
- IF C=#80 THEN Position:=Position+1;
- IF C=#72 THEN Position:=Position-1;
- IF C=#75 THEN Position:=Position-17;
- IF C=#77 THEN Position:=Position+17;
- IF C=#73 THEN
- BEGIN
- IF MoreD THEN
- BEGIN
- Counter:=TempCounter;
- Total:=0;
- KRestoreScr(BoxScr);
- MoreD:=False;
- Position:=1;
- MakeBox;
- END;
- END;
- IF C=#81 THEN
- BEGIN
- IF Counter>85 THEN
- BEGIN
- TempCounter:=Counter;
- Counter:=Counter-85;
- KRestoreScr(BoxScr);
- Total:=85;
- MoreD:=True;
- Position:=1;
- MakeBox;
- END;
- END;
- IF Position<1 THEN Position:=1;
- IF Position>Counter THEN Position:=Counter;
- IF Position>85 THEN Position:=85;
- HiLite(Position);
- END;
-
- END;
- UNTIL Done;
- KRestoreScr(MainScr); {replace the main screen }
- DISPOSE(BoxScr); {free up heap space}
- DISPOSE(MainScr);
- END;
-
- (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
- (*
- This is done to initialize the ActiveDp and LineWidth variables when the
- program is first run. The VideoMode variable may also be used along with
- ActiveDP & LineWidth.
- *)
-
- BEGIN
- DirectVideo := TRUE;
- VideoMode := CurrentVideoMode;
- END.
-
- (******************************************************************************
-
- Additions & Revisions
- ~~~~~~~~~~~~~~~~~~~~~
-
- {010188 ver 2.0}
- Changed KFill : placed number of cols to fill in CX versa advancing cursor and
- writing one position per call to BIOS. I originally thought this would show how
- to use the bios calls to write to different x/y positions, however it was just
- to slow to be truly useful. The current code shows the use of the bios call
- plus the use of the CX register in this type of bios function.
-
- Added Function : KUCase,KLCase & Color.
-
- {010688 ver 2.1}
- Fixed bug in KTrim. Trailing blanks were not being seen inside FOR loop.
-
- Fixed bug in KBox which was advancing the screen one row when the 25,80 was
- passed as the bottom right corner of the box.
-
- {010788 ver 2.2}
- Added Function : KVertMenu & KHorizMenu
-
- {011188 ver 3.0}
- Added KSaveScr & KRestoreScr
- Added Functions for light pen use.
- Added IntoHex,Space,CopyFile
- Added DirFill,SortDir,PikDir
-
- My close friend and associate "Gary Smith" offered the use of his DIR. routines
- for KTOOLS. The originals remain with him. I have modified these for use in
- the KTOOLS package and offer him my sincere thanks.
- "The Programmer's Corner"
- 300-2400 (301)794-4331
- Sysop(Gary Smith)
- ******************************************************************************)