unit MiscLib; interface uses crt,dos; const MaxFiles = 30; MaxChoices = 8; type STRING79 = string[79]; TOGGLE_REC = record NUM_CHOICES: integer; STRINGS : array [0..8] of STRING79; LOCATIONS : array [0..8] of integer; end; RESPONSE_TYPE = (NO_RESPONSE, ARROW, KEYBOARD, RETURN); MOVEMENT = (NONE, LEFT, RIGHT, UP, DOWN); FnameType = string[12]; FileListType = array[1..MaxFiles] of FnameType; ScrMenuRec = record Selection : array[1..MaxChoices] of STRING79; Descripts : array[1..MaxChoices,1..3] of STRING79; end; ScrMenuType = object NumChoices : integer; Last : integer; Line, Col : integer; MenuData : ScrMenuRec; procedure Setup(MData: ScrMenuRec); function GetChoice : integer; end; procedure Set_Video (ATTRIBUTE: integer); procedure Put_String (OUT_STRING: STRING79; LINE, COL, ATTRIB: integer); procedure Put_Text (OUT_STRING: STRING79; LINE, COL: integer); procedure Put_Colored_Text (OUT_STRING: STRING79; LINE, COL, TXTCLR, BKGCLR: integer); procedure Put_Centered_String (OUT_STRING: STRING79; LINE, ATTRIB: integer); procedure Put_Centered_Text (OUT_STRING: STRING79; LINE: integer); procedure Put_Error (OUT_STRING: STRING79; LINE, COL: integer); procedure End_Erase (LINE, COL: integer); procedure Put_Prompt (OUT_STRING: STRING79; LINE, COL: integer); procedure Get_Response (var RESPONSE : RESPONSE_TYPE; var DIRECTION : MOVEMENT; var KEY_RESPONSE: char); procedure Get_String (var IN_STRING: STRING79; LINE, COL, ATTRIB, STR_LENGTH: integer); procedure Get_Integer (var NUMBER: integer; LINE, COL, ATTRIB, NUM_LENGTH: integer); procedure Get_Prompted_String (var IN_STRING: STRING79; INATTR, STR_LENGTH: integer; STRDESC: STRING79; DESCLINE, DESCCOL: integer; PROMPT: STRING79; PRLINE, PRCOL: integer); procedure Put_1col_Toggle (TOGGLE: TOGGLE_REC; COL, CHOICE: integer); procedure Get_1col_Toggle ( TOGGLE: TOGGLE_REC; COL: integer; var CHOICE: integer; PROMPT: STRING79; PRLINE, PRCOL: integer); procedure Box_Text (TopX, TopY, BotX, BotY, BoxColor: integer); procedure Solid_Box (TopX, TopY, BotX, BotY, BoxColor: integer); procedure swap_fnames(var A,B: FnameType); procedure FileSort(var fname: FileListType; NumFiles: integer); function Get_Files_Toggle (choices: FileListType; NumChoices,NumRows,row,col:integer): FnameType; function Get_File_Menu(mask: string;NumRows,Row,Col: integer): FnameType; {-------------------------------------------------------------------------} implementation procedure Set_Video (ATTRIBUTE: integer); { NOTES: The attribute code, based on bits, is as follows: 0 - normal video 1 - reverse video 2 - bold video 3 - reverse and bold 4 - blinking video 5 - reverse and blinking 6 - bold and blinking 7 - reverse, bold, and blinking } var BLINKING, BOLD: integer; begin BLINKING := (ATTRIBUTE AND 4)*4; if (ATTRIBUTE AND 1) = 1 then begin BOLD := (ATTRIBUTE AND 2)*7; Textcolor (1 + BLINKING + BOLD); TextBackground (3); end else begin BOLD := (ATTRIBUTE AND 2)*5 DIV 2; Textcolor (7 + BLINKING + BOLD); TextBackground (0); end; end; {-------------------------------------------------------------------------} procedure Put_String (OUT_STRING: STRING79; LINE, COL, ATTRIB: integer); begin Set_Video (ATTRIB); GotoXY (COL, LINE); write (OUT_STRING); Set_Video (0); end; {-------------------------------------------------------------------------} procedure Put_Text (OUT_STRING: STRING79; LINE, COL: integer); begin GotoXY (COL, LINE); write (OUT_STRING); end; {-------------------------------------------------------------------------} procedure Put_Colored_Text (OUT_STRING: STRING79; LINE, COL, TXTCLR, BKGCLR: integer); begin GotoXY (COL, LINE); TextColor (TXTCLR); TextBackground (BKGCLR); write (OUT_STRING); end; {-------------------------------------------------------------------------} procedure Put_Centered_String (OUT_STRING: STRING79; LINE, ATTRIB: integer); begin Put_String (OUT_STRING, LINE, 40-Length(OUT_STRING) div 2, ATTRIB); end; {-------------------------------------------------------------------------} procedure Put_Centered_Text (OUT_STRING: STRING79; LINE: integer); begin Put_Text (OUT_STRING, LINE, 40-Length(OUT_STRING) div 2); end; {-------------------------------------------------------------------------} procedure Put_Error (OUT_STRING: STRING79; LINE, COL: integer); var ANY_CHAR : char; begin repeat Put_String (OUT_STRING, LINE, COL, 6); until keypressed = true; end; {-------------------------------------------------------------------------} procedure End_Erase (LINE, COL: integer); begin GotoXY (COL, LINE); ClrEol; end; {-------------------------------------------------------------------------} procedure Put_Prompt (OUT_STRING: STRING79; LINE, COL: integer); begin GotoXY (COL, LINE); ClrEol; Put_String (OUT_STRING, LINE, COL, 3); end; {-------------------------------------------------------------------------} procedure Get_Response (var RESPONSE : RESPONSE_TYPE; var DIRECTION : MOVEMENT; var KEY_RESPONSE: char); const BELL = 7; CARRIAGE_RETURN = 13; ESCAPE = 27; RIGHT_ARROW = 77; LEFT_ARROW = 75; DOWN_ARROW = 80; UP_ARROW = 72; var IN_CHAR: char; begin RESPONSE := NO_RESPONSE; DIRECTION := NONE; KEY_RESPONSE := ' '; repeat IN_CHAR := ReadKey; if IN_CHAR = #0 then begin RESPONSE := ARROW; IN_CHAR := ReadKey; if Ord(IN_CHAR) = LEFT_ARROW then DIRECTION := LEFT else if Ord(IN_CHAR) = RIGHT_ARROW then DIRECTION := RIGHT else if Ord(IN_CHAR) = DOWN_ARROW then DIRECTION := DOWN else if Ord(IN_CHAR) = UP_ARROW then DIRECTION := UP else begin RESPONSE := NO_RESPONSE; write (Chr(BELL)); end end else if Ord(IN_CHAR) = CARRIAGE_RETURN then RESPONSE := RETURN else begin RESPONSE := KEYBOARD; KEY_RESPONSE := UpCase (IN_CHAR); end; until RESPONSE <> NO_RESPONSE; end; {-------------------------------------------------------------------------} procedure Get_String (var IN_STRING: STRING79; LINE, COL, ATTRIB, STR_LENGTH: integer); var OLDSTR : STRING79; IN_CHAR: char; I : integer; const BELL = 7; BACK_SPACE = 8; CARRIAGE_RETURN = 13; ESCAPE = 27; RIGHT_ARROW = 77; begin OLDSTR := IN_STRING; Put_String (IN_STRING, LINE, COL, ATTRIB); for I := Length(IN_STRING) to STR_LENGTH-1 do Put_String (' ', LINE, COL + I, ATTRIB); GotoXY (COL, LINE); IN_CHAR := ReadKey; if Ord(IN_CHAR) <> CARRIAGE_RETURN then IN_STRING := ''; while Ord(IN_CHAR) <> CARRIAGE_RETURN do begin if Ord(IN_CHAR) = BACK_SPACE then begin if Length(IN_STRING) > 0 then begin IN_STRING[0] := Chr(Length(IN_STRING)-1); write (Chr(BACK_SPACE)); write (' '); write (Chr(BACK_SPACE)); end; end { if BACK_SPACE } else if IN_CHAR = #0 then begin IN_CHAR := ReadKey; if Ord(IN_CHAR) = RIGHT_ARROW then begin if Length(OLDSTR) > Length(IN_STRING) then begin IN_STRING[0] := Chr(Length(IN_STRING) + 1); IN_CHAR := OLDSTR[Ord(IN_STRING[0])]; IN_STRING[Ord(IN_STRING[0])] := IN_CHAR; write (IN_CHAR); end end { RIGHT_ARROW } else write (Chr(BELL)); end { IN_CHAR = #0 } else if Length (IN_STRING) < STR_LENGTH then begin IN_STRING[0] := Chr(Length(IN_STRING) + 1); IN_STRING[Ord(IN_STRING[0])] := IN_CHAR; TextColor (15); TextBackGround (11); write (IN_CHAR); end else write (Chr(BELL)); IN_CHAR := ReadKey; end; Put_String (IN_STRING, LINE, COL, ATTRIB); for I := Length(IN_STRING) to STR_LENGTH - 1 do Put_String (' ', LINE, COL+I, ATTRIB); end; {-------------------------------------------------------------------------} procedure Get_Integer (var NUMBER: integer; LINE, COL, ATTRIB, NUM_LENGTH: integer); const BELL = 7; var VALCODE : integer; ORIGINAL_STR, TEMP_STR : STRING79; TEMP_INT : integer; begin Str (NUMBER:NUM_LENGTH, ORIGINAL_STR); repeat TEMP_STR := ORIGINAL_STR; Get_String (TEMP_STR, LINE, COL, ATTRIB, NUM_LENGTH); while TEMP_STR[1] = ' ' do TEMP_STR := Copy (TEMP_STR, 2, Length (TEMP_STR)); Val (TEMP_STR, TEMP_INT, VALCODE); if (VALCODE <> 0) then write (Chr(BELL)); until VALCODE = 0; NUMBER := TEMP_INT; Str (NUMBER:NUM_LENGTH, TEMP_STR); Put_String (TEMP_STR, LINE, COL, ATTRIB); end; {-------------------------------------------------------------------------} procedure Get_Prompted_String (var IN_STRING: STRING79; INATTR, STR_LENGTH: integer; STRDESC: STRING79; DESCLINE, DESCCOL: integer; PROMPT: STRING79; PRLINE, PRCOL: integer); begin Put_String (STRDESC, DESCLINE, DESCCOL, 2); Put_Prompt (PROMPT, PRLINE, PRCOL); Get_String (IN_STRING, DESCLINE, DESCCOL + Length(STRDESC), INATTR, STR_LENGTH); Put_String (STRDESC, DESCLINE, DESCCOL, 0); end; {-------------------------------------------------------------------------} procedure Put_1col_Toggle (TOGGLE: TOGGLE_REC; COL, CHOICE: integer); var I: integer; begin with TOGGLE do begin Put_String (STRINGS[0], LOCATIONS[0], COL, 0); for I := 1 to NUM_CHOICES do Put_String (STRINGS[I], LOCATIONS[I], COL, 0); if (CHOICE <1) or (CHOICE > NUM_CHOICES) then CHOICE := 1; Put_String (STRINGS[CHOICE], LOCATIONS[CHOICE], COL, 1); end; end; {-------------------------------------------------------------------------} procedure Get_1col_Toggle ( TOGGLE: TOGGLE_REC; COL: integer; var CHOICE: integer; PROMPT: STRING79; PRLINE, PRCOL: integer); var RESP : RESPONSE_TYPE; DIR : MOVEMENT; KEYCH: char; begin Put_Colored_Text (PROMPT, PRLINE, PRCOL, 15, 0); with TOGGLE do begin Put_String (STRINGS[0], LOCATIONS[0], COL, 2); if (CHOICE < 1) or (CHOICE > NUM_CHOICES) then CHOICE := 1; Put_String (STRINGS[CHOICE], LOCATIONS[CHOICE], COL, 1); RESP := NO_RESPONSE; while RESP <> RETURN do begin Get_Response (RESP, DIR, KEYCH); case RESP of ARROW: if DIR = UP then begin Put_String (STRINGS[CHOICE], LOCATIONS[CHOICE], COL, 0); if CHOICE = 1 then CHOICE := NUM_CHOICES else CHOICE := CHOICE - 1; Put_String (STRINGS[CHOICE], LOCATIONS[CHOICE], COL, 1); end else if DIR = DOWN then begin Put_String (STRINGS[CHOICE], LOCATIONS[CHOICE], COL, 0); if CHOICE = NUM_CHOICES then CHOICE := 1 else CHOICE := CHOICE + 1; Put_String (STRINGS[CHOICE], LOCATIONS[CHOICE], COL, 1); end else write (Chr(7)); KEYBOARD: write (Chr(7)); RETURN: ; end; end; {while} Put_String (STRINGS[0], LOCATIONS[0], COL, 0); end; end; {-------------------------------------------------------------------------} procedure Box_Text (TopX, TopY, BotX, BotY, BoxColor: integer); var i : integer; width : integer; height: integer; begin TextBackGround (BoxColor); height := BotY - TopY; width := BotX - TopX; GotoXY (TopX, TopY); for i := 1 to width do write (' '); for i := TopY to (TopY+height) do begin GotoXY (TopX, i); write (' '); GotoXY (BotX-1, i); write (' '); end; GotoXY (TopX, BotY); for i := 1 to width do write (' '); end; {-------------------------------------------------------------------------} procedure Solid_Box (TopX, TopY, BotX, BotY, BoxColor: integer); var i : integer; j : integer; width : integer; begin TextBackGround (BoxColor); GotoXY (TopX, TopY); width := BotX - TopX; for i := TopY to BotY do begin for j := 1 to width do write (' '); GotoXY (TopX, i); end; end; procedure swap_fnames(var A,B: FnameType); var Temp : FnameType; begin Temp := A; A := B; B := Temp; end; procedure FileSort(var fname: FileListType;NumFiles: integer); var i,j : integer; begin for j := NumFiles downto 2 do for i := 1 to j-1 do if fname[i]>fname[j] then swap_fnames(fname[i],fname[j]); end; function Get_Files_Toggle (choices:FileListType; NumChoices,NumRows,row,col:integer): FnameType; var i,r : integer; Resp : Response_Type; dir : movement; keych : char; procedure Put_Files_Toggle (choices: FileListType; First,NumRows,row,col: integer); var i : integer; begin for i := 0 to NumRows-1 do Put_string (choices[First+i],row+i,col,0); end; procedure Padnames; var i,p : integer; begin for i := 1 to MaxFiles do begin p := 12-length(choices[i]); while p>0 do begin choices[i] := choices[i]+' '; p := p-1; end; end; end; begin Padnames; i := 1; r := 1; if NumChoices < NumRows then NumRows := NumChoices; Put_Files_Toggle (choices,1,NumRows,row,col); Get_Files_Toggle := choices[i]; Put_string(choices[i],row,col,1); resp := No_Response; while resp <> Return do begin Get_response (resp,dir,keych); case resp of ARROW: if dir=UP then begin Put_string(choices[i],row+r-1,col,0); if i=1 then begin i := NumChoices; r := NumRows; Put_Files_Toggle(choices,i+1-NumRows,NumRows,row,col); end else if r=1 then begin i := i-1; Put_Files_Toggle(choices,i,NumRows,row,col); end else begin i := i-1; r := r-1; end; Put_string(choices[i],row+r-1,col,1); end else if dir=DOWN then begin Put_string(choices[i],row+r-1,col,0); if i=NumChoices then begin i := 1; r := 1; Put_Files_Toggle(choices,i,NumRows,row,col); end else if r=NumRows then begin i := i+1; Put_Files_Toggle(choices,i+1-NumRows,NumRows,row,col); end else begin i := i+1; r := r+1; end; Put_string(choices[i],row+r-1,col,1); end else write (chr(7)); KEYBOARD: write (chr(7)); end; { case } end; Get_Files_toggle := choices[i]; end; function Get_File_Menu(mask: string;NumRows,Row,Col: integer): FnameType; var i : integer; NumFiles : integer; FileList : FileListType; dirinfo : SearchRec; begin i := 1; FindFirst(mask,Archive,dirinfo); while (DosError=0) AND (i Return do begin PutDescripts; Get_Response(Resp,Dir,KeyCh); case Resp of Arrow : if Dir = Up then begin Put_String(Selection[Last],Line+Last-1,Col,0); if Last = 1 then Last := NumChoices else Last := Last-1; Put_String(Selection[Last],Line+Last-1,Col,1); end else if Dir = Down then begin Put_String(Selection[Last],Line+Last-1,Col,0); if Last = NumChoices then Last := 1 else Last := Last+1; Put_String(Selection[Last],Line+Last-1,Col,1); end; end; end; end; end; { Initialization Area } begin end. {------------------------------------ TEST PROGRAM ------------------- } program testdir; { program attempts to read directory } { shows filenames as column } uses dos,crt,miscLib; var Fchoice : FnameType; i,n : integer; { *************** MAIN PROGRAM *************** } begin ClrScr; Fchoice := Get_File_Menu('*.*',8,10,30); Put_string(Fchoice,24,1,0); ReadLn; end. {------------------------------------ TEST PROGRAM ------------------- } program TestMenu; uses crt,MiscLib; const ChoiceData : ScrMenuRec = (selection : ('Choice 1','Choice 2','Choice 3','Choice 4','','','',''); Descripts : (('This is','No 1','The First Choice'), ('Number 2','The Second Choice and default',''), ('Number 3','Last Choice, for now...','Last Line'), ('Number 4','An added Selection','How bout that?'), ('','',''), ('','',''), ('','',''), ('','',''))); var ScrMenu : ScrMenuType; Choice : integer; begin TextColor(white); TextBackGround(Blue); ClrScr; ScrMenu.NumChoices := 4; ScrMenu.Last := 2; ScrMenu.Line := 6; ScrMenu.Col := 30; ScrMenu.Setup(ChoiceData); Choice := ScrMenu.GetChoice; ReadLn; end.