Advanced Function Library for the BASIC Compiler ADVBAS.LIB v4.0, 12/15/87 Copyright (C) Thomas Hanlin III, 1985-1987 1712 Maple Hill Place Alexandria, VA 22302 Requirements: An IBM PC or compatible with the IBM BASIC Compiler v2.x or any Microsoft QuickBASIC Compiler. PC-DOS/MS-DOS versions 2.0 or higher should be used. Some functions may require a PC AT or compatible, as noted. Please read the Operation Notes. Note that ADVBAS has been "frozen" into its current state. There will be no additions or further updates. I was able to convert ADVBAS to work with QuickBASIC 4.0 only by the kindness of HCSI in letting me "bend" my contract with them. While ADVBAS is full-featured and is not crippled in any way, I'd like you to consider it as a sample of the commercial library, ProBas. You may use ADVBAS subject to the restrictions below, but you will be much better off by upgrading to ProBas. ProBas contains nearly twice the routines in ADVBAS, and comes with a printed manual of nearly 600 pages, with tutorial and reference sections. See the PROBAS.DOC file for further information on ProBas. Copying and Distribution: ADVBAS may be copied and distributed freely EXCEPT FOR THE ASSEMBLY SOURCE CODE. If you distribute ADVBAS on communications systems such as BBSes or CompuServe, the Source, et al, you must include a minimum of the following unmodified files as a set (using ARC or an equivalent archive utility): ADVBAS.EXE, ADVBAS.LIB, ADVBAS.DOC, ADVBAS.NEW, ADVBAS.QRF, ADVBAS.ERR, CONTRIB.DOC, and PROBAS.DOC. No fee other than a disk and handling charge (of up to $10) may be charged. The copyright is to preserve my options, and to protect you from the untoward modifications of others. It is not intended to prevent the public distribution of ADVBAS, subject to the above limitations. Introduction: The BASIC Compiler is a powerful and flexible tool. However, it suffers from a number of limitations. It is hard to access many of the capabilities of DOS; any feature which requires error trapping cannot be used in a subprogram; the memory requirements are fairly substantial; and the speed is not all that it might be, for all its improvement over interpreted BASIC. To reduce these problems, I've designed a number of assembly language routines which perform various functions, and put them in a library which the compiler can access. Since I have found these functions to be useful, I thought I'd pass them on to other people. You may use ADVBAS functions in any of your programs. I'd appreciate it if you acknowledged use of these routines in your program or documentation. If you find ADVBAS useful, please support the author's efforts! A minimum contribution of $25 will get you a disk containing the latest version of ADVBAS, including source and object code. Support: Please read this manual before calling me with any problems. You can probably find the answer here, and save us both trouble. If you are a contributor (bless you!), I'll certainly be glad to help you with any difficulties you may encounter. U.S. Mail is the preferred method of exchange, but feel free to call if the situation gets out of hand. If you are not a contributor (sigh), please send a SASE, and I'll get back to you. PLEASE do not phone! If you don't care enough to contribute the minimal fee I ask, you should not expect me to pro- vide services. TANSTAAFL! (There Ain't No Such Thing As A Free Lunch) Caveats: These functions have not caused me any problems, and seem to be fully debugged. However, I will not be responsible for any damages caused by use, misuse, or inability to use ADVBAS. If you run into problems, please read through the first few pages of the manual. All the information you need to use ADVBAS is in there. Misc. Notes: This is the final shareware release of ADVBAS. I will continue to support it, but I will not be releasing any new versions. ADVBAS is being replaced by the ProBas library, which is being marketed through commercial channels. ProBas contains about twice as many routines as ADVBAS. Among other goodies: sorting, expanded memory support, dynamic array support, improved mouse routines, new equipment detection and control functions, more flexible screen handling, an improved pop-up window generator, controllable field input with editing, "long" number support (even if you don't have QuickBASIC 4.0!), and much more. One of the more powerful capabilities provided by ProBas lies in a full set of func- tions to support "virtual screens". These are screens which can be set up in memory, and then displayed (entirely or in part) instantly. Using conventional or expanded memory, you can store hundreds of screens in memory for instant recall. This is similar to the paging ability of EGA and most CGA displays, but will work with any system, and is not limited to just a few screens of information. An extensive (600-page) printed user manual contains detailed information on the routines in a format that is equally suited to the novice or the professional. Fully documented demonstration code in BASIC is also provided. ProBas is priced at $99.00. Shipping is $3.00. Sales tax is applicable for Maryland residents. There is an order form in PROBAS.DOC, or you may address your ProBas order to: HCSI 8008 Sandy Spring Rd Laurel, MD 20707 For more information, write to the above address, or you can call (301) 953-2191. C.O.D. orders are accepted, and credit card orders will hopefully be accepted in the near future. Using ADVBAS with QuickBASIC 4.0: Note the list of bugs in QuickBASIC 4.0 at the end of this manual! Some of them affect ADVBAS functions, so read up! If you use QuickBASIC in the programming environment, you need to have a copy of ADVBAS.QLB in the drive/subdirectory where you keep your library files (like BRUNxx.LIB). When you start up QuickBASIC, you need to tell it to load the ADVBAS library so you can use its features. Run QuickBASIC with the following syntax: "QB /L ADVBAS". You may also specify a program to load: "QB MYPROG /L ADVBAS". Note that you are not meant to type in the quotes, which are there for guidance only. You may also need to include a drive/path spec for ADVBAS if it is in a different drive/path than the default (which is either the current area, or the area specified by the DOS environ- ment variable "LIB"). That might look something like the following: "QB /L C:\LIB\ADVBAS" Using ADVBAS with QuickBASIC 2.0 - 3.0: If you use QuickBASIC in the programming environment, you need to have a copy of ADVBAS.EXE in the drive/subdirectory where you keep your library files (like BRUNxx.LIB). When you start up QuickBASIC, you need to tell it to load the ADVBAS library so you can use its features. Start up QuickBASIC using the syntax: "QB /L ADVBAS.EXE". You may also specify a program to load: "QB PROGRAM /L ADVBAS.EXE". Note that you are not meant to type in the quotes, which are there for guidance only. You may also need to include a drive/path spec for ADVBAS if it is in a different drive/path than the default. That might look something like "QB /L C:\LIB\ADVBAS.EXE". Using IBM or Microsoft BASIC compilers (command-line mode): Copy ADVBAS.LIB to the disk on which you keep your BASIC Compiler library files. For programs which use ADVBAS functions, specify ADVBAS when LINK asks you which libraries to use. That is, at the LINKer prompt "Libraries [.LIB]:" you should say "ADVBAS" (without the quotes!). You may need to provide a drive/path spec if your program is not in the same area that ADVBAS is, and if you don't have a SET LIB in your autoexec file to tell the compiler where the library is (only newer versions of the compilers have this feature). Other languages: A library for Microsoft C is available under the name of ADVC. It is in C source format, so you can convert any nonstandard func- tions to your own variety of C. If you can't find it on your local BBS, I'll send you a copy for the recommended minimum contribution of $15. Updates are not anticipated. Commercial versions of the ADVBAS library to support languages other than BASIC will be shipping in early 1988. Languages to be supported are Microsoft C, Pascal, and FORTRAN compilers, as well as assembly language. There will be no support for Borland's languages until they come up with a decent way to handle libraries. Advantages of ADVBAS: 1) Adds abilities which are not otherwise available. 2) Is faster than the corresponding Compiled BASIC code. 3) Usually takes up less space in the resulting EXEcutable file. 4) Often leaves more free programming space. 5) Provides a useful library of tested low-level routines. Operation Notes Function Requirements: Numeric variables used in function calls must be integers unless specified otherwise. Either declare them using DEFINT, or add a per- cent sign "%" to the end of the variable name. Strings must sometimes be defined to a certain minimum length, due to limitations on what assembly language routines are allowed to do to strings. Dynamic Arrays cannot be used interchangeably with normal (Static) arrays. Use only static arrays with functions which require arrays. Note that functions requiring static arrays cannot be used in the QuickBASIC 4.0 environment, due to a QB bug. However, you may still use them in the stand-alone version of the compiler, BC. Compatibility: These functions vary in what they demand of your PC. Some func- tions will work only on IBM PCs or clones, some will work on compati- bles, and some will work on any MS-DOS machine. The compatibility level of each function is now listed, using the categories CLONE (will work on hardware compatibles only), BIOS (close compatibles), DOS (any MS-DOS machine), and ANY (hardware independent). Be warned that the BASIC Compiler itself does not produce particularly compatible code (BASIC video routines seem to be BIOS-compatible, etc). Routine Reference Disk: CopyFile: copy a file DelSub, GetSub, MakeSub, SetSub: subdirectory handling DiskStat: assorted disk status information DrvSpace: space left on a given drive Exist: see if a file exists Fclose, Fcreate, Fopen, Fread, FsetEnd, FsetRec, Fclose: file i/o FindFirstF, FindNextF: handle file(s) with wildcards GetDrv, SetDrv: get/set the default drive GetFdate, GetFtime, SetFTD, GetFattr, SetFattr: file info control GetNameF, GetDateF, GetTimeF, GetAttrF, GetSizeF: file dir control Mload: a BLOAD routine SubExist: see if a subdirectory exists Input: ClrKbd: clear the keyboard buffer of pending keys DosInkey: get a key using DOS standard input GetKbd, SetKbd: get/set the status of the keyboard toggles GetKey: get one of a list of valid keys KeyPress: see if a key has been pressed MMcursorOn, MMcursorOff: mouse cursor control MMgetloc, MMsetloc, MMsetrange: mouse display control MMbutton, MMcheck, MMclick: mouse status info String: Bsq, BusqLen, Busq: text compression/decompression Checksum, CRC: error checking (for telecomm and other uses) Crunch: remove duplicates of a character from a string. DateN2S, DateS2N: convert the date (numbers <--> string) Extract: take delimited substrings from a string using an index Locase, Upcase: case conversion MultiAnd, MultiOr, MultiXor: bit manipulations on strings Strip, StripBlanks, StripRange: deletion of chars from a string LRotate, RRotate, Reverse: reorder chars in a string Soundex: return the Soundex code of a string TimeN2S, TimeS2N: convert the time (numbers <--> string) Tinstr: find a given type of char within a string Xlate: run the chars of a string through a translation table Routine Reference Array: AddMatI, SetMatI: integer array manipulation ReadBitF, WriteBitF: handle arrays of arbitrary bit length Video: CalcAttr: calculate attribute from fore and background colors ClrEol, BkSpace, DelChr, InsChr, MDelChr, MInsChr: screen control DMprint, Mprint, MprintC, Qprint, XQprint: various print routines GetCRT: get display type (mono or color) MakeWindow: make pop-up windows Mwindow, Scroll, BkScroll: display window control PrintScreen: print out the display to the default printer ScrSave, ScrRest, GetLine: save/restore the contents of a screen ScrSaveP, ScrSavePD, ScrRestP, ScrRestPD: variants on the above GetScreen, PutScreen: new flexible screen save/restore routines ReColor: change any screen color to another w/o clearing screen ResetPoint, SetPoint, TestPoint: low-res graphics in text mode Miscellaneous: Any2Dec, Dec2Any: radix conversion (decimal <--> another base) BlockMove: move data from one area of memory to another Carrier: check modem Carrier Detect signal DataSeg: return the value of the default Data Segment Date2int, Int2date: date compression Delay, Delay18th: delay for a given amount of time DTR: turn the communications line "DTR" on or off Equipment: get hardware info about memory and installed ports GetDOSv: get the version number of the MS-DOS being used GetExtM: return the amount of extended memory (AT systems only) GetLIMM: get the status of expanded memory in the system Month: given a month number, returns the name of the month SetComm: set up any comm port to any baud, without closing comm ShiftL, ShiftR: bit shifts for integers Speaker: turns sound effects on or off Time2int, Int2time: time compression WeekDay: returns the day of the week, Sunday through Saturday Compatibility Chart Works on ANY machine: ADDMATI, ANY2DEC, BLOCKMOVE, BSQ, BUSQ, BUSQLEN, CALCATTR, CHECKSUM, CRC, CRUNCH, DATASEG, DATE2INT, DEC2ANY, EXTRACT, GETLINE, INT2DATE, INT2TIME, LOCASE, LROTATE, MONTH, MULTIAND, MULTIOR, MULTIXOR, READBITF, REVERSE, RROTATE, SETMATI, SHIFTL, SHIFTR, SOUNDEX, STRIP, STRIPBLANKS, STRIPRANGE, TIME2INT, TINSTR, UPCASE, WRITEBITF, XLATE Works on DOS compatibles: COPYFILE, DELSUB, DISKSTAT, DMPRINT, DOSINKEY, DRVSPACE, EXIST, FCLOSE, FCREATE, FINDFIRSTF, FINDNEXTF, FOPEN, FREAD, FSETEND, FSETREC, FWRITE, GETATTRF, GETDATEF, GETDOSV, GETDRV, GETFATTR, GETFDATE, GETFTIME, GETNAMEF, GETSIZEF, GETSUB, GETTIMEF, MAKESUB, MLOAD, SETDRV, SETFATTR, SETFTD, SETSUB, SUBEXIST, WEEKDAY Works on BIOS compatibles (* if it requires the AT BIOS): BKSCROLL, BKSPACE, CARRIER, CLRKBD, CLREOL, DATEN2S, DATES2N, DELAY, DELAY18TH, EQUIPMENT, GETCRT, GETEXTM*, GETKEY, GETLIMM, KEYPRESS, MDELCHR, MINSCHR, MMBUTTON, MMCHECK, MMCLICK, MMCURSOROFF, MMCURSORON, MMGETLOC, MMSETLOC, MMSETRANGE, MPRINT, MPRINTC, MWINDOW, PRINTSCREEN, RESETPOINT, SETPOINT, SCROLL, TESTPOINT, TIMEN2S, TIMES2N, XMPRINT Works on CLONEs (hardware compatibles): DELCHR, DTR, GETKBD, GETSCREEN, INSCHR, MAKEWINDOW, PUTSCREEN, QPRINT, RECOLOR, SCRREST, SCRRESTP, SCRRESTPD, SCRSAVE, SCRSAVEP, SCRSAVEPD, SETCOMM, SETKBD, SPEAKER, XQPRINT, XQPRINTD Note that routines from higher sections will work on machines from lower sections (DOS-level routines will work on BIOS- and CLONE-level machines). It doesn't work the other way around (CLONE-level routines may not work on a DOS-level machine). Name: ADDMATI Type: Miscellaneous / ANY Description: Adds a scalar (integer) value to the first SIZ elements of an integer array. You can subtract by adding a negative number. If the results of the calculation ever go outside integer range (-32768 to 32767), the overflow flag is set on return. See SETMATI for more information. Example: OPTION BASE 1: DIM ACK%(10000): SIZ%=10000 . . ADDVAL%=-6: ARLOC%=VARPTR(ACK%(1)) CALL ADDMATI(ARLOC%,SIZ%,ADDVAL%,OVFLOW%) IF OVFLOW% THEN PRINT"Uh oh, overflowed somewhere..." REM we just subtracted six from each element of the array ACK. Name: ANY2DEC Type: Miscellaneous / ANY Description: Converts a number (in string form) from any base (2-35) to a decimal integer (base 10). The number to be converted may be in either signed integer range (-32768 to 32767) or unsigned integer range (0 to 65535). It is converted to a signed integer, which is the only integer type BASIC supports. Example: INPUT"Number, base of number";ANUM$,NBASE% CALL ANY2DEC(ANUM$,NBASE%,DNUM%,ERCD%) IF ERCD% THEN PRINT"Bad number!" ELSE PRINT"Decimal: ";DNUM% Name: BKSCROLL Type: Video / BIOS Description: The same as SCROLL (q.v.), but scrolls lines in the opposite direction (Back Scroll). Example: CALL BKSCROLL(LEFTCOL%,TOPROW%,RTCOL%,BOTROW%,NUMLINES%) Name: BKSPACE Type: Video / BIOS Description: Move cursor back one space, destroying the character on the space moved to. Will wrap from one line to the next higher if necessary. If at the top left corner of the screen, no action is performed. Two arguments return the new cursor coordinates. Works with 40 or 80 column screens in text mode. Example: CALL BKSPACE(COL%,ROW%): LOCATE ROW%,COL% Name: BLOCKMOVE Type: Miscellaneous / ANY Description: Copies information from one area of memory to another. You supply the source segment and offset, destination segment and offset, number of bytes to move (0 - 65535), and direction (zero, forward; nonzero, backward). This can be used, for instance, to duplicate numeric arrays. including dynamic arrays. Example: CALL BLOCKMOVE(FROMSEG%,FROMOFFSET%,TOSEG%,TOOFFSET%,BYTES%,DIRECTION%) Name: BSQ Type: String / ANY Description: Uses several techniques to compress blank spaces out of an ASCII string. Savings range from 16% (reliable, for ordinary text) to up around 50% or more for space-intensive info, such as lines in an assem- bly source file. BSQ cannot handle more than 127 spaces in a row on a single line, or lines which contain ASCII characters greater than 127 (which are IBM-specific graphics characters). Do not use BSQ on lines which may contain such information! BSQ compression is designed to produce printable (if odd-looking) text which you may read/write to ordinary sequential files. Example: INPUT"String to squeeze";ST$: CALL BSQ(ST$,SLEN%) PRINT"Squeezed string: ";LEFT$(ST$,SLEN%) Name: BUSQ Type: String / ANY Description: Decompresses a line squeezed by BSQ. Use BUSQLEN before this routine to find out how long the unsqueezed line will be! Example: see BUSQLEN Name: BUSQLEN Type: String / ANY Description: Tells how long a line squeezed with BSQ will be once it's unsqueezed. You must use this before unsqueezing the line with BUSQ. Example: CALL BUSQLEN(ST$,SLEN%) IF SLEN%<0 THEN line not squeezed, or damaged-- exit! ELSE UNSQ$=SPACE$(SLEN%): CALL BUSQ(ST$,UNSQ$) Name: CALCATTR Type: Video / ANY Description: Calculates the color attribute for such routines as XQPRINT. Unlike the BASIC formula it replaces, CALCATTR allows use of the "blink" attribute. Example: REM old formula was ATTR% = (BACKGND% AND 7)*16 + FOREGND% CALL CALCATTR(FOREGND%,BACKGND%,ATTR%) Name: CARRIER Type: Miscellaneous / BIOS Description: Returns the status of the modem Carrier Detect signal. You may specify communications port one or two. Example: COMMPORT% = 1 CALL CARRIER(COMMPORT%,CDSTATUS%) IF CDSTATUS% THEN PRINT "Carrier detected" ELSE PRINT "No carrier" Name: COPYFILE Type: Disk / DOS Description: Copies a file. This is faster than the corresponding DOS command, and doesn't have the overhead of using the SHELL command. Note: to avoid possibly wiping out an existing file on the destination end, you may wish to use the EXIST function before this one. The copy will usually fail for one of two reasons: the source file doesn't exist, or there is not enough room on the disk for the destination file. Example: SOURCE$="A:EXAMPLE.TXT"+CHR$(0) DESTINATION$="C:\DOCUMENT\EXAMPLE.TXT"+CHR$(0) CALL COPYFILE(SOURCE$,DESTINATION$,ERRCODE%) IF ERRCODE% THEN PRINT"The copy failed" Name: CHECKSUM Type: Miscellaneous / ANY Description: Calculates a checksum for a record. Can be used with Xmodem or Ymodem. Example: CALL CHECKSUM(REC$,CHKSM%) Name: CLREOL Type: Video / BIOS Description: Clears from the cursor position to the end of the line without moving the cursor. Example: CALL CLREOL Name: CLRKBD Type: Input / BIOS Description: Clears any pending keys from the keyboard buffer. Example: CALL CLRKBD INPUT"File not found. Continue (Y/N)";ANS$ Name: CRC Type: Miscellaneous / ANY Description: Calculates a cyclical redundancy check value for a record. This is useful for error detection, and can be used with Xmodem CRC or Ymodem CRC modem transfer protocols. Example: Sending a record: REC$=REC$+STRING$(2,0) : CALL CRC(REC$,HICRC%,LOCRC%) : MID$(REC$,LEN(REC$)-1,2) = CHR$(HICRC)+CHR$(LOCRC%) REM we're set to send an Xmodem record Receiving a record: CALL CRC(REC$,HICRC%,LOCRC%) : IF HICRC%=0 AND LOCRC%=0 THEN record is fine, save it ELSE record is bad, request it to be sent again Name: CRUNCH Type: String / ANY Description: Crunches duplicates of a given character in a string down to a single character. Example: ST$="This####is#a##test" CH$="#" CALL CRUNCH(ST$,CH$,SLEN%) ST$=LEFT$(ST$,SLEN%) REM the result here will be "This#is#a#test" Name: DATASEG Type: Miscellaneous / ANY Description: Returns BASIC's data segment. This is useful for BLOCKMOVE, among other things. Example: CALL DATASEG(DSEG%) Name: DATE2INT Type: Miscellaneous / ANY Description: Compresses a date down to a single integer, to reduce storage requirements. The date is assumed to be valid. The year should be within the range 1900-2026 (0-99 is ok, and is assumed to be 1900-1999). See also INT2DATE. Example: CALL DATE2INT(MONTH%,DAY%,YEAR%,SQZDATE%) Name: DATEN2S Type: String / ANY Description: Converts the date from numeric form to a string. You must reserve at least eight characters for the string. Example: MONTH% = 3: DAY% = 2: YEAR% = 1987 REM We could use YEAR%=87 instead DAT$ = SPACE$(8) CALL DATEN2S(MONTH%,DAY%,YEAR%,DAT$) REM From this, we will get DAT$ = "03/02/87" Name: DATES2N Type: String / ANY Description: Converts the date from a string to numeric form. The date string may be in either BASIC format ("03-15-1987") or normal format ("03/15/87"). Example: CALL DATES2N(MONTH%,DAY%,YEAR%,DATE$) Name: DEC2ANY Type: Miscellaneous / ANY Description: Converts a number from decimal (base 10) to any other base (2-35). The number will be converted to an unsigned integer (signed range of -32768 to 32767 is converted to unsigned range of 0 to 65535), to conform with the built-in BASIC conversion functions HEX$ and OCT$. ANUM$ must be initialized to the maximum size you expect the resultant number to be; this is recommended to be 16 characters, which is the maximum length possible. The result is right-justified in the field you provide, so if you want to keep leading zeroes, just ignore the actual-length specification ALEN%. Example: INPUT"Decimal number, to base";DNUM%,NBASE% ANUM$ = STRING$(16,"0"): CALL DEC2ANY(DNUM%,NBASE%,ANUM$,ALEN%) IF ALEN%<0 THEN PRINT"Bad base or ANUM$ initialized too short" ELSE PRINT"Result: ";RIGHT$(ANUM$,ALEN%) Name: DELAY Type: Miscellaneous / BIOS Description: Delays for a given number of seconds. This is based on the system clock, and will delay for the same amount of time on an 8088 or 80286-based computer. It is normally accurate to within about one percent. Example: SECONDS%=60 CALL DELAY(SECONDS%) REM sit and "do nothing" for one minute Name: DELAY18TH Type: Miscellaneous / BIOS Description: Delays for a given number of eighteenths of seconds. Otherwise, this is identical to DELAY (see). Example: MINIDELAY%=9 CALL DELAY18TH(MINIDELAY%) REM delay for half a second (9/18 = 1/2 second) Name: DELCHR Type: Video / CLONE Description: Deletes a character from the specified location on the screen. The character at that location will disappear, and all characters to the right of it on the same screen line will be shifted left one space. The first page only (on color monitors) is supported, and text mode is required. Example: COL%=POS(0): ROW%=CSRLIN CALL DELCHR(ROW%,COL%) Name: DELSUB Type: Disk / DOS Description: Deletes a subdirectory. Parameters used are the same as in SETSUB. Note that you may not delete a subdirectory if it has any files left in it, or if it is the main directory, or if it is the current default subdirectory. Example: TMP$=SUB$+CHR$(0) CALL DELSUB(TMP$,ERRCODE%) IF ERRCODE% THEN couldn't delete subdir ELSE subdir deleted Name: DISKSTAT Type: Disk / DOS Description: Returns status information for a given disk drive. The drive spec should be a letter, or use "@" for the default drive. Information returned will be Free Clusters, Total Clusters, Bytes per Sector, and Sectors per Cluster. This will enable you to calculate the total space on the disk, free space left on the disk, the actual amount of space a file takes up, and so forth. A "cluster" is the minimum block of space that can be allocated on a disk. The actual amount of space taken up by a file depends on the cluster size. If the cluster size is 1024 bytes, any file that is listed as being between 1 and 1024 bytes will take up 1024 bytes of disk space. Any file listed as having 1025 - 2047 bytes will take up 2048 bytes (1024 * 2), and so on. Example: DRIVE$ = "@": REM Use the default drive CALL DISKSTAT(DRIVE$,FRE.CLUST%,TOT.CLUST%,BYTES.SEC%,SECS.CLUST%) CLUSTER.SIZE# = CDBL(BYTES.SEC%) * CDBL(SECS.CLUST%) FREE.DISK.SPACE# = CDBL(FRE.CLUST%) * CLUSTER.SIZE# TOTAL.DISK.SPACE# = CDBL(TOT.CLUST%) * CLUSTER.SIZE# PRINT "There are";FREE.DISK.SPACE#;" bytes free out of"; PRINT TOTAL.DISK.SPACE#;" with";CLUSTER.SIZE#;" bytes per cluster" Name: DMPRINT Type: Video / DOS Description: Displays a string at the current cursor position, using DOS calls for output (so device drivers such as ANSI.SYS will work). This routine is faster than MPRINT (q.v.), but offers fewer amenities. Character translation is limited to what DOS provides, meaning that, for instance, Backspace just moves the cursor back without wiping out the previous character. Other control codes may not be translated as you might hope, either. Finally, since DOS provides no way of finding the current print position, you have to figure out where the cursor will be yourself if you need it (like other display routines, DMPRINT does not update the BASIC cursor position). You can gain control of such things by using the ANSI.SYS driver. See your DOS manual for more information on that. Example: CALL DMPRINT(ST$) Name: DOSINKEY Type: Keyboard / DOS Description: Gets a key from the standard input device. This is normally the keyboard, but redirection is allowed (to a file, or to a port via CTTY). Two parameters are returned: the first gives the key code, if any, and the second gives status information. If the CHRTYPE is zero, there is no key pressed. If it is one, the key returned is a normal keypress. If it is two, the key returned is the code of an Extended ASCII key (like a function key or arrow key). Example: REM This is an INKEY$-oriented routine to get a keypress. KY$ = "" WHILE KY$="" KY$ = INKEY$ WEND IF LEN(KY$)=2 THEN EXTCODE=-1: KY$=RIGHT$(KY$,1) ELSE EXTCODE=0 RETURN REM This is the same routine, using DOSINKEY. CHRTYPE% = 0 WHILE CHRTYPE%=0 CALL DOSINKEY(CHRCODE%,CHRTYPE%) WEND KY$ = CHR$(CHRCODE%) IF CHRTYPE%=2 THEN EXTCODE%=-1 ELSE EXTCODE%=0 RETURN Name: DRVSPACE Type: Disk / DOS Description: Returns the amount of free space left on a given disk drive. The drive string may be any legal disk drive, or "@" (AT sign) for the default drive, and must be at least one character long. An illegal drive or other error will cause free space to be returned as a negative value. See also DISKSTAT. Example: DRV$="A:" . . CALL DRVSPACE(DRV$,A%,B%,C%) FREE# = CDBL(A%)*CDBL(B%)*CDBL(C%) PRINT"Free space on drive ";DRV$;" is";FREE#;"bytes." Name: DTR Type: Miscellaneous / CLONE Description: Switches the communications signal DTR (Data Terminal Ready) on or off. Turning the DTR off has the effect of making most modems drop carrier (hang up the phone). The comm port should be one or two. Use zero to turn the DTR off, or nonzero to turn it back on. Example: COMMPORT% = 1 TOGGLE% = 0 : REM turn the DTR off CALL DTR(COMMPORT%,TOGGLE%) Name: EQUIPMENT Type: Miscellaneous / BIOS Description: Returns basic information about the hardware configuration of the computer: memory installed, in kilobytes; number of parallel (printer) ports, 0-3; number of RS232 serial (comm) ports, 0-7; and number of game ports, 0-1. Example: CALL EQUIPMENT(MEMORY%,PARALLEL%,SERIAL%,GAME%) Name: EXIST Type: Disk / DOS Description: Tells you if a given file already exists. Returns zero if it doesn't, or a nonzero value if it does. Requires an ASCIZ filename without wildcards. If you need to use wildcards, or are operating in a network environment, use the FINDFIRSTF function instead. Example: FIL$="TEST.TXT"+CHR$(0) CALL EXIST(FIL$,FILEXISTS%) IF FILEXISTS% THEN PRINT "File already exists" Name: EXTRACT Type: String / ANY Description: Extracts a delimited substring from a string given an index. Requires a string of any length, a delimiter of one character in length, and an index value from 1-256; returns the starting location and length of the substring. If the delimiter is null (an error), the substring length will be returned as -1. If the index value is greater than the number of delimited substrings, a length of zero will be returned. Example: ST$="John Doe/15 Maple Rd/Hometown, CA 99199/(300) 111-1111" INDEX%=2 DELIMITER$="/" CALL EXTRACT(ST$,DELIMITER$,INDEX%,START%,SLEN%) PRINT MID$(ST$,START%,SLEN%) REM This will print the second substring (INDEX%=2) of the string REM (ST$) delimited by "/" (DELIMITER$), which in this case REM will be "15 Maple Rd". Name: FCLOSE Type: Disk / DOS Description: Closes a file opened by MOPEN (q.v.) Related functions: MCREATE, MOPEN, MREAD, MSETEND, MSETREC, MWRITE. Example: CALL FCLOSE(HANDLE%) Name: FCREATE Type: Disk / DOS Description: Opens a file with a given attribute for read/write access in normal mode. If the file doesn't exist, it's created; if it does, it's set to zero bytes in length. A "handle" is returned, which is used to identify the file (like BASIC's file numbers). See FOPEN for an explanation of modes. For more information, see the end of this manual. Related functions: FOPEN, FREAD, FSETEND, FSETREC, FWRITE. Example: FIL$="TEST.TXT"+CHR$(0) ATTR%=0 CALL FCREATE(FIL$,ATTR%,TEST.HANDLE%,ERRCODE%) IF ERRCODE% THEN PRINT "Couldn't create file" Name: FINDFIRSTF Type: Disk / DOS Description: Given a filename (which may contain the wildcards "*" and "?", and a drive and path spec if you like), this searches the default (or specified) directory to find the first matching file. Further matches can be obtained through the FINDNEXTF routine (q.v.). If there is a match, ERCD% will return zero, otherwise it will return a positive value (unless you entered a null filename, in which case ERCD% will be -1 to flag an error). You can retrieve various informa- tion about the matched file via a number of supplementary functions: GETNAMEF to get the filename, GETATTRF to get the attribute (there's a page at the end of this document on file attributes), GETDATEF and GETTIMEF to get the date and time, and GETSIZEF to get the file size. You may specify a search attribute as well: 0 (zero) to match normal files, 2 to match hidden files, 4 for system files, and 16 for subdirec- tories. Attributes other than zero will return normal files as well as the specified type, and you can match on more than one kind of attribute (for instance, to get all kinds of files, you'd use an attri- bute of 22, or 2+4+16). You can read the volume label using an attri- bute of 8, which is supposed to return only the volume label, but may not (see notes in the File Attribute info at the end of this file). This function can be used to duplicate the DOS directory command, or to allow filename wildcards in your program, among other things. Example: FIL$=FIL$+CHR$(0) CALL FINDFIRSTF(FIL$,ATTR%,ERCD%) IF ERCD% THEN PRINT"No matching files" Name: FINDNEXTF Type: Disk / DOS Description: This is used after the FINDFIRSTF function (q.v.) in order to find further matching files. Example: CALL FINDNEXTF(ERCD%) IF ERCD% THEN PRINT"No more matching files" Name: FOPEN Type: Disk / DOS Description: Opens an already-existing file. If you want to create a new file, use the FCREATE function. You tell it the ASCIZ filename, ACCESS% method, and MODE%; it gives back a HANDLE% or ERRCODE%. The ACCESS% method is how you want to open the file: 0, read; 1, write; 2, read/write. The MODE% controls access to the file by other programs operating at the same time, and is hence only useful for multitasking or networking. MODE% is: 0, normal (no multitasking or networking); 1, exclusive (no other program can access the file); 2, deny write (no other program may change the file); 3, deny read (no other program may look at the file); 4, deny none (any other program may access the file). To activate handling of nonzero modes, you must execute the DOS utility SHARE, which is included on your DOS disk. For more information, see the end of this manual. Related functions: FCLOSE, FCREATE, FREAD, FSETEND, FSETREC, FWRITE. Example: FIL$="TEST.TXT"+CHR$(0) FACCESS%=2 : REM Open the file with read/write access FMODE%=0 : REM Normal mode, not networking or multitasking CALL FOPEN(FIL$,FACCESS%,FMODE%,TEST.HANDLE%,ERRCODE%) IF ERRCODE% THEN PRINT "Unable to open the file" Example: FIL$="C:\DOCUMENT\TEST.TXT"+CHR$(0) FACCESS%=2 : REM Open the file for read access FMODE%=2 : REM Deny Write mode, for networking/multitasking REM We "deny write" so nobody else can change the file while REM we're reading it. We'll let others read from the file while REM we are, though. (This works like Normal mode if SHARE wasn't REM executed) CALL FOPEN(FIL$,FACCESS%,FMODE%,TEST.HANDLE%,ERRCODE%) IF ERRCODE% THEN PRINT "Unable to open file" Name: FREAD Type: Disk / DOS Description: Reads information from a file opened by FOPEN or FCREATE. You tell it which file to read from by giving it the handle which was returned when you opened the file. You give it a buffer location to read into, which can be either an array (for use, say, with SCRREST) or a string (for more usual purposes). You are responsible for seeing that the buffer is large enough to hold all the bytes that you want to read! FREAD returns a nonzero ERRCODE% if anything went wrong. If ERRCODE% is -1, it was able to read only part of the information before hitting an end of file. In that case, BYTESREAD% will tell you how many bytes were actually read in. See the end of this manual for info on error codes. Related functions: FCLOSE, FCREATE, FOPEN, FSETEND, FSETREC, FWRITE Example: OPTION BASE 1: DIM ARRAY%(2000): REM Set up the array buffer . . REM Do a FOPEN to open the file BUFFER%=VARPTR(ARRAY%(1)): REM Use first element of array here BYTES%=4000: REM Read in 4000-byte saved screen into the array CALL FREAD(HANDLE%,BUFFER%,BYTES%,BYTESREAD%,ERRCODE%) IF ERRCODE% THEN PRINT "Error reading file..." REM Do a SCRREST to put the info on the screen Example: BYTES%=128 : REM Read in 128 bytes/characters BUF$=SPACE$(BYTES%) : REM Set up the string buffer V%=VARPTR(BUF$) BUFFER%=PEEK(V%+2)+PEEK(V%+3)*256 CALL FREAD(HANDLE%,BUFFER%,BYTES%,BYTESREAD%,ERRCODE%) IF ERRCODE% THEN PRINT "Error reading file..." Name: FSETEND Type: Disk / DOS Description: For use with files opened with FOPEN / FCREATE. This function sets the file pointer to the end of the file, so that any information written using FWRITE will be appended to the file. Related functions: FCLOSE, FCREATE, FOPEN, FREAD, FSETREC, FWRITE Example: CALL FSETEND(HANDLE%) Name: FSETREC Type: Disk / DOS Description: For use with files opened with FOPEN / FCREATE. This function sets the file pointer to a given record in the file, so that it will be the next record read or written. Related functions: FCLOSE, FCREATE, FOPEN, FREAD, FSETEND, FWRITE Example: RECSIZE%=128: REM Number of bytes in a record in our file RECNO%=34: REM Record number (starting from 1, as in BASIC) CALL FSETREC(HANDLE%,RECSIZE%,RECNO%) Name: FWRITE Type: Disk / DOS Description: Allows you to write to a file opened by FOPEN or FCREATE. The parameters are the same as in FREAD (q.v.), except for BYTESWRITTEN%, which replaces BYTESREAD%. Related functions: FCLOSE, FCREATE, FOPEN, FREAD, FSETEND, FSETREC Example: REM Do a SCRSAVE to save a screen into ARRAY%() BUFFER%=VARPTR(ARRAY%(1)) BYTES%=4000: REM 4000 bytes = 2000 integer array elements CALL FWRITE(TEST.HANDLE%,BUFFER%,BYTES%,BYTESWRITTEN%,ERRCODE%) IF ERRCODE% THEN PRINT "Unable to write to file..." REM See FREAD for an example of how to set up a string buffer REM as the setup is different than when using an array buffer Name: GETATTRF Type: Disk / DOS Description: Returns the actual attribute of a file matched using FINDFIRSTF or FINDNEXTF. See the end of this document for information on file attributes. Example: REM use this AFTER calling FINDFIRSTF / FINDNEXTF to initialize REM the appropriate file information! CALL GETATTRF(ATTR%) Name: GETCRT Type: Video / BIOS Description: Tells you what kind of display is being used. The returned value will be reset if it's monochrome, or set if color. Example: CALL GETCRT(COLORDISPLAY%) IF COLORDISPLAY% THEN PRINT"Color" ELSE PRINT"Monochrome" Name: GETEXTM Type: Miscellaneous / AT BIOS Description: Tells you how much extended memory is available. This function requires the AT BIOS, and shouldn't be used with PCs. See also GETLIMM. Example: CALL GETEXTM(KBYTES%) PRINT KBYTES%;" kilobytes of extended memory" Name: GETKBD Type: Input / CLONE Description: Gives the status of the keyboard toggles. The variable will be set if the toggle is on, and reset if it is off. See also SETKBD. Example: CALL GETKBD(INSERT%,CAPSLOCK%,NUMLOCK%,SCROLLLOCK%) IF INSERT% THEN PRINT"Insert mode is on" IF CAPSLOCK% THEN PRINT"Caps Lock is on" IF NUMLOCK% THEN PRINT"The keypad is in numeric mode" IF SCROLLLOCK% THEN PRINT"Scroll Lock is on" Name: GETDATEF Type: Disk / DOS Description: Returns the date associated with the file matched using FINDFIRSTF or FINDNEXTF. Example: CALL GETDATEF(MONTH%,DAY%,YEAR%) Name: GETDOSV Type: Miscellaneous / DOS Description: Gets MS-DOS version. The major version is returned in the first parameter, the minor version in the second (e.g., MS-DOS v. 2.11 would return MAJ% = 2, MIN% = 11). Example: CALL GETDOSV(MAJ%,MIN%) Name: GETDRV Type: Disk / DOS Description: Returns the letter of the default drive. The drive string must be at least one character long. Example: DRV$="x:": CALL GETDRV(DRV$) Name: GETFATTR Type: Disk / DOS Description: Gets the attribute of a file. See the section on file attributes at the end of this manual. Example: FIL$=FIL$+CHR$(0) CALL GETFATTR(FIL$,ATTR%) Name: GETFDATE Type: Disk / DOS Description: GETFDATE returns the file creation date, that is, the date you see on a file when you get a DIRectory. The file name must be terminated with a NUL character. If there is an error, such as there being no such file, the month will be set to -1. Example: FIL$="TESTFILE.TXT"+CHR$(0) CALL GETFDATE(FIL$,MONTH%,DAY%,YEAR%) Name: GETFTIME Type: Disk / DOS Description: This function complements GETFDATE, and returns the file creation time. The hour is in 24-hour (military) format, and will be returned as -1 if there is no such file or a bad file name. The seconds are rounded to the next lower even number, due to the DOS storage format. The file name must be terminated with a NUL character. Example: FIL$="ANYFILE.EXT"+CHR$(0) CALL GETFTIME(FIL$,HOUR%,MINUTE%,SECOND%) Name: GETKEY Type: Keyboard / BIOS Description: Waits until one of a list of keys is pressed, and returns it. The key list (any length) should be uppercase. If the key list is null, the first key pressed will be returned. The key returned will be capitalized. The variable to return the key in must be at least one character long. This function is designed for returning one of a menu of choices, for example. Example: PRINT "Would you like to try again (Y/N)? "; GOODKEYS$="YN" : REM Allow Y or N . . KY$="x": CALL GETKEY(GOODKEYS$,KY$) Name: GETLIMM Type: Miscellaneous / BIOS Description: Returns the status of expanded memory, in total pages and free pages (where a page is 16k bytes). GETLIMM should only be used on systems with EMS or EEMS memory installed. See also GETEXTM. Example: CALL GETLIMM(TOTPAGES%,FREEPAGES%) PRINT TOTPAGES%;"pages of expanded memory are installed." IF TOTPAGES%>0 THEN PRINT FREEPAGES%;"pages of that are free." Name: GETLINE Type: Video / ANY Description: Returns a selected line from a screen saved via SCRSAVE, with the trailing spaces removed. The line string must be at least 80 characters long. This will also return a line from a screen saved with GETSCREEN, as long as full 80-column lines were saved. Example: OPTION BASE 1: DIM SCR%(2000) WHERE%=VARPTR(SCR%(1)): CALL SCRSAVE(WHERE%): CLS LINENR%=10: LIN$=SPACE$(80): WHERE%=VARPTR(SCR%(1)) CALL GETLINE(WHERE%,LINENR%,LIN$,LLEN%) PRINT"Line 10 was:": PRINT LEFT$(LIN$,LLEN%) Name: GETNAMEF Type: Disk / DOS Description: Returns the filename of the file matched using FINDFIRSTF or FINDNEXTF. The FIL$ string must be initialized to at least 12 charac- ters in length. The actual length of FIL$ will be returned in FLEN%, which will be -1 if you didn't initialize FIL$ long enough. Note that the filename will not contain a drive or path spec. Example: FIL$=SPACE$(12) CALL GETNAMEF(FIL$,FLEN%) FIL$=LEFT$(FIL$,FLEN%) Name: GETSCREEN Type: Video / CLONE (not with QuickBASIC 4.0 or BC) Description: Allows you to save any part of a text screen display (on any page, active or inactive, if you have a color graphics adapter). You need to specify an integer array where the information will be stored, the coordinates of the upper left corner and bottom right corner of the part of the screen to save, the display page to save, and the screen mode. The screen mode should be zero for flicker-free screen saving if you have a low quality color graphics adapter and are saving the currently-active display page. Otherwise, set it to 1 or -1 for the fastest save speed. You specify the area of the screen to save as a rectangle, by giving the locations of the upper leftmost corner and lower rightmost corner of the area to save. This can range from a single character to the entire screen. Make sure that the coordinates do not get mixed up, or you will get unpredictable results. To figure out how many array elements you need to save an area of the screen, use the following calculation: ELEMENTS%=(BOTTOMROW%-TOPROW%+1)*(RIGHTCOLUMN%-LEFTCOLUMN%+1) You can store multiple screen areas in one array by specifying the proper starting element, which must be one after the previous saved area. You'll have to keep track of where each saved area is in the array yourself. If you have a monochrome adapter, or are not using unusual display pages, you should set the page specification to zero. Note that you don't have to restore the saved area of the screen (see PUTSCREEN) to the same area it was taken from. This allows you to move windows around, change the shape of windows, and other interes- ting tricks... See also PUTSCREEN, to restore a given area of the screen; and SCRSAVE, SCRREST, SCRSAVEP, SCRRESTP, SCRSAVEPD, and SCRRESTPD, earlier versions of similar functions. Note that if you save/restore a full 80-column, 25-row screen, the information in the save/restore array is identical whether you're using GETSCREEN/PUTSCREEN or SCRSAVExx/SCRRESTxx. On that level, the routines are completely compatible. Example: CALL GETSCREEN(SCRN%(0),TOPROW%,LFCOL%,BOTROW%,RTCOL%,PAGE%,SCRNMODE%) REM SCRN%(0) is the location in the array to save the area to. REM TOPROW%,LFCOL% and BOTROW%,RTCOL% are the corners of the area. REM PAGE% is the display page number (0-3 if Color, 0 if Mono). REM SCRNMODE% is screen access mode: 0, snowless; 1 / -1, fast. Name: GETSIZEF Type: Disk / DOS Description: Returns the size of the file matched via FINDFIRSTF or FINDNEXTF. Since the file size may be outside integer bounds, there is some additional code you will have to add which uses double-precision values (see the example). You can modify the example to use single-precision instead, but really large file sizes will then lapse into exponential notation. Example: CALL GETSIZEF(SIZELOW%,SIZEHIGH%) SIZELOW#=CDBL(SIZELOW%) IF SIZELOW%<0 THEN SIZELOW#=SIZELOW#+65536# FILESIZE#=SIZELOW#+CDBL(SIZEHIGH%)*65536# Name: GETSUB Type: Disk / DOS Description: Gets the default subdirectory. The subdirectory string must be 64 characters long, and it is recommended that you set it to NUL characters. Note that the returned string will NOT be started by a backslash "\" character-- you should add one if appropriate. Example: SUB$=STRING$(64,0) CALL GETSUB(SUB$,SLEN%) SUB$="\"+LEFT$(SUB$,SLEN%) Name: GETTIMEF Type: Disk / DOS Description: Returns the time associated with the file matched by FINDFIRSTF or FINDNEXTF. The hour is returned in military (24-hour) format. Example: CALL GETTIMEF(HOUR%,MINUTE%,SECOND%) Name: INSCHR Type: Video / CLONE Description: Inserts a space at the specified screen location. The character previously at that position and all characters to the right of it on the same screen line will be shifted right one space. Subject to the same limitations as DELCHR (q.v.). Example: COL%=POS(0): ROW%=CSRLIN CALL INSCHR(ROW%,COL%): PRINT"*"; Name: INT2DATE Type: Miscellaneous / ANY Description: Decompresses a date squeezed using DATE2INT (q.v.). The year will be a four-digit value (1900-2026). Example: CALL INT2DATE(MONTH%,DAY%,YEAR%,SQZDATE%) Name: INT2TIME Type: Miscellaneous / ANY Description: Decompresses a time squeezed using TIME2INT (q.v.). The seconds will be an even value (rounded down) due to the storage format. Example: CALL INT2TIME(HOUR%,MIN%,SEC%,SQZTIME%) Name: KEYPRESS Type: Keyboard / BIOS Description: Tells you whether a key is waiting in the keyboard buffer (for use with INKEY$ routines, etc). KYHIT is set if a key is waiting, cleared otherwise. Example: 100 CALL KEYPRESS(KYHIT%) IF KYHIT% THEN KY$=INKEY$ ELSE 100 Name: LOCASE Type: String / ANY Description: Converts a string to all lowercase characters. Example: MSG$="THis IS a test OF tHe lowercase CONVERTER!" . . CALL LOCASE(MSG$) Name: LROTATE Type: String / ANY Description: Rotates the characters in a string left. That is, the leftmost character is removed, and tacked onto the end of the string. This is useful for rotating queues and for character-graphics animation. If the string is of length one or less, it is returned unchanged. Example: ST$="12345" CALL LROTATE(ST$) REM ST$ will end up being "23451" Name: MAKESUB Type: Disk / DOS Description: Makes a subdirectory. Use a NUL-terminated string to specify the subdirectory. An error code will be returned if there was an error. Example: TMP$=SUB$+CHR$(0) CALL MAKESUB(TMP$,ERRCODE%) IF ERRCODE% THEN couldn't make subdir ELSE subdir created Name: MAKEWINDOW Type: Video / CLONE Description: Creates a pop-up window on the screen. You specify the window by giving the upper left corner and lower right corner of the inside of the window. The frame is drawn -outside- the window you've specified, so be sure to allow room for the frame! For normal windows, the frame takes up only one column or row on each side. For shadowed windows, the frame will instead take up three columns on the left and three rows on the bottom. There are four types of window: 0, Normal: the window pops onto the screen. 1, Growing: the window "grows" from a spot to a full-sized window. 2, Shadowed: the window is shadowed on the left and bottom for a 3D effect. 3, Growing/Shadowed: the window is shadowed and grows. You may also choose five types of frames: 0, None: composed of spaces. 1, Single: composed of a single line. 2, Double: composed of a double line. 3, Double/Single: made with a double vertical and a single horizontal line. 4, Single/Double: made with a single vertical and a double horizontal line. You must select fore and background colors. A label is optional. If you give one, it is bracketed within the top of the frame, on the left side. The screen page is selectable on color monitors. Example: LCOL%=5: TROW%=5: REM top left corner RCOL%=79: BROW%=20: REM bottom right corner LABEL$="Test Window" FORE%=7: BACK%=0: REM color/attributes PAGE%=0: REM screen display page FRAME%=1: REM single-line frame TYPE%=3: REM growing, shadowed window CALL MAKEWINDOW(LCOL%,TROW%,RCOL%,BROW%,LABEL$, FRAME%,TYPE%,FORE%,BACK%,PAGE%) REM the above line shouldn't be divided in your program! REM it's separated like that to accommodate my word processor. Name: MDELCHR Type: Video / BIOS Description: Deletes the character at the current cursor position. It obeys the window defined by MWINDOW. It's more compatible than DELCHR, but much slower. Note that this routine can be used to scroll a window left by doing an MDELCHR at the first location of each line to be scrolled. To scroll right, do the same using MINSCHR instead. Example: CALL MDELCHR Name: MINSCHR Type: Video / BIOS Description: Inserts a space at the current cursor position, obeying the window defined by MWINDOW. See notes at MDELCHR. Example: CALL MINSCHR Name: MMBUTTON Type: Input / BIOS Description: Returns which mouse buttons are currently being held down. See also MMCLICK. Example: CALL MMBUTTON(LFT%,RGT%) IF LFT% THEN PRINT"The left button is being pressed." IF RGT% THEN PRINT"The right button is being pressed." Name: MMCHECK Type: Input / BIOS Description: Returns whether a mouse is installed, and how many buttons it has if it is installed. Example: CALL MMCHECK(MOUSE%) IF MOUSE% THEN PRINT"A mouse with ";MOUSE%;" buttons is present." Name: MMCLICK Type: Input / BIOS Description: Returns which mouse buttons have been clicked since you last used this function. See also MMBUTTON. Example: CALL MMCLICK(LFT%,RGT%) IF LFT% THEN PRINT"The left button was pressed." IF RGT% THEN PRINT"The right button was pressed." Name: MMCURSORON Type: Input / BIOS Description: Makes the cursor associated with the mouse visible. This is normally a blinking block, and shows where the mouse is currently pointing. See also MMCURSOROFF. Example: CALL MMCURSORON Name: MMCURSOROFF Type: Input / BIOS Description: Makes the cursor associated with the mouse invisible. See also MMCURSORON. Example: CALL MMCURSOROFF Name: MMGETLOC Type: Input / BIOS Description: Gets the current location of the mouse cursor. This is returned as a value from 0-639 for columns, and 0-199 for rows. You need to adjust this for the current screen format. If you're in text mode, divide the columns by eight and the rows by eight. If you're in low res graphics mode, divide the columns by two. If you're in high res graphics, the numbers are fine. Example: CALL MMGETLOC(COL%,ROW%) LOCATE ROW%,COL%: PRINT "!"; Name: MMSETLOC Type: Input / BIOS Description: Sets the current value of the mouse cursor. Uses the same format as MMGETLOC (q.v.). Example: COL%=40*8-8: ROW%=24*8-8: REM middle of the text-mode screen CALL MMSETLOC(COL%,ROW%) Name: MMSETRANGE Type: Input / BIOS Description: Sets the range of locations where the mouse cursor is allowed to be. This is done by specifying the upper left corner and lower right corner of the edges of the mouse input field. Use the same format as MMGETLOC (q.v.). Example: LFTCOL%=20*8-8: TOPROW%=1*8-8 RGTCOL%=60*8-8: BOTROW%=10*8-8 CALL MMSETRANGE(LFTCOL%,TOPROW%,RGTCOL%,BOTROW%) REM sets up a text-mode input field Name: MLOAD Type: Disk / DOS Description: Works the same way as the BLOAD statement does. This is for use with older compilers, which don't have the BLOAD statement. MLOAD restores the information to the same place it was when BSAVEd. Example: FIL$="SCRNSAVE.BIN"+CHR$(0) CALL MLOAD(FIL$) Name: MONTH Type: Miscellaneous / ANY Description: Given the number of a month (1-12), this routine returns the name of the month (January - December). You must supply a string of at least nine spaces in length to hold the month. Example: MONTH$=SPACE$(9) CALL MONTH(MONTH$,MLENGTH%,MONTHNUMBER%) MONTH$=LEFT$(MONTH$,MLENGTH%) Name: MPRINTC Type: Video / BIOS Description: Using this function, you can access device drivers such as ANSI.SYS. This is a video output function which goes through MS-DOS function calls. It prints a single character to the display. MPRINTC allows use of ANSI.SYS and similar video drivers, and windowing via MWINDOW, but is slower and takes more memory that the usual PRINT statement. Example: CALL MPRINTC(CH$,COL%,ROW%): LOCATE ROW%,COL% Name: MPRINT Type: Video / BIOS Description: Same as MPRINTC (q.v.), only it allows you to send an entire string out to the display, rather than just a single character. Example: CALL MPRINT(ST$,COL%,ROW%): LOCATE ROW%,COL% Name: MULTIAND Type: String / ANY Description: This is a flexible function with many possible uses. Every charac- ter in a given string is ANDed with a value you supply. One thing this could be used for is translating Wordstar files to ASCII files, by using a bit mask (the value that will be ANDed with the character) of &H7F, which strips off the high bit of each character. The string may be any length; the bit mask is an integer, with only the low byte in use (value of 0-255). Example: ST$ = "" FOR X%=65 TO 70: ST$=CHR$(X%)+CHR$(X%+128): NEXT PRINT ST$ BITMASK%=&H7F CALL MULTIAND(ST$,BITMASK%) PRINT ST$ Name: MULTIOR Type: String / ANY Description: Does the exact opposite of MULTIAND-- instead of stripping off bits, it turns on bits. It ORs instead of ANDs. One possible use for this would be to encode a text string by ORing with 128, and later decoding by ANDing with 128. This would allow you to save the string to disk using text files, even if the string included control codes, although that won't work right if the string has graphics characters (using ExtASCII codes, which are codes from 128-255) in it. The para- meters are the same as for MULTIAND. Example: ST$ = "ABCDE": PRINT ST$ SETBITS%=&H80 CALL MULTIOR(ST$,SETBITS%) PRINT ST$ Name: MULTIXOR Type: String / ANY Description: An exclusive-or operation for strings. Bits in the string will be set only if they are set in the string byte or mask byte, but not in both of them. Note that this can be used as a "MULTINOT" function by using a mask of &HFF or 255. In this case, all bits are set in the mask, so the result of the XOR will be the same as a NOT operation on the string. Note that XORing a string with the same value twice will return the original string-- it can thus be used to encode and decode strings. Example: CALL MULTIXOR(ST$,MASK%) Name: MWINDOW Type: Video / BIOS Description: Sets up a window for the MPRINT and MPRINTC routines. Windows are defined by their upper left corner and lower right corner. The default window is thus (1,1,80,24), which leaves out the bottom line (BASIC's status line). To use the full screen, call this routine with values (1,1,80,25). Note that the cursor should be positioned inside the window before using MPRINT/MPRINTC. Note also that windows should be defined to contain at least two rows. Example: LFCOL%=20: TOPROW%=5: RTCOL%=60: BOTROW%=15 CALL MWINDOW(LFCOL%,TOPROW%,RTCOL%,BOTROW%) LOCATE TOPROW%,LFCOL% REM sets up a window (of 40 cols x 10 rows) REM in the middle of the screen. Name: PRINTSCREEN Type: Miscellaneous / BIOS Description: This sends an image of the current screen display out to the first printer device. It works exactly in the same way as doing a Shift-PrtSc from the keyboard, so it can display graphics as well as text if you have the DOS GRAPHICS program installed. Name: PUTSCREEN Type: Video / CLONE (not with QuickBASIC 4.0 or BC.EXE) Description: This restores an area of the screen that was saved using the GETSCREEN function (q.v.). You need not restore an area to the same screen coordinates or to the same display page. It is possible to change the shape of an area by changing the coordinates specified. For instance, suppose you had saved a six character, one line message, "FOOBAR", at coordinates (1,1)-(1,6). You could restore it as a three char by two line message, "FOO" "BAR" by specifying the coordinates (1,1)-(2,3). Note that these coordinates are in Microsoft's mixed up form of (ROW,COLUMN), not the normal alge- braic format. It is also possible to restore only part of the screen that was saved. For instance, suppose you had saved the entire screen in an array SCRN starting at element 0, and only wanted to restore the bottom half of the screen. Using the calculation for screen elements given in GETSCREEN, you would find that 2000 elements were needed for the whole screen, or only 1000 elements for the bottom half of the screen. That means that in the array, elements 0-999 hold the top half of the screen, and 1000-1999 hold the bottom half (assuming a default OPTION BASE=0). So, you would tell PUTSCREEN to start with array element SCRN%(1000), and give it the starting and ending coordinates of the corners of the lower half of the screen. Parameters specifications are the same as they are for GETSCREEN. Example: CALL PUTSCREEN(SCRN%(0),TOPROW%,LFCOL%,BOTROW%,RTCOL%,PAGE%,SCRNMODE%) Name: QPRINT Type: Video / CLONE Description: This function bypasses the usual video routines, and prints a string directly on the screen, at a -much- higher speed than the normal PRINT statement does. It also contains a built-in LOCATE statement, and doesn't affect the cursor position. Note that control characters will show up as graphics characters instead of having their original functions, and the color/attributes used will be the ones already on the screen. Display page zero is used with color adapters. See also XQPRINT. Example: ST$="This is a test of fast screen printing" ROW%=10: COL%=20 CALL QPRINT(ST$,ROW%,COL%) Name: READBITF Type: Miscellaneous / ANY Description: Reads a word from an array of arbitrary bit length, given an index. The words in the array may be made of one to eight bits. Indices begin at zero and are limited by integer range. That is up to &HFFFF, subject to memory constraints-- the index is taken to be an unsigned integer value. This function allows very memory-efficient storage of arrays of numbers, provided that the numbers are within a restricted range. The simulated array is held within a normal integer array, which must be dimensioned large enough to hold all of the arbitrary-length words (will depend on bits per word and number of words desired). Example: OPTION BASE 0: DIM INTARRAY%(50): BITFSIZE%=8 . . ARRAYLOC%=VARPTR(INTARRAY%(0)) CALL READBITF(ARRAYLOC%,NDX%,BITFSIZE%,VALUE%) REM Returns a value from the array location indexed by NDX%, REM where the array is composed of bytes (8-bit words). REM See the disk file BITFTEST.BAS in the source files REM for a working example program. Name: RECOLOR Type: Video / CLONE Description: Takes everything on the screen that's of a given color and changes its color to whatever you like. This can be used for special effects, or just to change the screen color without having to clear the screen. This will work only in text mode. The color attributes must be defined from the foreground and background colors using the CALCATTR routine. Example: CALL CALCATTR(FOREGND%,BACKGND%,OLDCOLR%) CALL CALCATTR(NEWFORE%,NEWBACK%,NEWCOLR%) CALL RECOLOR(OLDCOLR%,NEWCOLR%) Name: RESETPOINT Type: Video / BIOS Description: Resets a point on a text screen. This is the opposite of SETPOINT (see). Example: ROW%=0 FOR COLUMN%=0 to 79 CALL RESETPOINT(COLUMN%,ROW%) NEXT COLUMN% REM this clears a line from the top of the screen REM (undoes the line from the SETPOINT example) Name: REVERSE Type: String / ANY Description: Reverses the order of characters in a string. This can be combined with the XLATE function and a judiciously-designed translation table to provide mirror images of strings for character-graphics-based displays. It can also be used with INSTR to provide a function which returns the last occurrence of a given substring within a string. Example: MSG$="This is a test" CALL REVERSE(MSG$) PRINT MSG$ Name: RROTATE Type: String / ANY Description: Rotates the characters in a string right. This is the same as LROTATE, only in reverse. See LROTATE for further details. Example: ST$="12345" CALL RROTATE(ST$) REM ST$ will end up being "51234" Name: SCROLL Type: Video / BIOS Description: Scrolls any selected portion of the screen as many times as you like (or use 0 to clear that part of the screen entirely). There are five parameters to this function: coordinates (LFCOL,TOPROW) of the upper left corner of the area to be scrolled, coordinates (RTCOL,BOTROW) of the lower right corner of the area to be scrolled, and the number of times to scroll the area. This routine may be used to create win- dows. Note that RTCOL must be at least one greater than LFCOL (no single-line scrolling, obviously). Note also that you should not try to scroll more times than there are lines in the area to be scrolled (use 0 instead). Parameters are not checked, so be careful not to use illegal screen coordinates. Example: CALL SCROLL(LFCOL%,TOPROW%,RTCOL%,BOTROW%,NUMLINES%) Name: SCRREST Type: Video / CLONE Description: Restores the screen display from an image put into an array by SCRSAVE. Same requirements and limitations of SCRSAVE. Example: WHERE%=VARPTR(SCR%(1)) CALL SCRREST(WHERE%) LOCATE OLDROW%,OLDCOL% Name: SCRSAVE Type: Video / CLONE Description: Stores the current screen display (page 0 only) in an array. Text modes only. Requires an array of 4000 bytes, and an integer which points to the location of the array. The cursor position is not saved. Example: OPTION BASE 1: DIM SCR%(2000) . . WHERE%=VARPTR(SCR%(1)) CALL SCRSAVE(WHERE%) OLDCOL%=POS(0): OLDROW%=CSRLIN REM Dim of 2000 w/ option base 1 gives us 2000 integers, REM which gives us 4000 bytes of storage space. REM Note: you can store more than one screen in an array by REM dimensioning it large enough. Use WHERE%=VARPTR(SCR%(2001)) REM to locate the second screen, and so forth. Name: SCRRESTP, SCRRESTPD, SCRSAVEP, SCRSAVEPD Type: Video / CLONE Description: These functions are variations of SCRREST and SCRSAVE. All of them allow specification of a page number, for color monitors. They will save or restore text to a given page. When used with monochrome monitors, the page specification should always be zero. SCRRESTPD and SCRSAVEPD write directly to the screen at high speed. This will cause "snow" if you have an old or poorly designed color display adapter and are writing to the active screen page. Under those conditions, you should use SCRRESTP/SCRSAVEP or SCRREST/SCRSAVE. Example: WHERE%=VARPTR(SCR%(1)): SCRNPAGE%=0 CALL SCRRESTP(WHERE%,SCRNPAGE%): LOCATE OLDROW%,OLDCOL% Name: SETCOMM Type: Miscellaneous / CLONE Description: Sets communications parameters on an opened communications device. This allows you to set the baud rate higher than BASIC normal- ly allows, and to change the comm parameters without having to close the comm device. Why is it bad to have to close the comm device? Because that will make the DTR signal drop, which will cause many modems to drop the carrier and lose your connection. In fact, for Hayes-type modems, that's a much more reliable way to end communications than using the ATH "hang up modem" command. If you try to set a comm port which does not exist, the port number will be set to zero after the call. If you give illegal para- meters elsewhere, the port will be set to a default of 300 baud, Even parity, Seven-bit words, and One stop bit (any of the parms which were legal will be used). Example: OPEN"R",1,"COM1:300,E,7,1,RS,CS,DS" COMMPORT%=1: BPS%=6: PARITY%=0: WORDLENGTH%=8 STOPBITS%=1 CALL SETCOMM(COMMPORT%,BPS%,PARITY%,WORDLENGTH%,STOPBITS%) REM sets the port to 19200 baud, No parity, 8 bit words REM and 1 stop bit. Settings: COMMPORT% may be 1 - 2, and will be returned as 0 if the specified port doesn't exist. BPS% ("baud rate") is specified by a number from 0 - 7. Use 0 for 300 bps, 1 for 600, 2 for 1200, 3 for 2400, 4 for 4800, 5 for 9600, 6 for 19200, and 7 for 38400 bps. Whether you can actually get speeds over 9600 will depend on the quality of your comm port. PARITY% is a number 0-2. Use 0 for None, 1 for Odd, 2 for Even. WORDLENGTH% may be 7 or 8. STOPBITS% may be 1 or 2. Name: SETDRV Type: Disk / DOS Description: Sets the default drive. The drive string must be at least one character long, and start with a letter specifying a disk drive. Example: DRV$="B:" . . CALL SETDRV(DRV$) Name: SETFATTR Type: Disk / DOS Description: Sets the attribute of a file. See the section on file attributes at the end of this manual. Example: FIL$=FIL$+CHR$(0) CALL SETFATTR(FIL$,ATTR%) Name: SETFTD Type: Disk / DOS Description: Sets file time/date stamp. The filename must be terminated with a NUL character. The year may be either a four digit or two digit number (e.g., either 1986 or just 86). DOS will round the seconds value off to the next lower even number. If there is a problem with the filename, the month will be returned as -1. Note that midnight is 24:00, not 00:00 (which tells DOS not to display the file's time). Example: FIL$=FIL$+CHR$(0) CALL SETFTD(FIL$,MONTH%,DAY%,YEAR%,HOUR%,MINUTE%,SECOND%) IF MONTH%=-1 THEN PRINT "No such file" Name: SETMATI Type: Miscellaneous / ANY Description: Sets the first SIZ% elements of an integer array to a given (scalar) value, INITVAL%. It will work on multi-dimensional arrays, in which case the leftmost dimension increments first (unless you've set the compiler option telling it to do otherwise). See examples for clarification. Example: OPTION BASE 0: DIM BANANA%(9) SIZ%=10: INITVAL%=-3: ARLOC%=VARPTR(BANANA%(0)) CALL SETMATI(ARLOC%,SIZ%,INITVAL%) REM we have just initialized all 10 elements of the array to REM the value -3. Example: OPTION BASE 1: DIM FOO%(3,5) SIZ%=5: INITVAL%=20000: ARLOC%=VARPTR(FOO%(1,1)) CALL SETMATI(ARLOC%,SIZ%,INITVAL%) REM we have just set the first five elements of the array to REM 20000. The first five elements are FOO%(1,1), FOO%(2,1), REM FOO%(3,1), FOO%(1,2), FOO%(2,2). If you want to initialize REM the whole array to 20000, set SIZ%=3*5 for OPTION BASE 1 REM or SIZ%=(3+1)*(5+1) for OPTION BASE 0. REM By changing the first element (in the ARLOC% assignment), you REM can set any part of the array, not just the first elements. REM See SCRSAVE/SCRREST if you need to clear up that last point. Name: SETKBD Type: Input / CLONE Description: Sets the status of the keyboard toggles. The toggle is set on if the value is nonzero, and off if the value is zero. Good style suggests that, before using this function for the first time, you should get the toggles with GETKBD (see) and save them. You should then restore the keyboard to that original state before exiting the program. Example: REM Let's turn off Insert, Caps Lock, and Scroll Lock REM and put the keypad into numeric mode by turning on Num Lock INSERT%=0: CAPSLOCK%=0: NUMLOCK%=1: SCROLLLOCK%=0 CALL SETKBD(INSERT%,CAPSLOCK%,NUMLOCK%,SCROLLLOCK%) Name: SETPOINT Type: Video / BIOS Description: Sets a point on a text screen. This allows low-resolution graphics on monochrome as well as color monitors. Normal text can also be mixed with the graphics. Resolution is 80x50 (0-79 columns by 0-49 rows). See also RESETPOINT and TESTPOINT. Example: ROW%=24 FOR COLUMN%=0 TO 79 CALL SETPOINT(COLUMN%,ROW%) NEXT COLUMN% REM this draws a line across the middle of the screen. Name: SETSUB Type: Disk / DOS Description: Sets the default subdirectory. The subdirectory string must be terminated by a NUL character. An error will be returned if the specified subdirectory doesn't exist. Example: TMP$=SUB$+CHR$(0): CALL SETSUB(TMP$,ERRCODE%) IF ERRCODE% THEN bad subdir ELSE new default subdir selected Name: SHIFTL Type: Miscellaneous / ANY Description: Shifts all the bits in an integer left COUNT times, putting zeroes in the bit positions which have been vacated. This effectively multi- plies the value by a power of two in most instances. This function is included for those advanced programmers who know what it's good for... Example: VALUE%=47: COUNT%=3 CALL SHIFTL(VALUE%,COUNT%) REM we just shifted VALUE% left three bits REM (in this case getting 47 * 2^3, or 376) Name: SHIFTR Type: Miscellaneous / ANY Description: Same as SHIFTL, but shifts the bits right instead of left. This is similar in effect to an integer divide by a power of two. Example: VALUE%=47: COUNT%=3 CALL SHIFTR(VALUE%,COUNT%) REM we just shifted VALUE% right 3 bits REM (here getting 47 \ 2^3, or 5) Name: SOUNDEX Type: String / ANY Description: This routine returns the Soundex code for a string you give it. I'm not sure who invented Soundex, but it's pretty handy. The Soundex routine takes a word and returns a string which represents what the word sounds like in an abstract format. Similar-sounding words can thus be identified easily by your program after Soundex processing. This can be useful in applications where a person is not sure of the exact spelling of a word/name/city, etc. To use, put the word in WORD$, initialize the return string SCODE$ to the same length as WORD$, and execute the routine. SLEN% will return the actual length of SCODE$, which may vary from zero to the length of WORD$. If SCODE$ is not as long as WORD$ when the routine is called, SLEN% will be returned as -1 to flag an error. The Soundex code is returned as a series of digits in SCODE$, although you can represent this any way you choose in your program. Example: WORD$="AnyWord": SCODE$=WORD$ CALL SOUNDEX(WORD$,SCODE$,SLEN%) PRINT"The Soundex code for ";WORD$;" is ";LEFT$(SCODE$,SLEN%);"." REM Try this routine a few times to get a feel for it. Name: SPEAKER Type: Miscellaneous / CLONE Description: This function allows you to turn the speaker on or off. This allows you to disable sound effects for a program. Your sound routines will still be executed, but will not produce any sound if you have turned the speaker off. Thus, your routines will execute at the same speed whether or not sound is turned on, and the timing will remain the same. Note that you should turn the speaker back on before exiting the program! Use zero to turn off the speaker, nonzero to turn it back on. NOTE: This function appears to be erratic, especially when used with slightly incompatible machines such as the AT. It is unlikely to work on a PCjr. Test it to see if it works for you. Example: SPKR% = 0 CALL SPEAKER(SPKR%) REM turn the speaker off Name: STRIP Type: String / ANY Description: Strips all occurrences of a given target character from a given source string. The target string must be at least one character in length (if more, the first character will be used). Example: MSG$="12 - 2 = 10" . . CH$=" ": CALL STRIP(MSG$,CH$,MLEN%): MSG$=LEFT$(MSG$,MLEN%) Name: STRIPBLANKS Type: String / ANY Description: Strips blanks (and control characters) from either the left or right side of a string, or both sides. Specify 0 (zero) for no strip, 1 to strip left, 2 to strip right, or 3 to strip both sides. Example: STRIPWHICH=3: REM strip both sides of blanks CALL STRIPBLANKS(ST$,STRIPWHICH%,SLEN%) ST$=LEFT$(ST$,SLEN%) Name: STRIPRANGE Type: String / ANY Description: Strips all characters within a given range out of a source string. Example: MSG$="ALL uppercase letters will be G-O-N-E gone" LO%=ASC("A"): HI%=ASC("Z") CALL STRIPRANGE(MSG$,LO%,HI%,MLEN%) MSG$=LEFT$(MSG$,MLEN%) Name: SUBEXIST Type: Disk / DOS Description: Tests to see if a given subdirectory exists. You may include a drive spec in the subdirectory name, which must be terminated by a null. Example: SUBDIR$="C:\TEMP"+CHR$(0) CALL SUBEXIST(SUBDIR$,VALID%) IF VALID% THEN PRINT"Subdirectory exists" ELSE PRINT"No such subdirectory" Name: TESTPOINT Type: Video / BIOS Description: Tests a pixel on a text screen to see if it's on or off (see SETPOINT for information about text graphics). The value returned will be set if the point is set, or reset if the point is not set. Example: COL%=39: ROW%=24: REM check a point near the middle of the screen CALL TESTPOINT(COL%,ROW%,STATUS%) IF STATUS% THEN PRINT"The point is lit" ELSE PRINT"The point is not lit" Name: TIME2INT Type: Miscellaneous / ANY Description: Squeezes the time down to a single integer, for reduced storage requirements. You will lose some accuracy in the seconds, which will be converted to an even number (odd numbers will be rounded down). To avoid ambiguity, it is recommended that you specify hours using a 24-hour clock. See also INT2TIME. Example: CALL(HOUR%,MIN%,SEC%,SQZTIME%) Name: TIMEN2S Type: String / ANY Description: Converts the time from numbers to a string. The string should be at least eight characters long. See also TIMES2N. Example: HOUR%=13: MIN%=30: SEC%=8: TIM$=SPACE$(8) CALL TIMEN2S(HOUR%,MIN%,SEC%,TIM$) REM From this, we get TIM$="13:30:08" Name: TIMES2N Type: String / ANY Description: Converts the time from a string to numbers. The seconds are optional, and will be set to zero if nonexistent. Example: TIM$="13:09:42" CALL TIMES2N(HOUR%,MIN%,SEC%,TIM$) REM We get HOUR%=13, MIN%=9, SEC%=42 TIM$="03:15" CALL TIMES2N(HOUR%,MIN%,SEC%,TIM$) REM We get HOUR%=3, MIN%=15, SEC%=0 Name: TINSTR Type: STRING / ANY Description: Allows you to search for a given type of character within a string. You may search for any of several character types by adding the values of the types to search for. This also allows you to search for the opposite of a character type (that is, search for anything other than that type). Character types: 1 Alphabetic A-Z, a-z 2 Numeric 0-9 4 Symbolic (anything not covered by other types) 8 Control (control codes: ASCII 0-31, 127) 16 Graphics (PC graphics codes: 128-255) 32 Blank (a blank space, ASCII 32) Example: CHRTYPE%=1+2+4+8+16 : REM search for first non-blank character CALL TINSTR(ST$,CHRTYPE%,PLACE%) IF PLACE%=0 THEN PRINT"The string contains no non-blank chars" ELSE PRINT"The first nonblank character is at location";PLACE%;"." Example: CHRTYPE%=2 : REM search for first numeric character ST$="Springfield, VA 22152" CALL TINSTR(ST$,CHRTYPE%,PLACE%) PRINT"The zip code is: ";MID$(ST$,PLACE%,5) Name: UPCASE Type: String / ANY Description: Converts a string to all uppercase. Example: MSG$="Four score and seven years ago" . . CALL UPCASE(MSG$) Name: WEEKDAY Type: Miscellaneous / DOS Description: Returns an integer from 1 - 7 indicating the day of the week, Sunday through Saturday. The example routine turns this integer into the week day. Example: CALL WEEKDAY(DAY%) DLEN%=VAL(MID$("3346535",DAY%,1)) DLOC%=ASC(MID$("ADGKQVY",DAY%))-64 REM The above string MUST be in uppercase! PRINT"Today is"; PRINT MID$("SunMonTuesWednesThursFriSatur",DLOC%,DLEN%);"day." Name: WRITEBITF Type: Miscellaneous / ANY Description: Allows a value to be written into a given location of a simulated array of words of arbitrary bit length (1-8 bits per word). This goes with the READBITF function above. The "BITF" is for Bit Field, because the functions work by creating fields of arbitrary bit length within what is actually an integer array. Example: CALL WRITEBITF(ARRAYLOC%,INDEX%,BITFSIZE%,VALUE%) REM See the READBITF function, and see the BITFTEST.BAS if you REM have the ADVBAS contributor disk, to better idea of what's REM going on. This function is not for novice programmers! Name: XLATE Type: String / ANY Description: This function translates a string, character by character, using a table you supply. The character's ASCII value is used as the index to the table, and the value at that location replaces the character's current value. The character may be one byte in length, in which case it will be translated, or zero bytes, in which case nothing will happen. The translation string must be 256 bytes long (remember, strings may be longer than 255 bytes in Compiled BASIC, so this is ok). Example: XLT$="" FOR X%=0 TO 255: XLT$=XLT$+CHR$(X%): NEXT MID$(XLT$,1,5)="ABCDE": CH$=CHR$(0) CALL XLATE(CH$,XLT$) PRINT CH$ REM CH$ ends up "A", since the start of the table + zero bytes REM contains "A". We add zero bytes, because CH$ was REM originally equal to CHR$(0). Name: XMPRINT Type: Video / BIOS Description: This routine combines the XLATE and MPRINTC functions. It takes a character, runs it through a translation table, and prints it to the screen unless the translated value is NUL (ASCII zero). If it's NUL, no printing takes place. MS-DOS calls are used for printing, so ANSI.SYS will work. See the XLATE and MPRINTC routines for further information. Example: CALL XMPRINT(CH$,XLATE$,COL%,ROW%): LOCATE ROW%,COL% Name: XQPRINT Type: Video / CLONE Description: This function is an extended version of QPRINT. It is more flexible, and only a trifle slower. XQPRINT has two advantages over QPRINT: it allows you to choose a color/attribute to use, and lets you choose a display page (color/graphics adapters only!). The attribute ATTR must be set up using the CALCATTR routine. The page argument is ignored for monochrome adapters. Example: ST$="This is a test of fast screen printing" ROW%=10: COL%=20: PAGE%=0 CALL CALCATTR(FOREGND%,BACKGND%,ATTR%) CALL XQPRINT(ST$,ROW%,COL%,ATTR%,PAGE%) Name: XQPRINTD Type: Video / CLONE Description: This function is identical to XQPRINT, with the one exception that it writes directly to the screen. That makes it even faster than XQPRINT, but means that it will cause snow on some color monitors when printing to the active display page. File Attributes Every file has an "attribute byte" which tells something about the file. This can be modified to some extent. For instance, any file can be made "hidden", in which case it will be invisible; this includes subdirectories, which can still be used even if you can't see that they're there. Some kinds of changes are not possible, how- ever: you can't change a subdirectory into a normal file, for example. Attribute Code Description Normal 00h A normal file. Read-only 01h File can't be killed or rewritten. Hidden 02h File disappears from view. System 04h Like HIDDEN. For system (DOS, BIOS) files. Volume label 08h A disk's volume label. Only one, in the root. Directory 10h Subdirectory. Archive 20h Usually set. May be used for disk backup. Combinations of the codes are possible, as I've mentioned. For instance, a hidden subdirectory would have a code of 10h + 02h = 12h. A normal file, because of the archive bit, might show up as either 00h or 20h... and so on. Note this is all in hexadecimal, hence the "h" postfix. Convert to decimal form as necessary when calling routines which use the file attribute. BASIC has functions to handle this for you if you don't understand hex-- see the HEX$ function and &H prefix in your BASIC manual. NOTE: Reading the volume label is unreliable in versions of DOS prior to MS-DOS 3.1, due to a DOS bug. The most secure way of handling it is to do a search with the label attribute (8), then to doublecheck the actual attribute of the file (if any) which was returned. If it's not the volume label, use FINDNEXTF and try again. New file I/O routines This contains some general information about the new file I/O routines: FCLOSE, FCREATE, FOPEN, FREAD, FSETEND, FSETREC, and FWRITE. These routines duplicate a number of extant BASIC functions. They are useful, however, for a number of reasons. They provide you with low-level control over the details of file input and output. They may be safely used in subprograms, since they return error codes rather than using error trapping (subprograms have severe limitations on use of error trapping). They provide access to the file-level locking capabilities of DOS 2.0 and above, which allows creation of programs which work on normal computers as well as those with multi- tasking or networking (BASIC's record-level locking is incompatible with normal computers unless SHARE is activated). In BASIC, you give the file a number when you open it, and refer to the file by that number from then on. With the ADVBAS functions, you are given a "handle" when you open the file, which serves the same purpose. In BASIC, a file is automatically created (or truncated if it exists) if you open it for output. With ADVBAS, you must use FCREATE to produce that result. If you have an existing file which you want to modify (or read), use FOPEN. With ADVBAS, like BASIC, you can read or write to a file, or move the file pointer to a given record or to the end of file (to append information). Also like BASIC, you must close a file when you are finished using it. The error codes returned by these functions are as follows: -1 Unable to read or write the entire record 2 File not found 3 Path not found 4 No handle available 5 Access denied 6 Invalid handle 15 Invalid drive specification If you get "no handle available", you have run out of room to open files. You can fix this by not opening so many files at the same time, or by increasing the FILES=xx statement in your CONFIG.SYS. See your DOS manual for further information. BASCOM Bugs Microsoft QuickBASIC Compiler v1.00: If there is not enough memory when you try to execute the SHELL command, your program will crash. The error STRING FORMULA TOO COMPLEX appears erratically in some programs, for no apparently good reason. Microsoft QuickBASIC Compiler v1.02: This release solves the SHELL crash problem. Also, more control characters are now printed out just like BASICA. Many miscellaneous problems have been fixed... but not the infamous STRING FORMULA TOO COMPLEX error. BASCOM Bugs Microsoft QuickBASIC Compiler v2.0 and v3.0: If your program uses error trapping, it must have at least one line number in the program, even you normally only use labels. Other- wise the program will crash if it runs into an error. Screen paging doesn't work in v2.0. If you have a REMark on the same line as a DATA statement, you'll get peculiar error messages. The programming environment doesn't work properly with user lib- raries (such as ADVBAS) under certain conditions. In particular, compiling to an EXE or BRUN file will produce flaky code. If you run into this problem, just compile the program the old way, from the command line. Instead of QB PROGRAM.BAS /L ADVBAS.EXE you would use something like QB PROGRAM; LINK PROGRAM,,,ADVBAS to compile and link the program. You may need to provide additional information, depending on whether your program uses things like error trapping or event trapping. See your QuickBASIC manual for details. Microsoft QuickBASIC 4.0: ADVBAS functions which require static arrays will not work in the environment, due to a bug in QuickBASIC. Do not try to use them, at the risk of crashing your system! You can still use these routines in programs compiled with the stand-alone version, BC.EXE, however, except for GETSCREEN and PUTSCREEN. Note that this problem does not affect ProBas functions, which were written to deal with dynamic arrays as well (and the static arrays in the QB4 environment behave somewhat similarly to dynamic arrays). When you try to produce an .EXE file from the QuickBASIC environ- ment, the compiler (QB.EXE) executes the stand-alone version of the compiler (BC.EXE) in order to compile your program. No problem so far, although it means you must have your libraries in both .QLB and .LIB form. Then QB executes the LINK utility (LINK.EXE) in order to create the final .EXE file. Trouble! For no conceivable reason, QuickBASIC specifies the parameters for the LINK command in the wrong order. This works, sort of... that is, if you're using libraries, it will make your programs much larger, because it links everything in the library rather than just the routines you use. It also ignores your DOS environment setting for the library location, meaning that you need to have your libraries in the current drive/subdirectory. Finally, it may not work at all if you have a lot of routines in your library. This is really unforgivable, since both QuickBASIC and LINK are Microsoft products. I mean, honestly, you'd think they'd know how to use their own utilities! Solution: don't create .EXE files from within the environment. Only use the environment for debugging, and create the final .EXE files yourself with BC and LINK, using the old syntax. Don't try to add the library to the filename, the way QB tries to do, but instead specify the library name when LINK asks you for libraries. Notes on Microsoft's QuickBASIC v4.0: You might guess from the version number that this is merely another in a series of improvements to QuickBASIC. In fact, this version represents an entire rewrite of the compiler. The result is in general much more powerful than earlier versions of QuickBASIC, but does have its own quirks. Some of the nice new features: recursive functions and procedures (at last!), long integers (with a range of plus or minus two billion, this numeric type is very handy, and is provided in many languages), code which can be linked with other languages (subject to a number of limitations), and an improved compiling environment. The editor provided in the environment now accepts Wordstar-type commands, as well as Microsoft's own esoteric commands. Programs are instantly compiled into "p-code" as you enter them, which gives you automatic syntax checking (can be turned off) and reformatting (which can't be turned off), and means you never have to wait for your program to compile. The reformatter makes all BASIC keywords uppercase, puts spaces between parameters to a function call, makes all occurrences of a given variable have the same case as the last time you entered it, and so forth. Many people find this a nuisance, but on the whole, I think I like it. Input and output now take place through DOS, so you can easily redirect input or output from the command line. Output to the screen is also faster, if you've got an ANSI driver installed, since ANSI is more efficient than the old BIOS calls. The screen is no longer automatically cleared when your program starts, which is very nice. Problems: there is a new library format for the environment-- QLB instead of EXE. Old assembly routines usually need to be modified to work with QB4 whether or not the environment is used. Procedures and functions are kept in separate areas from your main program, and it takes several keystrokes to get at them. If you are particular about the style of your code, you may hate the reformatter. Code produced is about the same size or larger, but is much slower unless you have a numeric coprocessor (8087, 80287, or 80387) installed. There is less string space available than in older compilers, which may cause trouble with large programs. Personally, I really like most of the changes. I have been look- ing for some of these features for a long time, and it's great to see them. There are a lot of drawbacks too, though, and many people don't like the new compiler. You'll have to come to your own conclusions on this one. It's worth the (painful) wait for the upgrade, though-- if QB4 suits you, it will improve your productivity immensely. If not... put it up for sale, this is going to be a top seller. Despite its other problems, QB4 is a very convenient environ- ment for beginners, especially those moving from interpreted BASIC. This is one product that is going to do Real Well. Notes on Borland's Turbo BASIC v1.0: Turbo BASIC is almost completely compatible with BASICA/GWBASIC, and fairly compatible with QuickBASIC. It supports recursive func- tions, local variables, long integers, and the 8087 chip, among other things. It has a fairly slick windowing programming environment, and features online, context-sensitive help. The editor is a configur- able Wordstar-type editor. Code size and speed seem to be roughly comparable to QuickBASIC (probably better than QuickBASIC 4.0). Turbo BASIC's main fault seems to be that it lacks an assembly language interface-- it uses a machine-language INLINE format like that in Turbo Pascal. This is more than enough to dissuade me from converting ADVBAS to work with Turbo BASIC. Otherwise, though, it's nearly as strong a product as Microsoft's QuickBASIC, and it looks like we're shaping up for some fine marketing battles. BASIC Bugs This is a peculiar one... it seems that BASIC can create files having names which contain blank spaces. This is a problem, because DOS considers the space to be a delimiter, and thus cannot handle these files. Such files will not be listed correctly in the directory, and will be impossible to manipulate from DOS (can't read, delete, or otherwise handle the file). So, be careful to screen out spaces when creating files from BASIC! This caveat also applies to subdirec- tories, including those created with the MAKESUB routine of ADVBAS. If you take the VAL() of a string, you expect the value converter to stop when it runs into the end of the string or a non-numeric charac- ter. Trouble is, BASIC ignores spaces rather than treating them as non-numeric characters. So if you try A = VAL("256 12") you will not get A = 256, as you thought, but actually A = 25612. Surprise! Microsoft does not consider this a bug, although it's hard to think of an application in which this behavior might be appropriate.