SLWindow and MenuUnit are TP4.0+ modules containing the windowing and menu routines used in Swiss Army Shell, a hard disk file management program being distributed as Shareware. Full source code is included.

Contents of the SLWINDOW.DOC file

SLWindow.Pas & MenuUnit.Pas Written by and Placed in the Public Domain by Steven C. Lee 71076,1216

SLWindow and MenuUnit are Turbo Pascal 4.0 units containingthe windowing and menu routines used in Swiss Army Shell, a harddisk file management program being distributed as Shareware. Swiss Army Shell is available as SAS10.ARC on Compuserve's IBMSoftware Forum in DL1 and on The ST BBS in Birmingham, Alabama(205)836-9311 300/1200/2400-8-N-1.

SLWindow and MenuUnit are written entirely in Turbo Pascal.I used the CURSORS unit by Scott Bussinger (available onCompuserve's BORPROGA) to turn the cursor off and on duringwindow writing, but SLWindow will work fine without it byremoving the MakeCursor statements.

SLWindow and MenuUnit are not fancy, and not as fast asassembler routines. However I have found their performance to bequite adequate even on my ancient 4.77 Mhz Columbia. They arevery easy to use and I am placing them in the public domain. Youmay do with them as you wish.

There is virtually no error checking, and they are designedto work only in CGA mode. Swiss Army Shell has been tested on anIBM PS/2 model 60 with VGA and worked fine, so these routinesshould work fine on CGA, EGA, or VGA in CGA mode.

SLWindow.Pas ------------

SLWindow provides one type - TextWindow - and thirteenprocedures and functions. It defines one variable - WholeScrn -which is automatically initialized at startup.

TextWindow is a record type which stores the upper left andlower right corners of the window. It also contains the windowtitle and the foreground and background colors of the window.

Windows are drawn with a one character border, so the upperleft corner should never be outside coordinates X = 2 and Y = 2.The lower right corner should never be outside X = 79 and Y = 24.The border characters are defined as constants which can bechanged to whatever you like.

SLWindow uses the heap to allocate memory to save windowcontents. You will need to allocate enough heap to store all ofthe windows you plan to use at one time, but since RestScrnreleases the memory when it restores the screen, the same memorymay be used for multiple windows as long as they are not saved ontop of each other. A minimum of 4000 bytes is required, sincethat is the amount used by WholeScrn. To calculate the amount ofheap required, you should use the following formula :

(X2 - X1 + 3) * (Y2 - Y1 + 3) * 2

This will give you the memory required for an individualwindow. You should figure this for your largest window, and ifyou will be performing multiple window saves between restores,you will need to allow for those as well. Remember that RestScrnwill free the memory used by SaveScrn, so you don't need enoughmemory to store all the windows in your program, just enough forthe maximum requirements of the windows on screen at one time. When you have totaled up the individual window requirements, add4000 for WholeScrn.

If you save the same window twice without calling RestScrnin between, when RestScrn is called you will get the contents ofthe screen when the second SaveScrn was performed. You will alsodestroy the pointer to the memory allocated by the first call toSaveScrn leaving you with no way to free it. (As I said, thereis virtually no error checking.) By changing the windowcoordinates between calls to SaveScrn and RestScrn you couldrestore the window to a different location on the screen.

The procedures and functions in SLWindow are describedbelow:

procedure PressaKey;--------------------PressaKey simply writes the message 'Press a key to continue...'and waits for a key to be pressed.

procedure Beep;---------------Beep just beeps. You can change the frequencies and timing ifyou don't like it.

procedure Message(Msg : string);--------------------------------Message places a message window in the center of the screen andclears the message when a key is pressed.

procedure SwitchTo(Wind : TextWindow);--------------------------------------SwitchTo switches to the window specified and sets the foregroundand background colors to those previously defined for thatwindow. The cursor will be placed in the upper left corner ofthe window.

procedure ReverseVideo(Wind : TextWindow);------------------------------------------ReverseVideo reverses the foreground and background colors. Ifforeground has been defined as a high intensity color it will bechanged to the low intensity version of that color. Backgroundcolors can only be low intensity, so ReverseVideo always changesthem to high intensity.

procedure NormalVideo(Wind : TextWindow);-----------------------------------------NormalVideo simply switches the foreground and background colorsto those originally defined for that window.

procedure SaveScrn(var Wind : TextWindow);------------------------------------------SaveScrn requests the amount of memory specified byStoreSize from the heap manager, and stores the screensegment defined for that window at the address returned.

procedure RestScrn(var Wind : TextWindow);------------------------------------------RestScrn restores a screen segment previously saved by SaveScrn.It also frees the memory allocated for that window by SaveScrn.

procedure SetWindow(var WindowRec : TextWindow);------------------------------------------------SetWindow will place a previously defined window on the screenand draw a border around it. It also sets the previously definedforeground and background colors, and places the cursor at theupper left corner of the window. If the window title is definedas the null string or is too long to fit the top border, no titlewill be printed. Results are unpredictable if the title is notinitialized.

function GetString(Name,Prompt,Default : string; MaxLen :integer):string;---------------------------------------------------------------------------GetString centers a window on the screen and prompts for input.It returns the string entered, or the default if only Return ispressed. GetString will not allow entry of more characters thanspecified by MaxLen. Backspace will work in the expected manner.Pressing Escape will return the null string. It is actually apretty crude routine because I tried to write it to handle anysize string up to 74 characters. When I got it working I hadother things to do, so I never bothered to improve it. Theparameters required are as follows:

Name : The title of the window. May be ''.Prompt : The prompt you want to show such as 'Enter Path : '.Default : The default string to be returned. May be ''.MaxLen : The maximum allowable length of the input string.

function YesNo(Question : string):boolean;------------------------------------------YesNo centers a window on the screen and displays the Questionyou specify. It will return true if 'Y' or 'y' is pressed, andfalse if any other key is pressed.

procedure UseWholeScrn;-----------------------UseWholeScrn will save the entire screen, clear it, and place thecursor at the upper left corner. A subsequentRestScrn(WholeScrn) will restore it. The colors are defined asWhite and Black in the initialization section of SLWindow, butyou can change them to whatever you like.

This will initialize a window which a subsequent call toSetWindow would place with upper left coordinates of X = 10,Y = 10 and lower right coordinates of X = 20, Y = 20. Theforeground color would be set to White and the background colorto Blue. The window title would be 'MyWindow'.

InitWindow also initializes MyWindow.StoreSize which willcontain the number of bytes requested from the heap manager whenSaveScrn saves the screen segment.

MenuUnit.Pas ------------

MenuUnit defines one type - MenuType - and one variable- HiLiteColor -. HiLiteColor must be initialized by yourprogram. This will be the color used to highlight the 'HOT' keyfor each menu choice.

There is only one function in MenuUnit - MenuChoice. Itwill return the number of the menu selection made. The normalusage is:

The above is a procedure used in ArcView.Exe, the VIEWcomponent of Swiss Army Shell. (It is available seperately asARCVW.ARC and is Freeware.)

Name is the title of the menu. The menu choices are storedin an array of strings. The array is defined with a maximum of15 choices, but you may change that to whatever you want. Themaximum width of each choice may be up to 77 characters. (A wordof caution : if you define and place a menu that will not fit onthe screen the results will be unpredictable. No error checkingis performed.) You must also initialize NumChoices, which is thenumber of menu choices, and Default. This menu would be placedwith the upper left corner at X = 40, Y = 3.

Default selects the choice on which the bar cursor will beplaced when MenuChoice is called. If your program can determinewhat the most likely choice is, you can assign a value to Defaultbefore calling MenuChoice, and the user can simply hit Returnwhen the menu is displayed.

HiLite must be initialized to a string consisting of the'HOT' characters to be used by MenuChoice. In the procedureabove, the letter E would be highlighted in Choice[1], U inChoice[2], and D in Choice[3]. HiLiteColor determines the colorused to highlight. Only the first matching character will behighlighted. In the above case, if HiLite = 'EnD' then the first'n' in 'UnArc Entire Archive' would be highlighted, however thatHiLite key would not work because MenuChoice converts lower caseletters input to upper case to prevent the shift key status frominterfering with its operation. Any character other than a lowercase letter may be used.

If E is pressed, then the procedure ExTagged would becalled, U would call UnArc, and D would call DeleteTagged. Youcould also move the bar with the cursor keys and press Return tomake a selection. Escape returns a choice of 0.

KeyCodes.Def ------------

KEYCODES.DEF is an include file which can be placed in theconstant declaration section of your program. It provides namesfor all (I think) of the extended keyboard scan codes, andseveral of the normal scan codes. You can easily add to it bydetermining the appropriate codes from an ASCII table. To seehow to use the codes just read the Screen Routines Section inChapter 5 of the Turbo Pascal 4.0 manual. Pay particularattention to the repeat loop on page 80 and the HandleKey andHandleFuncKey routines on page 81-82. You should also look atthe internal routine NormalKey and FuncKey in MenuChoice.Pas.

Wrap Up -------

I have included a short program, SLDemo.Pas, whichdemonstrates how to use these units. By no means does itdemonstrate all of the possibilities. For example, you coulddefine a two dimensional array of menus and write a procedure todisplay multilevel pull down menus.

There are no comments in SLWindow.Pas and MenuUnit.Pas, soyou will be on your own figuring out how they work, but theroutines are short enough so that it should not be too difficult.I did try to comment SLDemo.Pas heavily, so the use of theseunits should be fairly clear. I hope you have fun with theseroutines. Good luck!