'=========================================================================== ' Subject: USEFUL SUBROUTINES & FUNCTIONS Date: 06-27-96 (07:37) ' Author: Matthew Richard Usner Code: QB, QBasic, PDS ' Origin: mattu@ix.netcom.com Packet: LIBRARY.ABC '=========================================================================== 'ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» 'ºThese are subprograms and functions that I have found useful over the lastº 'ºfew years. Most I have written, some I have modified from stuff I found º 'ºon BBS's or the 'Net. I have used all these at one time or another and º 'ºthey all seem to work fine. A couple, like Scroll, provide functions thatº 'ºnormally are accessible only by CALL INTERRUPT. These routines are not º 'ºextensively commented but they're pretty self-explanatory so feel free to º 'ºuse and abuse 'em. Do what you will, I believe in freeware. If you have º 'ºa comment or have ideas for useful routines you may e-mail me at º 'ºmattu@ix.netcom.com or 75342.1777@compuserve.com. º 'ºHave fun! Matthew R. Usner 06/27/96 º 'ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ DECLARE FUNCTION AttributeByte% (Fore%, Back%) DECLARE FUNCTION Background% (Row%, Col%) DECLARE FUNCTION Bin% (Bit$) DECLARE FUNCTION BinarySearch% (Array$(), Find$) DECLARE FUNCTION BinDec& (Binary$) DECLARE FUNCTION Capitalize$ (Orig$) DECLARE FUNCTION CountIn% (Search$, LookFor$) DECLARE FUNCTION Crunch$ (Text$, CTC$) DECLARE FUNCTION CurrentDirectory$ () DECLARE FUNCTION DateToJulian! (Dat$) DECLARE FUNCTION DateValid% (Month%, Day%, Year%) DECLARE FUNCTION DayOfTheWeek$ (Dat$) DECLARE FUNCTION DecBin$ (Decimal&) DECLARE FUNCTION EnglishDate$ (Dat$) DECLARE FUNCTION Foreground% (Row%, Col%) DECLARE FUNCTION GetChar$ () DECLARE FUNCTION InputString$ (Row%, Column%, InputString$, Foreground%, Background%, ValidCharacters$, ReturnMode%, EntryMode%, CaseMode%) DECLARE FUNCTION InvertString$ (StringToInvert$) DECLARE FUNCTION IsAlpha% (Text$) DECLARE FUNCTION IsNumeric% (Text$) DECLARE FUNCTION LeadZero$ (Number, NewLength%) DECLARE FUNCTION LeapYear% (Year%) DECLARE FUNCTION MonthName$ (Month%) DECLARE FUNCTION Pad$ (Orig$, NewLength%, Side%, Char$) DECLARE FUNCTION RandInt% (Lower, Upper) DECLARE FUNCTION Replace$ (Text$, LookFor$, ReplaceWith$) DECLARE FUNCTION Reverse$ (Text$) DECLARE FUNCTION Rinstr% (Start%, Search$, LookFor$) DECLARE FUNCTION RotateLeft$ (S$) DECLARE FUNCTION RotateRight$ (S$) DECLARE FUNCTION Squeeze$ (Orig$, Char$) DECLARE FUNCTION Strip$ (Text$, Delete$) DECLARE SUB ActivateCapsLock () DECLARE SUB ArrayAdd (Array(), StartElement%, EndElement%, Num) DECLARE SUB ArraySet (Array(), StartElement%, EndElement%, Num) DECLARE SUB Box (Row%, Column%, BoxWidth%, Height%, BoxColor%, BoxCharacter%, BorderType%, BorderColor%) DECLARE SUB CenterString (StringToCenter$, Row%, Fore%, Back%) DECLARE SUB ClearKeyboard () DECLARE SUB CopyFile (InFile$, OutFile$) DECLARE SUB Directory (D$(), Mask$, SortType%, FileCount%) DECLARE SUB DisplayTime (Row%, Column%, Format%, Fore%, Back%) DECLARE SUB Dissolve () DECLARE SUB Drop (Text$, Row%, Col%) DECLARE SUB GetArguments (Arguments$(), MaxArguments%, ArgsFound%) DECLARE SUB PrintAt (Row%, Col%, Fore%, Back%, StringToPrint$) DECLARE SUB QuickSort (SortArray%(), Lower%, Upper%) DECLARE SUB ReColor (StartRow%, StartCol%, EndRow%, EndCol%, ChangeAtt%, ReplaceAtt%) DECLARE SUB RestoreScreen (FileName$) DECLARE SUB Rise (Text$, Row%, Col%) DECLARE SUB SaveScreen (FileName$) DECLARE SUB SaveScreenToTextFile (FileName$) DECLARE SUB Scroll (StartRow%, StartCol%, EndRow%, EndCol%, Direction%) DECLARE SUB SetCursor (CursorType%) DECLARE SUB Slide (Text$, LeftOrRight%, Row%, Col%, Delay) DECLARE SUB Spread (Text$, Row%, Col%, Delay) DECLARE SUB StuffBuf (Keys$) DECLARE SUB TeleType (Text$, Delay) DECLARE SUB Warp () DECLARE SUB WipeArea (Row1%, Col1%, Row2%, Col2%) DECLARE SUB WipeCol (Col%, Rows%) DECLARE SUB WipeEOL () DECLARE SUB WipeEOP () DECLARE SUB WipeRow (StartCol%, EndCol%) DECLARE SUB WipeSOL () DECLARE SUB WipeSOP () SUB ActivateCapsLock '******************************************************************************* '* this subroutine makes sure CapsLock is activated (may not light up key) * '******************************************************************************* DEF SEG = &H40 POKE &H17, (PEEK(&H17) OR 64) DEF SEG END SUB SUB ArrayAdd (Array(), StartElement%, EndElement%, Num) '******************************************************************************* '* adds Num to each one-dim. array element from StartElement to EndElement * '* if StartElement and EndElement = 0, entire array is used * '******************************************************************************* IF StartElement% = 0 AND EndElement% = 0 THEN StartElement% = LBOUND(Array) EndElement% = UBOUND(Array) END IF FOR X% = StartElement% TO EndElement% Array(X%) = Array(X%) + Num NEXT X% END SUB SUB ArraySet (Array(), StartElement%, EndElement%, Num) '******************************************************************************* '* sets each element in an 1-dim array to Num from StartElement to EndElement * '* if StartElement and EndElement = 0, entire array is used * '******************************************************************************* IF StartElement% = 0 AND EndElement% = 0 THEN StartElement% = LBOUND(Array) EndElement% = UBOUND(Array) END IF FOR X% = StartElement% TO EndElement% Array(X%) = Num NEXT X% END SUB FUNCTION AttributeByte% (Fore%, Back%) '******************************************************************************* '* returns a screen attribute byte given the foreground and background colors * '******************************************************************************* AttributeByte% = (Back% * 16) + Fore% END FUNCTION FUNCTION Background% (Row%, Col%) '******************************************************************************* '* returns background color at given screen location * '******************************************************************************* IF (Row% < 1 OR Row% > 25) OR (Col% < 1 OR Col% > 80) THEN Background% = 128 EXIT FUNCTION END IF Background% = ((SCREEN(Row%, Col%, 1)) AND 112) / 16 END FUNCTION FUNCTION Bin% (Bit$) '******************************************************************************* '* converts binary string to integer ("10" converts to 2, which is 10 binary) * '******************************************************************************* Temp& = 0 Length% = LEN(Bit$) FOR X% = 1 TO Length% IF MID$(Bit$, Length% - X% + 1, 1) = "1" THEN Temp& = Temp& + 2 ^ (X% - 1) END IF NEXT X% IF Temp& > 32767 THEN Bin% = Temp& - 65536 ELSE Bin% = Temp& END IF END FUNCTION FUNCTION BinarySearch% (Array$(), Find$) '******************************************************************************* '* locates Find$ in sorted array Array$ () and returns element number or -1 * '******************************************************************************* BinarySearch% = -1 ' no matching element yet Min = LBOUND(Array$) ' start at first element Max = UBOUND(Array$) ' consider through last DO Try = (Max + Min) \ 2 ' start testing in middle IF Array$(Try) = Find$ THEN BinarySearch% = Try ' return matching element EXIT DO END IF IF Array$(Try) > Find$ THEN ' too high, cut in half Max = Try - 1 ELSE Min = Try + 1 ' too low, cut other way END IF LOOP WHILE Max >= Min END FUNCTION FUNCTION BinDec& (Binary$) STATIC '******************************************************************************* '* converts binary string to decimal equivalent * '******************************************************************************* Decimal& = 0 Power% = 0 Binary$ = UCASE$(Binary$) FOR I% = LEN(Binary$) TO 1 STEP -1 Digit% = ASC(MID$(Binary$, I%, 1)) - 48 IF Digit% < 0 OR Digit% > 1 THEN Decimal& = 0 EXIT FOR END IF Decimal& = Decimal& + Digit% * 2 ^ (Power%) Power% = Power% + 1 NEXT I% BinDec& = Decimal& END FUNCTION SUB Box (Row%, Column%, BoxWidth%, Height%, BoxColor%, BoxCharacter%, BorderType%, BorderColor%) '******************************************************************************* '* displays a box of definable attributes on the screen * '******************************************************************************* StartRow% = Row% SELECT CASE BorderType% ' no border CASE 0 UpperLeft$ = CHR$(BoxCharacter%) UpperRight$ = CHR$(BoxCharacter%) LowerLeft$ = CHR$(BoxCharacter%) LowerRight$ = CHR$(BoxCharacter%) Vertical$ = CHR$(BoxCharacter%) Horizontal$ = CHR$(BoxCharacter%) ' single border CASE 1 UpperLeft$ = CHR$(218) UpperRight$ = CHR$(191) LowerLeft$ = CHR$(192) LowerRight$ = CHR$(217) Vertical$ = CHR$(179) Horizontal$ = CHR$(196) ' double border CASE 2 UpperLeft$ = CHR$(201) UpperRight$ = CHR$(187) LowerLeft$ = CHR$(200) LowerRight$ = CHR$(188) Vertical$ = CHR$(186) Horizontal$ = CHR$(205) END SELECT InnerWidth% = BoxWidth% - 2 InnerHeight% = Height% - 2 InnerFilling$ = STRING$(InnerWidth%, CHR$(BoxCharacter%)) BoxTopBottom$ = STRING$(InnerWidth%, Horizontal$) COLOR BorderColor%, BoxColor% LOCATE StartRow%, Column% PRINT UpperLeft$ + BoxTopBottom$ + UpperRight$; StartRow% = StartRow% + 1 FOR FillLoop% = 1 TO InnerHeight% LOCATE StartRow%, Column% PRINT Vertical$ + InnerFilling$ + Vertical$; StartRow% = StartRow% + 1 NEXT FillLoop% LOCATE StartRow%, Column% PRINT LowerLeft$ + BoxTopBottom$ + LowerRight$; END SUB FUNCTION Capitalize$ (Orig$) '******************************************************************************* '* capitalizes the first letter of each word in a string after first * '* converting the whole thing to lower case * '******************************************************************************* ' if original is null, return null IF Orig$ = "" THEN Capitalize$ = "" EXIT FUNCTION END IF New$ = LCASE$(Orig$) ' capitalize the first character MID$(New$, 1, 1) = UCASE$(MID$(New$, 1, 1)) ' process string, capitalizing anything that follows a space FOR X% = 1 TO (LEN(New$) - 1) IF MID$(New$, X%, 1) = " " THEN MID$(New$, (X% + 1), 1) = UCASE$(MID$(New$, (X% + 1), 1)) END IF NEXT X% Capitalize$ = New$ END FUNCTION SUB CenterString (StringToCenter$, Row%, Fore%, Back%) '******************************************************************************* '* this subroutine centers a line of text on the screen * '******************************************************************************* COLOR Fore%, Back% LOCATE Row%, 40 - INT(LEN(StringToCenter$) / 2) PRINT StringToCenter$; END SUB SUB ClearKeyboard '******************************************************************************* '* clears the keyboard buffer to help prevent accidental keystrokes * '******************************************************************************* FOR X% = 1 TO 15 A$ = INKEY$ NEXT X% END SUB SUB CopyFile (InFile$, OutFile$) STATIC '******************************************************************************* '* copies file InFile$ to file OutFile$ * '******************************************************************************* File1% = FREEFILE OPEN InFile$ FOR BINARY AS #File1% File2% = FREEFILE OPEN OutFile$ FOR BINARY AS #File2% BytesRemaining& = LOF(File1%) DO IF BytesRemaining& > 4096 THEN ThisPass = 4096 ELSE ThisPass = BytesRemaining& END IF Buffer$ = SPACE$(ThisPass) GET #File1%, , Buffer$ PUT #File2%, , Buffer$ BytesRemaining& = BytesRemaining& - ThisPass LOOP WHILE BytesRemaining& CLOSE File1#, File2# END SUB FUNCTION CountIn% (Search$, LookFor$) '******************************************************************************* '* Returns the number of times that a substring is found within a string. * '******************************************************************************* Count% = 0 ' exit if searching in or looking for a null string IF Search$ = "" OR LookFor$ = "" THEN CountIn% = Count% EXIT FUNCTION END IF ' find first occurrence X% = INSTR(Search$, LookFor$) ' proc. string, incrementing count and start pos each time sub is found DO WHILE X% > 0 Count% = Count% + 1 Last% = X% X% = INSTR((Last% + 1), Search$, LookFor$) LOOP CountIn% = Count% END FUNCTION FUNCTION Crunch$ (Text$, CTC$) '******************************************************************************* '* Text$ = "this is a test", CTC$ = " " returns "this is a test" * '******************************************************************************* Temp$ = "" X% = 1 WHILE X% <= LEN(Text$) C$ = MID$(Text$, X%, 1) Temp$ = Temp$ + C$ IF C$ = CTC$ THEN WHILE MID$(Text$, X%, 1) = CTC$ X% = X% + 1 WEND ELSE X% = X% + 1 END IF WEND Crunch$ = Temp$ END FUNCTION FUNCTION CurrentDirectory$ '******************************************************************************* '* returns current directory (i.e. C:\WINDOWS) * '******************************************************************************* SHELL "CD >CD.TXT" F% = FREEFILE OPEN "I", F%, "CD.TXT" LINE INPUT #F%, CD$ CLOSE F% KILL "CD.TXT" CurrentDirectory$ = CD$ END FUNCTION FUNCTION DateToJulian (Dat$) '******************************************************************************* '* converts gregorian-style mm/dd/yyyy date to julian date * '******************************************************************************* Month% = VAL(MID$(Dat$, 1, 2)) Day% = VAL(MID$(Dat$, 4, 2)) Year% = VAL(MID$(Dat$, 7, 4)) SELECT CASE Month% CASE IS > 2 Month% = Month% - 3 CASE IS <= 2 Month% = Month% + 9 Year% = Year% - 1 END SELECT A = 146097# * FIX(FIX(Year% / 100) / 4) B = FIX(1461# * (Year% MOD 100) / 4) C = FIX((153# * Month% + 2) / 5) + Day% + 1721119 DateToJulian = A + B + C END FUNCTION FUNCTION DateValid% (Month%, Day%, Year%) '******************************************************************************* '* returns 1 if date given is a legal date * '******************************************************************************* SELECT CASE Month% 'verify date within month CASE 4, 6, 9, 11 'months that should SELECT CASE Day% 'only have CASE 1 TO 30 '30 days CASE ELSE 'otherwise DateValid% = 0 'not valid EXIT FUNCTION END SELECT CASE 1, 3, 5, 7, 8, 10, 12 'months that SELECT CASE Day% 'should have CASE 1 TO 31 '31 days CASE ELSE 'otherwise DateValid% = 0 'not valid EXIT FUNCTION END SELECT CASE 2 'February SELECT CASE Year% MOD 4 'account for leap years CASE 0 'a leap year SELECT CASE Day% CASE 1 TO 29 'may have 29 days CASE ELSE ' DateValid% = 0 'not valid EXIT FUNCTION END SELECT CASE ELSE 'not a leap year SELECT CASE Day% CASE 1 TO 28 'only 28 days acceptable CASE ELSE DateValid% = 0 EXIT FUNCTION END SELECT END SELECT CASE ELSE 'anything else DateValid% = 0 'is invalid date entry EXIT FUNCTION END SELECT DateValid% = 1 'Date passes all tests END FUNCTION FUNCTION DayOfTheWeek$ (Dat$) '******************************************************************************* '* returns day of week given date in form mm/dd/yyyy * '******************************************************************************* JulianDate = DateToJulian(Dat$) SELECT CASE JulianDate - (FIX(JulianDate / 7) * 7) + 1 CASE 0, 7 DayOfTheWeek$ = "Monday" CASE 1 DayOfTheWeek$ = "Tuesday" CASE 2 DayOfTheWeek$ = "Wednesday" CASE 3 DayOfTheWeek$ = "Thursday" CASE 4 DayOfTheWeek$ = "Friday" CASE 5 DayOfTheWeek$ = "Saturday" CASE 6 DayOfTheWeek$ = "Sunday" END SELECT END FUNCTION FUNCTION DecBin$ (Decimal&) STATIC '******************************************************************************* '* converts decimal number to binary string * '******************************************************************************* BinNum$ = "" H$ = HEX$(Decimal&) FOR I% = 1 TO LEN(H$) Digit% = INSTR("0123456789ABCDEF", MID$(H$, I%, 1)) - 1 IF Digit% < 0 THEN BinNum$ = "" EXIT FOR END IF J% = 8 K% = 4 DO BinNum$ = BinNum$ + RIGHT$(STR$((Digit% \ J%) MOD 2), 1) J% = J% - (J% \ 2) K% = K% - 1 IF K% = 0 THEN EXIT DO END IF LOOP WHILE J% NEXT I% DecBin$ = BinNum$ END FUNCTION SUB Directory (D$(), Mask$, SortType%, FileCount%) '******************************************************************************* '* places pertinent directory info in array D$(), one entry per element. * '* quicksorts by name, extension, size, date or time ascending or descending * '******************************************************************************* SHELL "DIR " + Mask$ + ">DIRLIST.TXT" F% = FREEFILE OPEN "I", F%, "DIRLIST.TXT" ' get past opening garbage FOR X% = 1 TO 5 INPUT #F%, DirLine$ NEXT X% ' read in directory file information FileCount% = 0 LINE INPUT #F%, DirLine$ WHILE LEFT$(DirLine$, 8) <> " " IF MID$(DirLine$, 16, 5) <> "" THEN FileCount% = FileCount% + 1 IF SortType% = 7 OR SortType% = 8 THEN TempDate$ = MID$(DirLine$, 35, 2) + MID$(DirLine$, 29, 2) + MID$(DirLine$, 32, 2) MID$(DirLine$, 29, 6) = TempDate$ END IF IF SortType% = 9 OR SortType% = 10 THEN TempTime$ = MID$(DirLine$, 38, 6) MID$(DirLine$, 38, 6) = RIGHT$(TempTime$, 1) + LEFT$(TempTime$, 5) END IF D$(FileCount%) = MID$(DirLine$, 1, 43) END IF LINE INPUT #F%, DirLine$ WEND CLOSE #F% KILL "DIRLIST.TXT" ' no files matching pattern IF D$(1) = "" THEN EXIT SUB END IF ' sort directory, if desired - 1,3,5,7,9=ascending, 2,4,6,8,10 descending SELECT CASE SortType% CASE 0 ' no sort EXIT SUB CASE 1, 2 ' sort by filename (ascending/descending) Start% = 1 Length% = 8 ' filename is characters 1-8 CASE 3, 4 ' sort by extension (ascending/descending) Start% = 10 Length% = 3 ' extension is characters 10-12 CASE 5, 6 ' sort by file size (ascending/descending) Start% = 13 Length% = 14 ' file size is characters 13-26 CASE 7, 8 ' sort by last save date (ascending/descending) Start% = 29 Length% = 6 ' save date is characters 29-36, reorder 29-34 CASE 9, 10 ' sort by last save time (ascending/descending) Start% = 38 Length% = 6 ' last save time is characters 38-43 END SELECT ' quicksort DIM SortStackLow%(128) DIM SortStackHigh%(128) StackPointer% = 1 SortStackLow%(StackPointer%) = 1 SortStackHigh%(StackPointer%) = FileCount% StackPointer% = StackPointer% + 1 DO StackPointer% = StackPointer% - 1 Low% = SortStackLow%(StackPointer%) High% = SortStackHigh%(StackPointer%) DO I% = Low% J% = High% Mid% = (Low% + High%) \ 2 Compare$ = MID$(D$(Mid%), Start%, Length%) DO SELECT CASE SortType% ' ascending sort order CASE 1, 3, 5, 7, 9 DO WHILE MID$(D$(I%), Start%, Length%) < Compare$ I% = I% + 1 LOOP DO WHILE MID$(D$(J%), Start%, Length%) > Compare$ J% = J% - 1 LOOP ' descending sort order CASE 2, 4, 6, 8, 10 DO WHILE MID$(D$(I%), Start%, Length%) > Compare$ I% = I% + 1 LOOP DO WHILE MID$(D$(J%), Start%, Length%) < Compare$ J% = J% - 1 LOOP END SELECT IF I% <= J% THEN SWAP D$(I%), D$(J%) I% = I% + 1 J% = J% - 1 END IF LOOP WHILE I% <= J% IF J% - Low% < High% - I% THEN IF I% < High% THEN SortStackLow%(StackPointer%) = I% SortStackHigh%(StackPointer%) = High% StackPointer% = StackPointer% + 1 END IF High% = J% ELSE IF Low% < J% THEN SortStackLow%(StackPointer%) = Low% SortStackHigh%(StackPointer%) = J% StackPointer% = StackPointer% + 1 END IF Low% = I% END IF LOOP WHILE Low% < High% LOOP WHILE StackPointer% <> 1 ' reassemble date or time information, if necessary IF SortType% = 7 OR SortType% = 8 THEN FOR X% = 1 TO FileCount% TempDate$ = MID$(D$(X%), 29, 6) MID$(D$(X%), 29, 8) = MID$(TempDate$, 3, 2) + "-" + RIGHT$(TempDate$, 2) + "-" + LEFT$(TempDate$, 2) NEXT X% END IF IF SortType% = 9 OR SortType% = 10 THEN FOR X% = 1 TO FileCount% TempTime$ = MID$(D$(X%), 38, 6) MID$(D$(X%), 38, 6) = RIGHT$(TempTime$, 5) + LEFT$(TempTime$, 1) NEXT X% END IF END SUB SUB DisplayTime (Row%, Column%, Format%, Fore%, Back%) '******************************************************************************* '* displays time in 12 or 24 hour format * '******************************************************************************* LOCATE Row%, Column% COLOR Fore%, Back% SELECT CASE Format% CASE 0 Hour% = VAL(LEFT$(TIME$, 2)) SELECT CASE Hour% CASE IS > 12 Hour% = Hour% - 12 Hour$ = STR$(Hour%) Hour$ = RIGHT$(Hour$, LEN(Hour$) - 1) Hour$ = RIGHT$(" " + Hour$, 2) PRINT Hour$ + RIGHT$(TIME$, 6) + " P.M."; CASE IS = 12 PRINT TIME$ + " P.M."; CASE IS = 0 Hour% = 12 PRINT "12" + RIGHT$(TIME$, 6) + " A.M."; CASE IS < 12 Hour$ = STR$(Hour%) Hour$ = RIGHT$(Hour$, LEN(Hour$) - 1) Hour$ = RIGHT$(" " + Hour$, 2) PRINT Hour$ + RIGHT$(TIME$, 6) + " A.M."; END SELECT CASE 1 PRINT TIME$; END SELECT END SUB SUB Dissolve '******************************************************************************* '* use instead of cls for an interesting way to clear the screen * '******************************************************************************* DIM ScreenPos%(2000) FOR X% = 1 TO 2000 ScreenPos%(X%) = X% NEXT X% FOR X% = 1 TO 2000 SWAP ScreenPos%(X%), ScreenPos%(INT(RND(1) * 2000) + 1) NEXT X% FOR X% = 1 TO 2000 R% = ScreenPos%(X%) \ 80 + 1 IF R% = 0 THEN R% = 1 IF R% > 25 THEN R% = 25 C% = ABS(ScreenPos%(X%) - (80 * R%)) IF C% = 0 THEN C% = 1 LOCATE R%, C% PRINT " "; NEXT X% LOCATE 1, 80: PRINT " "; ' cheap temporary fix END SUB SUB Drop (Text$, Row%, Col%) '******************************************************************************* '* prints text vertically on the screen, dropping from the specified row and * '* column position. If the length of the text would continue past row 24, * '* printing will stop at that point * '******************************************************************************* R% = Row% FOR X% = 1 TO LEN(Text$) LOCATE R%, Col% PRINT MID$(Text$, X%, 1); R% = R% + 1 ' don't go past bottom of screen IF R% = 26 THEN EXIT FOR END IF NEXT X% END SUB FUNCTION EnglishDate$ (Dat$) '******************************************************************************* '* Returns English date from mm/dd/yyyy date * '******************************************************************************* Day$ = MID$(Dat$, 4, 2) IF VAL(Day$) < 10 THEN Day$ = MID$(Dat$, 5, 1) END IF Month% = VAL(MID$(Dat$, 1, 2)) EnglishDate$ = DayOfTheWeek$(Dat$) + ", " + MonthName$(Month%) + " " + Day$ + ", " + RIGHT$(Dat$, 4) END FUNCTION FUNCTION Foreground% (Row%, Col%) '******************************************************************************* '* returns foreground color at given screen location * '******************************************************************************* IF (Row% < 1 OR Row% > 25) OR (Col% < 1 OR Col% > 80) THEN Foreground% = 128 EXIT FUNCTION END IF ab% = SCREEN(Row%, Col%, 1) Foreground% = (ab% AND 128) / 8 + (ab% AND 15) END FUNCTION SUB GetArguments (Arguments$(), MaxArguments%, ArgsFound%) STATIC '******************************************************************************* '* this procedure parses command line and extracts arguments * '******************************************************************************* True% = -1 False% = 0 ArgsFound% = 0 In% = False% CommandLine$ = COMMAND$ CommandLineLength% = LEN(CommandLine$) FOR Character% = 1 TO CommandLineLength% Char$ = MID$(CommandLine$, Character%, 1) IF Char$ <> " " AND Char$ <> CHR$(9) THEN IF NOT In% THEN IF ArgsFound% = MaxArguments% THEN EXIT FOR END IF ArgsFound% = ArgsFound% + 1 In% = True% END IF Arguments$(ArgsFound%) = Arguments$(ArgsFound%) + Char$ ELSE In% = False% END IF NEXT Character% END SUB FUNCTION GetChar$ '******************************************************************************* '* returns keystroke * '******************************************************************************* A$ = "" WHILE A$ = "" A$ = INKEY$ WEND GetChar$ = A$ END FUNCTION FUNCTION InputString$ (Row%, Column%, InputField$, Foreground%, Background%, ValidCharacters$, ReturnMode%, EntryMode%, CaseMode%) '******************************************************************************* '* this function inputs a string of the desired length and desired characters* '* at the selected row, column and color * '******************************************************************************* ' parameter list: ' Row% - line# on screen to input string ' Column% - column on screen to input string ' InputField$ - the original string to edit ' Foreground% - character color of input field ' Background% - background color of input field ' ValidCharacters$ - list of allowable input characters: "" = all allowed ' ReturnMode% - way to return string: ' 1: return entire field as-is ' 2: return field less any trailing blanks ' 3: return field less any leading blanks ' 4: return field less both leading and trailing blanks ' 5: return field with all blanks removed ' 6: left justify and kill blanks between 1st and last char ' 7: right justify and kill inner blanks ' EntryMode% - way to terminate input: ' 1: terminates only when enter is pressed ' 2: terminates after cursor goes past last character in field ' CaseMode% - forces uppercase, lowercase or no preference ' 1: accept as entered ' 2: forces upper case ' 3: forces lower case True% = 1 ' logical true False% = 0 ' logical false EnterKey$ = CHR$(13) ' signifies end of entry Escape$ = CHR$(27) ' emergency exit from function EraseToEOF$ = CHR$(20) ' ^T erase from cursor to EOF RestoreField$ = CHR$(18) ' ^R restore original field EraseField$ = CHR$(25) ' ^Y erase entire field BackSpace$ = CHR$(8) ' dragging, destructive backspace RightArrow$ = "M" ' input cursor right LeftArrow$ = "K" ' input cursor left InsertKey$ = "R" ' insert mode toggle DeleteKey$ = "S" ' character delete HomeKey$ = "G" ' input cursor start of field EndKey$ = "O" ' input cursor after last char InputFinished% = False% ' set to true on enter or escape InsertMode% = False% ' start off in insert off mode OriginalField$ = InputField$ ' for ^R restore original field Length% = LEN(InputField$) ' total input field length CurrentColumn% = Column% ' cursor at first entry column CursorPosition% = 1 ' 1st position in entry string EndColumn% = Column% + Length% - 1 ' last column in entry string COLOR Foreground%, Background% ' set specified colors LOCATE Row%, Column%, 0 ' locate cursor PRINT InputField$; ' display original field LOCATE Row%, Column%, 1, 6, 7 ' locate at first character WHILE InputFinished% = False% ' main loop InputKey$ = INKEY$ ' get a keystroke if present EditKey$ = MID$(InputKey$, 2, 1) ' editing key pressed? IF EditKey$ <> "" THEN SELECT CASE EditKey$ CASE RightArrow$ IF CurrentColumn% <= EndColumn% THEN CurrentColumn% = CurrentColumn% + 1 CursorPosition% = CursorPosition% + 1 LOCATE Row%, CurrentColumn%, 1 END IF CASE LeftArrow$ IF CurrentColumn% > Column% THEN CurrentColumn% = CurrentColumn% - 1 CursorPosition% = CursorPosition% - 1 LOCATE Row%, CurrentColumn%, 1 END IF CASE InsertKey$ IF InsertMode% = True% THEN LOCATE Row%, CurrentColumn%, 1, 6, 7 InsertMode% = False% ELSE LOCATE Row%, CurrentColumn%, 1, 3, 7 InsertMode% = True% END IF CASE DeleteKey$ IF CurrentColumn% <= EndColumn% THEN FOR Index% = CursorPosition% TO Length% - 1 MID$(InputField$, Index%, 1) = MID$(InputField$, Index% + 1, 1) NEXT Index% MID$(InputField$, Length%, 1) = " " LOCATE Row%, Column%, 0 PRINT InputField$; LOCATE Row%, CurrentColumn%, 1 END IF CASE HomeKey$ IF CursorPosition% > 1 THEN CurrentColumn% = Column% CursorPosition% = 1 LOCATE Row%, CurrentColumn%, 1 END IF CASE EndKey$ IF CursorPosition% < Length% THEN FOR Index% = Length% TO 1 STEP (-1) IF MID$(InputField$, Index%, 1) <> " " THEN EXIT FOR END IF NEXT Index% CursorPosition% = Index% + 1 CurrentColumn% = Column% + Index% LOCATE Row%, CurrentColumn%, 1 END IF END SELECT ELSE SELECT CASE InputKey$ CASE Escape$ InputString$ = InputKey$ EXIT FUNCTION CASE BackSpace$ IF CurrentColumn% > Column% THEN N$ = "" FOR Index% = 1 TO CursorPosition% - 2 N$ = N$ + MID$(InputField$, Index%, 1) NEXT Index% FOR Index% = CursorPosition% TO Length% N$ = N$ + MID$(InputField$, Index%, 1) NEXT Index% InputField$ = LEFT$(N$ + SPACE$(Length%), Length%) CurrentColumn% = CurrentColumn% - 1 CursorPosition% = CursorPosition% - 1 LOCATE Row%, Column%, 0 PRINT InputField$; LOCATE Row%, CurrentColumn%, 1 END IF CASE EraseField$ InputField$ = SPACE$(Length%) LOCATE Row%, Column%, 0 PRINT InputField$; CursorPosition% = 1 CurrentColumn% = Column% LOCATE Row%, Column%, 1 CASE EraseToEOF$ IF CurrentColumn% <= EndColumn% THEN MID$(InputField$, CursorPosition%, Length% - CursorPosition% + 1) = SPACE$(Length% - CursorPosition% + 1) LOCATE Row%, Column% PRINT InputField$; LOCATE Row%, CurrentColumn%, 1 END IF CASE RestoreField$ InputField$ = OriginalField$ LOCATE Row%, Column%, 0 PRINT InputField$; CursorPosition% = 1 CurrentColumn% = Column% LOCATE Row%, Column%, 1 CASE EnterKey$ InputFinished% = True% CASE ELSE ValidKey% = False% ' null string for valid characters means all input accepted IF ValidCharacters$ = "" OR INSTR(ValidCharacters$, UCASE$(InputKey$)) > 0 THEN ValidKey% = True% END IF IF ValidKey% = True% AND InputKey$ <> "" AND CurrentColumn% <= EndColumn% THEN SELECT CASE CaseMode% CASE 1 ' do nothing, accept as entered CASE 2 InputKey$ = UCASE$(InputKey$) CASE 3 InputKey$ = LCASE$(InputKey$) END SELECT SELECT CASE InsertMode% CASE True% InputField$ = LEFT$(InputField$, CursorPosition% - 1) + InputKey$ + RIGHT$(InputField$, Length% - CursorPosition% + 1) InputField$ = LEFT$(InputField$, Length%) LOCATE Row%, Column% PRINT InputField$; CASE False% PRINT InputKey$; MID$(InputField$, CursorPosition%, 1) = InputKey$ END SELECT CursorPosition% = CursorPosition% + 1 CurrentColumn% = CurrentColumn% + 1 LOCATE Row%, CurrentColumn%, 1 ' check entry mode to see if end of field entry terminates entry IF CurrentColumn% > EndColumn% AND EntryMode% = 2 THEN InputFinished% = True% END IF END IF END SELECT END IF WEND ' return entered string appropriately SELECT CASE ReturnMode% CASE 1 ' return entire field InputString$ = InputField$ CASE 2 ' return field less any trailing blanks InputString$ = RTRIM$(InputField$) CASE 3 ' return field less any leading blanks InputString$ = LTRIM$(InputField$) CASE 4 ' return field less both leading and trailing blanks InputString$ = LTRIM$(RTRIM$(InputField$)) CASE 5 ' return field with all blanks removed N$ = "" FOR Index% = 1 TO Length% IF MID$(InputField$, Index%, 1) <> " " THEN N$ = N$ + MID$(InputField$, Index%, 1) END IF NEXT Index% InputString$ = N$ CASE 6 ' left justify and kill blanks between 1st and last char N$ = "" FOR Index% = 1 TO Length% IF MID$(InputField$, Index%, 1) <> " " THEN N$ = N$ + MID$(InputField$, Index%, 1) END IF NEXT Index% InputString$ = RIGHT$(N$ + SPACE$(Length%), Length%) CASE 7 ' right justify and kill inner blanks N$ = "" FOR Index% = 1 TO Length% IF MID$(InputField$, Index%, 1) <> " " THEN N$ = N$ + MID$(InputField$, Index%, 1) END IF NEXT Index% InputString$ = RIGHT$(SPACE$(Length%) + N$, Length%) END SELECT END FUNCTION FUNCTION InvertString$ (StringToInvert$) '******************************************************************************* '* "12345" returns "54321" * '******************************************************************************* IF StringToInvert$ = "" THEN InvertString$ = "" EXIT FUNCTION END IF New$ = "" FOR X% = LEN(StringToInvert$) TO 1 STEP (-1) New$ = New$ + MID$(StringToInvert$, X%, 1) NEXT X% InvertString$ = New$ END FUNCTION FUNCTION IsAlpha% (Text$) '******************************************************************************* '* Returns 1 if the text contains only letters and spaces, otherwise 0 * '******************************************************************************* ' if null, return 1 IF Text$ = "" THEN IsAlpha% = 1 EXIT FUNCTION END IF ' define allowed characters Allowed$ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ" FOR X% = 1 TO LEN(Text$) C$ = UCASE$(MID$(Text$, X%, 1)) IF INSTR(Allowed$, C$) = 0 THEN IsAlpha% = 0 EXIT FUNCTION END IF NEXT X% ' string passed IsAlpha% = 1 END FUNCTION FUNCTION IsNumeric% (Text$) '******************************************************************************* '* Returns 1 if the text contains only digits and +-. otherwise 0 * '******************************************************************************* ' if null, return 1 IF Text$ = "" THEN IsNumeric% = 0 EXIT FUNCTION END IF ' define allowed characters Allowed$ = "0123456789.+-" FOR X% = 1 TO LEN(Text$) C$ = UCASE$(MID$(Text$, X%, 1)) IF INSTR(Allowed$, C$) = 0 THEN IsNumeric% = 0 EXIT FUNCTION END IF NEXT X% ' string passed IsNumeric% = 1 END FUNCTION FUNCTION LeadZero$ (Number, NewLength%) '******************************************************************************* '* converts a number to a string and pads it on the left with leading zeros * '* up to the desired length. * '* If used on a negative number, the minus sign will be included when * '* calculating the new length. * '* Examples: LeadZero$(5,5) --> "00005" * '* LeadZero$(-5,5) --> "-0005" * '******************************************************************************* ' convert number to string New$ = LTRIM$(STR$(Number)) L% = LEN(New$) ' if string is = or longer than new length, retrun original IF NewLength% <= L% THEN LeadZero$ = New$ EXIT FUNCTION END IF ' remove minus sign if number is negative IF Number < 0 THEN New$ = RIGHT$(New$, (L% - 1)) END IF Diff% = NewLength% - L% ' pad string with leading zeroes New$ = STRING$(Diff%, "0") + New$ ' add minus sign if necessary IF Number < 0 THEN New$ = "-" + New$ END IF LeadZero$ = New$ END FUNCTION FUNCTION LeapYear% (Year%) '***************************************************************************** '* returns True (-1) if the specified year is a leap year * '***************************************************************************** LY% = (Year% MOD 4 = 0) AND (Year% MOD 100 <> 0) LY% = LY% OR (Year% MOD 400 = 0) LeapYear% = LY% END FUNCTION FUNCTION MonthName$ (Month%) '******************************************************************************* '* prints a string at desired location, with attributes * '******************************************************************************* SELECT CASE Month% CASE 1 MonthName$ = "January" CASE 2 MonthName$ = "February" CASE 3 MonthName$ = "March" CASE 4 MonthName$ = "April" CASE 5 MonthName$ = "May" CASE 6 MonthName$ = "June" CASE 7 MonthName$ = "July" CASE 8 MonthName$ = "August" CASE 9 MonthName$ = "September" CASE 10 MonthName$ = "October" CASE 11 MonthName$ = "November" CASE 12 MonthName$ = "December" CASE ELSE MonthName$ = "INVALID" END SELECT END FUNCTION FUNCTION Pad$ (Orig$, NewLength%, Side%, Char$) '******************************************************************************* '* Pads a string with a specified character on the specified side(s) up to * '* the new length. * '* The Side% argument is expressed: <0 = Left, 0 = Center, >0 = Right * '* Examples: Pad$("Hello!",10,1," ") --> "Hello! " * '* Pad$("$500",10,-1,"*") --> "******$500" * '* Pad$("WOW",20,0,"!") --> "!!!!!!!!WOW!!!!!!!!!" * '******************************************************************************* ' if char$ is null, default to space IF Char$ = "" THEN C$ = " " ELSE C$ = Char$ END IF L% = LEN(Orig$) ' if already = to new length, return the original IF L% = NewLength% THEN Pad$ = Orig$ EXIT FUNCTION END IF ' create string of pad characters Padx$ = STRING$(NewLength%, C$) SELECT CASE Side% ' pad left CASE IS < 0 Pad$ = RIGHT$(Padx$ + Orig$, NewLength%) ' pad right CASE IS > 0 Pad$ = LEFT$(Orig$ + Padx$, NewLength%) ' pad center CASE ELSE IF L% > NewLength% THEN C$ = Orig$ ' trim 1 char off alternating sides until string is new length DO WHILE L% > NewLength% L% = L% - 1 IF L% MOD 2 = 0 THEN C$ = RIGHT$(C$, L%) ELSE C$ = LEFT$(C$, L%) END IF LOOP Pad$ = C$ ELSE Diff% = NewLength% - L L% = Diff% \ 2 R% = Diff% - L Pad$ = STRING$(L%, C$) + Orig$ + STRING$(R%, C$) END IF END SELECT END FUNCTION SUB PrintAt (Row%, Col%, Fore%, Back%, StringToPrint$) '******************************************************************************* '* prints a string at desired location, with attributes * '******************************************************************************* LOCATE Row%, Col% COLOR Fore%, Back% PRINT StringToPrint$; END SUB SUB QuickSort (SortArray%(), Lower%, Upper%) '******************************************************************************* '* non-recursive quicksort algorithm * '* the data type for SortArray and Compare need to be changed if array to be * '* sorted is non - integer * '******************************************************************************* DIM SortStackLow%(128) DIM SortStackHigh%(128) StackPointer% = 1 SortStackLow%(StackPointer%) = Lower% SortStackHigh%(StackPointer%) = Upper% StackPointer% = StackPointer% + 1 DO StackPointer% = StackPointer% - 1 Low% = SortStackLow%(StackPointer%) High% = SortStackHigh%(StackPointer%) DO I% = Low% J% = High% Mid% = (Low% + High%) \ 2 Compare% = SortArray%(Mid%) DO DO WHILE SortArray%(I%) < Compare% I% = I% + 1 LOOP DO WHILE SortArray%(J%) > Compare% J% = J% - 1 LOOP IF I% <= J% THEN SWAP SortArray%(I%), SortArray%(J%) I% = I% + 1 J% = J% - 1 END IF LOOP WHILE I% <= J% IF J% - Low% < High% - I% THEN IF I% < High% THEN SortStackLow%(StackPointer%) = I% SortStackHigh%(StackPointer%) = High% StackPointer% = StackPointer% + 1 END IF High% = J% ELSE IF Low% < J% THEN SortStackLow%(StackPointer%) = Low% SortStackHigh%(StackPointer%) = J% StackPointer% = StackPointer% + 1 END IF Low% = I% END IF LOOP WHILE Low% < High% LOOP WHILE StackPointer% <> 1 END SUB FUNCTION RandInt% (Lower, Upper) STATIC '******************************************************************************* '* returns a pseudorandom number between lower and upper inclusive * '******************************************************************************* RandInt% = INT(RND * (Upper - Lower + 1)) + Lower END FUNCTION SUB ReColor (StartRow%, StartCol%, EndRow%, EndCol%, ChangeAtt%, ReplaceAtt%) '******************************************************************************* '* changes fore/back colors in given area of screen - assumes color monitor * '* if ChangeAtt% < 0, all attributes are changed to ReplaceAtt% '******************************************************************************* DEF SEG = &HB800 ' i'm assuming color here, use &HB000 for mono FOR Row% = StartRow% TO EndRow% FOR Col% = StartCol% TO EndCol% IF ChangeAtt% < 0 THEN POKE (Row% - 1) * 160 + ((Col% - 1) * 2) + 1, ReplaceAtt% ELSE IF PEEK((Row% - 1) * 160 + ((Col% - 1) * 2) + 1) = ChangeAtt% THEN POKE (Row% - 1) * 160 + ((Col% - 1) * 2) + 1, ReplaceAtt% END IF END IF NEXT Col% NEXT Row% DEF SEG END SUB FUNCTION Replace$ (Text$, LookFor$, ReplaceWith$) '******************************************************************************* '* replaces specified char/text in string with chosen replacement char/text * '* Using "" as ReplaceWith$ effectively eliminates (squeezes out) LookFor$ * '******************************************************************************* ' check for null original string, not in at all, or equal IF (Text$ = "") OR (INSTR(Text$, LookFor$) < 1) OR (Text$ = ReplaceWith$) OR LEN(Text$) < LEN(LookFor$) THEN Replace$ = Text$ EXIT FUNCTION END IF New$ = "" LengthOfReplacement% = LEN(ReplaceWith$) LengthOfText% = LEN(Text$) LengthOfStringToLookFor% = LEN(LookFor$) I% = 1 WHILE I% <= LengthOfText% - LengthOfStringToLookFor% + 1 IF MID$(Text$, I%, LengthOfStringToLookFor%) = LookFor$ THEN New$ = New$ + ReplaceWith$ I% = I% + LengthOfStringToLookFor% ELSE New$ = New$ + MID$(Text$, I%, 1) I% = I% + 1 END IF PRINT New$ WEND Replace$ = New$ END FUNCTION SUB RestoreScreen (FileName$) '******************************************************************************* '* Restores a screen saved by SaveScreen() * '******************************************************************************* ' display controller port ScreenType& = PEEK(&H63) + PEEK(&H64) * 256 ' mono or color? IF ScreenType& = &H3B4 THEN ScreenType& = &HB000 ' mono ELSE ScreenType& = &HB800 ' color END IF ' restore screen from disk DEF SEG = ScreenType& BLOAD FileName$, 0 DEF SEG END SUB FUNCTION Reverse$ (Text$) '******************************************************************************* '* ABCDE returns EDCBA * '******************************************************************************* Temp$ = "" FOR X% = LEN(Text$) TO 1 STEP (-1) Temp$ = Temp$ + MID$(Text$, X%, 1) NEXT X% Reverse$ = Temp$ END FUNCTION FUNCTION Rinstr% (Start%, Search$, LookFor$) '******************************************************************************* '* "Reverse INSTR". Returns the character position of the LAST occurrence * '* of a substring within another. If the Start argument is greater than zero, * '* search$ is truncated to (Start-1) before the search begins. The Start * '* argument is useful for subsequent calls to Rinstr, i.e., to find the second* '* to last occurrence, etc. * '* Example: Rinstr(0,"Peter Piper","er") --> 10 * '* Rinstr(10,"Peter Piper","er") --> 4 (Searches "Peter Pip") * '******************************************************************************* ' if either argument is null, return 0 IF Search$ = "" OR LookFor$ = "" THEN Rinstr% = 0 EXIT FUNCTION END IF ' return 0 if Start% > length of Search$ or is negative IF Start% > LEN(Search$) OR Start < 0 THEN Rinstr% = 0 EXIT FUNCTION END IF ' truncate if start pos is > 0, otherwise use original search string IF Start% > 0 THEN S$ = LEFT$(Search$, Start% - 1) ELSE S$ = Search$ END IF Last% = 0 ' get first occurrence X% = INSTR(S$, LookFor$) ' go thru string, increasing start pos each time substring is found WHILE X% > 0 Last% = X% X% = INSTR((Last% + 1), S$, LookFor$) WEND Rinstr% = Last% END FUNCTION SUB Rise (Text$, Row%, Col%) '******************************************************************************* '* Prints text vertically on the screen, rising from the specified row and * '* column position. If the length of the text would continue above row 1, * '* printing will stop at that point * '******************************************************************************* R% = Row% FOR X% = 1 TO LEN(Text$) LOCATE R%, Col% PRINT MID$(Text$, X%, 1); R% = R% - 1 IF R% = 0 THEN EXIT FOR NEXT X% END SUB FUNCTION RotateLeft$ (S$) '******************************************************************************* '* "1234567890" returns "2345678901" * '******************************************************************************* IF LEN(S$) < 1 THEN RotateLeft$ = "INVALID" ELSE RotateLeft$ = RIGHT$(S$, LEN(S$) - 1) + LEFT$(S$, 1) END IF END FUNCTION FUNCTION RotateRight$ (S$) '******************************************************************************* '* "1234567890" returns "0123456789" * '******************************************************************************* IF LEN(S$) < 1 THEN RotateRight$ = "INVALID" ELSE RotateRight$ = RIGHT$(S$, 1) + LEFT$(S$, LEN(S$) - 1) END IF END FUNCTION SUB SaveScreen (FileName$) '******************************************************************************* '* saves current text screen to the specified binary file. If file already * '* exists, it will be overwritten. SCREEN 0 (text mode) only * '******************************************************************************* ' display controller port ScreenType& = PEEK(&H63) + PEEK(&H64) * 256 ' mono or color? IF ScreenType& = &H3B4 THEN ' mono ScreenType& = &HB000 ELSE ScreenType& = &HB800 ' color END IF ' save screen to disk DEF SEG = ScreenType& BSAVE FileName$, 0, 4000 DEF SEG END SUB SUB SaveScreenToTextFile (FileName$) '******************************************************************************* '* saves text screen w/o attributes to an ASCII text file * '******************************************************************************* F% = FREEFILE OPEN "O", F%, FileName$ ' display controller port ScreenType& = PEEK(&H63) + PEEK(&H64) * 256 ' mono or color? IF ScreenType& = &H3B4 THEN ' mono ScreenType& = &HB000 ELSE ScreenType& = &HB800 ' color END IF ' save screen to disk DEF SEG = ScreenType& FOR Row% = 1 TO 25 SL$ = "" FOR Col% = 1 TO 80 SL$ = SL$ + CHR$(PEEK((Row% - 1) * 160 + ((Col% - 1) * 2))) LOCATE Row%, Col% NEXT Col% PRINT #F%, SL$ NEXT Row% DEF SEG CLOSE F% END SUB SUB Scroll (StartRow%, StartCol%, EndRow%, EndCol%, Direction%) '******************************************************************************* '* scrolls a given area of the screen up (direction=1) or down (dir <>1) once * '******************************************************************************* DEF SEG = &HB800 ' use &HB000 for mono IF Direction% = 1 THEN SRow% = StartRow% + 1 ERow% = EndRow% Inc% = 1 ELSE SRow% = EndRow% - 1 ERow% = StartRow% Inc% = (-1) END IF FOR Row% = SRow% TO ERow% STEP Inc% FOR Col% = StartCol% TO EndCol% CharacterAddress% = (Row% - 1) * 160 + ((Col% - 1) * 2) CharacterToScroll% = PEEK(CharacterAddress%) IF Direction% = 1 THEN MoveToAddress% = CharacterAddress% - 160 ELSE MoveToAddress% = CharacterAddress% + 160 END IF POKE MoveToAddress%, CharacterToScroll% POKE MoveToAddress% + 1, PEEK(CharacterAddress% + 1) 'attribute POKE CharacterAddress%, 32 NEXT Col% NEXT Row% DEF SEG END SUB SUB SetCursor (CursorType%) '******************************************************************************* '* set cursor - 0=none, 1 = underscore, 2 = block cursor * '******************************************************************************* SELECT CASE CursorType% CASE 0 'None - turn it off LOCATE , , 0 CASE 1 'Insert - underscore cursor LOCATE , , 1, 7 CASE 2 'Overwrite - block cursor LOCATE , , 1, 0, 7 END SELECT END SUB SUB Slide (Text$, LeftOrRight%, Row%, Col%, Delay) '**************************************************************************** '* Slides text onto the screen to the left or right starting at the * '* specified row and column. Direction is determined by the argument * '* LeftOrRight%, where a zero value equals left, non-zero equals right. * '* Delay is measured in 100ths of a second. * '**************************************************************************** ' convert delay to single precision D! = Delay ' minimum 1/20th sec delay IF D! < 1 THEN D! = 5 END IF ' convert delay to 100ths of a second D! = D! / 100 FOR X% = 1 TO LEN(Text$) ' slide to the left IF LeftOrRight% = 0 THEN ' check column for illegal value (<1) IF (Col% - X% + 1) < 1 THEN EXIT FOR END IF ' print 1 char at a time, from left to right LOCATE Row%, Col% - X% + 1 PRINT LEFT$(Text$, X%); ELSE ' slide from right to left, 1 char at a time LOCATE Row%, Col% PRINT RIGHT$(Text$, X%); END IF ' current value of TIMER CurrentTimer! = TIMER ' delay appropriate time WHILE TIMER < (CurrentTimer! + D!) WEND ' stop delaying if a key is pressed IF INKEY$ <> "" THEN D! = 0 END IF NEXT X% END SUB SUB Spread (Text$, Row%, Col%, Delay) '******************************************************************************* '* Spreads text on the screen in both directions starting from the specified * '* coordinates. Delay is measured in 100ths of a second * '******************************************************************************* ' convert delay to single precision D! = Delay ' always have at least 1/20 sec. delay IF D! < 1 THEN D! = 5 END IF ' change to 100ths D! = D! / 100 ' if null, get out IF Text$ = "" THEN EXIT SUB END IF Txt$ = Text$ ' make text length even if not already so IF LEN(Txt$) MOD 2 = 1 THEN Txt$ = Txt$ + " " END IF ' divide text into left and right sides LeftSide$ = LEFT$(Txt$, LEN(Txt$) \ 2) RightSide$ = RIGHT$(Txt$, LEN(Txt$) \ 2) FOR X% = 1 TO LEN(RightSide$) LOCATE Row%, Col% PRINT RIGHT$(RightSide$, X%); ' print a letter from the left side IF (Col% - X%) >= 1 THEN LOCATE Row%, Col% - X% PRINT LEFT$(LeftSide$, X%); END IF CurrentTimer! = TIMER WHILE TIMER < (CurrentTimer! + D!) WEND 'Wait for timer to increase by d! IF INKEY$ <> "" THEN D! = 0 'if a key is pressed, stop delaying END IF NEXT X% END SUB FUNCTION Squeeze$ (Orig$, Char$) '******************************************************************************* '* removes all occurrences of a substring from within a string * '* example: Squeeze$("Peter Piper","er") --> "Pet Pip" * '******************************************************************************* IF Orig$ = "" OR Char$ = "" THEN Squeeze$ = Orig$ EXIT FUNCTION END IF New$ = Orig$ DO WHILE INSTR(New$, Char$) > 0 X% = INSTR(New$, Char$) L$ = LEFT$(New$, X% - 1) R$ = MID$(New$, X% + LEN(Char$)) New$ = L$ + R$ LOOP Squeeze$ = New$ END FUNCTION FUNCTION Strip$ (Text$, Delete$) '******************************************************************************* '* any characters in Text$ that are in Delete$ will be removed from Text$ * '******************************************************************************* ' check for null Text$ or Delete$ IF Text$ = "" OR Delete$ = "" THEN Strip$ = Text$ EXIT FUNCTION END IF Temp$ = "" ' build new string, less delete characters FOR X% = 1 TO LEN(Text$) Char$ = MID$(Text$, X%, 1) IF INSTR(Delete$, Char$) = 0 THEN Temp$ = Temp$ + Char$ END IF NEXT X% Strip$ = Temp$ END FUNCTION SUB StuffBuf (Keys$) STATIC '******************************************************************************* '* Inserts Keys$ into the keyboard buffer just as if it had been * '* entered from the keyboard. Note that only fifteen characters may * '* be inserted or the machine may lock up. * '******************************************************************************* Work$ = LEFT$(Keys$, 15) '15 characters maximum Length% = LEN(Work$) DEF SEG = 0 POKE &H41A, &H1E 'buffer head POKE &H41C, &H1E + Length% * &H2 'buffer tail FOR X% = 1 TO Length% 'POKE each char one by one POKE &H41C + X% * &H2, ASC(MID$(Work$, X%)) NEXT X% DEF SEG Work$ = "" END SUB SUB TeleType (Text$, Delay) '******************************************************************************* '* Prints text one character at a time beginning at the current cursor * '* location. Delay between each character being printed is measured in * '* 1/100ths second (delay of 100 = 1 second). If a value of zero or less * '* is specified, the delay defaults to 5/100ths of a second. If a key is * '* pressed during the SUB, remainder of string is printed with no delay * '******************************************************************************* D! = Delay ' if no delay, assign default IF D! < 1 THEN D! = 5 END IF ' change delay to 100ths second D! = D! / 100 ' print text 1 char at a time, with a "click" after non-space characters FOR X% = 1 TO LEN(Text$) T$ = MID$(Text$, X%, 1) PRINT T$; IF T$ <> " " THEN SOUND 20000, 1 END IF ' get current value of TIMER CurrentTimer! = TIMER ' delay appropriate time WHILE TIMER < (CurrentTimer! + D!) WEND ' stop delaying if a key is pressed IF INKEY$ <> "" THEN D! = 0 END IF NEXT X% END SUB SUB Warp '******************************************************************************* '* starfield screen saver (hi-res, must repaint screen 0) * '******************************************************************************* DIM Sine%(360), Cosine%(360) DIM StarAngle%(100), StarDistance%(100) DIM OldStarX%(100), OldStarY%(100) DIM StarTransX%(100), StarTransY%(100) DIM StarSpeed%(100) NumStars% = 100 FOR N% = 0 TO 360 Sine%(N%) = SIN(N% / 57.2958) * 10 Cosine%(N%) = COS(N% / 57.2958) * 10 NEXT N% FOR N% = 1 TO NumStars% StarAngle%(N%) = INT((360 - 1 + 1) * RND + 1) StarDistance%(N%) = INT((1000 - 1 + 1) * RND + 1) StarSpeed%(N%) = INT((100 - 1 + 1) * RND + 1) NEXT N% SCREEN 13 WINDOW (-10000, -10000)-(10000, 10000) DO FOR N% = 1 TO NumStars% StarDistance%(N%) = (StarDistance%(N%) + StarSpeed%(N%)) MOD 1000 StarTransX%(N%) = (Cosine%(StarAngle%(N%))) - (Sine%(StarAngle%(N%))) * StarDistance%(N%) StarTransY%(N%) = (Sine%(StarAngle%(N%))) + (Cosine%(StarAngle%(N%))) * StarDistance%(N%) NEXT N% FOR N% = 1 TO NumStars% PSET (OldStarX%(N%), OldStarY%(N%)), 0 PSET (StarTransX%(N%), StarTransY%(N%)), StarDistance%(N%) \ 68 + 17 OldStarX%(N%) = StarTransX%(N%) OldStarY%(N%) = StarTransY%(N%) NEXT N% Key$ = INKEY$ LOOP UNTIL Key$ <> "" OR MID$(Key$, 2, 1) <> "" SCREEN 0 END SUB SUB WipeArea (Row1%, Col1%, Row2%, Col2%) '******************************************************************************* '* clears an area of the screen * '******************************************************************************* Sp$ = SPACE$(Col2% - Col1% + 1) FOR X% = Row1% TO Row2% LOCATE X%, Col1% PRINT Sp$; NEXT X% ' place cursor at top left of area LOCATE Row1%, Col1% END SUB SUB WipeCol (Col%, Rows%) '******************************************************************************* '* clears a column on the screen, taking into account 50-line display (Rows%) * * '******************************************************************************* R% = CSRLIN C% = POS(0) LOCATE 1, Col% FOR X% = 1 TO Rows% LOCATE X%, Col% PRINT " "; NEXT X% ' restore original cursor position LOCATE R%, C% END SUB SUB WipeEOL '******************************************************************************* '* clears display from cursor position to end of current line * '******************************************************************************* R% = CSRLIN C% = POS(0) PRINT SPACE$(80 - C% + 1); LOCATE R%, C% END SUB SUB WipeEOP '******************************************************************************* '* clears display from cursor to end of display, inclusive * '******************************************************************************* R% = CSRLIN C% = POS(0) PRINT SPACE$(80 - C% + 1); FOR X% = R% + 1 TO 25 LOCATE X%, 1 PRINT SPACE$(80); NEXT X% LOCATE R%, C% END SUB SUB WipeRow (StartCol%, EndCol%) '******************************************************************************* '* clears a row on the screen between StartCol and EndCol inclusive * '******************************************************************************* IF (StartCol% < 1 OR StartCol% > 80) OR (EndCol% < 1 OR EndCol% > 80) THEN EXIT SUB END IF R% = CSRLIN C% = POS(0) LOCATE R%, 1 PRINT SPACE$(EndCol% - StartCol% + 1); ' restore original cursor position LOCATE R%, C% END SUB SUB WipeSOL '******************************************************************************* '* clears display from start of current line to cursor position inclusive * '******************************************************************************* R% = CSRLIN C% = POS(0) LOCATE R%, 1 PRINT SPACE$(C%); LOCATE R%, C% END SUB SUB WipeSOP '******************************************************************************* '* clears display from start of display to cursor, inclusive * '******************************************************************************* R% = CSRLIN C% = POS(0) FOR X% = 1 TO R% - 1 LOCATE X%, 1 PRINT SPACE$(80); NEXT X% LOCATE R%, 1 PRINT SPACE$(C%); LOCATE R%, C% END SUB