 Microsoft BASIC Professional Development System
 =============================================================================


 1. How Microsoft BASIC ON ERROR Handles DOS General Drive Failure

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q19842

 Error trapping in Microsoft BASIC programs (invoked with the ON ERROR
 statement) will trap a DOS general drive failure.

 A DOS general drive failure occurs if an error occurs while trying to
 read the specified drive (for example, the drive door is not closed or
 the disk is improperly formatted). The general drive failure message
 is usually of the following form:

    General failure reading drive A:
    (Abort, Retry, Ignore)?

 BASIC error trapping invoked with the BASIC ON ERROR statement traps
 the DOS general drive failure and returns a BASIC error number 57,
 "Device I/O error."


 2. LIB Errors During SETUP.EXE If Directory Has "-" in Its Name

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  7-FEB-1990    ArticleIdent: Q37304

 If you specify a library directory name that contains a minus sign
 (such as LIB-BAS) during the SETUP.EXE program for Microsoft BASIC
 Compiler Version 6.00 or 6.00b, or Microsoft BASIC Professional
 Development System (PDS) Version 7.00, the LIB.EXE manager may have
 problems creating the BASIC stand-alone and run-time libraries.

 This problem occurs because when the Library Manager (LIB) is run from
 the SETUP program, it uses the pathname to your library directory in
 its "Operations:+" step and is confused by an operator (such as "-")
 in the directory name.

 For example, if you specified the directory name C:\LIB-BAS for your
 BASIC libraries, a library build would look like the following:

    Microsoft (R) Library Manager  Version 3.11
    Copyright (C) Microsoft Corp 1983-1988.  All rights reserved.

    Library name:BRUN60ER.LIB
    Library does not exist.  Create? (y/n) Y
    Operations:+ C:\LIB-BAS\BRUN60R.LIB
    LIB : error V2155: BAS\BRUN60ER.LIB : module not in library; ignored
    &
    Operations:+ .\B4 ;
    LIB : error V2157: C:\LIB.obj : cannot access file

 The LIB thinks the "-" character in the LIB-BAS directory is an extra
 operation trying to subtract BAS\BRUN60ER.LIB. It then tries to add a
 file called C:\LIB.obj, which does not exist.

 Then, when trying to compile a BASIC program and link it with the
 BRUN60ER.LIB library, the compile will seem to work correctly, but the
 link can return errors, such as the following:

    LINK : warning L4021: no stack segment
    LINK : error L2029: Unresolved externals:
      < here would be a list of the unresolved library references >

 If you avoid the following operators in the directory name for BASIC
 libraries, the LIB shouldn't have any problems initially creating the
 libraries:

    +  -  -+  *  -*


 3. How DEFINT, DEFSNG, DEFDBL Affect Type of DEF FN Function

 Product Version(s): 5.35 5.36 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS                         | OS/2
 Flags: ENDUSER | B_QuickBas B_BasicInt
 Last Modified: 17-JAN-1991    ArticleIdent: Q21311

 This article discusses the default type declaration of DEF FN
 user-defined functions in Microsoft BASIC.

 The DEFINT, DEFLNG, DEFDBL, and DEFSNG statements affect the first
 letter of the variable part of a DEF FN function name, and not the FN
 part of the function name. This information applies to all Microsoft
 BASIC compilers and interpreters for MS-DOS, MS OS/2, Macintosh, and
 CP/M-80.

 Microsoft BASIC Compiler versions 6.00 and later, and QuickBASIC
 versions 4.00 and later for the IBM PC, introduced the DEFLNG
 statement for long integer declaration, which also behaves this way.

 Example
 -------

 The following program prints 1.2 (a noninteger):

    10 DEFINT F   ' DEFINT F doesn't affect the DEF FN below.
    20 DEF FNAB=1.2
    30 PRINT FNAB

 The following program prints 1 (truncated to an integer):

    10 DEFINT A   ' DEFINT A does affect the DEF FN below.
    20 DEF FNAB=1.2
    30 PRINT FNAB


 4. BRUNxx.EXE Run-Time Module Must Reload from Disk After SHELL

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# G881101-5556 B_QuickBas
 Last Modified:  1-FEB-1990    ArticleIdent: Q37767

 When the SHELL statement is executed, some portions of the BASIC
 run-time module (BRUNxx.EXE) are unloaded. This is done to free up as
 much memory as possible for COMMAND.COM. When the SHELL is complete,
 the run-time module must be reloaded.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2, and to Microsoft
 QuickBASIC Compiler Versions 4.00, 4.00b, 4.50 and earlier for MS-DOS.

 If the run-time module is located on a floppy disk removed during the
 SHELL statement, it must be re-inserted before the BASIC program can
 continue. If the program cannot find the run-time module, it will
 prompt you for its location.

 To avoid the need to reload the run-time module after SHELL, you can
 compile with the /O (stand alone) option, which includes the run-time
 routines into the BASIC .EXE program at LINK time.


 5. "Device I/O" Error Using LPRINT or "LPT1:" After a CHAIN

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00
 Last Modified: 17-JAN-1990    ArticleIdent: Q32214

 The following problem occurs in OS/2 protected mode programs compiled
 with Microsoft BASIC Compiler Versions 6.00 and 6.00b or Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS OS/2.
 Using LPRINT, or sending output to the "LPT1:" device name, then
 chaining to a second routine that uses the printer produces the
 following error:

    Device I/O error in line 0 of module PROG2

 This problem can be worked around in OS/2 protected mode by sending
 output to the DOS "LPT1" (without a colon) device name instead of
 using LPRINT or "LPT1:". This problem does not occur in OS/2 real
 mode.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b and in Microsoft BASIC PDS Version
 7.00. We are researching this problem and will post new information
 here as it becomes available.

 The following chained programs demonstrate the "Device I/O" error.
 These programs must be compiled with the BRUN library option for
 protected mode.

    ' prog1
    OPEN "O",15,"LPT1:"
    PRINT #15,"program 1"
    CHAIN "prog2"

    ' prog2
    PRINT #15,"program 2"
    CLOSE #15

 The problem occurs only when sending output to the BASIC "LPT1:"
 printer device. If the DOS device, "LPT1" (without a colon) is used,
 the problem does not occur. For example, the following programs CHAIN
 correctly:

    ' prog1
    OPEN "O",15,"LPT1"
    PRINT #15,"program 1"
    CHAIN "prog2"

    ' prog2
    PRINT #15,"program 2"
    CLOSE #15
    SYSTEM


 6. MS-DOS BASIC Compiler Does Not Provide ISAM File Support

 Product Version(s): 5.35 5.36 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q21331

 Microsoft BASIC Compiler Versions 5.35, 5.36, 6.00, and 6.00b for
 MS-DOS does not support Index Sequential Files (ISAM). You must write
 your own routine or use a third-party vendor's routine that is
 compatible with the BASIC compiler.

 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS does support ISAM files. BASIC PDS 7.00 currently supports
 single-user ISAM, however.


 7. A Single-Precision Number as a File Number Causes "Overflow"

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q37339

 A program compiled with Microsoft BASIC Compiler Version 6.00 or
 6.00b, or QuickBASIC Version 4.00 or 4.00b, generates an "Overflow"
 error message if you are using a single-precision variable as the
 number of a file to be opened.

 This behavior does not occur in Microsoft QuickBASIC Version 4.50 for
 MS-DOS or Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2.

 The following sample code demonstrates the problem. If the file number
 "F" is redefined as an integer, the program works correctly. The
 program also can be forced to work correctly using any of the
 following alternatives:

 1. By compiling with the /o, /d, /v, or /x compiler-option switches

 2. By putting line numbers on affected lines

 3. By deleting a few lines of code in the subroutine

 Earlier versions of Microsoft QuickBASIC do not have this problem.

 The following is an example:

    DIM SHARED f9$(22, 9), id$(9), size%(9), fdr$(9)
    CLS
    f = 1
    fi$ = "FILENAME.DAT"
    CALL OPEN.ISAM(f, fi$)
    END

    SUB OPEN.ISAM (f, fid$) STATIC
         OPEN "r", f, fid$, 256
            FIELD #f, 256 AS f9$
         fdr$(f) = SPACE$(256)
            size%(f) = LOF(f) / 256
            id$(f) = fid$
    END SUB


 8. "Feature Unavailable" Using FRE(-3) in .EXE Compiled in 7.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900125-132
 Last Modified: 26-FEB-1990    ArticleIdent: Q58123

 The FRE(-3) function, which returns available expanded memory in the
 QuickBASIC Extended (QBX.EXE) environment, normally gives a "Feature
 Unavailable" (run-time error 73) in .EXE files created with BC.EXE. An
 exception is if an executable .EXE file is linked with overlays that
 are each no larger than 64K, and if a LIM 4.0 EMS expanded memory
 driver (defined below) is installed, then the FRE(-3) function returns
 a value for the amount of free expanded memory. This information
 applies to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 The FRE(-3) function returns the amount of free LIM 4.0 EMS expanded
 memory available for arrays, SUBs, and functions in the QBX.EXE
 environment.

 Note that the only way that compiled BASIC .EXE applications can take
 advantage of expanded memory is with linked overlays, but then only if
 each overlay is smaller than 64K. (If expanded memory is not
 accessible, overlays just swap to disk.) The FRE(-3) function returns
 a value for an .EXE program only when a LIM 4.0 EMS driver is
 installed and the .EXE program is able to successfully store its
 overlays in expanded memory.

 To check the amount of available expanded memory from an EXE program,
 see Pages 204-206 in Ray Duncan's "Advanced MS-DOS Programming, 2nd
 Edition" (Microsoft Press, 1988). The method described there uses
 assembly language and interrupts.

 Note: LIM 4.0 EMS is defined as follows:

    LIM  = Lotus, Intel, Microsoft
    4.0  = Version number 4.0 (of the standard LIM EMS)
    EMS  = Expanded Memory Specification, a standard for addressing
           expanded memory

 For more information about linker overlays in BASIC PDS 7.00, search
 for a separate article with the following keywords:

    BASIC and 7.00 and linker and overlays and modules

 Also see Pages 612-614 of the "Microsoft BASIC 7.0: Programmer's
 Guide," in the section "Linking with Overlays".


 9. LINK Overlays Not Supported in BASIC 6.00/6.00b, or QuickBASIC

 Product Version(s): 6.00 6.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_QuickBas
 Last Modified: 30-MAY-1990    ArticleIdent: Q31153

 Microsoft QuickBASIC versions 1.00, 1.02, 2.00, 2.01, 3.00, 4.00,
 4.00b, and 4.50 for MS-DOS and Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS do NOT support code overlays. These versions of
 BASIC compiler and QuickBASIC are not designed to output the special
 object format necessary to support overlays under MS-DOS.

 The description of LINK.EXE provided in the "Microsoft CodeView and
 Utilities: Software Development Tools for MS-DOS" manual, supplied
 with Microsoft BASIC Compiler versions 6.00 and 6.00b, is a general
 description for the linker. However, this description is misleading.
 Although Pages 285-286 discuss linker overlays, overlays are not
 supported by these versions of BASIC.

 Microsoft has introduced support for linker overlays in Microsoft
 BASIC Professional Development System (PDS) version 7.00 under MS-DOS.
 For more information, search for a separate article with the following
 words:

    how and use and LINK and overlays and BASIC and PDS and 7.00

 Other Microsoft languages, such as Microsoft C and Microsoft FORTRAN,
 also support linker overlays.

 The error message "L2048 cannot find overlay manager" will be
 generated if you try to link with overlays using BASIC compiler
 version 6.00.

 Overlays are useful in a memory-restricted environment because overlay
 capability allows programs to load portions of code from disk into
 memory when needed, and overlays in memory not currently being used
 are automatically swapped out when loading the needed overlays.

 The CHAIN, RUN, and SHELL statements in BASIC offer capabilities that
 are similar to code overlays, but more limited.


 10. "Formal Parameter Specification Illegal" from BC But Not QB

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q27856

 For the following statement, the BC.EXE compiler correctly generates
 the compile-time error message "Formal parameter specification
 illegal," while the QuickBASIC QB.EXE editor does not produce any
 error messages:

    DECLARE SUB prompt (prompt$)

 This error message results from the requirement in QuickBASIC Versions
 4.00, 4.00b, and 4.50, in Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 that procedure and variable names must be different.
 Therefore, programs may not contain functions or subprograms whose
 names are the same as those of variables.

 Note that the QB.EXE environment of QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and the QBX.EXE environment of BASIC PDS 7.00 correctly gives
 you a "Duplicate Definition" error on the following CALL or SUB
 statement:

    CALL PROMPT(PROMPT$)

 Therefore, the lack of warning of "Duplicate Definition" for the
 DECLARE statement is a minor issue.

 An error message occurs even in the case in which the variable and
 procedure names differ by a data-typing character (for example, %, &,
 !, #, $). The error message displays because the compiler makes no
 distinction between the variable "prompt$" and the subprogram name
 "prompt".

 The requirement that procedure and variable names be different was
 introduced in QuickBASIC Version 4.00 and BASIC compiler Version 6.00.
 This was not a requirement in earlier versions.


 11. "Error During Run-Time Initialization": Mixing /FPa and /FPi

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  4-SEP-1990    ArticleIdent: Q31505

 When you link separate modules together to make an .EXE program, all
 the modules must have been compiled with the same math package. The
 two math packages available in Microsoft BASIC Compiler versions 6.00
 and 6.00b and in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 are as follows:

 1. BC /FPi (IEEE coprocessor-emulation math, the default)
 2. BC /FPa (alternate math)

 If you LINK modules or libraries together that were compiled with both
 the BC /FPa and /FPi options, the .EXE program gives the following
 error message at run time and usually hangs:

    Error during run-time initialization

 Combining math packages can cause unpredictable results in the .EXE
 program at run time. After the error message appears, a warm boot
 (CTRL+ALT+DEL) does not work. To reboot, you must turn the computer
 off, then back on.

 To avoid this problem, make sure when you LINK routines that they were
 compiled with the same math package. Also, remember that the QB.EXE
 environment of the BASIC compiler and the QBX.EXE environment of BASIC
 PDS 7.00 and 7.10 do not support the alternate math package. In other
 words, object modules compiled with the /FPa switch cannot be placed
 into a Quick library (.QLB file) for use in QB.EXE or QBX.EXE.


 12. PCOPY & Multiple Pages Not Supported in MS OS/2 Protected Mode

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# G880910-3123 docerr
 Last Modified:  2-FEB-1990    ArticleIdent: Q35519

 Multiple video pages are not supported in the protected mode of MS
 OS/2. As stated on Page 40 of the "Microsoft BASIC Compiler 6.0:
 User's Guide" and on Page 522 of the "Microsoft BASIC 7.0:
 Programmer's Guide," the SCREEN function ignores the active and visual
 page parameters.

 Since multiple pages are not supported, the PCOPY function is not
 allowed in MS OS/2 protected mode. This fact needs to be added to the
 section on BASIC language changes for MS OS/2 protected mode.

 Through BASIC, there is no way to manipulate the video buffer directly
 in MS OS/2 protected mode. However, it can be done through the use of
 OS/2 API calls. The following API calls can be used to modify the
 video buffer:

    VioGetBuf
    VioShowBuf
    VioGetPhysBuf
    VioScrLock
    VioScrUnLock

 The VioGetBuf function retrieves the address and length of the logical
 video buffer (LVB). The address of the buffer is returned in a long.
 The high 2 bytes are the segment and the low 2 bytes are the offset,
 as in the following example:

    x = VioGetBuf(pointer, length, 0)
    segment& = pointer / &H10000
    offset& = pointer MOD &H10000

 To modify the buffer, change the segment to the segment value returned
 and use PEEK and POKE to read and modify the information. Once the
 information is changed, VioShowBuf is used to display the changes.

 The VioGetPhysBuf function retrieves the selector of the physical
 video buffer. The physical video buffer contains the current screen
 image. To modify the screen, change the segment to the selector
 returned and use PEEK and POKE to read and modify the screen. This
 method is faster than using VioGetBuf/VioShowBuf because you are
 directly modifying the screen.

 For more information about these VIO API calls, please refer to your
 OS/2 documentation. Listed below are two sample programs that use the
 methods discussed above.

 Code Examples
 -------------

 'The following program uses VioGetPhysBuf:
 DEFINT A-Z
 TYPE PhysBufData
      bufstart AS LONG
      buflength AS LONG
      selector1 AS INTEGER
      selector2 AS INTEGER
 END TYPE

 DECLARE FUNCTION VioGetBuf (_
    SEG p1 AS LONG,_
    SEG p2 AS INTEGER,_
    BYVAL p3 AS INTEGER)

 DECLARE FUNCTION VioShowBuf (_
    BYVAL p1 AS INTEGER,_
    BYVAL p2 AS INTEGER,_
    BYVAL p3 AS INTEGER)

 DECLARE FUNCTION VioGetPhysBuf (_
    SEG p1 AS PhysBufData,_
    BYVAL p2 AS INTEGER)

 DECLARE FUNCTION VioScrLock (_
    BYVAL p1 AS INTEGER,_
    SEG p2 AS INTEGER,_
    BYVAL p3 AS INTEGER)

 DECLARE FUNCTION VioScrUnLock (_
    BYVAL p1 AS INTEGER)

 CLS
 FOR i = 1 TO 10
     PRINT "This is a test"
 NEXT i
 DIM stuff AS PhysBufData
 x = VioScrLock(1, status, 0)
 PRINT
 PRINT "Lock Status: "; status
 stuff.bufstart = &HB8000
 stuff.buflength = 43 * 80 * 2
 x = VioGetPhysBuf(stuff, 0)
 IF (x) THEN
     PRINT "Error: "; x; " occurred."
     END
 ELSE
     PRINT
     PRINT "Start: "; HEX$(stuff.bufstart)
     PRINT "Length: "; stuff.buflength
     PRINT "Selector1: "; stuff.selector1
     PRINT "Selector2: "; stuff.selector2
     PRINT
     PRINT
     PRINT "Enter a key to begin changing..."
     WHILE INKEY$ = "": WEND
     offset = 0
     DEF SEG = stuff.selector1
     FOR i = offset TO offset& + stuff.buflength - 1 STEP 2
        POKE i, 65     'Character
        POKE i + 1, &H17'Attribute
     NEXT i
     DEF SEG
     x = VioScrUnLock(0)
 END IF
 PRINT "Enter a key to quit..."
 WHILE INKEY$ = "": WEND
 END

 'The following program uses VioGetBuf/VioShowBuf:
 DEFINT A-Z
 TYPE PhysBufData
      bufstart AS LONG
      buflength AS LONG
      selector1 AS INTEGER
      selector2 AS INTEGER
 END TYPE

 DECLARE FUNCTION VioGetBuf (_
    SEG p1 AS LONG,_
    SEG p2 AS INTEGER,_
    BYVAL p3 AS INTEGER)

 DECLARE FUNCTION VioShowBuf (_
    BYVAL p1 AS INTEGER,_
    BYVAL p2 AS INTEGER,_
    BYVAL p3 AS INTEGER)

 DECLARE FUNCTION VioGetPhysBuf (_
    SEG p1 AS PhysBufData,_
    BYVAL p2 AS INTEGER)

 DECLARE FUNCTION VioScrLock (_
    BYVAL p1 AS INTEGER,_
    SEG p2 AS INTEGER,_
    BYVAL p3 AS INTEGER)

 DECLARE FUNCTION VioScrUnLock (_
    BYVAL p1 AS INTEGER)

 CLS
 FOR i = 1 TO 10
     PRINT "This is a test"
 NEXT i
 DIM pointer AS LONG
 DIM length AS INTEGER
 DIM handle AS INTEGER
 x = VioGetBuf(pointer, length, 0)
 segment& = pointer / &H10000
 offset& = pointer MOD &H10000
 IF (x) THEN
     PRINT "Error: "; x; " occurred."
     END
 ELSE
     PRINT "POINTER = "; HEX$(pointer)
     PRINT "LENGTH = "; length
     PRINT
     PRINT "SEGMENT = "; HEX$(segment&)
     PRINT "OFFSET = "; HEX$(offset&)
     PRINT
     PRINT "Enter a key to begin changing the buffer..."
     WHILE INKEY$ = "": WEND
     CLS
     DEF SEG = segment&
     FOR i = offset TO offset& + length - 1 STEP 2
       POKE i, 65     'Character
       POKE i + 1, &H17'Attribute
     NEXT i
     DEF SEG
     PRINT "Enter a key to see the changes..."
     WHILE INKEY$ = "": WEND
     x = VioShowBuf(0, length, 0)
 END IF
 PRINT "Enter a key to quit..."
 WHILE INKEY$ = "": WEND
 END


 13. ERDEV & ERDEV$ "Advanced Feature" Error in OS/2 Protected Mode

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q35653

 The statements ERDEV and ERDEV$ give the run-time error message
 "Advanced Feature Unavailable" when compiled and run in OS/2 protected
 mode because these functions are set by DOS interrupt 24H, which is
 not available in OS/2 protected mode.

 ERDEV and ERDEV$ are not supported in OS/2 protected mode. This
 restriction should be added to Page 40 of the "Microsoft BASIC
 Compiler 6.0: User's Guide" for Versions 6.00 and 6.00b and to Page
 520 of the "Microsoft BASIC 7.0: Programmer's Guide" for Microsoft
 BASIC Professional Development System (PDS) Versions 7.00 and 7.10.

 Code Example
 ------------

 I% = ERDEV
 A$ = ERDEV$


 14. /FPa; "Symbol Defined More Than Once" Linking BASIC and Pascal

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# G880915-3308 buglist6.00 buglist6.00b buglist7.00
 Last Modified:  2-MAR-1990    ArticleIdent: Q35902

 If you compile Microsoft BASIC and Microsoft Pascal modules with the
 alternate-math library (/FPa) option, a "Symbol Defined More than
 Once" error occurs when you LINK the BASIC and Pascal modules. This
 problem occurs in Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b and in Microsoft BASIC PDS Version
 7.00. We are researching this problem and will post new information
 here as it becomes available.

 The programs correctly link together if you compile the BASIC program
 with the stand-alone (BC /O) option.

 To duplicate the problem, follow the steps below:

 1. Compile the BASIC program -- BC prog /Fpa;

 2. Compile the Pascal routine -- PL /FPa /C  progr.pas

 3. Link the BASIC and Pascal modules -- LINK prog + progr /noe;

 4. The linker displays the following error:

       LIBPASA.LIB(fcall.ASM) : error L2025: __fpmath : symbol defined
       more than once
       pos: 1339E Record type: 7F04



 15. How to Call OS/2 Function DosAllocHugeSeg and DosGetHugeShift

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35904

 Below is a sample program that makes a call to the MS OS/2 functions
 DosAlocHugeSeg, DosGetHugeShift, DosReallocHuge, and DosMemAvail. This
 program can be compiled in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for MS OS/2.

 The following is code example:

 DECLARE FUNCTION DosAllocHuge%(_
                  BYVAL P1 AS INTEGER,_
                  BYVAL P2 AS INTEGER,_
                  SEG P3 AS INTEGER,_
                  BYVAL P4 AS INTEGER,_
                  BYVAL P5 AS INTEGER)

 DECLARE FUNCTION DosGetHugeShift%(SEG P1 AS INTEGER)

 DECLARE FUNCTION DosReallocHuge%(_
                  BYVAL P1 AS INTEGER,_
                  BYVAL P2 AS INTEGER,_
                  BYVAL P3 AS INTEGER)

 DECLARE FUNCTION DosMemAvail%(SEG P1 AS LONG)

 DEFINT A-Z
 DIM mem AS LONG

 CLS
 MEM=0
 x=DosMemAvail%(mem)

 IF (x) THEN
    PRINT "An error occurred.  The number is : ";x
 ELSE
    PRINT "The amount of available memory is : ";mem
 END IF

 INPUT "Enter the number of Segments : ";NUMSEG

 SIZE=0
 SELECTOR=0
 SHAREID=0
 input "Enter the Number of MAXSEG for REALLOCATION: ";MAXNUMSEG
 print
 x=DosAllocHuge%(numseg,size,selector,shareid,maxnumseg)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    PRINT "The selector is : ";selector
 END IF
 SHIFTCOUNT=0

 x=DosGetHugeShift%(shiftcount)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    PRINT "The Huge Shift Count is : ";shiftcount
 END IF

 print
 INPUT "Enter the number of segments in reallocation : ";NUMSEG
 SIZE=0
 print
 x=DosReAllocHuge%(numseg,size,selector)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    PRINT "Memory was been reallocated"
 END IF

 end


 16. Example of BASIC Calling MS OS/2 Function DosStartSession

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35905

 Below is a sample program that makes a call to the MS OS/2 function
 DosStartSession. This program can be compiled in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC
 Professional Development System (PDS) Version 7.00.

 The full pathname must be specified for the program to be executed. If
 this is not done when you are using OS/2 Version 1.00, an error 203 is
 generated. OS/2 Version 1.10 and 1.20 produce an error 2.

 The following is a code example:

 'This information can be found in BSEDOSPC.BI
 TYPE ADDRESS
   Offset    as INTEGER
   Segment   as INTEGER
 END TYPE

 TYPE STARTDATA
   cb    as INTEGER
   Related   as INTEGER
   FgBg      as INTEGER
   TraceOpt  as INTEGER
   PgmTitle  as ADDRESS
   PgmName   as ADDRESS
   PgmInputs as ADDRESS
   TermQ     as ADDRESS
 END TYPE

 DECLARE FUNCTION DosStartSession%(_
                  SEG P1 AS StartData,_
                  SEG P2 AS INTEGER,_
                  SEG P3 AS INTEGER)

 DIM info AS STARTDATA
 DIM apinputs AS ADDRESS, apname AS ADDRESS, aptitle AS ADDRESS
 DIM title AS STRING*32
 DIM flname AS STRING*32
 DIM pinput AS STRING*32

 title="BASIC TEST"+chr$(0)
 INPUT "Enter filename with extension", flname
 flname=flname+chr$(0)
 pinput=chr$(0)

 apname.segment=varseg(flname)
 apname.offset=varptr(flname)

 apinputs.segment=varseg(pinputs)
 apinputs.offset=varptr(pinputs)

 aptitle.segment=varseg(title)
 aptitle.offset=varptr(title)

 info.cb=24
 info.Related=0
 info.FgBg=1
 info.TraceOpt=0
 info.PgmTitle=aptitle
 info.PgmName=apname
 info.PgmInputs=apinputs

 y=DosStartSession%(info,a%,b%)

 if (y) then
    print "An error occurred.  The number is : ";y
 else
    Print "Successful"
    while inkey$="" :wend
 end if
 END


 17. LINE Statement with BF Option Outside Window Will Hang

 Product Version(s): 6.00   | 6.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist6.00 fixlist6.00b SR# S881221-109 viewport
 Last Modified: 17-JAN-1990    ArticleIdent: Q40546

 If a LINE statement with the BF (box filled) option is executed
 outside the boundaries of the physical view port set up by the VIEW
 statement, the computer will hang. The program runs properly inside
 the QuickBASIC QB.EXE environment, but fails when compiled with BC.EXE
 from Microsoft BASIC Compiler Version 6.00.

 Microsoft has confirmed this to be a problem with BC.EXE in Microsoft
 BASIC Compiler Version 6.00. This problem was corrected in Microsoft
 BASIC Compiler Version 6.00b.

 This problem does not occur in Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50, or in Microsoft BASIC Professional Development System
 (PDS) Version 7.00.

 The following program sets up a physical view port with the VIEW
 statement and then draws a line using the BF option, starting inside
 the box and moving outside the window's boundaries. If the program is
 compiled with Version 6.00 of Microsoft BASIC Compiler, the program
 will hang upon attempting to draw the first box that lies outside the
 window view port.

 The following is a code example:

 SCREEN 2
 xmin = 0: ymin = 0
 xmax = 1000: ymax = 1000
 dx = (xmax - xmin) / 10
 dy = (ymax - ymin) / 10
 VIEW (200, 50)-(400, 150)
 WINDOW SCREEN (xmin, ymin)-(xmax, ymax)
 LINE (xmin, ymin)-(xmax, ymax), 1, B
 x0 = xmin
 loop1:  x0 = x0 + dx
         LOCATE 5, 35: PRINT USING "x0=####"; x0
         LINE (x0, ymin + dy)-(x0 + 5, ymax - dy), 1, BF
 stall:  x$ = INKEY$: IF x$ = "" THEN GOTO stall
         IF x$ = CHR$(27) THEN END
         GOTO loop1


 18. BUILDRTM Puts C Routines in BC 6.00 Extended Run-Time Library

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q37092

 You can include Microsoft C routines in a Microsoft BASIC Compiler
 Version 6.00 or 6.00b or a Microsoft BASIC Professional Development
 System (PDS) Version 7.00 extended run-time library by using the
 BUILDRTM utility, provided that the C routine does not have C graphics
 support (such as GRAPH.H). The following is an example of this for a
 void function called "test" located in a source file named PROG1.C:

 1. Compile the C program with the medium or large model as follows:

       CL prog1 /Al

 2. Create an export list and include the new routine(s) to be added to
    the BASIC compiler extended run-time library, as follows (call this
    file "EXP.LST"):

       #Here is the export list example.
       #OBJECTS
       prog1
       #EXPORTS
       _test
       #LIBRARIES
       llibcer.lib

 3. Invoke BUILDRTM using the EXP.LST to create the new run-time
    library with the following:

       BUILDRTM /LR /FPI NEWRUN EXP.LST

 The above steps are covered more completely on Pages 13-19 of the
 "Microsoft BASIC Compiler 6.0: User's Guide" or Pages 661-668 of the
 "Microsoft BASIC 7.0: Programmer's Guide."

 The above steps produce a new run-time library called "NEWRUN.EXE" and
 a matching "NEWRUN.LIB" file. Now your Microsoft BASIC programs can be
 linked with NEWRUN to allow a program to call the C void function
 "_test" at any time. For example, if you want your new BASIC program,
 named PROG2.BAS, to call "_test," compile normally as follows:

    BC PROG2.BAS;

 This produces the PROG2.OBJ file. Then link with your new extended
 run-time library using IMPORT.OBJ as the first object file. This helps
 LINK understand that there are more support routines than the standard
 run-time library. The following is an example:

    LINK IMPORT.OBJ+PROG2.OBJ,PROG2.EXE,,NEWRUN.LIB/NOD;

 This produces the .EXE file PROG2.EXE, which requires the NEWRUN.EXE
 extended run-time library to run.


 19. Asynchronous SHELL Leaves Cursor Turned Off in New Process

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28157

 The following program starts CMD.EXE as an asynchronous process.
 However, CMD.EXE starts without a cursor visible.

    x=SHELL("CMD.EXE")

 This is because there can be only one cursor on the screen at a time.
 When you do an asynchronous shell, the shelled program is subordinate
 to the main program that controls the screen/keyboard. Thus the cursor
 displayed is that of the main program. The cursor is turned off
 immediately after the shell (in the main program), so it disappears
 from the screen. If the cursor is explicitly turned on in the main
 program, there will be a cursor in the (asynchronously) shelled
 program.


 20. Bound EXE Must Run on DOS 2.10 Default Drive

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  2-FEB-1990    ArticleIdent: Q27904

 The following is a change/addition to Page 3 of the "Microsoft BASIC
 Compiler 6.0: User's Guide" for Versions 6.00 and 6.00b:

    If you use DOS Version 2.10, note that all bound executable files
    must be run from the default disk drive. (A "bound executable" is a
    Family API application, which can run under OS/2 protected mode,
    OS/2 real mode, or MS-DOS.)

 Note: This correction does not apply to the documentation for
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 because BASIC PDS 7.00 requires DOS Version 3.00 or later.

 For instance, if the default drive is A, the following command does
 not work:

    B:SETUP

 Before running a bound executable file under DOS Version 2.10, you
 should move to the directory and drive that contain that file.

 The above is not a limitation with bound executable files under DOS
 Versions 3.x.

 This information is taken from the README.DOC disk file.


 21. Sample Program That Makes OS/2 CALL DosSetDateTime

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q27905

 Below is an example of how to make the DosSetDateTime OS/2 call.

 ' The user-defined TYPE and function DECLARE are found in BSEDOSPE.BI
 TYPE DateTime
      Hour        AS STRING*1
      Minutes     AS STRING*1
      Seconds     AS STRING*1
      Hundredths  AS STRING*1
      Day         AS STRING*1
      Month       AS STRING*1
      Year        AS INTEGER
      Timezone    AS INTEGER
      DayOfWeek   AS STRING*1
 END TYPE

 DECLARE FUNCTION DosSetDateTime%(SEG P1 AS DateTime)

 DIM dayt AS DateTime
 CLS
 input "Enter the HOUR : ";h%
 dayt.hour=chr$(h%)
 input "Enter the Minutes : ";m%
 dayt.minutes=chr$(m%)
 input "Enter the Seconds : ";s%
 dayt.seconds=chr$(s%)
 input "Enter the Hundredths : ";hd%
 dayt.hundredths=chr$(hd%)
 input "Enter the Month : ";mn%
 dayt.month=chr$(mn%)
 input "Enter the Date  : ";dt%
 dayt.day=chr$(dt%)
 input "Enter the Year  : ";yr%
 dayt.year=yr%
 input "Enter the TimeZone (number of hours from Greenwich Mean Time) : ";tz%
 dayt.timezone=tz%*60%

 x=DosSetDateTime%(dayt)

 IF (x) THEN
   Print "An error occurred.  The error number is : ";x
 ELSE
   print "The system time and date have been reset."
 END IF
 END


 22. CALLing Pascal and FORTRAN Modules in QuickBASIC Programs

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q27906

 The following information is from the README.DOC disk file for
 Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2. This
 information also applies to BASIC compiler 6.00b, to Microsoft BASIC
 Professional Development System (PDS) Version 7.00, and to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS (and is also found in the
 README.DOC disk file for all these products except BASIC PDS 7.00).

 Modules compiled with Microsoft Pascal or FORTRAN can be linked with
 compiled BASIC programs, as described in the "Microsoft Mixed-Language
 Programming Guide" (which comes with Microsoft Macro Assembler
 Versions 5.00 and 5.10 or Microsoft C Versions 5.00 and 5.10). These
 modules can also be incorporated in Quick libraries for use in the
 QuickBASIC QB.EXE or BASIC PDS 7.00 QBX.EXE environments. However,
 BASIC programs containing code compiled with Microsoft Pascal must
 allocate at least 2K of near-heap space for Pascal. This can be done
 using the DIM statement to allocate a static array of 2K or greater in
 the NMALLOC named common block, as shown in the following example:

    DIM name%(2048)
    COMMON SHARED /NMALLOC/ name%()

 The Pascal run time assumes it always has at least 2K of near-heap
 space available. If the Pascal code cannot allocate the required
 space, BASIC may hang. This applies to Pascal code in Quick libraries
 as well as to Pascal code linked into executable files. The situation
 is similar for FORTRAN I/O, which also requires near buffer space, and
 which can be provided by the same means as the Pascal near malloc
 space.


 23. MS-DOS 3.20 Patch for Coprocessor Math Exceptions in BC and QB

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified: 22-JAN-1990    ArticleIdent: Q27911

 The information below is taken from the following files, and only
 applies to the product versions shown:

 1. The README.DOC file from the Program Disk of Microsoft BASIC
    Compiler Versions 6.00 and 6.00b for MS-DOS

 2. The UPDATE.DOC file from the Program Disk for QuickBASIC Version
    4.00b

 Note: This information was not included with Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS (except
 for a brief mention in the PACKING.LST file) but it still applies
 since PATCH87.EXE is shipped with BASIC PDS 7.00.

 This article is relevant only if your system has all of the following
 characteristics:

 1. Uses MS-DOS Version 3.20

 2. Boots from a hard-disk drive

 3. Has a math coprocessor (for instance, an 8087 or 80287 chip)

 4. Runs programs that use floating-point math

 The following DOS patch is not necessary if you have PC-DOS; the patch
 only applies to MS-DOS. (Attempting to patch PC-DOS may give you an
 error such as the following: "File Not Found: IO.SYS".)

 For systems that satisfy all of the preceding conditions, you may be
 able to eliminate floating-point math problems by installing a small
 patch in DOS. The problem that usually arises is hanging when a math
 exception occurs. Math exceptions are items such as "divide by zero"
 or "overflow" errors. If you are not sure whether you need the patch,
 perform the following steps:

 1. Copy the program PATCH87.EXE (included in this release) to the
    root directory of your hard-disk drive.

 2. Reboot your system from the hard disk, and do not perform any
    floppy-disk operations after rebooting. It is very important
    that you avoid floppy-disk I/O after rebooting because that will
    affect the reliability of the diagnostic test that you are about
    to perform.

 3. If necessary, use the CD command to move to the root directory
    of your hard-disk drive.

 4. Run the PATCH87.EXE program by entering the following command at
    the DOS prompt:

       PATCH87

 5. The program performs a diagnostic test on your system to determine
    whether it needs the DOS patch, and if the patch is needed, whether
    the patch can be installed successfully. If the program tells you
    that you need to install the DOS patch, and that it can be done,
    follow the procedure described in the next section.

 Please note that the floating-point problem has been eliminated in
 versions of MS-DOS later than Version 3.20. This includes MS-DOS
 Versions 3.21 and 3.30. If you performed the preceding test and
 determined that you should install the DOS patch on your system,
 perform the following steps:

 1. Format a blank floppy disk. (Do not use the /s formatting option to
    transfer system files to the disk.)

 2. Use the SYS command to copy IO.SYS and MS-DOS.SYS from the root
    directory of your hard disk to the new floppy disk. For instance,
    if you boot from Drive C, enter the following commands:

       C: SYS A:

 3. Use the COPY command to copy COMMAND.COM and SYS.COM to the same
    floppy disk.

 4. Use the COPY command to copy the program PATCH87.EXE (included in
    this release) to the same floppy disk.

 5. Change the current drive and directory to the floppy disk by
    entering the following command:

       A:

 6. Install the DOS patch by entering the following command:

       PATCH87 /F

 Please note that if you experience any disk errors during Steps 2
 through 6, do not proceed with Step 7. Reboot from your hard disk and
 repeat the entire process.

 7. If you have not experienced any errors, use the SYS command to
    transfer the files IO.SYS and MS-DOS.SYS from the floppy disk back
    to your hard disk. For instance, if the boot directory of your
    system is the root directory of Drive C, enter the following
    command at the DOS prompt:

       A: SYS C:

 8. The DOS patch has been installed. Reboot the system.


 24. BASIC 6.00 & 7.00 Can't Make Family API (Bound) Applications

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified: 22-JAN-1990    ArticleIdent: Q27921

 Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2 cannot
 create "bound" applications (Family API applications). (A given bound
 EXE application can run under OS/2 protected mode, OS/2 real mode,
 and/or MS-DOS.) The compiler can only create EXE files that run under
 either OS/2 protected mode or real mode but not both. ("Real mode"
 includes both the DOS 3.x-compatibility box in OS/2, and straight
 MS-DOS.)

 To have the functionality of BASIC, the BASIC run-time module contains
 routines that are outside OS/2's Family API (Applications Programming
 Interface).


 25. EGA and VGA Graphics Are Not Supported in OS/2 Protected Mode

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q27925

 EGA and VGA graphics are not supported in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b and Microsoft BASIC Professional Development
 System (PDS) Version 7.00 programs in the protected mode of OS/2.
 (Note also that COLOR is ignored in SCREEN 1.)

 The BASIC compiler talks directly to the hardware to perform EGA or
 VGA graphics. Applications that sit in OS/2 "ring 4" are not allowed
 to perform EGA or VGA graphics in the protected mode of OS/2.

 If the application needs to talk to the hardware, it must go through a
 device driver. There is currently not a device driver for EGA or VGA
 graphics in OS/2 protected mode.


 26. QBX /NOF (NOFrills) Option Saves 19K, Not 22K in BASIC 7.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 31-JAN-1990    ArticleIdent: Q58218

 The "Microsoft BASIC 7.0: Getting Started" manual incorrectly states
 on Page 15 that the /NOFrills command-line option for QBX.EXE reduces
 memory usage by 22K.

 However, the manual correctly states on Page 16 that QBX actually uses
 about 19K less memory with the /NOF command-line option.

 This information applies to QBX.EXE in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS.

 Please note that the /NOF option for QBX.EXE is unrelated to the /NOF
 (/NOFarcalls) option for the linker (LINK.EXE) in BASIC PDS 7.00.


 27. Routines Compiled /FPa (Alt. Math) Can't Be in Quick Library

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified:  4-SEP-1990    ArticleIdent: Q27928

 The linker error message "L2025: Symbol defined more than once" occurs
 when you attempt to create a Quick library (LINK /Q) from .OBJ modules
 that were compiled with the alternate math package (BC /FPa) option.

 Routines compiled with BC /FPa (the alternate math package switch)
 cannot be placed into a Quick library because the QB.EXE or QBX.EXE
 environment does not support the use of the alternate math package.
 The QuickBASIC and QuickBASIC extended environments support only the
 IEEE coprocessor-emulation math package (/FPi). The alternate math
 package (/FPa) is only supported in compiled EXE programs.

 This information applies to the QB.EXE environment supplied with
 Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS, and to
 the QBX.EXE environment supplied with Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10.

 The purpose of the alternate floating-point math package is to provide
 faster floating-point calculations on computers that do not have a
 coprocessor. The alternate math package is significantly faster than
 the IEEE coprocessor-emulation math package when run on a computer
 without a coprocessor installed.

 Note that the alternate math package is about 50 percent slower than
 the Microsoft Binary Format (MBF) floating-point math found in the
 noncoprocessor version of QuickBASIC versions 3.00 and earlier.
 (QuickBASIC versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler
 versions 6.00 and 6.00b, and Microsoft PDS versions 7.00 and 7.10 only
 offer support for the older MBF math with a /MBF compiler option and
 some MBF numeric conversion functions. These BASIC versions have
 adopted IEEE and alternate math to be compatible with the other
 Microsoft language products [FORTRAN, Pascal, and C] and to support
 the math coprocessor.)

 For the greatest speed, applications should be compiled with the BC
 /FPi switch and run on a computer with a coprocessor installed.


 28. Cannot Create Dynamic Link Libraries from BC 6.00 Modules

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q27929

 Under MS OS/2 protected mode, you cannot create dynamic link libraries
 (DLLs) out of BASIC modules created with Microsoft BASIC Compiler
 Version 6.00 or 6.00b or Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 The following are a number of fundamental reasons why you cannot
 create dynamic link libraries out of compiled BASIC programs:

 1. Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft
    BASIC PDS Version 7.00 code is not reentrant.

 2. These compilers assume that the data (DS) and stack (SS) segments
    are the same, which is not allowed in a .DLL.

 3. Compiled BASIC routines cannot be called directly from an EXE
    written in another language, since a BASIC EXE must be the
    initiating program. This is not compatible with a dynamic link
    library.

 However, you can add your own BASIC routines to the BASIC run-time
 module with the BUILDRTM utility provided with BASIC compiler Versions
 6.00 and 6.00b and Microsoft BASIC PDS 7.00. The BASIC run-time module
 is a dynamic link library.

 BASIC compiler routines can also call routines contained in dynamic
 link libraries other than the BASIC run-time library.


 29. Sample Program That Makes OS/2 Call DosGetDateTime

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q27931

 Below is a sample program that CALLs the OS/2 routine DosGetDateTime.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 ' The user-defined TYPE and function DECLARE are found in
 ' BSEDOSPE.BI

 TYPE DateTime
      Hour        AS STRING*1
      Minutes     AS STRING*1
      Seconds     AS STRING*1
      Hundredths  AS STRING*1
      Day         AS STRING*1
      Month       AS STRING*1
      Year        AS INTEGER
      Timezone    AS INTEGER
      DayOfWeek   AS STRING*1
 END TYPE

 DECLARE FUNCTION DosGetDateTime%(SEG P1 AS DateTime)
 DECLARE FUNCTION FDAY$ (x%)

 DIM dayt AS DateTime
 CLS
 x=DosGetDateTime%(dayt)

 IF (x) THEN
   Print "An error occurred.  The error number is : ";x
 ELSE
   t$=str$(asc(dayt.hour))+":"+str$(asc(dayt.minutes))+":"_
      +str$(asc(dayt.seconds))  +":"+str$(asc(dayt.hundredths))

   d$=str$(asc(dayt.month))+"/"+right$(str$(asc(dayt.day)),2)_
       +"/"+right$(str$(dayt.year),4)

   Print "TIME : ";t$
   Print "DATE : ";d$
   print "Number of hours from Greenwich Mean Time : ";(dayt.timezone)/60%
   print "The day of the week : "; fday$(asc(dayt.dayofweek))
 END IF
 end

 FUNCTION FDAY$(x%) STATIC

 SELECT CASE x%
    case 0
        fday$="Sunday"
    case 1
        fday$="Monday"
    case 2
        fday$="Tuesday"
    case 3
        fday$="Wednesday"
    case 4
        fday$="Thursday"
    case 5
        fday$="Friday"
    case 6
        fday$="Saturday"
    case else
        fday$="XXXXXXXXX"
   END SELECT
 END FUNCTION


 30. Sample Program That Makes OS/2 Call to DosChdir

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q27936

 The following sample program makes an OS/2 call to DosChdir.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for MS OS/2.

 ' The function declaration is found in BSEDOSFL.BI

 DECLARE FUNCTION DosChdir%(_
                  BYVAL P1s AS INTEGER,_
                  BYVAL P1o AS INTEGER,_
                  BYVAL P2 AS LONG)
 DIM a AS LONG

 Input "Enter Directory: ";dr$
 dr$=dr$+chr$(0)
 x%=DosChdir%(varseg(dr$),sadd(dr$),a)
 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   Print "Directory changed for the process."
 END IF
 END


 31. Sample Program That Makes OS/2 Call to DosQCurDir

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q27937

 Below is a sample program that makes an OS/2 call to DosQCurDir.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 ' The function declaration is found in BSEDOSFL.BI

 DECLARE FUNCTION DOSQCURDIR%(_
         BYVAL P1 AS INTEGER,_
         BYVAL P2s AS INTEGER,_
         BYVAL P2o AS INTEGER,_
         SEG P3 AS INTEGER)

 DIM dirp AS STRING*80

 DEFINT a-z

 dpl=80
 number=0

 x=DosQCurDir%(number,varseg(dirp),varptr(dirp),dpl)

 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   dr$=left$(dirp,instr(1,dirp,chr$(0)))
   Print "The DIR path : ";dr$
 END IF
 END


 32. Sample Program That Makes OS/2 Call to DosSetFileMode

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q27938

 Below is a sample program that makes an OS/2 call to DosSetFileMode.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 ' The function declaration is found in BSEDOSFL.BI

 DECLARE FUNCTION DosSetFileMode%(_
                  BYVAL P1s AS INTEGER,_
                  BYVAL P1o AS INTEGER,_
                  BYVAL P2 AS INTEGER,_
                  BYVAL P3 AS LONG)
 DIM c AS LONG

 INPUT "Enter the Filename : ";flname$
 flname$=flname$+chr$(0)
 PRINT "Attributes can be: Normal = 0"
 PRINT "                   Read only = 1"
 PRINT "                   Hidden = 2"
 PRINT "                   System = 4"
 PRINT "                   Directory = 16"
 PRINT "                   Archived = 32"
 INPUT "Enter desired file attribute : ";attr%

 x=DosSetFileMode%(varseg(flname$),sadd(flname$),attr%,c)

 IF (x) THEN
    print "An error has occurred.  The error number is ";x
 ELSE
   print "Attribute has been changed."
 END IF
 END


 33. Sample Program That Makes OS/2 Call to DosMkdir

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q27939

 Below is a sample program that makes a call to the OS/2 DosMkdir
 routine.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 ' The function declaration is found in BSEDOSFL.BI.

 DECLARE FUNCTION DosMkdir%(_
                  BYVAL P1s AS INTEGER,_
                  BYVAL P1o AS INTEGER,_
                  BYVAL P2 AS LONG)

 DIM a AS LONG

 Input "Enter the directory : ";dr$
 dr$=dr$+chr$(0)

 x=DosMkdir(varseg(dr$),sadd(dr$),a)

 IF (x) THEN
    print "An error has occurred.  The error number is ";x
 ELSE
   print "Directory was made"
 END IF
 END


 34. How to Modify the BASIC 6.00 Run-Time Module with BUILDTRM

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  7-FEB-1990    ArticleIdent: Q28020

 Using BUILDRTM, you can modify the default BASIC run-time modules. The
 runtime can be customized to a particular application. You can add
 routines to or delete routines from the BASIC runtime.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2. The
 following are the default run-time module names for the applicable
 products:

    BC 6.00          BC 6.00b        PDS 7.00
    -------          --------        --------

    BRUN60ER.EXE     BRUN61ER.EXE    BRT70ENR.EXE
    BRUN60AR.EXE     BRUN61AR.EXE    BRT70EFR.EXE
                                     BRT70ANR.EXE
                                     BRT70AFR.EXE

 For more information, please refer to Section 3.3 of the "Microsoft
 BASIC Compiler 6.0: User's Guide" for Microsoft BASIC Compiler Version
 6.00 or 6.00b, or Chapter 21 of the "Microsoft BASIC 7.0: Programmer's
 Guide" for Microsoft BASIC PDS Version 7.00.

 The following is an example:

    ===== EXPORT.LST =====

    #OBJECTS
    NOLPT.OBJ
    NOGRAPH.OBJ
    MYROUTINE.OBJ

    #EXPORTS
    myroutine1
    myroutine2
    myroutine3

    ===== COMMAND LINE to CREATE the RUNTIME =====

    BUILDRTM newruntime export.lst

    ===== COMMAND LINE to USE the RUNTIME =====

    LINK IMPORT.OBJ your objects,executable,,NEWRUNTIME.LIB /NOD


 35. MS Floating Point Is Faster Than BC /FPa Alternate Math

 Product Version(s): 6.00 6.00b 7.00  | 6.00 6.00b 7.00
 Operating System:   MS-DOS           | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28023

 An EXE compiled with the Alternate Math package (BC /FPa) performs
 floating-point calculations more slowly than an EXE compiled with
 QuickBASIC Versions 3.00 and 2.x Microsoft Floating Point.

 However, an EXE compiled with the alternate math package is between 40
 and 50 percent faster than an EXE compiled with IEEE Floating Point
 (with no /FPa switch) when run on a computer that does not have a
 coprocessor.

 Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 do not support
 Microsoft Floating Point. If you want the greatest floating-point
 speed on a computer that does not have a coprocessor, compile with the
 BC /FPa switch. ("FPa" stands for "Floating Point Alternate-Math
 Library"). If you want the greatest floating-point speed on a computer
 that has a coprocessor, compile with the BC /FPi switch. ("FPi" stands
 for "Floating Point In-line Instructions"). In-line Instructions is
 the default when you compile with BC and without /FPa or /FPi switch.

 Microsoft Floating Point is an older format found in the
 noncoprocessor version of QuickBASIC Version 3.00. It also is found in
 all prior versions of QuickBASIC (Versions 2.10, 2.00, 1.02, 1.01,
 1.00).

 Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft BASIC
 PDS Version 7.00 do not support Microsoft Floating Point. These
 products have adopted IEEE and Alternate Math in order to be linkable
 with FORTRAN, PASCAL, and C.

 Compiling with BC /FPa gives you the Alternate Math floating-point
 format. (The QuickBASIC interpreter uses only IEEE and cannot use
 Alternate Math.)

 Compiling without /FPa gives you IEEE floating-point format. IEEE
 floating-point format is fastest when run on a computer that has a
 coprocessor installed.


 36. EXE May Be Slower in OS/2 Protected Mode than in DOS

 Product Version(s): 6.00 6.00b 7.00  | 6.00 6.00b 7.00
 Operating System:   MS-DOS           | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28024

 Because of the event scheduling in OS/2, programs run under protected
 mode may run more slowly than they did under DOS. This is expected
 behavior.

 Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 are all capable of
 compiling programs to run under OS/2 protected mode.


 37. SETUP Program Can Create Subdirectory Only If Parent Exists

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  7-FEB-1990    ArticleIdent: Q28027

 The SETUP.EXE program can create a subdirectory only if the parent
 directory already exists. For example, if you want to place the
 library files in a subdirectory named \BC6\LIB, the directory \BC6
 must exist before SETUP is run.

 This information applies to the SETUP.EXE program in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2, Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2, and Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50 for the
 MS-DOS.

 This is also a limitation of DOS. You cannot use the MKDIR command to
 create a subdirectory in a directory that does not exist.


 38. QB Fast Load Format Source Code Cannot Be Used in MS CodeView

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER |
 Last Modified: 17-JAN-1991    ArticleIdent: Q28030

 Microsoft CodeView is not able to read the QuickBASIC source file if
 it is saved in Fast Load format. If you plan to use the Microsoft
 CodeView debugger, be sure that the source file is saved in ASCII
 format.

 To save a file in ASCII format, use the Save As command on the File
 menu in the QB.EXE environment of Microsoft BASIC Compiler version
 6.00 or 6.00b, or in the QBX.EXE environment of Microsoft BASIC
 Professional Development System (PDS) version 7.00 or 7.10.

 To compile a BASIC program for use with CodeView, follow these steps:

 1. BC filename /Zi [other switches]

 2. LINK filename /Co [other switches]


 39. No "Incompatible Runtime" CHAIN Error with Mismatched COMMON

 Product Version(s): 6.00   | 6.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 runtime
 Last Modified: 30-MAY-1990    ArticleIdent: Q28038

 The problem under Microsoft BASIC Compiler version 6.00 and 6.00b is
 as follows:

 1. A routine that has a blank COMMON block is built into a custom
    run-time module with BUILDRTM.EXE.

 2. Main1 contains the same blank COMMON (matched exactly in length).

 3. Main2 contains the same blank COMMON plus some more blank COMMON.

 4. Main3 contains the same blank COMMON as Main2.

 5. Main1 chains to Main2, which puts something in the EXTENDED portion
    of COMMON, then chains to Main3. Main3 expects something to be
    there, but it is gone.

 There should be an error on the chain to Main2 since we cannot enlarge
 blank COMMON when there is a set size of blank COMMON in the custom
 run-time module. An error should have been generated during the chain.
 When Main2 is run as a stand alone, the "incompatible runtime module"
 error message appears.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Compiler versions 6.00 and 6.00b, and in Microsoft BASIC Professional
 Development System (PDS) version 7.00. We are researching this problem
 and will post new information here as it becomes available.

 When using Microsoft BASIC PDS version 7.00 for MS-DOS and MS OS/2,
 any inclusion of a COMMON block into a custom run-time module will
 result in an "incompatible runtime module" error, even if the COMMON
 statement(s) in the run-time match the COMMON in the program(s).
 If you link IMPORT.OBJ as the first .OBJ file on the link line,
 this is not a problem.

 The following is code example for Microsoft BASIC Compiler versions
 6.00 and 6.00b:

 MAIN1:

   common a,b,c     'This COMMON matches the COMMON in the custom run time
   a=1
   b=2
   c=3
   chain "main2"
   end

 MAIN2:

   common a,b,c,d,e  'It is not legal to add more elements to the blank
                     'COMMON if you are using a custom run time.
   d=4
   e=5
   chain "main3"
   end

 MAIN3:

   common a,b,c,d,e
   print a,b,c,d,e
   end


 40. LOCATE Has 8 lines Resolution DOS & Real Mode, 16 in Protected

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28042

 The BASIC statement LOCATE X,Y,1,0,7 executed under DOS and real mode
 generates a cursor block eight lines tall. Executing the same
 statement under protected mode generates a small block of a cursor.
 For a full-height cursor under protected mode, the statement must be
 LOCATE X,Y,1,0,15. This is expected behavior and is documented in the
 "Microsoft BASIC 7.0: Language Reference" on Page 196.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.


 41. Misleading QB.EXE Message Using Reserved Word in SUB

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q28158

 Illegally using the reserved word "SEG" in a SUB statement can give
 you a misleading error message.

 To generate the misleading message, start up the QB.EXE environment of
 Microsoft BASIC Compiler Version 6.00 or 6.00b or Microsoft QuickBASIC
 Version 4.00, 4.00b, or 4.50, and type the following:

    SUB foo(SEG x AS INTEGER)

 The environment highlights the SEG keyword and returns the following:

    Expected: variable or BYVAL or SEG or )

 This is because the parser correctly detects that SEG is illegal in a
 SUB statement, but shares the error message with DECLARE, so SEG is
 misleadingly listed as "expected."

 This error message has been clarified in the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2. This situation now produces the following error,
 indicating that the SEG keyword is not allowed in that context:

    Expected: parameter or )


 42. QB /L A: Does Not Find QB.QLB If SET LIB=A: Is Not Set

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28160

 Problem:

 If the default Quick library file QB.QLB is on Drive A and no LIB
 environment variable is set, then the following command line fails to
 find QB.QLB:

    QB /L A:

 Response:

 This is how the Quick library search is supposed to work. If no
 argument is given to the /L switch, QB.EXE looks for a filename of
 QB.QLB. Otherwise, if you specify a drive such as Drive A, QB.EXE
 assumes that you are specifying a Quick library name other than
 QB.QLB.

 The following are easy workarounds:

 1. Specify QB /L A:QB, which is only two characters longer.

 2. An alternate workaround is to perform the following command from
    the DOS command line before running QB /L:

       SET LIB=A:


 43. Missing END IF in FOR NEXT Gives Different Errors in QB and BC

 Product Version(s): 6.00 6.00b 7.00   | 6.00 6.00b 7.00
 Operating System:   MS-DOS            | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28162

 The following program gives a "NEXT without FOR" error in QB.EXE and
 the QBX.EXE environment shipped with Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS, and a "BLOCK IF
 WITHOUT END IF" error from an EXE compiled in BC.EXE (the following is
 a code example):

    for i=1 to 10
       if x=10 then
         a=c
       else
          d=c
     next i

 Both error messages are correct, depending on how you view the program.
 This feature will not be changed.


 44. Unexpected PRINT USING ".##" Rounding for .xx5

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28163

 Problem:

 For the following statement

    PRINT USING " ###.##"; .245, .255, .265, .275, .285

 the output is as follows

    0.25  0.25  0.26  0.28  0.28

 whereas you would expect the following

    0.25  0.26  0.27  0.28  0.29

 or with IEEE rounding, you would expect the following:

       0.24  0.26  0.26  0.28  0.28

 Response:

 The internal representation of the numbers used by BASIC differs
 slightly from the decimal numbers typed into the source code.

 IEEE floating-point format cannot accurately represent numbers that
 are not of the form 1.x to the power of y (where x and y are base 2
 numbers). The internal representation will be slightly more or
 slightly less than the decimal numbers typed into the source code.

 The internal representations are correctly rounded and displayed. This
 is not a software problem.


 45. "String Formula Too Complex" with Recursive String Function

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q28165

 The program below, which recursively invokes a string function, causes
 a "String Formula Too Complex" run-time error. This program shows a
 design limitation in Microsoft BASIC Compiler Version 6.00 and 6.00b,
 Microsoft BASIC Professional Development System (PDS) Version 7.00,
 and in QuickBASIC that is not usually encountered.

 In the following program, QuickBASIC is computing RIGHT$(TEXT$,1),
 assigning the value to a temporary string descriptor, and then
 recursing on REVERSE$(LEFT$(TEXT$,LEN(TEXT$)-1)):

    DECLARE FUNCTION Reverse$ (Text$)
    CLS
    PRINT Reverse$ ("123456789 1234567890")

    FUNCTION Reverse$ (Text$)
    IF LEN(Text$) = 0 THEN
      EXIT FUNCTION
    ELSE
      Reverse$ = RIGHT$(Text$, 1) + Reverse$ (LEFT$(Text$, LEN(Text$) -1))
    END IF
    END FUNCTION

 The temporary string descriptor is not released until the recursion is
 completed. Each recursive REVERSE$ function call locks one string
 descriptor. Because QuickBASIC allows only 20 temporary descriptors
 (more than enough for most applications), after around 20 function
 calls the program gives the error "String Formula Too Complex."

 The workaround is to use a real string descriptor as follows (which
 will be allocated from stack space):

    Temp$ = Reverse$(LEFT$(Text$,LEN(Text$)-1))
    Reverse$ = RIGHT$(Text$,1) + Temp$


 46. QB Uses Up Default String Space When Concatenating Far String

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q28166

 Problem:

 When running the program below inside the QB.EXE environment, after
 about 72 iterations of concatenating a variable-length string onto a
 fixed-length string, an "Out of String Space" error is generated.
 However, the FRE("") and FRE(-1) functions both return the same value
 all the way through the loop. Note that the array of fixed-length
 strings is dynamically allocated, putting it into the far heap.

 The program runs properly when compiled and run as an EXE file.

 Response:

 The problem is that QuickBASIC assumes that a far fixed-length string
 will always stay far.

 However, the BASIC run-time routines must have the string in DGROUP in
 order to manipulate it with string functions like LTRIM$ and RTRIM$.
 LTRIM$ and RTRIM$ require two copies of the string at one point, and
 the program eventually runs out of string space in the default data
 segment in DGROUP. This will also happen in a version of the program
 compiled with BC /O if the strings are made longer. This limitation of
 BASIC is inherent in its construction, and Microsoft currently has no
 plans to change this construction.

 The following is a code example:

    REM $DYNAMIC
    DIM srv(0) AS STRING * 28000

    abc$ = STRING$(330,"0")

    srv(0) = abc$
    FOR t = 1 to 79
       srv(0) = RTRIM$(srv(0)) + abc$
       PRINT t, LEN(RTRIM$(srv(0))), FRE(""), FRE(-1)
    NEXT t


 47. A RETURN Without a GOSUB in a Subprogram Hangs in EXE

 Product Version(s): 6.00    | 6.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 11-JUL-1990    ArticleIdent: Q28154

 Executing a RETURN statement without a corresponding GOSUB in a
 subprogram hangs an EXE program when compiled without the BC /D
 option. You must compile with the BC /D option (or compile in the
 QuickBASIC environment) to trap a "RETURN without GOSUB" programming
 error (just as you must use BC /D to trap array bounds violations).

 This information applies to BC.EXE in Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, to BC.EXE in Microsoft
 BASIC Professional Development System (PDS) version 7.00 for MS-DOS
 and MS OS/2, and to BC.EXE in QuickBASIC versions 4.00, 4.00b, and
 4.50 for MS-DOS.

 Compile the test program below with BC.EXE and then link it. If you
 compile with the BC /D option, the program gives run-time error,
 "RETURN without GOSUB." If you don't compile with /D, the program
 hangs the computer at run time without telling you about your
 programming mistake.

 To avoid hanging due to a programming error like this, use the QB.EXE
 or QBX.EXE environment as a debugger, since the interpreter
 environment correctly traps the "Return without GOSUB" error. The
 program should be modified to remove the "Return without GOSUB"
 programming error.

 Code Example
 ------------

 ' test.bas
    defint a-z
    declare sub atest ( x )

      i = 1
      print i
      call atest (i)
      print i
    end

    sub atest ( j )
       print j
       j = 2
       print j
       return
    end sub


 48. BC 6.00 Example Calling OS/2 API Function DosSetMaxFH

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35906

 Below is a sample program that makes a call to the MS OS/2 function
 DosSetMaxFH. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS OS/2.

 By default, 20 file handles are allocated to a file. To increase the
 number of file handles available, the DosSetMaxFH function must be
 called. The maximum number of file handles is 255. When determining
 the required number of handles, add several for dynamic-link modules
 (these modules use several handles), and three more for the default
 system I/O handles.

 The following is a code example:

 'This information is found in BSEDOSFL.BI
 DECLARE FUNCTION DOSSETMAXFH%(BYVAL P1 AS INTEGER)

 INPUT "Enter the maximum number of file handles : ",fh%
 x=DosSetMaxFH%(fh%)

 IF (x) THEN
    Print "An error occurred.  The error number is ";x
 ELSE
    Print "Maximum number of file handles has been changed."
 END IF

 ON ERROR GOTO DONE

 for i = 1 to 255
   fl$="xxxxx"+mid$(str$(i),2,len(str$(i)))
   open fl$ for output as i
 next i
 stop

 done:
   Print i

 end


 49. It Is Illegal to Pass a CONST Type Constant in COMMON

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28283

 A user-defined CONST constant cannot be passed in COMMON.

 CONST constants never need to be passed in COMMON since you can put
 the CONST definitions in a $include file to include for use in any
 desired module.

 A given user-defined CONST constant is local to each separately
 compiled module, and can be used throughout a given source file.

 The following is an example of illegally passing a CONST type symbol
 in COMMON. In the QB.EXE environment that comes with Microsoft BASIC
 Compiler Versions 6.00 and 6.00b or in the QBX.EXE environment
 supplied with Microsoft BASIC Professional Development System (PDS)
 Version 7.00, the following program correctly gives a "duplicate
 definition" error on x in the COMMON SHARED:

    CONST x = 5
    COMMON SHARED x, y, z   ' "duplicate definition" error for x
    TYPE person
      test AS STRING * x
    END TYPE
    DIM joe AS person

 Please note that when you use STRING * x, x must be a CONST type or a
 numeric constant, according to the "Microsoft QuickBASIC 4.0: BASIC
 Language Reference" manual on Page 430.

 The following shows how the above program can be modified to work
 correctly:

    CONST x = 5
    COMMON SHARED y, z
    TYPE person
      test AS STRING * x
    END TYPE
    DIM joe AS person


 50. OS/2 Protected Mode Restrictions for BASIC Compiler 6.00/6.00b

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28442

 The following is a list of restrictions under MS OS/2 protected mode
 for Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft
 BASIC Professional Development System (PDS) Version 7.00:

  1. Programs using statements that refer directly to addresses in the
     machine's physical memory may need modification when run in
     protected mode, for example, CALL ABSOLUTE, DEF SEG, PEEK, POKE,
     BLOAD, BSAVE, VARPTR, and VARSEG.

  2. Graphics are limited to screens 1 and 2. EGA and VGA graphics are
     not supported in protected mode.

  3. Except for BEEP, no sound is supported. SOUND or PLAY statements
     are not allowed in protected mode. As a workaround, you can make
     an OS/2 CALL to create a sound with a specified frequency and
     duration.

  4. Light pens and joysticks are not allowed in protected mode.

  5. CALL INT86, INT86OLD, INT86X, INTERRUPT, and INTERRUPTX are not
     available in protected mode.

  6. COLOR is ignored in Screen 1 in protected mode.

  7. INP and OUT are not available in protected mode.

  8. IOCTL and IOCTL$ are not available in protected mode.

  9. PALETTE [USING] is not available in protected mode.

 10. WAIT is not available in protected mode.

 11. If a program in real mode is using the serial communications port
     (COM1 or COM2), then you cannot use that port in protected mode at
     the same time. This is an OS/2 restriction. The reverse is also
     true: if a program in protected mode is using the communications
     port (COM1 or COM2), then you cannot use that port in real mode at
     the same time.


 51. Example of Calling OS/2 Function DosRmDir

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28443

 The following is a sample program that makes OS/2 call to DosRmDir:

 ' The DosRmDir FUNCTION declaration is found in the file BSEDOSFL.BI

    DECLARE FUNCTION DosRmDir%(_
            BYVAL P1s AS INTEGER,_
            BYVAL P1o AS INTEGER,_
            BYVAL P2 AS LONG)

    DIM a AS LONG

    Input "Enter Directory to be removed : ";dr$
    dr$=dr$+chr$(0)

    x=DosRmdir(varseg(dr$),sadd(dr$),a)
    IF (x) THEN
       print "An error has occurred.  The error number is ";x
    ELSE
       print "Directory ";dr$;" was REMOVED"
    END IF
    END


 52. Example of Calling OS/2 DosGetVersion and DosGetMachineMode

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28444

 Below is a sample program that makes calls to the OS/2 functions
 DosGetVersion and DosGetMachineMode.

 ' The function declarations are found in BSEDOSPC.BI

 DECLARE FUNCTION DosGetVersion%(_
         SEG P1 AS INTEGER)

 DECLARE FUNCTION DosGetMachineMode(_
         BYVAL P1s AS INTEGER,_
         BYVAL P1o AS INTEGER)

 DEFINT A-Z
 CLS
 DIM mode AS STRING*1

 x=DosGetMachineMode%(varseg(mode),varptr(mode))
 IF (x) THEN
    Print "An error occurred. The number is : ";x
 ELSE
    IF mode=chr$(0) THEN
       print "Real Mode"
    ELSE
       print "Protect Mode"
    END if
 END IF

 x=DosGetVersion(version)
 IF (x) THEN
    Print "An error occurred. The number is : ";x
 ELSE
    Print "The version number is : ";
    Print  peek(varptr(version)+1);".";peek(varptr(version))
 END IF


 53. Example of Calling OS/2 DosSetFSInfo and DosQFSInfo

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28445

 Below is a sample program that makes OS/2 calls to DOSSetFSInfo and
 DOSQFSInfo.

 ' The function declarations are found in file BSEDOSFL.BI

 TYPE FSAllocate1
      Filesysid    AS LONG
      SecPerUnit   AS LONG
      NumUnits     AS LONG
      AvailUnits   AS LONG
      ByteSec     AS INTEGER
 END TYPE

 TYPE FSAllocate2
      VolumeDate  AS INTEGER
      VolumeTime  AS INTEGER
      VLen        AS STRING*1
      VLabel      AS STRING*11
 END TYPE

 TYPE SetInfo2
      Vlen        AS STRING*1
      VLabel      AS STRING*11
 END TYPE

 DECLARE FUNCTION DOSSetFSInfo%(_
         BYVAL P1 AS INTEGER,_
         BYVAL P2 AS INTEGER,_
         BYVAL P3s AS INTEGER,_
         BYVAL P3o AS INTEGER,_
         BYVAL P4 AS INTEGER)

 DECLARE FUNCTION DOSQFSInfo%(_
         BYVAL P1 AS INTEGER,_
         BYVAL P2 AS INTEGER,_
         BYVAL P3s AS INTEGER,_
         BYVAL P3o AS INTEGER,_
         BYVAL P4 AS  INTEGER)

 'Routine to Shift and Print Information

 DECLARE FUNCTION wdate$(p1 as integer)
 DECLARE FUNCTION wtime$(p1 as integer)
 DECLARE FUNCTION RightShift%(P1 as LONG,P2 as Integer)
 DECLARE FUNCTION LeftShift%(P1 as LONG, P2 as Integer)
 DECLARE FUNCTION unsigned&(P1 as integer)

 DEFINT a-z
 DIM info1 AS FSAllocate1
 DIM info2 AS FSAllocate2
 DIM info3 AS SetInfo2
 cls

 Input "Enter Drive Number (0=default, 1=A, etc) : ",drivenumber
 level = 1
 bufsize=18

 x = DosQFSInfo%(drivenumber,level,varseg(info1),varptr(info1),bufsize)

 print
 Print "Level One Information"
 print
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "File System ID : ";info1.Filesysid
    print "Number of sectors per allocation unit : ";info1.secperunit
    print "Number of allocation units : ";info1.numunits
    print "Available allocation units : ";info1.availunits
    print "Bytes per sector : ";info1.bytesec
 END IF

 level=2
 bufsize=16
 print
 Print "Level Two Information"
 print

 x = DosQFSInfo%(drivenumber,level,varseg(info2),varptr(info2),bufsize)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    PRINT "Volume Creation Date : ";wdate$(info2.VolumeDate)
    PRINT "Volume Creation Time : ";wtime$(info2.VolumeTime)
    PRINT "Length of Label : ";asc(info2.Vlen)
    PRINT "Volume Label : ";info2.Vlabel
 END IF

 print
 input "Enter the new VOLUME name : ";info3.Vlabel
 info3.vlen=chr$(len(info3.vlabel))
 info3.vlabel=info3.vlabel+chr$(0)
 level=2
 bufsize=12

 x = DosSetFSInfo%(drivenumber,level,varseg(info3),varptr(info3),bufsize)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    Print "The volume label is changed."
    level=2
    bufsize=16
    print
    Print "Level Two Information"
    print
    x = DosQFSInfo%(drivenumber,level,varseg(info2),varptr(info2),bufsize)
    IF (x) THEN
      Print "An error occurred.  The number is : ";x
   ELSE
      PRINT "Volume Creation Date : ";wdate$(info2.VolumeDate)
      PRINT "Volume Creation Time : ";wtime$(info2.VolumeTime)
      PRINT "Length of Label : ";asc(info2.Vlen)
      PRINT "Volume Label : ";info2.Vlabel
   END IF
 END IF

 END

 FUNCTION wdate$(d%) static
 DIM dl AS LONG
     dl=unsigned&(d%)
     mn=(RightShift%(dl,5)) AND (&h0f)
     IF mn < 10 THEN
        mn$="0"+ltrim$(str$(mn))
     ELSE
        mn$=ltrim$(str$(mn))
     END IF
     dy= dl AND (&h1f)
     IF dy < 10 THEN
        dy$="0"+ltrim$(str$(dy))
     ELSE
        dy$=ltrim$(str$(dy))
     END IF
     yr$=str$(RightShift(dl,9)+1980)
     wdate$=mn$+"/"+dy$+"/"+ltrim$(yr$)
 END FUNCTION

 FUNCTION wtime$(d%)
 DIM dl AS LONG
    dl=unsigned&(d%)
    hr=RightShift%(dl,11) AND (&h1f)
    IF hr < 10 THEN
       hr$="0"+ltrim$(str$(hr))
    ELSE
       hr$=ltrim$(str$(hr))
    END IF
    mt=(RightShift%(dl,5) AND (&h3f))
    IF mt < 10 THEN
       mt$="0"+ltrim$(str$(mt))
    ELSE
       mt$=ltrim$(str$(mt))
    END IF
    wtime$=ltrim$(hr$)+":"+mt$+string$(5,32)
 END FUNCTION

 FUNCTION RightShift%(number&,amount)
    Rightshift=number&\2^amount
 END FUNCTION

 FUNCTION LeftShift%(number&,amount)
   LeftShift=number&*(2^amount)
 END FUNCTION

 FUNCTION unsigned&(num)
    IF num >=0 THEN
       unsigned&=num
    ELSE
       unsigned&=65536+num
    END IF
 END FUNCTION


 54. Example of Calling OS/2 Function DosGetEnv

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28446

 Below is a sample program that invokes the OS/2 function DosGetEnv.

 ' The function declarations are found in file BSEDOSPC.BI

 DECLARE FUNCTION DosGetEnv%(_
         SEG P1 AS INTEGER,_
         SEG P2 AS INTEGER)
 cls
 x=DosGetEnv(y%,z%)

 IF (x) then
   Print "An error occurred.  The error number is ";x
 ELSE
   Print "Address to Place Segment Handle : ";y%
   Print "Address to Place Command Line Start : ",z%
 END IF

 def seg = y%

 PRINT "THE INFORMATION IN THE ENVIRONMENT TABLE :" : PRINT

 For i = 0 to z%-20
   t%=peek(i)
   IF t%=42 THEN
      hold%=i
   END IF

   IF t% = 0 THEN
     print " "
   ELSE
     print chr$(t%);
   END IF
 next i
 print
 i = 0
 PRINT "The Command Line Argument is : ";

 DO
  t%=peek(z%+i)
  print chr$(t%);
  i = i + 1
 LOOP WHILE t% <> 0
 PRINT " "

 print
 PRINT "POKING SOME INFORMATION INTO THE ENVIRONMENT TABLE... " : print
 PRINT

 IF hold%<>0 THEN
    for i = 0 to 9
      poke hold%-i, 74-i
    next i
    def seg
    PRINT "The information was poked into the environment variable FOO;"
    PRINT "which was previously set to **********"

    print "The NEW contents of FOO  : ";environ$("FOO") : print
    Print "When the program is exited, notice the environment table";
    Print "isn't changed."
    PRINT "BASCOM uses only a copy of the actual DOS environment table"
    print
 ELSE
    print "The FOO environment variable is not set. "
    print "To have the complete demo, set the FOO=**********"
 END IF
 END


 55. Calling OS/2 DOSInsMessage, DOSGetMessage, DOSPutMessage

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28447

 Below is an example of calling OS/2 DOSInsMessage, DOSGetMessage, and
 DOSPutMessage.

 ' The function declarations are found in file BSEDOSPC.BI

 TYPE ADDRESS
      OFFSET  AS INTEGER
      SEGMENT AS INTEGER
 END TYPE

 DECLARE FUNCTION DOSINSMESSAGE%(_
         BYVAL P1s AS INTEGER,_
         BYVAL P1o AS INTEGER,_
         BYVAL P2  AS INTEGER,_
         BYVAL P3s AS INTEGER,_
         BYVAL P3o AS INTEGER,_
         BYVAL P4  AS INTEGER,_
         BYVAL P5s AS INTEGER,_
         BYVAL P5o AS INTEGER,_
         BYVAL P6  AS INTEGER,_
         SEG   P7  AS INTEGER)

 DECLARE FUNCTION DOSGETMESSAGE%(_
         BYVAL P1s AS INTEGER,_
         BYVAL P1o AS INTEGER,_
         BYVAL P2  AS INTEGER,_
         BYVAL P3s AS INTEGER,_
         BYVAL P3o AS INTEGER,_
         BYVAL P4  AS INTEGER,_
         BYVAL P5  AS INTEGER,_
         BYVAL P6s AS INTEGER,_
         BYVAL P6o AS INTEGER,_
         SEG   P7  AS INTEGER)

 DECLARE FUNCTION DOSPUTMESSAGE%(_
         BYVAL P1  AS INTEGER,_
         BYVAL P2  AS INTEGER,_
         BYVAL P3s AS INTEGER,_
         BYVAL P3o AS INTEGER)

 DEFINT a-z

 DIM VarTable(9) AS ADDRESS   'Array of address of Strings
 VarCount=2
 CLS
 MsgIn$="This is a test.  My Name is %1 %2"+chr$(0)
 MsgInLen=len(MsgIn$)

 DIM MsgOut AS STRING*80

 MsgOutLen=len(MsgOut)
 MsgOut=string$(MsgOutLen-1,32)

 one$="Joe"+chr$(0)
 two$="Smith"+chr$(0)

 VarTable(0).offset=sadd(one$)
 VarTable(0).segment=varseg(one$)
 VarTable(1).offset=sadd(two$)
 VarTable(1).segment=varseg(two$)

 x=DosInsMessage%(varseg(VarTable(0)),varptr(VarTable(0)),VarCount,_
                  varseg(MsgIn$),sadd(MsgIn$),MsgInLen,_
                  varseg(MsgOut),varptr(MsgOut),MsgOutLen,number)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
   print MsgOut
 END IF

 DIM buffer as STRING*80
 BufferLen=80

 'This is a file by the OS/2 Message Utilities.
 'See Microsoft OS/2 Programmer's Guide, Section 20.5, Pages 205-212)

 Filename$="JoeSmith.msg"+chr$(0)

 FOR i = 100 to 104
 x=DosGetMessage%(varseg(VarTable(0)),varptr(VarTable(0)),VarCount,_
                  varseg(buffer),varptr(buffer),BufferLen,_
                  i,varseg(filename$),sadd(filename$),number)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
   x=DosPutMessage(1,number,varseg(buffer),varptr(buffer))
   IF (x) THEN
      Print "An error occurred.  The number is : ";x
   END IF
 END IF
 NEXT i
 locate 10,1

 END


 56. Example Calling OS/2 DosFindFirst, DosFindNext, DosFindClose

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q28448

 Below is an example of calling OS/2 DosFindFirst, DosFindNext, and
 DosFindClose.

 'Declarations found in file BSEDOSFL.BI
 'Compiler options: /D/W (/V requires modifications to the code)
 CONST TRUE=-1
 CONST FALSE=0

 TYPE FILEFINDBUF
         fdateCreation  AS INTEGER
         ftimeCreation  AS INTEGER
         fdateLastAccess AS INTEGER
         ftimeLastAccess AS INTEGER
         fdateLastWrite AS INTEGER
         ftimeLastWrite AS INTEGER
         cbFile         AS LONG
         cbFileAlloc    AS LONG
         attrFile       AS INTEGER
         cchName        AS STRING * 1
         achName        AS STRING * 13
 END TYPE

 DECLARE FUNCTION DosFindFirst%( _
         BYVAL P1s AS INTEGER,_
         BYVAL P1o AS INTEGER,_
         SEG   P2 AS INTEGER,_
         BYVAL P3 AS INTEGER,_
         SEG   P4 AS FILEFINDBUF,_
         BYVAL P5 AS INTEGER,_
         SEG   P6 AS INTEGER,_
         BYVAL P7 AS LONG)

 DECLARE FUNCTION DosFindNext%( _
         BYVAL P1 AS INTEGER,_
         SEG   P2 AS FILEFINDBUF,_
         BYVAL P3 AS INTEGER,_
         SEG   P4 AS INTEGER)

 DECLARE FUNCTION DosFindClose%( _
         BYVAL P1 AS INTEGER)

 'Routines to print Date/Time and File Type

 DECLARE FUNCTION wdate$(p1 as integer)
 DECLARE FUNCTION wtime$(p1 as integer)
 DECLARE FUNCTION RightShift%(P1 as LONG,P2 as Integer)
 DECLARE FUNCTION LeftShift%(P1 as LONG, P2 as Integer)
 DECLARE FUNCTION FileType$(P1 as Integer)

 DEFINT a-z

 COLOR 15,1
 DIM buffer AS FileFindBuf
 DIM filelist(255) as FileFindBuf
 DIM reserved  AS LONG

 CLS
 print "Test of DOSFINDFIRST..."

 INPUT "Enter the Filename(s) : ";flname$
 flname$=flname$+chr$(0)

 atr= 0+2+4+16    'normal + hidden + system + subdirectory
 dirh=1
 searchcount=1
 bufflen=36

 x=DosFindFirst%(varseg(flname$),sadd(flname$),_
                 dirh,atr,buffer,bufflen,searchcount,reserved)
 IF (X=0) THEN
    DO
      counter=counter+1
      filelist(counter)=buffer
      buffer.achname=string$(13,32)  'assign blanks
      buffer.fdatelastwrite=0
      buffer.ftimelastwrite=0
    LOOP WHILE (DosFindNext%(dirh,buffer,bufflen,searchcount) = 0 )
 ELSE
     PRINT "No MATCH was found"
     END
 END IF
 CLS

 print  "FILENAME : "; : LOCATE 1,30 : PRINT "FILE SIZE : ";
 locate 2,1 : PRINT "LAST WRITE DATE : ";
 locate 3,1 : PRINT "LAST WRITE TIME : ";
 locate 4,1 : PRINT "FILE TYPE : ";
 COLOR 5

 i = 1

 done=FALSE

 key 15, chr$(&h00)+chr$(&h01) 'ESC KEY to EXIT
 on key (15) gosub FINISH
 on key (11) gosub UP
 on key (14) gosub DOWN
 key (15) on
 key (11) on
 key (14) on

 locate 20,1 : Print "Enter ESC to quit, UP/DOWN ARROWS to scroll list";

 while (not DONE)
 lp:
  LOCATE 1,14 : PRINT filelist(i).achname;
  LOCATE 1,45 : PRINT filelist(i).cbfile;"/";filelist(i).cbfilealloc;"       "
  LOCATE 2,20 : PRINT wdate$(filelist(i).fdatelastwrite);"        ";
  LOCATE 3,20 : PRINT wtime$(filelist(i).ftimelastwrite);"        ";
  LOCATE 4,15 : PRINT filetype$(filelist(i).attrfile);"       ";
  a$=inkey$
  if a$="" then goto lp
 wend

 color 15
 x=DosFindClose%(dirh)
 IF (x) THEN
   color 7 : PRINT "An error occurred. The number is : ";x : color 15
 ELSE
   color ,0
   cls
 END IF
 END
 STOP

 FINISH:
    DONE = TRUE
    RETURN
    STOP
 UP:
    IF i = 1 THEN
       locate 24,1
       color 7
       print "At the top of the list                       ";
       color 5
    ELSE
       locate 24,1 : print string$(78,32);
       i = i - 1
    END IF
    RETURN
    STOP
 DOWN:
    IF i = counter THEN
       locate 24,1
       color 7
       Print "At the bottom of the list                  ";
       color 5
    ELSE
       i = i + 1
       locate 24,1 : print string$(78,32);
    END IF
    RETURN
    STOP

 FUNCTION wdate$(d%) static
 DIM dl AS LONG
     dl=unsigned&(d%)
     mn=(RightShift%(dl,5)) AND (&h0f)
     IF mn < 10 THEN
        mn$="0"+ltrim$(str$(mn))
     ELSE
        mn$=ltrim$(str$(mn))
     END IF
     dy= dl AND (&h1f)
     IF dy < 10 THEN
        dy$="0"+ltrim$(str$(dy))
     ELSE
        dy$=ltrim$(str$(dy))
     END IF
     yr$=str$(RightShift(dl,9)+1980)
     wdate$=mn$+"/"+dy$+"/"+ltrim$(yr$)
 END FUNCTION

 FUNCTION wtime$(d%)
 DIM dl AS LONG
    dl=unsigned&(d%)
    hr=RightShift%(dl,11) AND (&h1f)
    IF hr < 10 THEN
       hr$="0"+ltrim$(str$(hr))
    ELSE
       hr$=ltrim$(str$(hr))
    END IF
    mt=(RightShift%(dl,5) AND (&h3f))
    IF mt < 10 THEN
       mt$="0"+ltrim$(str$(mt))
    ELSE
       mt$=ltrim$(str$(mt))
    END IF
    wtime$=ltrim$(hr$)+":"+mt$+string$(5,32)
 END FUNCTION

 FUNCTION FileType$(attr)
   SELECT CASE attr
      CASE 0
         FileType$="Normal File"
      CASE 1
         FileType$="Read-Only File"
      CASE 2
         FileType$="Hidden File"
      CASE 4
         FileType$="System File"
      CASE &h10
         FileType$="Subdirectory"
      CASE &h20
         FileType$="File Archive"
      CASE ELSE
         FileType$="Unknown Type"
   END SELECT
 END FUNCTION

 FUNCTION RightShift%(number&,amount)
    Rightshift=number&\2^amount
 END FUNCTION

 FUNCTION LeftShift%(number&,amount)
   LeftShift=number&*(2^amount)
 END FUNCTION

 FUNCTION unsigned&(num)
    IF num >=0 THEN
       unsigned&=num
    ELSE
       unsigned&=65536+num
    END IF
 END FUNCTION


 57. "Device Unavailable" Using Communications Port in Real Mode

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00B 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified: 26-FEB-1990    ArticleIdent: Q30855

 If a "Device Unavailable" message occurs when trying to do
 communications under real mode (the DOS 3.x compatibility box in
 OS/2), then setcom40 must be run. This process allows the program to
 access the COM port in real mode. Setcom40 sets the serial-port
 address before starting the real mode program.

 Real mode applications use the BIOS COM-port base addresses, which
 begin at 400H to determine the presence of serial ports. However, the
 OS/2 COM.SYS device driver fills these addresses with zeros to keep
 real mode programs from interfering with protected mode applications
 that might try to access the COM ports.

 Setcom40 sets the port base addresses to values that real mode
 applications will recognize.

 The following syntax writes the port address for COMx in the BIOS area
 of the disk, where x is the number of the serial port:

    setcom40 comx=on

 The following syntax removes the address from the BIOS area of the
 disk when the real mode application no longer requires it:

    setcom40 comx=off (where x is the number of the serial port)

 For more information, please refer to Page 190 in the "Microsoft
 Operating System/2 Beginning User's Guide" of the Microsoft OS/2 SDK
 (Software Development Kit) Version 1.00.


 58. Sample BASIC Program That Makes OS/2 Call to DosSearchPath

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35271

 Below is a sample program that makes a call to the MS OS/2 function
 DosSearchPath. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS OS/2.

 'This information is in the include File: BSEDOSPC.BI

 DECLARE FUNCTION DOSSEARCHPATH%(_
         BYVAL P1 AS INTEGER,_
         BYVAL P2o AS INTEGER,_
         BYVAL P2s AS INTEGER,_
         BYVAL P3o AS INTEGER,_
         BYVAL P3s AS INTEGER,_
         BYVAL P4o AS INTEGER,_
         BYVAL P4s AS INTEGER,_
         BYVAL P5 AS INTEGER)

 DEFINT a-z

 DIM Buffer   AS STRING*60
 CLS
 bufferlen=len(buffer)
 buffer=string$(bufferlen,32)

 PRINT " 0 - SEARCH DIRECTORY GIVEN AS PATH"
 PRINT " 1 - SEARCH DEFAULT THEN PATH"
 PRINT " 2 - SEARCH STRING OF DIRECTORIES"
 PRINT " 3 - SEARCH DEFAULT THEN DIRECTORIES IN ENVIRONMENT VARIABLE GIVEN"
 INPUT "Enter OPTION : ";opt
 INPUT "Enter the PATH : ";pathref$
 pathref$=pathref$+chr$(0)
 INPUT "Enter the FILENAME : ";flname$
 flname$=flname$+chr$(0)

 x=DosSearchPath%(opt,varseg(PathRef$),sadd(PathRef$),_
                  varseg(FlName$),sadd(FlName$),_
                  varseg(buffer),varptr(buffer),bufferlen)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    Print Buffer
 END IF
 end


 59. Missing Text: DECLARE Statement

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  2-FEB-1990    ArticleIdent: Q28962

 There is a documentation error on Page 43 of the "Microsoft BASIC
 Compiler 6.0: Programming in BASIC: Selected Topics" manual for
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2. The last sentence of the first paragraph in the Note that
 appears in the center of the page is missing some text.

 The sentence should read as follows:

    A DECLARE statement ensures that only the correct number and type
    of arguments are passed to a procedure, and allows your program to
    call procedures defined in separate modules. See the "BASIC
    Language Reference" manual for more information on DECLARE.

 This documentation error was corrected in the documentation for
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.


 60. LINK /PAC and /F Options Are Not Supported by BASIC Compiler

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q31881

 The /F (far call translation) and /PAC (packcode) options of LINK.EXE
 Version 5.01.20 should not be used with BASIC programs.

 The LINK section on Pages 276-278 of the "Microsoft CodeView and
 Utilities: Software Development Tools for MS-DOS" manual states that
 if the /F and /PAC options are used together, slightly faster code and
 smaller executable file size are generated.

 This process is performed by directing the linker to group together
 neighboring code segments and by optimizing far CALLs.

 However, this information does not apply to BASIC. When you link
 compiled BASIC routines with LINK /F/PAC, the executable .EXE file
 size remains the same as the .EXE file size when linked without these
 options, and speed is not increased.

 This information applies to the BC.EXE that comes with QuickBASIC
 Versions 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2.


 61. Example of Using SetUEvent, ON UEVENT to Detect Mouse Presence

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified: 17-JAN-1991    ArticleIdent: Q31936

 The following example uses the SetUEvent routine and the ON UEVENT
 statement to trap a user-defined event. An event occurs in the sample
 program below if the Microsoft Mouse is not installed. The program
 traps the event if and when it occurs, and then prints a message.

 The user-defined event-trapping feature is found in QuickBASIC version
 4.00b, Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS,
 and Microsoft BASIC Professional Development System (PDS) versions
 7.00 and 7.10 for MS-DOS. The SetUEvent routine and the ON UEVENT
 statement are not found in QuickBASIC version 4.00 or earlier.

 For more information on the CALL INTERRUPT statement used in the code
 example below to call the Microsoft Mouse, query on the following
 words in this database:

    mouse and CALL and INTERRUPT

 INTERRUPT is an external routine located in QB.LIB on the QuickBASIC
 release disk.

 Code Example
 ------------

 DECLARE SUB mouse (m0, m1, m2, m3)
 ' change following line to include QBX.BI if in BASIC PDS 7.00/7.10
 REM $INCLUDE: 'QB.BI'

 ON UEVENT GOSUB handler
 UEVENT ON

 m0 = 0: CALL mouse(m0, m1, m2, m3)                 'Initialize the MOUSE
    IF NOT m0 THEN CALL SetUEvent    'If no Mouse installed print message
 '-------------- Other program code can be written here -----------------
 END
 handler:
    PRINT "No Mouse installed"
 END

 SUB mouse (m0, m1, m2, m3) STATIC         'Talks to the MOUSE.COM driver
 DIM inregs AS RegType: DIM outregs AS RegType
    inregs.ax = m0                                    'Load the registers
    inregs.bx = m1
    inregs.cx = m2
    inregs.dx = m3
    CALL INTERRUPT(51, inregs, outregs)   'Call the mouse driver interrupt
    m0 = outregs.ax
    m1 = outregs.bx                             'Return values from driver
    m2 = outregs.cx
    m3 = outregs.dx
 END SUB


 62. Two Ways to Pass Arrays in Compiled BASIC to Assembler Routine

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  8-AUG-1990    ArticleIdent: Q32216

 An array in a compiled BASIC program can be passed to an assembly
 language program in the two ways shown below. The array can be passed
 either through the CALL statement's parameter list or, for static
 arrays only, through a COMMON block.

 Microsoft does not support passing dynamic arrays through COMMON to
 assembler (since this depends upon a Microsoft proprietary dynamic
 array descriptor format that changes from version to version). Dynamic
 arrays can be passed to assembler only as parameters in the CALL
 statement.

 This information applies to the following products:

 1. Microsoft QuickBASIC Compiler versions 4.00, 4.00b, and 4.50

 2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 3. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 The following information pertains to passing an array to an assembly
 routine through the CALL parameter list:

 If the array is passed through the parameter list, all the information
 about the array must be passed. This includes the length of each item,
 the number of items, and the segment and offset of the base element of
 the array. The first two items may be hardcoded into the assembler
 program, but the latter two must be passed because there is no way of
 knowing where the array will be located before the program starts. The
 following is an example:

    DECLARE SUB PutInfo (BYVAL Segment%, BYVAL Offset%)
    DIM a%(100)
    CALL PutInfo(VARSEG(a%(0)),VARPTR(a%(0)))

 The assembly-language program pulls the information off the stack,
 then continues with its purpose. Please note that this method works
 with both static and dynamic arrays.

 The following information pertains to passing an array to an assembly
 language routine through a COMMON block:

 Passing information through a COMMON block to an assembly language
 program is fairly simple. In the assembly language program, a segment
 is set up with the same name as the COMMON block and then grouped with
 DGROUP, as follows:

    BNAME segment 'BC_VARS'
      x  dw 1 dup (?)
      y  dw 1 dup (?)
      z  dw 1 dup (?)
    BNAME ends

   dgroup group BNAME

 The above assembler code matches the following BASIC code named COMMON
 block:

    DEFINT A-Z
    COMMON /BNAME/ x,y,z

 Passing arrays through the COMMON block is done in a similar fashion.
 However, only static arrays may be passed to assembler through COMMON.

 Note: This information does not apply to passing far
 variable-length-strings in BASIC PDS version 7.00 or 7.10. For
 information on accessing far variable-length-strings in BASIC PDS
 version 7.00 or 7.10, see Chapter 13, "Mixed-Language Programming with
 Far Strings," in the "Microsoft BASIC 7.0: Programmer's Guide" for
 versions 7.00 and 7.10.

 When static arrays are used, the entire array is stored in the COMMON
 block. Consider the following example:

 BASIC Program
 -------------

       DECLARE SUB PutInfo ()
       DIM b%(100)
       COMMON /BNAME/ a%, b%(), c%
       CALL PutInfo
       CLS
       PRINT a%, c%
       FOR i = 0 TO 100
        PRINT b%(i);
       NEXT i
       END

 Assembly Program
 -----------------

       ;Note, this program uses MASM version 5.x directives.

       .model Medium

        BNAME segment COMMON 'BC_VARS'
          a  dw 1 dup (?)
          b  db 202 dup (?)      ;Note that all the space for the
                                 ;array is set up
          c  dw 1 dup (?)
        BNAME ends

        dgroup group BNAME

        .code

             public PutInfo
        PutInfo      proc   far
             push   bp
             mov    bp,sp
             push   di

             inc    word ptr dgroup:a
             inc    word ptr dgroup:c

             mov    cx,101
             mov    di,offset dgroup:b

        repeat:
             mov    [di],cx
             add    di,2
             loop   repeat

             pop    di
             pop    bp
             ret
        PutInfo      endp
             end

 As noted in the assembly source, the space for the array must be set up
 in the COMMON segment.

 When dynamic arrays are used, the array is not placed in the COMMON
 block. Instead, a multibyte array descriptor is placed on the COMMON
 block. The dynamic array descriptor changes from version to version,
 and is not released by Microsoft -- it is considered Microsoft
 proprietary information.


 63. Using B_OnExit Across a CHAIN Hangs System; Compiled BASIC

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 B_QuickBas
 Last Modified: 17-JAN-1990    ArticleIdent: Q32217

 Chaining to and from programs that use B_OnExit causes the system to
 hang.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b (buglist4.00, buglist4.00b), in Microsoft
 BASIC Compiler Version 6.00 and 6.00b for MS-DOS and MS OS/2, and in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 Please note that the B_OnExit routine is documented on Pages 319-321
 of the "Microsoft QuickBASIC 4.0: Learning and Using" manual for
 Microsoft QuickBASIC Versions 4.00 and 4.00b (this is the same manual
 for Microsoft BASIC Compiler Versions 6.00 and 6.00b), and in the
 "Microsoft BASIC 7.0: Programmer's Guide" on Pages 474-475.

 The following steps reproduce the problem using source code provided
 farther below:

 1. Use the following software to reproduce the problem:

    a. Microsoft QuickBASIC Versions 4.00, 4.00b, Microsoft BASIC
       Compiler Version 6.00 or 6.00b, or Microsoft BASIC PDS Version
       7.00.

    b. Microsoft C Compiler Version 5.10

 2. Type the following command lines:

       BC BUGTEST.BAS;
       BC BUGNEXT.BAS;
       CL /c /AM BUGC.C
       LINK /NOE BUGTEST+BUGC;
       LINK /NOE BUGNEXT+BUGC;

 3. Run BUGTEST.EXE from the DOS prompt.

 4. At the "CHAIN Y/N?" prompt, type Y.

 The system locks up when BUGNEXT exits.

 Please note the following:

 1. You must link BUGC.OBJ with BUGNEXT.OBJ even though it is not
    called.

 2. Both programs apparently run correctly until you exit BUGNEXT.

 Code Example
 ------------

 'BUGTEST.BAS

         DECLARE SUB IntProc CDECL
         DEFINT A-Z
         PRINT "[***** ENTRY TO MAIN  *****]"
         CALL InProc
         INPUT "CHAIN Y/N";T$
         IF T$="Y" OR T$="y" THEN
            CHAIN "BUGNEXT.EXE"
         END IF
         SYSTEM
         END

 'BUGNEXT.BAS

         DEFINT A-Z
         PRINT "[***** CHAIN *****]"
         SYSTEM
         END

 /* BUGC.C */

 #include <malloc.h>
 extern pascal far B_OnExit();  /* Declare the routine */

 void IntProc()
 {
   void TermProc();             /* Declare TermProc routine */
   printf ("\nIn the C IntProc routine\n");
   B_OnExit(TermProc);          /* Log termination routine with BASIC */
 }

 void TermProc()                         /* The TermProc function is */
 {                                       /* called before any restarting */
   printf ("\nIn C TermProc routine\n"); /* or termination of the program. */
 }


 64. DosGetPid and DosGetInfoSeg Get Process Identification (PID)

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q32219

 Two MS OS/2 API calls return the process identification (PID) of the
 current process. The two calls are DosGetPid and DosGetInfoSeg, which
 are illustrated in a code example below.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 DosGetPid is the simplest and most direct way of retrieving the
 current PID. This function is passed the address of a structure
 containing three integers or words. The function declarations are as
 follows:

       TYPE PidInfo
            Pid as integer        'Process Pid
            Tid as integer        'Thread Pid
            pidParent as integer 'Parent Pid
       END TYPE

       DECLARE FUNCTION DosGetPid%(_
                    SEG P1 AS PidInfo)

 The PID information is returned in the structure.

 The information returned by DosGetInfoSeg also helps find the PID, but
 the procedure is more difficult. This function returns the address of
 both the GDT and LDT. The LDT contains the process information. To
 locate the PID, you must set the segment to the LDT (DEF SEG=address
 of LDT), then look at the bytes that contain the desired information.
 The program below demonstrates this method. (This program also
 contains an example of DosGetPid.)

        'Declarations used below can be found in BSDOSPC.BI
        TYPE PidInfo
             Pid as integer
             Tid as integer
             pidParent as integer
        END TYPE
        DECLARE FUNCTION DosGetInfoSeg%(_
                     SEG P1 AS INTEGER,_
                     SEG P2 AS INTEGER)
        DECLARE FUNCTION DosGetPid%(_
                     SEG P1 AS PidInfo)

        DEFINT A-Z
        CLS
        DIM info AS PidInfo

        x=DosGetInfoSeg%(global,localo)

        IF (x) THEN
          Print "Error, the number is : ";x
        ELSE
          Print "The Global Segment : ";Global
          Print "The Local Segment : ";localo
          def seg=localo            'Change Segment
          pid1=peek(0)+(256*(peek(1))) 'First Word in segment
          pid2=peek(2)+(256*(peek(3))) 'Second Word
          pid3=peek(6)+(256*(peek(7))) 'Fourth Word
          def seg
          print "         Current Process ID : ";pid1
          print "       Process ID of Parent : ";pid2
          print "Thread ID of Current Thread : ";pid3
        END IF

        x=DosGetPid%(info)

        IF (x) THEN
          Print "Error, the number is : ";x
        ELSE
          print "         Current Process ID : ";info.pid
          print "       Process ID of Parent : ";info.pidParent
          print "Thread ID of Current Thread : ";info.tid
        END IF


 65. Cannot Use Alternate Math Library Without Compiling BC /FPa

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q32415

 The alternate math libraries should not be used without compiling with
 the BC /FPa switch; otherwise, unpredictable results may occur.

 The following alternate math libraries can be used in MS OS/2
 protected mode:

    BC 6.00           BC 6.00b         PDS 7.00
    -------           --------         --------

    BRUN60AP.DLL      BRUN61AP.DLL     BRT70ANP.DLL
    BCOM60AP.LIB      BCOM61AP.LIB     BRT70ANP.LIB
                                       BRT70AFP.DLL
                                       BRT70AFP.LIB

 The following alternate math libraries can be used in MS-DOS or MS
 OS/2 real mode:

    BC 6.00           BC 6.00b         PDS 7.00
    -------           --------         --------

    BRUN60AR.EXE      BRUN61AP.EXE     BRT70ANR.EXE
    BCOM60AR.LIB      BRUN61AP.LIB     BRT70ANR.LIB
                                       BRT70AFR.EXE
                                       BRT70AFR.LIB

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.


 66. Linker Module-Definition Files for MS OS/2 or Windows

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q33137

 A module-definition file, used by LINK.EXE, describes the name,
 attributes, exports, imports, and other characteristics of an
 application or library for MS OS/2 (or Microsoft Windows). This file
 is required for dynamic link libraries (DLLs) that run under MS OS/2
 (and for Microsoft Windows applications and libraries).

 Note that Microsoft BASIC Compiler Versions 6.00 and 6.00b and
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 cannot make Microsoft Windows applications or libraries. These
 products can only make OS/2 applications.

 For more information about the module-definition file used by LINK,
 see Page Update 39 in the "Microsoft CodeView and Utilities: Software
 Development Tools for MS OS/2 and MS-DOS: Update" manual.

 For more information about BASIC compatibility with Microsoft Windows,
 search for a separate article with the following words:

    Windows and SDK and BASIC and compiler


 67. 7.00 Problem Passing Near Fixed String to Recursive FUNCTION

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q58409

 The problem described below is so rare that it will not be encountered
 by most readers.

 When passing a fixed-length string variable as a variable-length
 string parameter to a recursive FUNCTION procedure in the program
 below, the fixed-length string variable is nulled (reduced to "") when
 the FUNCTION procedure returns if you compiled with BC.EXE using near
 strings. Renaming the FUNCTION procedure eliminates this problem.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS and MS
 OS/2. This problem was corrected in BASIC PDS version 7.10.

 Note that this problem occurs only if the original variable is a
 fixed-length string and you are executing from a program compiled to
 use near strings. If the original variable is a variable-length string
 or the program uses far strings (either in the QBX.EXE environment or
 in a compiled program), this error does not occur.

 The program below demonstrates the error. To reproduce the problem,
 compile and link the program using Microsoft BASIC PDS 7.00 as
 follows:

    BC /o Recfun.bas;
    LINK Recfun.bas;

 Executing the program below shows that the string variable "parm1" is
 nulled after the return from the recursive function call to "CTRL".

 To work around the problem, do one of the following:

 1. Add the /Fs (far strings) option to the compile line.

 2. Rename the CTRL FUNCTION procedure to FUN2 (or some other name).

 3. Change the DIM statement for "original" to read as follows:

       DIM original AS STRING

 Code Example
 ------------

 The following program, RECFUN.BAS, shows the problem:

    DECLARE FUNCTION Fun1% (parm1 AS STRING)
    DECLARE FUNCTION ctrl% (parm1 AS STRING, parm2 AS STRING)
    CONST CASEONE = "1"
    CONST CASETWO = "2"
    DIM original AS STRING * 3   'Remove "* 3" to work around problem.
    CLS
    original = "ooo"
    retval% = Fun1%(original)
    END

    FUNCTION ctrl% (parm1 AS STRING, parm2 AS STRING)
      DIM retval       AS INTEGER
      IF parm2 = CASEONE THEN
        PRINT "Caseone: parm1=["; parm1; "]": SLEEP 1
      ELSE
        PRINT "Case two:"
        PRINT "before recursion:  parm1=["; parm1; "]": SLEEP 1
        retval = ctrl%(parm1, CASEONE)
        PRINT "after recursion :  parm1=["; parm1; "]": SLEEP 1
      END IF
    END FUNCTION

    FUNCTION Fun1% (parm1 AS STRING)
      DIM retval         AS INTEGER
      retval = ctrl%(parm1, CASETWO)
    END FUNCTION

 Workaround
 ----------

 To work around the problem, rename CTRL to FUN2 as follows:

    DECLARE FUNCTION Fun1% (parm1 AS STRING)
    DECLARE FUNCTION fun2% (parm1 AS STRING, parm2 AS STRING)
    CONST CASEONE = "1"
    CONST CASETWO = "2"
    DIM original AS STRING * 3   'Remove "* 3" to make it work
    CLS
    original = "ooo"
    retval% = Fun1%(original)
    END

    FUNCTION Fun1% (parm1 AS STRING)
      DIM retval         AS INTEGER
      retval = fun2%(parm1, CASETWO)
    END FUNCTION

    FUNCTION fun2% (parm1 AS STRING, parm2 AS STRING)
      DIM retval       AS INTEGER
      IF parm2 = CASEONE THEN
        PRINT "Caseone: parm1=["; parm1; "]": SLEEP 1
      ELSE
        PRINT "Case two:"
        PRINT "before recursion:  parm1=["; parm1; "]": SLEEP 1
        retval = fun2%(parm1, CASEONE)
        PRINT "after recursion :  parm1=["; parm1; "]": SLEEP 1
      END IF
    END FUNCTION


 68. Example to Load OS/2 Disk Directory into String Array

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q33178

 This article discusses two methods to put a disk directory listing
 into a string array under OS/2 protected mode. (Note: This article was
 written because the FILES statement in BASIC only outputs to the
 screen, not to a file or to string variables.)

 Example 1 shows a simple method to SHELL to the DIR command, redirect
 the output to a file, and input from the file into string variables.
 (Example 1 also works correctly in MS-DOS.)

 Example 2 shows how to invoke OS/2 API functions (DosFindFirst and
 DosFindNext) to retrieve a disk directory into string variables.

 This article applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Note: In Microsoft BASIC PDS 7.00, the DIR$ function can be used to
 accomplish the same thing as these two routines show. The use of DIR$
 is documented on Page 107 of the "Microsoft BASIC 7.0: Language
 Reference" manual.

 For an article about how to invoke MS-DOS (or OS/2 real mode)
 functions to accomplish the same thing, query in this Knowledge Base
 on the following keywords:

    INTERRUPT and FINDFIRST and FINDNEXT

 In MS OS/2 protected mode, you can use the API CALLs DosFindFirst and
 DosFindNext to retrieve a disk directory listing and load it into a
 string array, as shown in Example 2 below. Example 2 does NOT apply to
 QuickBASIC Versions 4.50 and earlier because they cannot compile
 programs for OS/2 protected mode.

 Example 1 (the simplest technique) is as follows:

 ' Works in QuickBASIC 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50, and
 ' BASIC compiler 6.00 and 6.00b.
 nf = 200   ' Handles directory listing up to 200 lines.
 DIM buffer$(nf)
 INPUT "Enter Search Path: ", path$   ' Enter path such as c:
 SHELLSTRING$ = "dir " + path$ + " >dirfile.dat"
 SHELL SHELLSTRING$   ' SHELL to the MS-DOS DIRectory command.
 OPEN "dirfile.dat" FOR INPUT AS #1
 pntr% = 0
 WHILE NOT EOF(1) AND pntr% < nf
   pntr% = pntr% + 1
   INPUT #1, buffer$(pntr%)  ' Inputs one directory line at a time.
   PRINT buffer$(pntr%)
 WEND
 CLOSE #1
 KILL "dirfile.dat"
 END

 Example 2 is as follows:

 The following sample program is for MS OS/2 protected mode (to be
 compiled only in BASIC compiler Version 6.00 or 6.00b in MS OS/2
 protected mode or BASIC PDS Version 7.00 in MS OS/2 protected mode):

 'The TYPE below is taken from the following include file: BSEDOSFL.BI
 TYPE FILEFINDBUF
         fdateCreation   AS INTEGER
         ftimeCreation   AS INTEGER
         fdateLastAccess AS INTEGER
         ftimeLastAccess AS INTEGER
         fdateLastWrite  AS INTEGER
         ftimeLastWrite  AS INTEGER
         cbFile          AS LONG
         cbFileAlloc     AS LONG
         attrFile        AS INTEGER
         cchName         AS STRING * 1
         achName         AS STRING * 13
 END TYPE

 DECLARE FUNCTION DosFindFirst%( _
         BYVAL P1s AS INTEGER,_
         BYVAL P1o AS INTEGER,_
         SEG   P2  AS INTEGER,_
         BYVAL P3  AS INTEGER,_
         SEG   P4  AS FILEFINDBUF,_
         BYVAL P5  AS INTEGER,_
         SEG   P6  AS INTEGER,_
         BYVAL P7  AS LONG)

 DECLARE FUNCTION DosFindNext%( _
         BYVAL P1 AS INTEGER,_
         SEG   P2 AS FILEFINDBUF,_
         BYVAL P3 AS INTEGER,_
         SEG   P4 AS INTEGER)

 DEFINT a-z

 DIM buffer AS FileFindBuf
 DIM filelist(255) as string*13
 DIM reserved  AS LONG

 CLS

 INPUT "Enter the Filename(s) : ";flname$
 flname$=flname$+chr$(0)

 atr= 0+2+4+16    'normal + hidden + system + subdirectory
 dirh=1
 searchcount=1
 bufflen=36
 x=DosFindFirst%(varseg(flname$),sadd(flname$),_
                 dirh,atr,buffer,bufflen,searchcount,reserved)
 IF (X=0) THEN
    DO
      counter=counter+1
      filelist(counter)=buffer.achName
      buffer.achName=string$(13,32)  'assign blanks
    LOOP WHILE (DosFindNext%(dirh,buffer,bufflen,searchcount) = 0 )
 ELSE
     PRINT "No MATCH was found"
     END
 END IF

 for i = 1 to counter
     print filelist(i)
 next i

 END


 69. Sample Program That Makes OS/2 Call to DosQCurDisk Function

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q35273

 Below is a sample program that makes a call to the MS OS/2 function
 DosQCurDisk. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 'The declarations are in BSEDOSFL.BI

 DECLARE FUNCTION DosQCurDisk%(_
                  SEG P1 AS INTEGER,_
                  SEG P2 AS LONG)

 DIM number AS INTEGER
 DIM LogicalDriveMap AS LONG

 x=DosQCurDisk%(number,LogicalDriveMap)
 if (x) then
     print "An error occurred.  The number is : ";number
 else
     print "Logical Drive Map; ";LogicalDriveMap
 end if
 end


 70. Sample Program That Makes MS OS/2 Call to DosSleep Function

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q35274

 Below is a sample program that makes a call to the MS OS/2 function
 DosSleep. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 'The declaration is in BSEDOSPC.BI
 DECLARE FUNCTION DOSSLEEP%(BYVAL P1 AS LONG)

 DIM a AS LONG

 INPUT "Enter the amount of time to SLEEP (in seconds) :";longer

 longer=longer*1000

 x=timer
 y=DosSleep%(longer)
 z=timer

 IF (y) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   Print "The amount of time you slept is : ";z-x
 END IF
 end


 71. Sample Program That Makes MS OS/2 Call to DosScanEnv Function

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q35275

 Below is a sample program that makes a call to the MS OS/2 function
 DosScanEnv. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS OS/2.

 'The declarations are in BSEDOSPC.BI
 TYPE address
      offset AS INTEGER
      segment AS INTEGER
 END TYPE

 DECLARE FUNCTION DOSSCANENV%(_
         BYVAL P1s AS INTEGER,_
         BYVAL P1o AS INTEGER,_
         SEG P2 AS Address)

 DEFINT a-z
 DIM info AS address

 INPUT "Enter the item to be searched for in the Environment Table : ";item$
 item$=ucase$(item$)+chr$(0)

 x=DosScanEnv%(varseg(item$),sadd(item$),info)

 IF (x) THEN
    print "An error occurred.  The error number is ";x
 ELSE
    counter=0
    def seg = info.segment
    do
      c$=chr$(peek(info.offset+counter))
      result$=result$+c$
      counter=counter+1
    loop while c$<>chr$(0)
    print item$;" = ";result$
 END IF
 END


 72. Sample Program That Makes MS OS/2 Call to DosPhysicalDisk

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35276

 Below is a sample program that makes a call to the MS OS/2 function
 DosPhysicalDisk. This program can be compiled in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 'The declaration is in BSEDOSFL.BI

 DECLARE FUNCTION DOSPHYSICALDISK%(_
         BYVAL P1 AS INTEGER,_
         BYVAL P2s AS integer,_
         BYVAL P2o AS integer,_
         BYVAL P3 AS INTEGER,_
         BYVAL P4s AS INTEGER,_
         BYVAL P4o AS INTEGER,_
         BYVAL P5 AS INTEGER)

 DEFINT a-z
 DIM DataPtr AS LONG
 DIM ParmLength AS INTEGER
 DIM DataBuff AS STRING*2
 DIM ParmBuff AS STRING*3

 databuff="**"

 func = 1
 DataLength = 2
 ParmLength = 0

 x=DosPhysicalDisk%(func,varseg(DataBuff),varptr(DataBuff),datalength,_
                    0,0,parmlength)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    PRINT "Number partitionable drives: ";
    PRINT asc(mid$(databuff,1,1));asc(mid$(databuff,2,2))
 END IF

 func = 2
 DataLength = 2
 ParmLength = 3
 ParmBuff="1:"+chr$(0)
 x=DosPhysicalDisk%(func,varseg(DataBuff),varptr(DataBuff),datalength,_
                    varseg(Parmbuff),varptr(ParmBuff),parmlength)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    PRINT "Handle: ";
    PRINT asc(mid$(databuff,1,1));asc(mid$(databuff,2,2))
 END IF
 END


 73. Sample Program That Makes MS OS/2 Call to DosDelete Function

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35277

 Below is a sample program that makes a call to the MS OS/2 function
 DosDelete. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS OS/2.

 'The declaration is in BSEDOSFL.BI
 DECLARE FUNCTION DOSDELETE%(_
                  BYVAL P1o AS INTEGER,_
                  BYVAL P1s AS INTEGER,_
                  BYVAL P2 AS LONG)

 DEFINT A-Z
 DIM reserved AS LONG

 INPUT "Enter the file to be deleted : ";fl$
 fl$=fl$+chr$(0)

 x=DosDelete%(varseg(fl$),sadd(fl$),reserved)

 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   Print fl$; "was DELETED"
 END IF
 end


 74. Sample Program That Makes MS OS/2 Call to DosBeep Function

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35278

 Below is a sample program that makes a call to the MS OS/2 function
 DosBeep. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00.

 REM $INCLUDE: 'bsedospc.bi'
 DEFINT a-z
 PRINT "Test of DOSBEEP..."
 i = &H25
 WHILE ((INKEY$ = "") and (i < &H7EFF))
    i = i + &H100
    x = DOSBEEP(i, 400)
 WEND


 75. Sample Program That Makes MS OS/2 Call to DosQFileMode

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q35279

 Below is a sample program that makes a call to the MS OS/2 function
 DosQfileMode. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00.

 'The declaration is in BSEDOSFL.BI
 DECLARE FUNCTION DOSQFILEMODE%(_
                  BYVAL P1s AS INTEGER,_
                  BYVAL P1o AS INTEGER,_
                  SEG P2 AS INTEGER,_
                  BYVAL P3 AS LONG)
 DIM c AS LONG
 INPUT "Enter the Filename : ";flname$
 flname$=flname$+chr$(0)
 x=dosqfilemode%(varseg(flname$),sadd(flname$),attr%,c)
 IF (x) then
    print "An error has occurred.  The error number is ";x
 else
   print "Attribute Number is ";hex$(attr%)
 end if


 76. LINK "Symbol Defined More Than Once" Mixing Math Packages

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q37342

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 You can pass variables between BASIC and other languages that have the
 alternate math package if each of the modules is compiled using that
 option. The error message L2025, "symbol defined more than once",
 results from any attempt to link modules that were compiled using
 different math package options.

 The code example below, which shows a BASIC program calling a C
 function, should be compiled and linked using the following syntax:

    bc cf.bas /FPa [other optional switches are OK];
    cl /AM /Gs /FPa /c cfunc.c
    link cf+cfunc /noe;

 The alternate math package is not available in QuickBASIC, or in
 versions of the BASIC compiler earlier than Version 6.00.

 The following is sample code:

 ' BASIC PROGRAM CF.BAS:
 DECLARE function cfunc# CDECL (byval x AS double)
 input "enter a floating point number ";x#
 print x#;" * 2 = ";cfunc(x#)

 /*   C FUNCTION CFUNC.C:   */
    double  cfunc(double value)
    {
       return  (value * 2);
    }


 77. Sample BASIC 6.00/7.00 Program to CALL OS/2 Mouse Functions

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | O_OS2API O_OS2SDK
 Last Modified: 26-MAR-1990    ArticleIdent: Q37410

 Below is a sample program that calls the following MS OS/2 API
 function calls for accessing the mouse in MS OS/2 protected mode:

    MouReadEventQue
    MouSetEventMask
    MouOpen
    MouRemovePtr
    MouDrawPtr

 This program can be compiled in MS OS/2 protected mode in Microsoft
 BASIC Compiler Version 6.00 or 6.00b for MS OS/2 and in Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS OS/2.

 Code Example
 ------------

 ' Summary of Program:
 '
 ' The following program loops until any key is pressed.
 ' As the mouse is moved, a "smiley" face is displayed.
 ' Pressing the left mouse button causes the face to
 ' change colors. The colors are random.
 ' Pressing the right mouse button causes the screen to
 ' clear and be the same color as the last face.
 '
 ' The following is taken from BSESUBMO.BI
 ' OS/2 Subroutine Include File - Mouse Support
 ' Copyright (c) 1987,1988 Microsoft Corporation

 TYPE MOUEVENTINFO
       fs        AS INTEGER
       Time      AS LONG
       row       AS INTEGER
       col       AS INTEGER
 END TYPE

 TYPE NOPTRRECT
       row       AS INTEGER
       col       AS INTEGER
       cRow      AS INTEGER
       cCol      AS INTEGER
 END TYPE

 TYPE PTRSHAPE
       cb        AS INTEGER
       col       AS INTEGER
       row       AS INTEGER
       colHot    AS INTEGER
       rowHot    AS INTEGER
 END TYPE

 DECLARE FUNCTION MouReadEventQue%( _
       SEG   P1 AS MOUEVENTINFO,_
       SEG   P2 AS INTEGER,_
       BYVAL P3 AS INTEGER)

 DECLARE FUNCTION MouSetEventMask%( _
       SEG   P1 AS INTEGER,_
       BYVAL P2 AS INTEGER)

 DECLARE FUNCTION MouOpen%( _
       BYVAL P1s AS INTEGER,_
       BYVAL P1o AS INTEGER,_
       SEG   P2 AS INTEGER)

 DECLARE FUNCTION MouClose%( _
       BYVAL P1 AS INTEGER)

 DECLARE FUNCTION MouRemovePtr%( _
       SEG   P1 AS NOPTRRECT,_
       BYVAL P2 AS INTEGER)

 DECLARE FUNCTION MouDrawPtr%( _
       BYVAL P1 AS INTEGER)

 DEFINT a-z
 DIM MouEvent as MOUEVENTINFO
 DIM Pointer as PTRSHAPE
 CLS
  x=MouOpen(0,0,hMouse) 'OPEN MOUSE DRIVER
  IF x THEN
     PRINT "*** Unable to load Mouse Driver ***"
     END
  ELSE
     x=MouDrawPtr(hMouse)  'Draw the mouse
     mask=&h001F '(2 buttons 1F)
     x=MouSetEventMask(mask,hMouse)
     ReadType=0
     while inkey$=""
        x=MouReadEventQue(MouEvent,ReadType,hMouse)
        'Structure is all zeros if no event
        IF (MouEvent.time<>0) THEN
           IF (MouEvent.fs AND &h0004) THEN  'left button
              y=INT(16 * RND)
              color ,y
           END IF

           IF (MouEvent.fs AND &h0010) THEN  'right button
              CLS
           END IF
              CALL HideMouse(MouEvent.Row,MouEvent.Row,MouEvent.Col,_
                             MouEvent.col,hMouse)
              locate MouEvent.row+1,MouEvent.col+1 : print chr$(1);
        END IF
     WEND
  END IF

 SUB HideMouse(a,b,c,d,driver) STATIC
 DIM NoMouse  as NoPtrRect
    NoMouse.row=a
    NoMouse.cRow=b
    NoMouse.col=c
    NoMouse.cCol=d
    x=MouRemovePtr(NoMouse,driver)
 END SUB


 78. BSEDOSPC.BI Is Missing DosSetSigHandler Definition; for OS/2

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q37420

 The include file BSEDOSPC.BI fails to include the definition for
 DosSetSigHandler. It should be defined as follows:

    DECLARE FUNCTION DosSetSigHandler%( _
            BYVAL P1seg AS INTEGER,_
            BYVAL P1offset AS INTEGER,_
            SEG   P2 AS LONG,_
            SEG   P3 AS INTEGER,_
            BYVAL P4 AS INTEGER,_
            BYVAL P5 AS INTEGER)

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development System
 (PDS) Versions 7.00 and 7.10 for MS OS/2.


 79. Sample Program That Makes OS/2 Function Call DosMove

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q37426

 Below is a sample program that makes a call to the MS OS/2 function
 DosMove. This program can be compiled in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS OS/2.

 The sample program is as follows:

 ' This definition is from the include file BSEDOSFL.BI
 DECLARE FUNCTION DosMove%(_
                  BYVAL P1S AS INTEGER,_
                  BYVAL P1O AS INTEGER,_
                  BYVAL P2S AS INTEGER,_
                  BYVAL P2O AS INTEGER,_
                  BYVAL P3 AS LONG)

 DIM reserved AS LONG

 INPUT "Enter the ORIGINAL filename : ";f1$
 INPUT "Enter the NEW filename : ";f2$

 f1$=f1$+chr$(0)
 f2$=f2$+chr$(0)

 x=DosMove%(varseg(f1$),sadd(f1$),varseg(f2$),sadd(f2$),reserved)

 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   Print UCASE$(f1$)" ===> " UCASE$(f2$)
 END IF
 END


 80. Sample Program That Makes OS/2 Function Call DosSelectDisk

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q37427

 Below is a sample program that makes a call to the MS OS/2 function
 DosSelectDisk. This program can be compiled in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 The sample program is as follows:

 ' This definition is from the include file BSEDOSFL.BI
 DECLARE FUNCTION DosSelectDisk%(BYVAL P1 AS INTEGER)

 DIM number AS INTEGER
 INPUT "Enter disk number (A - &H0001, B - &H0002, etc.): ";number
 x=DosSelectDisk%(number)
 IF (x) THEN
     Print "DosSelectDisk returned an error ";x
 ELSE
     shell "dir"
     print "Hit any key to continue..."
     while inkey$="" : wend
 END IF
 END


 81. READ/DATA Statement Slower in QB 4.00 & BC 6.00 Than QB 3.00

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# G881102-5637 B_QuickBas
 Last Modified:  1-FEB-1990    ArticleIdent: Q37768

 The following are two reasons why READ/DATA statements are slower in
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, Microsoft BASIC
 Professional Development System (PDS) Version 7.00, and QuickBASIC
 Versions 4.00, 4.00b, and 4.50 than in the noncoprocessor version of
 QuickBASIC Version 3.00:

 1. Math Package

    The noncoprocessor version of QuickBASIC Version 3.00 (QB.EXE) uses
    Microsoft Binary Format (MBF) for floating-point numbers, while
    QuickBASIC Versions 4.x, Microsoft BASIC PDS, and the BASIC
    compiler Versions 6.00 and 6.00b use IEEE. If a math coprocessor is
    not present, the later compilers emulate one and, thus, are slower
    than the noncoprocessor version of QuickBASIC 3.00.

    To increase its speed without a coprocessor, the BASIC compiler
    Versions 6.00 and 6.00b and Microsoft BASIC PDS Version 7.00
    provide support for the alternate math library. Alternate math is a
    subset of IEEE and is 40 to 50 percent faster than emulating a math
    coprocessor (but is still slower than MBF). To use alternate math,
    compile with the BC /FPa switch. Note that the alternate math
    library is not supported in Microsoft QuickBASIC Compiler Versions
    1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, or 4.50.

 2. Microsoft rewrote the code for READ and DATA statements to support
    both the QB.EXE 4.00, 4.00b, and 4.50 environment and separate
    compilation in the BC.EXE BASIC compiler. QuickBASIC 3.00 is highly
    dependent upon a particular format and location for DATA
    statements. In QuickBASIC 4.00 and later, and in the QuickBASIC
    extended environment included with Microsoft BASIC PDS Version
    7.00, the support is generalized to allow for DATA statements in
    Quick libraries.


 82. Using Run-Time Module, RUN Makes Program Lose 70K Memory

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10 B_QuickBas
 Last Modified: 20-SEP-1990    ArticleIdent: Q37769

 When a program compiled without the /O option executes the RUN
 statement to run a second program, the run-time module (BRUNxx.EXE or
 BRTMxx.EXE) is unloaded from memory. However, the 70K of space for the
 run-time module fragments memory, and approximately 70K of RAM is
 unavailable to the program run with the RUN statement. When the second
 program quits or transfers control, the 70K of memory is available
 again.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS, Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS, and Microsoft QuickBASIC Compiler versions 4.00, 4.00b, and
 4.50 (buglist4.00, buglist4.00b, buglist4.50) for MS-DOS. We are
 researching this problem and will post new information here as it
 becomes available. This problem doesn't occur in QuickBASIC version
 3.00.

 This temporary fragmentation of memory can contribute towards causing
 any one of the following errors when attempting to RUN another .EXE
 program: "Out of Memory," "Error R6005," or the MS-DOS message "Not
 enough memory to Exec."

 To work around this problem, you can make the program that uses the
 run-time module RUN another BASIC program compiled with the BC /O
 (stand-alone) option, which in turn can RUN the desired .EXE program.

 If the first BASIC program is compiled with the BC /O (stand-alone)
 option, all but 200 bytes are available after the RUN statement. In
 this case, the 200 missing bytes are the expected overhead associated
 with the RUN statement.

 The following are two different examples (1 and 2) that duplicate the
 problem:

 1. To duplicate the problem, do the following:

    a. Compile the following program WITHOUT the BC /O (stand-alone)
       option:

          ' TEST1.BAS
          PRINT FRE(-1)
          RUN "TEST2"

    b. Compile the following program WITH the BC /O (stand-alone)
       option:

          ' TEST2.BAS
          PRINT FRE(-1)

    c. Run TEST1.EXE. The following is sample output:

          439432  (from TEST1)
          429432  (from TEST2)

    d. Run TEST2.EXE alone. The following is sample output:

          500232  (from TEST2)

       There is about 70K more far heap available for TEST2 when it is
       run alone compared to when it is run from a BASIC program using
       the BRUNxx.EXE module.

 2. The problem was originally reported using the RUN statement to
    execute a Microsoft C .EXE program.

    To duplicate this problem, compile (without /O) and run the BASIC
    program below, which RUNs a Microsoft C program. The C routine
    prints the approximate amount of memory free. When the BASIC
    routine is compiled with the run-time module, about 70K is lost.

    If you RUN the C program from the BASIC routine compiled with /O
    and then compare with running the C program from MS-DOS, the memory
    numbers are within 200 bytes of one another.

    The following BASIC routine RUNS the C routine:

       RUN "memtest.exe"

    The following Microsoft C routine prints available memory:

 /*   memtest.c   */
 #include <dos.h>
 #include <malloc.h>
 #include <stdio.h>
 long l;
 unsigned int j,pp;
 main()
 {
 union REGS inregs, outregs;
 inregs.h.ah=0x48;
 inregs.x.bx=0xffff;
 intdos(&inregs,&outregs);
 l=(long)(outregs.x.bx * 16L); /*amount available from far heap*/
 j=_memavl();/*calculate approximate amount available from near heap*/
 printf("approximate # of bytes available for allocation %ld\n",l+j);
 }


 83. "Program Memory Overflow": Break into SUBprograms

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# G881028-5376 B_QuickBas
 Last Modified: 10-AUG-1990    ArticleIdent: Q37770

 The code generated by BC.EXE in Microsoft BASIC Compiler versions 6.00
 and 6.00b, Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10, and QuickBASIC versions 4.00, 4.00b, and 4.50
 may be larger (on disk or in run-time memory) than that compiled with
 previous versions. With the increase in product features, the program
 size has grown. Therefore, it is possible that your program will no
 longer compile and will give a "Program Memory Overflow" error. This
 error can be avoided by breaking the program into smaller, separately
 compiled subprograms or FUNCTION procedures.

 At compile time, the BC.EXE compiler options can make a big difference
 in object file size. The /D (debug), /E (error handling with RESUME
 label), and /V (event handling between statements) compiler options
 generate the largest amount of code. The /X (error handling with
 RESUME NEXT, RESUME, and RESUME 0) and /W (event handling between
 lines) options generate less code than /E and /V; however, /X and /W
 still generate a fair amount of code.

 If you find that even with a careful choice of compiler options the
 program is still too big to compile, the program should be broken up
 into smaller modules that can be linked together.

 Each module can contain up to 64K in code and share a 64K data segment
 with the other modules. For code to be placed into its own module, it
 must be a subprogram or FUNCTION procedure. A subprogram procedure is
 surrounded by the SUB and END SUB statements. A FUNCTION procedure is
 surrounded by the FUNCTION and END FUNCTION statements. For more
 information about the memory the compiler uses and how to determine
 segment sizes for code and data, query in this Knowledge Base for the
 following words:

    determining and segment and sizes and LINK and /Map

 Also, if a program works in the QuickBASIC environment, BC.EXE usually
 compiles it to an executable program. However, there are two
 exceptions. If the program contains a large $INCLUDE file with RESUME
 and RESUME NEXT in it, the BC.EXE compiler may fail. The BC.EXE
 compiler builds a table of line numbers for RESUME/RESUME NEXT
 statements at 4 bytes each so it can tell where to resume back to.
 This adds additional code to the program and causes memory depletion.
 The QB.EXE interpreter does not have to keep the table, so less code
 is generated.

 To work around this situation, you can do the following two things:

 1. Use RESUME <label> instead of RESUME NEXT. Note that RESUME <label>
    should only be used to return to the same procedure level as where
    the error occurred, or else stack space will be consumed without
    being released, which can result in an "Out of stack space" error.
    For example, if an error occurs in a SUB procedure that is handled
    by an error handler in the main level code that performs RESUME
    <label> to a label in the main level code, then return addresses
    for the SUB remain unused on the stack and unavailable to the
    program.

 2. Break the program into smaller separate modules.

 If you have a large number of static numeric arrays, the BC.EXE
 compiler can run out of memory. In the QuickBASIC QB.EXE or QBX.EXE
 environment, static numeric arrays are not stored in the DGROUP data
 segment; they are stored in an additional segment. When the program is
 compiled with BC.EXE, these arrays are placed into the DGROUP data
 segment. This segment is limited to 64K. One way to work around this
 segment limitation is to make the static arrays dynamic to put them in
 the far heap.

 Dynamic non-variable-length-string arrays are stored on the far heap
 and not in the DGROUP data segment. There are three different ways to
 make an array dynamic, as follows:

 1. Use the REM $DYNAMIC metacommand to make all arrays dynamic.

 2. Use a variable as the number of elements in the DIM statement, as
    in the following example:

       x=20
       DIM array(x)

 3. Place the array in COMMON and dimension the array after the COMMON
    statement:

       COMMON SHARED array()
       DIM array(100)

 Once the program compiles, there are a few things that can be done to
 reduce the size of the linked executable file. The following is a list
 of ways to help reduce the size of .EXE files:

 1. Use the /E (/EXEPACK) linker option. This linker option removes
    sequences of repeated bytes and optimizes the load-time relocation
    table. The result is that executable files linked with this option
    may be smaller and may load faster than files linked without this
    option. Note: The /EXEPACK option cannot be used with the /Q
    option.

 2. For stand-alone .EXE files (that is, those compiled with the BC /O
    option) that use a string variable for the filename in the OPEN
    statement, linking in the file NOCOM.OBJ reduces the size of the
    programs by about 4K. (NOCOM.OBJ should be used only if your
    program contains no OPEN "COM" statements.) For example, the
    following is a program that NOCOM.OBJ will help make smaller:

       X$="test.dat"
       OPEN X$ FOR OUTPUT AS #1

 In addition to NOCOM.OBJ, BASIC compiler version 6.00 provides other
 NOxxx.OBJ files, including NOCGA.OBJ, NOEGA.OBJ, NOGRAPH.OBJ,
 NOHERC.OBJ, NOLPT.OBJ, NOVGA.OBJ, and SMALLERR.OBJ. These files are
 discussed in both the "Microsoft BASIC Compiler 6.0: User's Guide" and
 the README.DOC found on Disk 1. These NOxxx.OBJ files can also be used
 when a custom run-time module is built with the BUILDRTM.EXE utility.

 For more information about stub files and optimizing code for size and
 speed, see Chapter 15, "Optimizing Program Size and Speed," in the
 "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10.


 84. BASIC Example to Call OS/2 Function DosSetVerify, DosQVerify

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q37772

 The sample program below makes a call to the MS OS/2 functions
 DosSetVerify and DosQVerify. This program can be compiled in Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS OS/2 and in Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS OS/2.

 The program is as follows:

 DEFINT A-Z

 'The declarations can be found in BSEDOSFL.BI

 DECLARE FUNCTION DosSetVerify%(_
                  BYVAL P1 AS INTEGER)

 DECLARE FUNCTION DosQVerify%(_
                  SEG P1 AS INTEGER)

 x=DosQVerify(opt%)

 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   SELECT CASE opt%
      CASE 0
         Print "Verify is off"
      CASE 1
         PRINT "Verify is on"
      CASE ELSE
         PRINT "An unexpected error occurred."
   END SELECT
 END IF

 Print  "(0) to deactivate verify "
 input  "(1) to activate for this Application : ";opt%

 x=DosSetVerify(opt%)

 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   SELECT CASE opt%
      CASE 0
         Print "Verify is set off"
      CASE 1
         PRINT "Verify is set on"
      CASE ELSE
         PRINT "An unexpected error occurred."
   END SELECT
 END IF
 INPUT "Enter Any Key to Verify the Status of VERIFY";a$

 x=DosQVerify(opt%)

 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   SELECT CASE opt%
      CASE 0
         Print "Verify is off"
      CASE 1
         PRINT "Verify is on"
      CASE ELSE
         PRINT "An unexpected error occurred."
   END SELECT
 END IF
 END


 85. Compiled BASIC Example to Call OS/2 Function DosKillProcess

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q37773

 The sample program below makes a call to the MS OS/2 function
 DosKillProcess. This program can be compiled in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 The program is as follows:

 DEFINT A-Z

 'This declaration can be found in BSEDOSPC.BI
 DECLARE FUNCTION DosKillProcess%(_
                  BYVAL p1 AS INTEGER,_
                  BYVAL p2 AS INTEGER)

 Input "Enter PID to KILL : ";pid%
 Input "Enter ACTION code : ";action%

 x% = DosKillProcess%(action%,pid%)

 if (x%) then
     Print "Error: ";x%
 else
     Print "PID : ";pid%;" - stopped"
 end if
 end


 86. "Duplicate Definition" LINKing C Graphics Library to BASIC, /O

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | S_C S_QuickC B_QuickBas SR# G881109-6007
 Last Modified: 27-JUL-1990    ArticleIdent: Q37901

 The C graphics library, GRAPHICS.LIB, is incompatible with programs
 compiled with BC /O in QuickBASIC versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler versions 6.00 or 6.00b, or Microsoft BASIC
 Professional Development System (PDS) version 7.00. The FONT and CHART
 graphics in QuickC version 2.00 are also incompatible with programs
 compiled with BC /O in these versions of QuickBASIC and BASIC
 compiler. Many of the C graphics routines conflict with the BASIC
 graphic routines in the BASIC stand-alone library. If you need to do
 graphics when you link BASIC stand-alone programs with C, the graphics
 should be done in BASIC. An alternative is to compile without the BC
 /O option in BASIC.

 Linking BASIC programs compiled BC /O with Microsoft C graphics
 routines gives many "Duplicate Definition" errors, even if you LINK
 with the /NOE option. Compile without /O to eliminate the errors.


 87. BASIC Sample Program for OS/2 Function Calls for DLL Modules

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q37905

 Below is a sample program that makes a call to the following MS OS/2
 functions:

    DosLoadModule
    DosFreeModule
    DosGetProcAddr
    DosGetModHandle
    DosGetModName

 The program below can be compiled in Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2 and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The program below should be compiled with BASIC compiler Version 6.00
 or 6.00b, or BASIC PDS 7.00 and should use the default run-time module
 (BRUN60EP.DLL for BASIC compiler 6.00, BRUN61EP.DLL for BASIC compiler
 6.00b, and BRT70ENP.DLL for BASIC PDS 7.00). The run-time module is
 required because the call to DosGetModHandle is searching for the
 handle of the run-time module. The program can be modified to search
 for any given DLL (dynamic link library).

 The following is a code example:

 'The function declarations can be found in BSEDOSPE.BI

 DECLARE FUNCTION DosLoadModule%(_
       BYVAL P1s AS INTEGER,_
       BYVAL P1o AS INTEGER,_
       BYVAL P2  AS INTEGER,_
       BYVAL P3s AS INTEGER,_
       BYVAL P3o AS INTEGER,_
       SEG   P4  AS INTEGER)

 DECLARE FUNCTION DosFreeModule%(_
       BYVAL P1  AS INTEGER)

 DECLARE FUNCTION DosGetProcAddr%(_
       BYVAL P1  AS INTEGER,_
       BYVAL P2s AS INTEGER,_
       BYVAL P2o AS INTEGER,_
       SEG   P3  AS LONG)

 DECLARE FUNCTION DosGetModHandle%(_
       BYVAL P1s AS INTEGER,_
       BYVAL P1o AS INTEGER,_
       SEG   P2  AS INTEGER)

 DECLARE FUNCTION DosGetModName%(_
       BYVAL P1  AS INTEGER,_
       BYVAL P2  AS INTEGER,_
       BYVAL P3s AS INTEGER,_
       BYVAL P3o AS INTEGER)

 DEFINT a-z

 dllname$="BRUN60EP"+chr$(0)  'Change this "BRUN61EP" for 6.00B

 x=DosGetModHandle%(varseg(dllname$),sadd(dllname$),handle)

 IF (x) THEN
    Print "An error occurred in DosGetModHandle.  The number is : ";x
 ELSE
    Print "The handle for ";dllname$;" is : ";handle

    'Using the handle returned, find the name
    DIM buffer AS STRING*40
    length=40
    x=DosGetModName%(handle,length,varseg(buffer),varptr(buffer))
    IF (x) THEN
       Print "An error occurred in DosGetModName.  The number is : ";x
    ELSE
       Print "The module name for handle ";handle;" is ";buffer
    END IF

    'Load another DLL
    DIM bad AS STRING*128
    dllname$="DOSCALLS1"+chr$(0)
    x=DosLoadModule%(varseg(bad),varptr(bad),128,varseg(dllname$),_
              sadd(dllname$),handle)
    IF (x) THEN
       Print "An error occurred in DosLoadModule.  The number is : ";x
    ELSE
       Print "The handle for ";dllname$;" is : ";handle

       '#150 is an routine that can be found in DOSCALLS1
       routine$="#150"+chr$(0)
       DIM address AS LONG
       x=DosGetProcAddr%(handle,varseg(routine$),sadd(routine$),address)
       IF (x) THEN
        Print "An error occurred in DosGetProcAddr.  The number is : ";x
       ELSE
        Print "The address of ";routine$;" is ";address
       END IF

       'Unload module
       x=DosFreeModule%(handle)
       IF (x) THEN
        print "An error occurred in DosFreeModule.  The number is : ";x
       ELSE
        Print "DLL was freed."
       END IF
    END IF
 END IF
 END


 88. BC /A or CodeView Finds Run-Time Error Segment:Offset Address

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified: 26-FEB-1990    ArticleIdent: Q39190

 The following information applies to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2, to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2, and to
 QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS.

 When a run-time error message is displayed with a segment and offset
 address, the address is in hexadecimal notation. For example, "error
 in module [name] at 5517:0059" means a code segment address of 5517
 hexadecimal and a code offset address of 0059 hexadecimal.

 To find out where this address corresponds to a statement in your
 program, you can compile your program with the BC /A option and
 generate a .LST file. The .LST file lists the code offsets along with
 the BASIC statements and their translation into assembly-language
 code. You can use the module name and code offset from the run-time
 error message to find the error line in that module's .LST file. (The
 segment address from the error message is not needed to find the error
 line in the .LST file).

 You can also use the run-time error's segment:offset address in the
 Microsoft CodeView debugger to see which BASIC code caused the
 run-time error.

 The BC /A option requires the file to be saved in Text format. (If you
 save the source file in Fast Load and Save format, BC /A gives the
 compiler error "Cannot generate listing for BASIC binary source
 files.")

 Page 196 of the "Microsoft CodeView and Utilities: Software
 Development Tools for MS-DOS" manual states that you can use "V" to
 view an address in the segment:offset format. To view the source code
 executed at an address, type the following in CodeView:

    V &H5517:&H0059

 Note: QuickBASIC Versions 4.00, 4.00b, and 4.50 are not sold with the
 CodeView debugger. The CodeView debugger comes with Microsoft BASIC
 Compiler Version 6.00 or 6.00b, Microsoft BASIC PDS Version 7.00, or
 with Microsoft Macro Assembler Versions 5.00 and 5.10, but is not sold
 separately.

 The following is an example of finding the statement in error in a
 BASIC program based upon the code offset given in the run-time error
 message. The BASIC .EXE program below generates a "File Not Found"
 error at a specific address. Note that the error occurred at an offset
 (0057) right after a call to B$OPEN. This is a clue that the error
 occurred with the open routine.

 The following is a code example to be compiled with the BC /A option:

    CLS
    PRINT "This is a test of the /a option"
    OPEN "NONEXIST.DAT" FOR INPUT AS #1

 This program generates the following output:

    This is a test of the /a option

    File not found in module TEST     at address 5CCD:0057

 The .LST file generated with BC /A is as follows:
                                                            PAGE   1
                                                           28 Dec 88
                                                            09:35:26
 Offset  Data    Source Line      Microsoft (R) QuickBASIC

  0030   0006    CLS
  0030   0006    PRINT "This is a test of the /a option"
  0030   0006    OPEN "NONEXIST.DAT" FOR INPUT AS #1
  0030   0006
  0030   0006
  0030    **            I00002: mov   ax,0FFFFh
  0033    **                    push  ax
  0034    **                    call  B$SCLS
  0039    **                    mov   ax,offset <const>
  003C    **                    push  ax
  003D    **                    call  B$PESD
  0042    **                    mov   ax,offset <const>
  0045    **                    push  ax
  0046    **                    mov   ax,0001h
  0049    **                    push  ax
  004A    **                    mov   ax,0FFFFh
  004D    **                    push  ax
  004E    **                    mov   ax,0001h
  0051    **                    push  ax
  0052    **                    call  B$OPEN      <<-- offending line
  0057    **                    call  B$CENP
  005C   0006

 43613 Bytes Available
 43308 Bytes Free

     0 Warning Error(s)
     0 Severe  Error(s)


 89. Sample Program; BASIC Invoking C Function That Returns String

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881207-17
 Last Modified:  1-FEB-1990    ArticleIdent: Q39361

 The sample program below demonstrates a BASIC program calling a C
 routine that returns a BASIC string descriptor. This programming
 example is a variation of the sample program located on Page 310 of
 the "Microsoft QuickBASIC 4.0: Learning and Using" manual.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Note: The Microsoft C medium-memory model should be used to ensure
 that the C string is in DGROUP.

 Note: This information does not apply if using far string support in
 BASIC PDS Version 7.00 or when running inside the QuickBASIC extended
 (QBX.EXE) environment with BASIC PDS Version 7.00. For information on
 programming with mixed-languages using far strings refer to Chapter
 13, "Mixed-Language Programming with Far Strings," in the "Microsoft
 BASIC 7.0: Programmer's Guide."

 The COMPILE and LINK instructions are as follows:

    BC test.bas;
    CL /AM /c tc.c
    LINK test tc /noe;

 The BASIC routine is as follows:

    DECLARE FUNCTION t1$()
    a$ = t1$
    PRINT a$

 The C function is as follows:

    struct bas_str{
            int sd_len;
            char *sd_addr;
            };
    char cstr[]="ABC";
    struct bas_str pascal t1()
    {
       struct bas_str str_des;
       str_des.sd_addr = cstr;
       str_des.sd_len = strlen(cstr);
       return (str_des);
    }


 90. Can't Define SUB/FUNCTION in INCLUDE File

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas SR# S881209-27
 Last Modified:  1-FEB-1990    ArticleIdent: Q39581

 The command line compiler BC.EXE fails to flag the error if you put a
 procedure definition (SUB...END SUB or FUNCTION...END FUNCTION) into
 an INCLUDE file. The program compiles, LINKs, and runs without error.

 QB.EXE, and QBX.EXE included with Microsoft BASIC Professional
 Development System (PDS) Version 7.00, correctly gives the error
 "Statement cannot occur within include file." Procedure definitions
 are not allowed in $INCLUDE files.

 This information applies to QuickBASIC Versions 4.00b and 4.50, to
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 The BC.EXE from QuickBASIC Version 4.00 correctly flags the error.

 The following is a example:

    DIM arr(50)
    REM $INCLUDE: 'getsub.inc'
    FOR i = 1 TO 50
       arr(i) = i
    NEXT i
    CALL prntarray(arr())
    END

    'This is GETSUB.INC, the separate include file:
    SUB prntarray (a())
       FOR j = 1 TO 50
          PRINT a(j)
       NEXT j
    END SUB


 91. BC 6.00 Example to Manipulate File with OS/2 API Calls

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890125-57
 Last Modified:  1-FEB-1990    ArticleIdent: Q40865

 Below is a sample program that calls the following MS OS/2 API
 functions:

    DosBufReset
    DosChgFilePtr
    DosClose
    DosOpen
    DosQFHandState
    DosQHandType
    DosRead
    DosSetFHandState
    DosWrite

 This program can be compiled in Microsoft BASIC Compiler Version 6.00
 or 6.00b for MS OS/2 and Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 The following is the sample program:

 CONST TRUE=-1
 CONST FALSE=0

 REM $INCLUDE: 'BSEDOSFL.BI'
 DEFINT A-Z
 DIM sizel AS LONG
 DIM reserved AS LONG
 DIM buf AS STRING*512
 DIM distance AS LONG
 DIM NewPointer AS LONG

 CLS
 input "Enter the Filename : ";fl$
 fl$=fl$+chr$(0)
 openflag = 17
 openmode = &h6092
 PRINT
 PRINT "Enter a Key to OPEN the file"
 WHILE INKEY$="" : WEND
 PRINT
 x=DosOpen(varseg(fl$),sadd(fl$),handle,action,sizel,_
           filea,openflag,openmode,reserved)

 IF (x) THEN
    print "An error occurred.  The number is : ";x
    end
 ELSE
   print "The handle is : ";handle
   print "The action is : ";action
   print "The size is   : ";sizel
   print "The filea is  : ";filea
   print "The openflag  : ";openflag
   print "The openmode  : ";openmode
   size=512
   buffer$=string$(size/4,65)+string$(size/4,66)
   buffer$=buffer$+string$(size/4,67)+string$(size/4,68)+chr$(0)
   PRINT
   PRINT "Enter a Key to WRITE to the file"
   WHILE INKEY$="" : WEND
   PRINT
   x=DosWrite%(handle,varseg(buffer$),sadd(buffer$),size,nw)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     print "The information was placed into the file."
     print "The number of bytes written was : ";nw
   END IF
 END IF
 PRINT
 PRINT "Enter a Key to CLOSE the file"
 WHILE INKEY$="" : WEND
 PRINT

 x=DosClose%(handle)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The file is closed." : print
 END IF
 PRINT
 PRINT "Enter a Key to RE-OPEN the file"
 WHILE INKEY$="" : WEND
 PRINT
 x=DosOpen(varseg(fl$),sadd(fl$),handle,action,sizel,_
           filea,openflag,openmode,reserved)

 IF x THEN
    print "error: ";x
    stop
 END IF
 DONE=FALSE
 WHILE NOT(done)
   size=256
   buf=string$(size,42)
   PRINT
   PRINT "Enter a Key to READ the file"
   WHILE INKEY$="" : WEND
   PRINT

   x=DosRead%(handle,varseg(buf),varptr(buf),size,nr)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     IF nr=0 THEN
        PRINT "EOF Detected"
        DONE=TRUE
     ELSE
        PRINT "The number of bytes read is : ";nr
        PRINT "The bytes were : ";buf
     END IF
   END IF
 WEND
   PRINT
   PRINT "Enter a Key to RESET the file BUFFER"
   WHILE INKEY$="" : WEND
   PRINT
   x=DosBufReset%(handle)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     PRINT "The BUFFER was flushed"
   END IF
 PRINT
 PRINT "Enter a Key to CHANGE the file POINTER"
 WHILE INKEY$="" : WEND
 PRINT
 distance=192
 MoveType=0

 x=DosChgFilePtr%(handle,distance,MoveType,NewPointer)
 IF (x) THEN
   Print "An error occurred.  The number is : ";x
 ELSE
   Print "The file pointer is moved.  The information will be read."
   size=256
   buf=string$(size,42)
   PRINT
   PRINT "Enter a Key to READ the file"
   WHILE INKEY$="" : WEND
   PRINT

   x=DosRead%(handle,varseg(buf),varptr(buf),size,nr)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     IF nr=0 THEN
        PRINT "EOF Detected"
        DONE=TRUE
     ELSE
        PRINT "The number of bytes read is : ";nr
        PRINT "The bytes were : ";buf
     END IF
   END IF
 END IF
 PRINT
 PRINT "Enter a Key to get the GET/Modify File Handle State"
 WHILE INKEY$="" : WEND
 PRINT

 x=DosQFHandState%(handle,FileHandleState)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The filehandle state is : ";FileHandleState
 END IF

 NewHandState=&h0010
 x=DosSetFHandState%(handle,NewHandleState)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The filehandle state was changed."
 END IF

 x=DosQFHandState%(handle,FileHandleState)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The filehandle state is : ";FileHandleState
 END IF

 x=DosQHandType%(handle,HandType,FlagWord)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    IF (HandleType) THEN
        print "The handle type is a Device handle"
        print "The Flag Word is : ";Flag Word
    ELSE
        print "The handle type is a File-System handle"
    END IF
 END IF
 PRINT
 PRINT "Enter a Key to CLOSE the file"
 WHILE INKEY$="" : WEND
 PRINT
 x=DosClose%(handle)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The file is closed."
 END IF
 END


 92. BC 6.00 Example of OS/2 API Calls DosGetPrty, DosSetPrty

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890125-56
 Last Modified:  1-FEB-1990    ArticleIdent: Q40866

 Below is a sample program that calls the MS OS/2 API functions
 DosGetPrty and DosSetPrty. This program can be compiled in Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS OS/2 and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 The following is the sample program:

 REM $INCLUDE: 'BSEDOSPC.BI'
 DEFINT a-z
 DIM pids AS PidInfo

 x%=DosGetPid(pids)
 IF (x%) THEN
    PRINT "An error occurred in DosGetPid: ";x%
    END
 ELSE
    pid=pids.pid
    scope = 0
    x% = DosGetPrty(scope,priority,pid)
    IF (x%) THEN
        PRINT "An error occurred in DosGetPrty: ";x%
        END
    ELSE
       PRINT
       PRINT "Priority: "; Priority
       PRINT
       CALL SetPrty(pid)
       PRINT
       PRINT "Enter a Key to Verify Change..."
       WHILE INKEY$="": WEND
       scope=0
       x%=DosGetPrty(scope,priority,pid)
       IF (x%) THEN
          PRINT "An error Occurred in DosGetPrty: ";x%
          END
       ELSE
          PRINT
          PRINT "Priority: "; Priority
       END IF
    END IF
 END IF
 END

 SUB SetPrty(pid) STATIC
     Print "Enter the SCOPE (0 - Process and all threads)"
     PRINT "                (1 - Process and all the descendants)"
     PRINT "                (2 - Thread calling the function)"
     INPUT "                                         OPTION: ";scope
     PRINT
     PRINT "Enter the CLASS (0 - No Change)"
     PRINT "                (1 - Idle-time)"
     PRINT "                (2 - Regular)"
     PRINT "                (3 - Time-Critical)"
     INPUT "                             OPTION: ";class
     PRINT
     INPUT "Enter CHANGE (-31 to + 31) : "; change
     x% = DosSetPrty%(scope,class,change,pid)
     if (x%) then
         PRINT "Error setting Priority - ";x%
     else
         PRINT "Priority Changed."
     end if
 END SUB


 93. BC 6.00 Example of OS/2 API Calls DosError, DosErrClass

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890125-55
 Last Modified:  1-FEB-1990    ArticleIdent: Q40867

 Below is an example of using the MS OS/2 API function DosError and
 DosErrClass. This program must be compiled with Microsoft BASIC
 Compiler Version 6.00 and 6.00b for MS OS/2 and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS OS/2.

 The following is the sample program:

 DEFINT a-z
 REM $include: 'bsedosfl.bi'
 REM $include: 'bsedospc.bi'
 PRINT "Note: This only affects OS/2 API calls you call"
 PRINT "      BASIC handles its own errors"
 PRINT
 PRINT "Enter (0) to SUSPEND system hard-error processing"
 INPUT "or (1) to RESUME system hard-error processing : ";y%
 PRINT
 x=DOSERROR%(y%)

 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    Print "Hard-Error Processing Suspended"
    Print "Open Drive Door A and Enter any Key..."
    PRINT
    WHILE INKEY$="" : WEND
 END IF
 fl$="A:\ABC.EXE"+chr$(0)

 code%=DosQFileMode(varseg(fl$),sadd(fl$),attribute%,0&)
 if (code%) then
    Print "Error Returned from DosQFileMode: " code%
    x% = DosErrClass(code%,class%,action%,locus%)
    IF (x%) THEN
       PRINT "An error was received determining class"
    ELSE
       CALL DetermineError(class%,action%,locus%)
    END IF
 END IF
 END

 SUB DetermineError(class%,action%,locus%) STATIC
 PRINT "Error Class: ";
 SELECT CASE class%
        CASE 1
          PRINT "ERRCLASS_OUTRES ==> Out of Resource"
        CASE 2
          PRINT "ERRCLASS_TEMPSIT ==> This is a Temporary Situation"
        CASE 3
          PRINT "ERRCLASS_AUTH ==> Authorization has failed"
        CASE 4
          PRINT "ERRCLASS_INTRN ==> An Internal Error has Occurred"
        CASE 5
          PRINT "ERRCLASS_HRDFAIL ==> A Device Hardware Failure"
        CASE 6
          PRINT "ERRCLASS_SYSFAIL ==> A System Failure has Occurred"
        CASE 7
 PRINT "ERRCLASS_APPERR ==> A Probable Application Error has Occurred"
        CASE 8
          PRINT "ERRCLASS_NOTFND ==> The Item was not Located"
        CASE 9
          PRINT "ERRCLASS_BADFMT ==> Bad Format"
        CASE 10
          PRINT "ERRCLASS_LOCKED ==> Locked"
        CASE 11
 PRINT "ERRCLASS_MEDIA ==> Incorrect Media; a CRC Error has Occurred"
        CASE 12
          PRINT "ERRCLASS_ALREADY ==> Everything is Ready"
        CASE 13
          PRINT "ERRCLASS_UNK ==> Error is Unclassified"
        CASE 14
          PRINT "ERRCLASS_CANT ==> Cannot perform Requested Action"
        CASE 15
          PRINT "ERRCLASS_TIME ==> Time-out has Occurred"
        CASE ELSE
          PRINT "UnKnown Class"
 END SELECT
 Print "Recommended Action: ";
 SELECT CASE action%
        CASE 1
          PRINT "ERRACT_RETRY ==> Retry Immediately"
        CASE 2
          PRINT "ERRACT_DLYRET ==> Delay and Retry"
        CASE 3
          PRINT "ERRACT_USER ==> Bad User Input; Get New values"
        CASE 4
          PRINT "ERRACT_ABORT ==> Terminate in an Orderly Manner"
        CASE 5
          PRINT "ERRACT_PANIC ==> Terminate Immediately"
        CASE 6
          PRINT "ERRACT_IGNORE ==> Ignore the Error"
        CASE 7
          PRINT "ERRACT_INTRET ==> Retry After User Intervention"
        CASE ELSE
          PRINT "UnKnown Class"
 END SELECT
 PRINT "Location: ";
 SELECT CASE locus%
        CASE 1
          PRINT "ERRLOC_UNK ==> The Origin of the Error is Unknown"
        CASE 2
          PRINT "ERRLOC_DISK ==> The Error Occurred in a Random-Access"
          PRINT "                Device, such as a Disk Drive"
        CASE 3
          PRINT "ERRLOC_NET ==> This is a Network Error"
        CASE 4
          PRINT "ERRLOC_SERDEV ==> This is a Serial-Device Error"
        CASE 5
          PRINT "ERRLOC_MEM ==> This is a Memory Parameter Error"
        CASE ELSE
          PRINT "Unknown Location Error"
 END SELECT
 END SUB


 94. BC 6.00 Example of OS/2 API Function Call DosExecPgm

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890125-54
 Last Modified:  1-FEB-1990    ArticleIdent: Q40868

 Below is an example of using the MS OS/2 API function DosExecPgm. This
 program must be compiled with Microsoft BASIC Compiler Versions 6.00
 or 6.00b for MS OS/2 or Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 The following is the example code:

 'The definitions are taken from BSEDOSPC.BI
 TYPE ResultCodes
      codeterminate as integer
      coderesult as integer
 END TYPE
 DECLARE FUNCTION DosExecPgm%(_
         BYVAL p1S AS INTEGER,_
         BYVAL p1o AS INTEGER,_
         BYVAL p2  AS INTEGER,_
         BYVAL p3  AS INTEGER,_
         BYVAL p4s AS INTEGER,_
         BYVAL p4o AS INTEGER,_
         BYVAL p5s AS INTEGER,_
         BYVAL p5o AS INTEGER,_
         SEG   p6  AS ResultCodes,_
         BYVAL p7s AS INTEGER,_
         BYVAL p7o AS INTEGER)
 DEFINT A-Z
 DIM results as ResultCodes

 INPUT "Enter NAME of EXE file (with .EXE) to execute: "; fln$
 fln$ = fln$ + chr$(0)
 buffer$=space$(255)+chr$(0)
 bufferlen = len(buffer$)
 AsyncTraceFlags = 1  'Execute Asynchronously to the parent
 ArgPointer$=chr$(0)
 EnvPointer$=chr$(0)
 x% = DosExecPgm(varseg(buffer$),sadd(buffer$),_
                 bufferlen,AsyncTraceFlags,_
                 varseg(ArgPointer$),sadd(ArgPointer$),_
                 varseg(EnvPointer$),sadd(EnvPointer$),_
                 results, varseg(fln$),sadd(fln$))
 PRINT "ExecPgm Error CODE : ";x%
 SLEEP(5)
 PRINT "This Parent is Complete"
 END


 95. BC 6.00 Example of OS/2 API Function Call DosNewSize

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890125-34
 Last Modified:  1-FEB-1990    ArticleIdent: Q40870

 Below is a sample program that makes a call to the MS OS/2 API
 function DosNewSize. This function can be used to truncate or expand a
 file. If the file is expanded, the new bytes are undefined. The
 program also makes calls to DosOpen and DosClose.

 The program can be compiled in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS OS/2 and Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 The following is the sample program:

 REM $INCLUDE: 'bsedosfl.bi'
 DEFINT a-z
 CLS
 DIM filelist AS FileStatus
 DIM sizel AS LONG
 DIM reserved AS LONG
 DIM buf AS STRING*512
 DIM distance AS LONG
 DIM NewPointer AS LONG

 input "Enter the Filename : ";fl$
 fl$=fl$+chr$(0)
 openflag=17
 openmode=&h6092

 x=DosOpen(varseg(fl$),sadd(fl$),handle,action,sizel,_
           filea,openflag,openmode,reserved)

 IF (x) THEN
    print "An error occurred.  The number is : ";x
    end
 ELSE
   input "Enter the new size ",newsize&
   x=DosNewSize(handle,newsize&)
   IF (x) THEN
      Print "An error occurred.  The number is : ";x
   ELSE
      Print "File size was changed"
   END IF
   x=DosClose%(handle)
   IF (x) THEN
      color 7 :PRINT "An error occurred. The number is : ";x :color 15
   ELSE
      print "File Closed."
      print "Enter any key to exit..."
      while inkey$="" :wend
   END IF
 END IF
 END


 96. Some Coprocessor Assembler Instructions Are Not Emulated

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas S_C H_Fortran H_MASM SR# S890111-171
 Last Modified:  1-FEB-1990    ArticleIdent: Q40872

 Microsoft Macro Assembler Version 5.10 does not come with routines to
 emulate a math coprocessor.

 Page 382 of the "Microsoft Macro Assembler 5.1: Programmer's Guide"
 states that to emulate math-coprocessor instructions, you must link
 with a Microsoft high-level language that supports floating-point
 emulation of the coprocessor. You would write the assembler procedure
 using coprocessor instructions, then assemble with the /E option, and
 finally link it with the high-level language modules.

 However, only a subset of coprocessor instructions are emulated by the
 Microsoft high-level languages.

 If you link your Microsoft higher-level language to an assembler
 routine that invokes an instruction that is NOT emulated by the
 higher-level language, then the program gives a run-time error (or
 possibly hangs, or gives incorrect results) when run on a machine that
 has no coprocessor.

 This information applies to the following products:

 1.  Microsoft BASIC Compiler Versions 6.00 and 6.00b

 2.  Microsoft BASIC Professional Development System (PDS) Version 7.00

 3.  Microsoft QuickBASIC Version 4.50

 4.  Microsoft C Compiler Version 5.10

 5.  Microsoft FORTRAN Compiler Version 4.10

 Below is a list of the coprocessor (8087 or 80287) instructions that
 are not emulated by Microsoft high-level languages:

    FBLD    - packed decimal load
    FBSTP   - packed decimal store and pop
    FCOS    - cosine function
    FDECSTP - decrement stack pointer
    FINCSTP - increment stack pointer
    FINIT   - initialize processor
    FLDENV  - load environment
    FNOP    - No operation
    FPREM1  - partial remainder
    FRSTOR  - restore saved state
    FSAVE   - save state
    FSETPM  - set protected mode
    FSIN    - only sine function
    FSINCOS - sine and cosine function
    FSTENV  - store environment
    FUCOM   - unordered comparison
    FUCOMP  - unordered comparison and pop
    FUCOMPP - unordered comparison and double pop
    FXTRACT - extract exponent and significant

 Also, some of the No-Wait forms of instructions are not emulated, such
 as FNSTENV and FNINIT.


 97. BC 6.00 Example of OS/2 API Function Call DosDupHandle

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890125-58
 Last Modified:  1-FEB-1990    ArticleIdent: Q40873

 Below is a sample program that makes a call to the MS OS/2 API
 function DosDupHandle. It also uses the following MS OS/2 API
 functions:

    DosOpen
    DosRead
    DosWrite
    DosClose

 This program can be compiled in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS OS/2 and Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 The following is the sample program:

 CONST TRUE=-1
 CONST FALSE=0
 REM $include: 'BSEDOSFL.BI'

 DEFINT A-Z
 DIM sizel AS LONG
 DIM reserved AS LONG
 DIM buf AS STRING*512
 DIM distance AS LONG
 DIM NewPointer AS LONG
 CLS

 input "Enter the Filename : ";fl$
 fl$=fl$+chr$(0)
 openflag=17
 openmode=&h6092

 x=DosOpen(varseg(fl$),sadd(fl$),handle,action,sizel,_
           filea,openflag,openmode,reserved)

 IF (x) THEN
    print "An error occurred.  The number is : ";x
    end
 ELSE
   print "The handle is : ";handle
   print "The action is : ";action
   print "The size is   : ";sizel
   print "The filea is  : ";filea
   print "The openflag  : ";openflag
   print "The openmode  : ";openmode
   size=512
   buffer$=string$(size/4,65)+string$(size/4,66)+string$(size/4,67)
   buffer$=buffer$+string$(size/4,68)+chr$(0)

   x=DosWrite%(handle,varseg(buffer$),sadd(buffer$),size,nw)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     print "The information was placed into the file."
     print "The number of bytes written was : ";nw
   END IF
 END IF

 x=DosClose%(handle)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The file is closed." : print
 END IF
 print "Enter Any Key OPEN file and DUPLICATE Handle..."
 while inkey$="" :wend

 x=DosOpen(varseg(fl$),sadd(fl$),handle,action,sizel,_
           filea,openflag,openmode,reserved)
 x=DosDupHandle%(handle,newhandle)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     Print "Handle was Duplicated."
   END IF
 PRINT
 PRINT "Enter any Key to READ with Both handles"
 PRINT
 WHILE INKEY$="" : WEND
 size=256
 buf=string$(size,42)
 x=DosRead%(handle,varseg(buf),varptr(buf),size,nr)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     IF nr=0 THEN
        PRINT "EOF Detected"
     ELSE
        PRINT "ORIGINAL HANDLE"
        PRINT "The number of bytes read is : ";nr
        PRINT "The bytes were : ";buf
     END IF
   END IF
 size=256
 buf=string$(size,42)
 x=DosRead%(newhandle,varseg(buf),varptr(buf),size,nr)
   IF (x) THEN
     Print "An error occurred.  The number is : ";x
   ELSE
     IF nr=0 THEN
        PRINT "EOF Detected"
     ELSE
        PRINT "NEW HANDLE"
        PRINT "The number of bytes read is : ";nr
        PRINT "The bytes were : ";buf
     END IF
   END IF

 x=DosClose%(handle)
 IF (x) THEN
    Print "An error occurred.  The number is : ";x
 ELSE
    print "The file is closed."
 END IF
 END


 98. Mouse Not Supported on VGA in OS/2 Real Mode; OK in MS-DOS

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# S890222-67 B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q42589

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 In MS OS/2 real mode under MS OS/2 Versions 1.00 and 1.10, due to
 limitations of the MS OS/2 mouse controller, the mouse driver does not
 support operating with VGA graphics. The mouse works correctly in EGA,
 CGA, and text modes. This problem was corrected in MS OS/2 Version
 1.20.

 In MS OS/2 protected mode, the MS OS/2 mouse driver does not support
 the drawing of the mouse pointer in graphics modes. It is up to the
 application to draw its own pointer. The mouse driver provides
 notification of mouse movement to an MS OS/2 application, provided
 that the VioSetMode CALL (set graphics mode) is used AFTER the MouOpen
 (open the mouse) and the MouSetDevStatus (to disable pointer drawing)
 CALLs are performed.

 More information on the VioSetMode and MouSetDevStatus MS OS/2 API
 CALLs can be found in the "Microsoft Operating System/2: Programmer's
 Toolkit Programming Tools."


 99. "SYS2090" Error Using SETUP, LINK, or LIB with BASIC Compiler

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  1-FEB-1990    ArticleIdent: Q42591

 You can receive the error, "SYS2090: Unable to load User Program" when
 trying to run the SETUP.EXE, LINK.EXE, or LIB.EXE program (from
 Microsoft BASIC Compiler Versions 6.00 or 6.00b and Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2) in either the protected or real modes of Microsoft OS/2.

 This Microsoft OS/2 error typically occurs when trying to run a bound
 application that is not configured correctly in the real (MS-DOS)
 environment. Because bound applications can run under both real or
 protected mode, these applications are very sensitive to their
 environment.

 The following are some possible reasons for this error in real mode:

 1. A corrupted or zero-length .EXE file.

 2. When running under the standard MS-DOS environment, you may be
    using MS-DOS Versions 2.x. Running a bound application under MS-DOS
    2.x requires that the bound programs be placed in the current
    subdirectory. Using MS-DOS Versions 3.x will also correct the
    problem.

 3. Problems with the specific BIOS, possibly corrected by upgrading
    the ROM version.

 4. Interference by terminate-and-stay-resident (TSR) programs and some
    unpatched versions of Novell netware has been observed to cause
    SYS2090 errors. Novell users should contact their dealers to obtain
    patched versions of the netware that emulate MS-DOS 3.x correctly by
    preserving the SS and SP registers when spawning processes. Novell
    netware Version 2.0A++, and Versions 2.10 and later are patched
    properly, according to Novell.)


 100. BASIC User-Entry Points Cannot Be Called from Other Languages

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | docerr B_QuickBas H_MASM S_C S_PasCal H_Fortran
 Last Modified:  8-JAN-1991    ArticleIdent: Q42700

 The "Microsoft Mixed-Language Programming Guide" is packaged with
 Microsoft C Versions 5.00 and later, Microsoft Pascal Versions 4.00
 and later, Microsoft FORTRAN Versions 4.10 and later, and Microsoft
 Macro Assembler (MASM) Versions 5.00 and later.

 On the bottom of Page 39, there is a note that incorrectly states that
 QuickBASIC Version 4.00 provides a number of "user-entry points,"
 which are BASIC system-level functions that may be called directly
 from C, and that the README file provides more information. However,
 there is no information on these "user-entry points" in the README.DOC
 file provided with QuickBASIC Versions 4.00, 4.00b, or 4.50, Microsoft
 BASIC Compiler Versions 6.00 and 6.00b, or Microsoft BASIC
 Professional Development System (PDS) Version 7.00 or 7.10 for MS-DOS
 and MS OS/2. This note should be removed, since there are no such
 user-entry points available.


 101. M.EXE Editor's CALLTREE Does Not Support BASIC Source Files

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | B_QuickBas SR# S890212-9
 Last Modified:  1-FEB-1990    ArticleIdent: Q43788

 The CALLTREE program used by the Microsoft M.EXE editor does not
 produce meaningful results for BASIC source files. The CALLTREE
 utility is provided with the Microsoft Editor for use with Microsoft C
 and Microsoft Macro Assembler (MASM). It returns a listing of a C or
 MASM program's function-calling structure in a tree format. CALLTREE
 processes BASIC files with no error messages; however, the results are
 not correct.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, to Microsoft BASIC Professional
 Development System (PDS) Version 7.00, and to Microsoft QuickBASIC
 Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50. (Note: The Microsoft
 M.EXE editor comes with the BASIC compiler 6.00 and 6.00b and
 Microsoft BASIC PDS Version 7.00 but not with any version of the
 QuickBASIC package.)

 Code Example
 ------------

 The following is the BASIC SOURCE FILE for testing CALLTREE:

 DECLARE SUB anysub1 ()
 DECLARE SUB anysub3 ()
 DECLARE SUB anysub2 ()

 CLS
 CALL anysub3
 END

 SUB anysub1
   PRINT "inside of subroutine 1"
 END SUB

 SUB anysub2
 PRINT "Inside of subroutine 2"
 CALL anysub1
 END SUB

 SUB anysub3
   PRINT "Inside of subroutine 3"
   CALL anysub2
 END SUB

 The following is the CALLTREE OUTPUT for the above BASIC file:

 anysub1
 anysub3
 anysub2

 The following is the C SOURCE FILE for testing CALLTREE:

 void func1(void)
 {
   printf("Inside of function 1\n");
 }

 void func2(void)
 {
   printf("inside of function 2\n");
   func1();
 }

 void func3(void)
 {
   printf("Inside of function 3\n");
   func2();
 }

 void main(void)
 {
   func3();
 }

 The following is the CALLTREE OUTPUT for the above C program:

 func1
 |   printf?
 func2
 |   printf?
 |   func1
 |   |   printf?
 func3
 |   printf?
 |   func2
 |   |   printf?
 |   |   func1
 |   |   |   printf?
 main
 |   func3
 |   |   printf?
 |   |   func2
 |   |   |   printf?
 |   |   |   func1
 |   |   |   |   printf?


 102. BC 6.00's BUILDRTM Has Not Been Tested with QB 4.50's Compiler

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified:  4-JAN-1990    ArticleIdent: Q43931

 QuickBASIC Version 4.50 has not been tested with the BUILDRTM.EXE
 found in Microsoft BASIC Compiler Versions 6.00 and 6.00b and
 Microsoft BASIC PDS Version 7.00. Microsoft does not claim that
 BUILDRTM.EXE will work correctly with object modules compiled using
 the BC.EXE compiler from QuickBASIC 4.50.

 "Unresolved Externals" during linkage is one of the reported errors
 that occurs when using the BUILDRTM.EXE on an object module compiled
 with the BC.EXE from QuickBASIC 4.50.

 BUILDRTM is designed for use only with Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and OS/2 and Microsoft BASIC PDS
 Version 7.00 for MS-DOS and OS/2. BUILDRTM adds routines to extend the
 BRUN6xx.EXE run-time libraries for Versions 6.00 and 6.00b and the
 BRT70xxx.EXE run-time libraries for BASIC PDS 7.00.


 103. MARKEXE.EXE in OS/2 May Cause .EXE Hang at Run Time

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890424-101
 Last Modified:  4-JAN-1990    ArticleIdent: Q44230

 Microsoft BASIC Compiler programs running in OS/2 protected mode take
 over the full screen by default and will not run from an OS/2
 Presentation Manager (PM) windowed environment unless you first alter
 the .EXE program's header with the MARKEXE utility or with PM's Start
 Programs window (as shown further below).

 It has been reported that system crashes may intermittently occur
 while running graphics-mode programs from the PM windowed environment.
 Only nongraphics programs using SCREEN 0 in a PM windowed environment
 seem to work without problems, and this is not always the case either.
 It has also been reported that system crashes have occurred while
 running character-mode (SCREEN 0) programs from within a PM windowed
 environment.

 Microsoft has not tested programs running within a PM window that were
 compiled with Microsoft BASIC Compiler Versions 6.00, 6.00b, or
 Microsoft BASIC PDS Version 7.00. This feature is under review and
 will be considered for inclusion in a future release.

 While there are problems running BASIC programs from within a PM
 window, you can write OS/2 Presentation Manager (PM) applications
 using BASIC compiler Versions 6.00 and 6.00b and BASIC PDS Version
 7.00. This information is detailed in a separate article that can be
 found by querying on the following words:

   OS/2 and Presentation and Manager and BASIC

 The MARKEXE.EXE utility program is shipped on the Toolkit 1 disk
 with the Microsoft OS/2 Software Development Kit and is used for
 altering the header of a bound or protected-mode executable program
 (.EXE) to run from a PM windowed environment. The following is an
 example of running MARKEXE:

    MARKEXE progname windowcompat

 Another method to modify your compiled BASIC .EXE to run under a PM
 window (in protected mode) is to do the following:

 1. Choose the Add option from the Program menu of the Start Programs
    window in PM.

 2. Choose Change from the Program menu. The Change Program Information
    window now appears.

 3. Choose Other for the Program Type. Press the ENTER key. The How To
    Run The Program window now appears.

 4. Choose Run The Program In A Text Window to run your program in a
    PM window. Press the ENTER key.

 You can now run your program in a PM window from OS/2's Start Program
 window or from the OS/2 full-screen command prompt.

 If the program is deleted from the Start Program menu, the .EXE header
 is changed back to what it was prior to being entered into the Start
 Program menu.


 104. LPOS(0) and LPOS(1) Both Return Print Head Position for LPT1

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | docerr B_QuickBas
 Last Modified:  2-FEB-1990    ArticleIdent: Q45420

 The LPOS(0) and LPOS(1) functions both return the current position of
 the print head within the printer buffer for LPT1. LPOS(2) returns
 the current print position for LPT2.

 On Page 263 of the "Microsoft BASIC Compiler 6.0: BASIC Language
 Reference" manual for Versions 6.00 and 6.00b for MS OS/2 and MS-DOS,
 the program example uses LPOS(0) to return the current position of the
 line printer's print head within the print buffer, but no mention is
 made of LPOS(0) in the function description. LPOS(0) operates the same
 as LPOS(1), and there is no difference between the two functions.

 This information applies also to Page 263 of the "Microsoft QuickBASIC
 4.0: BASIC Language Reference" manual for QuickBASIC Versions 4.00 and
 4.00b, to Page 224 of the "Microsoft QuickBASIC 4.5: BASIC Language
 Reference" for Version 4.50, and to the QuickBASIC Version 4.50 QB
 Advisor online Help system.

 This documentation error was corrected on Page 204 of the "Microsoft
 BASIC 7.0: Language Reference" manual for Microsoft BASIC Professional
 Development System (PDS) Version 7.00.


 105. CodeView Can't Watch Array Passed to BASIC SUBprogram

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas buglist6.00 buglist6.00b buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q47060

 When debugging a BASIC program (compiled with BC.EXE versions 7.00 and
 earlier) with Microsoft CodeView (version 2.20, 2.30, 2.35, 3.00, or
 3.10), an attempt to watch an array passed to a SUBprogram produces
 the error "Not an array."

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 (even though they do not provide CodeView on the
 release disks) (buglist4.00, buglist4.00b, buglist4.50); in Microsoft
 BASIC Compiler versions 6.00 and 6.00b (which provide CodeView version
 2.20 on the release disks); and in Microsoft BASIC Professional
 Development System (PDS) version 7.00 (which provides CodeView version
 2.35 on the release disks). This problem is corrected by compiling the
 program with BASIC PDS version 7.10 and using Microsoft CodeView
 version 3.10, which comes with BASIC PDS 7.10.

 As a workaround in earlier versions, you can make the array global by
 putting it in a COMMON statement and not passing it through a CALL
 statement's parameter list.

 Note that CodeView version 2.20 is shipped with Microsoft BASIC
 Compiler versions 6.00 and 6.00b; CodeView 2.30 is shipped with
 Microsoft FORTRAN version 5.00; CodeView version 2.35 is shipped with
 Microsoft BASIC Professional Development System (PDS) version 7.00;
 CodeView version 3.00 is shipped with Microsoft C Compiler version
 6.00; and CodeView 3.10 is shipped with Microsoft BASIC PDS version
 7.10.

 The following program is CVTEST.BAS, which demonstrates the above
 problem when compiled in BC.EXE 7.00 or earlier, and run under
 Microsoft CodeView:

    DECLARE SUB test (a() AS INTEGER)
    DIM a(5) AS INTEGER
    a(3) = 3
    PRINT a(3)
    CALL test(a())
    END

    SUB test (a() AS INTEGER)
      PRINT a(3)
    END SUB

 To demonstrate the problem, compile and link as follows:

    BC /Zi TEST.BAS;
    LINK /CO TEST;

 Load the program into CodeView (CV.EXE) and set a Watch (CTRL+W) on
 the variable a(3), then single-step the program (by pressing function
 key F8) until you execute the PRINT a(3) statement inside the
 SUB...END SUB procedure. At this point, the "Not an array" error
 message appears.

 Additional article reference words: S_CodeView


 106. Using BASIC to Perform Serial Communications in MS OS/2

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890801-2
 Last Modified: 17-JAN-1991    ArticleIdent: Q48400

 This article contains a sample BASIC module that calls API routines in
 MS OS/2 protected mode to perform serial communications through
 communications port COM1, COM2, COM3, or COM4.

 You must link NOCOM.OBJ (which requires BC /O) with this module before
 attempting to use this module's routines.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 (in protected mode only) and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for MS
 OS/2 (in protected mode only).

 The following steps must be taken to use the COMPORT.BAS module
 (farther below):

 1. Create a program called COM.BAS that makes calls to the routines
    found in COMPORT.BAS and compile the program.

 2. Compile COMPORT.BAS. Ensure that COMPORT.BI (shown below) and
    BSEDOSFL.BI (included with BASIC compiler 6.00/6.00b and BASIC
    PDS 7.00/7.10) are in a directory that is in the $INCLUDE
    statement's explicit path.

 3. Link your program to COMPORT.OBJ in addition to NOCOM.OBJ.

 The following is a sample file that, when used as input for the MAKE
 utility, compiles and links a program called COM.BAS that uses the
 COMPORT module:

 #----------------------
 # MAKE file for COM.BAS
 #----------------------
 comport.obj : comport.bas comport.bi
      BC /LP /Z /O /D COMPORT.BAS;
 com.obj : com.bas comport.bi
      BC /LP /Z /O /D COM.BAS;
 com.exe : com.obj comport.obj
      link /EX com comport nocom;

 COMPORT.BI
 ----------

 ' parameter buffer for DosDevIOCtrl Function 41H
 TYPE F41Info
     BaudRate AS INTEGER
 END TYPE

 ' parameter buffer for DosDevIOCtrl Function 42H
 TYPE F42Info
     DataBits AS STRING * 1
     Parity AS STRING * 1
     StopBits AS STRING * 1
 END TYPE

 ' data buffer for DosDevIOCtrl Function 68H
 TYPE F68Info
     NumChars AS INTEGER   ' Number of characters waiting in
                           '   device queue
     QueueSize AS INTEGER  ' Size of queue
 END TYPE

 DECLARE FUNCTION InitComPort% (ComPort$, Baud%, Parity%,_
                                DataBit%,StopBit%)
 DECLARE SUB WriteCom (Handle%, ToCom$, BytesWritten%)
 DECLARE SUB PrintCom (Handle%, ToCom$, BytesWritten%)
 DECLARE SUB ReadCom (Handle%, FromCom$, BytesToRead%,_
                      BytesRead%)
 DECLARE SUB ComSize (Handle%, Size%)
 DECLARE SUB CloseCom (Handle%)

 COMPORT.BAS
 -----------

 ' $INCLUDE: 'COMPORT.BI'
 ' $INCLUDE: 'BSEDOSFL.BI'
 ' Note:
 '       These routines call OS/2 system functions
 ' that always return a value indicating whether or not an
 ' error has occurred. In this module, ReturnErr% always
 ' contains this value. A return value of 0 means no error
 ' occurred. This module does no error checking. This would
 ' have to be added using the values in ReturnErr%.
 '       For added flexibility in configuring the port, use
 ' DosDevIOCtrl Function 53H.
 '       All of the routines in this module (except
 ' InitComPort%) need a Handle% as one of the parameters.
 ' This Handle% is obtained from InitComPort%

 '***********************************************************
 ' InitComPort% returns a handle to the comport specified in
 ' the parameter ComPort$ (must be in the form: "COMn" where
 ' n is a number between 1 and 4.) Before the handle to the
 ' port is returned, the port is configured to the correct
 ' baud rate (110 to 19200), parity, data bit, and stop bit.
 '***********************************************************
 FUNCTION InitComPort% (ComPort$, Baud%, Parity%, DataBit%,_
                        StopBit%)
     DIM F42 AS F42Info
     DIM F41 AS F41Info
     DIM Temp AS STRING * 5 'Temp holds string of form "COMn"+null byte
     Temp = ComPort$
     F41.BaudRate = Baud%
     F42.DataBits = CHR$(DataBit%)
     F42.Parity = CHR$(Parity%)
     F42.StopBits = CHR$(StopBit%)

     ReturnErr% = DosOpen% (VARSEG(Temp), VARPTR(Temp),_
                            Handle%,_
                            Action%,_
                            0,_
                            0,_
                            1,_
                            &H12,_
                            0)
     IF (ReturnErr% = 0) THEN
         ReturnErr% = DosDevIOCtl%(0, 0,_
                                   VARSEG(F41), VARPTR(F41),_
                                   &H41,_
                                    1,_
                                    Handle%)
         ReturnErr% =  DosDevIOCtl%(0, 0,_
                                    VARSEG(F42),VARPTR(F42),_
                                    &H42,_
                                    1,_
                                    Handle%)
     END IF
     InitComPort% = Handle%
 END FUNCTION

 '***********************************************************
 ' WriteCom writes a string (ToCom$) to the port associated
 ' with Handle%. BytesWritten% will contain the actual
 ' number of bytes written after the call to WriteCom.
 '***********************************************************
 SUB WriteCom (Handle%, ToCom$, BytesWritten%)
     DIM Temp AS STRING * 512
     Temp = ToCom$
     Length = LEN(ToCom$)
     ReturnErr% = DosWrite%(Handle%,_
                            VARSEG(Temp), VARPTR(Temp),_
                            Length,_
                            BytesWritten%)
 END SUB

 '***********************************************************
 ' PrintCom Prints a string (ToCom$) to the port associated
 ' with Handle%. The string is written and an additional CR
 ' and LF. BytesWritten% will contain the actual number of
 ' bytes written after the call to PrintCom.
 '***********************************************************
 SUB PrintCom (Handle%, ToCom$, BytesWritten%)
     ToCom$ = ToCom$ + CHR$(13) + CHR$(10)
     DIM Temp AS STRING * 512
     Temp = ToCom$
     Length = LEN(ToCom$)
     ReturnErr% = DosWrite%(Handle%,_
                            VARSEG(Temp), VARPTR(Temp),_
                            Length,_
                            BytesWritten%)
 END SUB

 '***********************************************************
 ' ReadCom reads BytesToRead% number of bytes from the port
 ' associated with Handle%. The bytes read are placed in
 ' FromCom$, and the number of bytes read will be placed in
 ' BytesRead%.
 '***********************************************************
 SUB ReadCom (Handle%, FromCom$, BytesToRead%, BytesRead%)
     DIM Temp AS STRING * 512
     ReturnErr% = DosRead%(Handle%,_
                           VARSEG(Temp), VARPTR(Temp),_
                           BytesToRead%,_
                           BytesRead%)
     FromCom$ = MID$(Temp,1,BytesRead%)
 END SUB

 '***********************************************************
 ' ComSize returns the number of bytes waiting to be read at
 ' the port associated with Handle%. The number of bytes
 ' waiting is placed in Size%.
 ************************************************************
 SUB ComSize (Handle%, Size%)
     DIM F68 AS F68Info
     DIM FileInfo AS FILESTATUS
     ReturnErr% = DosDevIOCtl%(VARSEG(F68), VARPTR(F68),_
                               0, 0,_
                               &H68,_
                               1,_
                               Handle%)
     Size% = F68.NumChars
 END SUB

 '***********************************************************
 ' CloseCom closes the port associated with Handle%. This
 ' should be called before the end of the program.
 '***********************************************************
 SUB CloseCom (Handle%)
     ReturnErr% = DosClose% (Handle%)
 END SUB


 107. OS/2 Program Selector Fails to Show DOS Box If Using SCREEN 3

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | SR# S891010-116 B_QuickBas
 Last Modified: 15-DEC-1989    ArticleIdent: Q50625

 The Program Selector of OS/2 Version 1.00 or 1.10 can't correctly
 switch to the screen of a running BASIC application that is currently
 using SCREEN 3 (Hercules graphics) in the DOS 3.x box (real mode). To
 work around this OS/2 limitation, you must stop the BASIC program with
 CTRL+BREAK or switch back to SCREEN 0 (or text mode) within the
 program.

 This behavior occurs in Microsoft QuickBASIC Versions 4.00, 4.00b, and
 4.50 for MS-DOS, in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2, and in Microsoft BASIC PDS 7.00 for MS-DOS
 and MS OS/2.

 The Program Selector of OS/2 Version 1.00 or 1.10 is a simple
 interface that runs in character mode. When you invoke the OS/2 DOS
 box when it is running a program in Hercules graphics mode, OS/2
 maintains character mode and can't refresh the Hercules screen.
 QuickBASIC thinks it is still running under SCREEN 3 and the output is
 incorrect. Text mode must be reinvoked to restore visibility in the
 DOS box.

 Note that this problem does not occur for non-Hercules graphics screen
 modes (CGA, EGA, VGA) or for the Task Manager of OS/2 Presentation
 Manager (which can't run on Hercules graphics cards anyway).

 When you choose MS-DOS Command Prompt from the Switch To A Running
 Program menu in the OS/2 1.10 Program Selector screen and press ENTER,
 the highlighting on the menu selection disappears, the mouse pointer
 (if any) disappears, and the Program Selector appears to be hung
 (frozen) on the screen. If the BASIC program in the DOS box scrolls
 the screen during this time, the Program Selector will scroll upward
 showing some BASIC output, but the display will be incorrect
 (garbage).

 To stop the apparent hang or garbage on the screen, press CTRL+BREAK
 to abort the BASIC program and switch the screen over to text mode,
 thus making the DOS box visible. You can also press CTRL+ESC or
 ALT+ESC to go back to OS/2 at any time.

 Example
 -------

 To duplicate the problem, invoke the OS/2 Program Selector (CTRL+ESC),
 and then select MS-DOS Command Prompt from the Switch To A Running
 Program menu. Run the following code in the QuickBASIC QB.EXE editor
 or in a compiled .EXE program:

    SCREEN 3
    PRINT "This is a test"
    idle: GOTO idle

 [You must compile the .EXE program with /D (debug) so that CTRL+BREAK
 can stop the continuous loop in the program.] Invoke the OS/2 Program
 Selector (CTRL+ESC), and then select MS-DOS Command Prompt again. The
 menu highlight will disappear and the Program Selector screen will
 remain intact. The system will appear to be hung, but you are actually
 in the BASIC program. Pressing CTRL+BREAK will stop execution of the
 BASIC program and switch the DOS box back to text mode. When this is
 done, the Program Selector screen will be replaced with the DOS box
 screen.

 Note that if the BASIC application is not provided with a means to
 terminate or switch to the text mode screen, then the DOS box (for all
 practical purposes) will be hung. Technically, it can still be
 accessed by the keyboard, but the screen is never displayed correctly
 unless the program itself reinvokes SCREEN 0. The only way out of this
 condition is to reboot the computer.


 108. BASIC Program to Tell If Expanded Memory Driver Is Resident

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified: 26-FEB-1990    ArticleIdent: Q51293

 The following program shows how to determine if an expanded memory
 driver [or Expanded Memory Manager (EMM)] is loaded under MS-DOS. This
 program can be used either in the QuickBASIC editor or in an .EXE
 program created with the BC.EXE BASIC compiler under MS-DOS. This
 program also determines the amount of available expanded memory and
 the Lotus/Intel/Microsoft (LIM) specification version number of the
 EMS (Expanded Memory Specification) driver. For more information,
 refer to Pages 204-206 in "Advanced MS-DOS Programming, 2nd Edition"
 by Ray Duncan (Microsoft Press, 1988).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 Note that Microsoft BASIC PDS 7.00 introduces support for LIM 4.0 EMS
 (Expanded Memory Specification) for the following features: ISAM file
 buffers, the QBX.EXE editor environment, and LINK overlays at run
 time. Microsoft BASIC Compiler Versions 6.00b and earlier and
 QuickBASIC Versions 4.50 and earlier don't support expanded memory,
 ISAM, or LINK overlays.

 If an EMM driver is loaded, it is hooked to Interrupt 67 hex. This
 means that the address stored in the interrupt vector table for
 interrupt 67 hex points to the beginning of the driver. The device
 name for an Expanded Memory Manager driver must be "EMMXXXX0". This
 device name is located 0A hex bytes into the device header. This name
 can be checked to determine if a legitimate driver has been loaded. If
 this name is not found, you can assume that no expanded memory support
 is available.

 The strategy used in the program below is to use the DOS service
 (Interrupt 21 hex, function 35 hex) to get the address of the driver
 and then check the driver header found at that address for the correct
 name. Once the program determines that an expanded memory driver is
 available, it can access the driver through interrupt 67 hex, with
 functions 42 hex and 46 hex, to obtain the amount of expanded memory
 and LIM version numbers, respectively. The code example below
 illustrates one method for accomplishing this in Microsoft BASIC.

 For more information about how to use INTERRUPT or INTERRUPTX to
 access a DOS interrupt, ROM BIOS interrupt, or any other interrupt
 service, query for a separate article with the following word: QB4INT

 For more information about the interrupts necessary to access LIM EMS,
 see Pages 25-68 of "MS-DOS Extensions: Programmer's Quick Reference,"
 by Ray Duncan (Microsoft Press, 1989).

 Sample Program
 --------------

 '----------------------------- EXPCHK.BAS --------------------------
 '
 '   This program determines if an Expanded Memory Driver is loaded,
 '   displays the amount of available expanded memory, raw page
 '   size, EMM driver status, and the version number of the
 '   Lotus/Intel/Microsoft Expanded Memory Specification.

 '$INCLUDE: ''QBX.BI'              'Data Declarations for CALL INTERRUPT(X)
 DIM InRegsx AS RegTypeX, OutRegsx AS RegTypeX
 DIM InRegs AS RegType, OutRegs AS RegType
 DIM buffer(0 TO 4) AS INTEGER
 CLS
 LOCATE 10
 '-------------------------------------------------------------------
 'The Expanded Memory Manager is accessed through Interrupt &H67 if
 'present. Use the DOS Get Interrupt Vector (interrupt 21 hex, with
 'function 35 hex) service to retrieve the address of the device
 'driver and then get the device name from there. If the name is found
 'to be "EMMXXXX0", then the driver is loaded and calls can be made to
 'it.
 '-------------------------------------------------------------------

 InRegsx.ax = &H3500 + &H67         'DOS Get Interrupt Address Service
 InRegsx.ds = -1                    'Retain current DS and ES values
 InRegsx.es = -1
 CALL INTERRUPTX(&H21, InRegsx, OutRegsx)
 EMMDriverSEG = OutRegsx.es         'Segment of INT 67 EMM driver
 EMMDriverOFF = OutRegsx.bx         'Offset  of INT 67 EMM driver

 DEF SEG = EMMDriverSEG
 index = &HA   'Driver name located at offset &H0A into device header
 DO UNTIL LEN(EMMName$) > 7         'Retrieve Device Name (8 chars)
         EMMName$ = EMMName$ + CHR$(PEEK(index))
         index = index + 1
 LOOP

 IF EMMName$ = "EMMXXXX0" THEN
         PRINT TAB(10); "Expanded Memory Available"
 ELSE
         PRINT TAB(10); "No Expanded Memory Driver Loaded"
         END
 END IF

 InRegs.ax = &H4000                'EMM get status function
 CALL INTERRUPT(&H67, InRegs, OutRegs)

 IF OutRegs.ax < 0 THEN            'Isolate high byte of AX
         highbyte = (OutRegs.ax + 2 ^ 16) \ 256&   'High bit set case
 ELSE
         highbyte = OutRegs.ax \ 256&
 END IF

 IF highbyte = 0 THEN          'Check for error codes in AH
         PRINT TAB(10); "Extended Memory Driver Status: FUNCTIONAL"
 ELSE
         PRINT TAB(10); "Extended Memory Driver Status: NON-FUNCTIONAL"
         PRINT TAB(10); "Error Code: "; OutRegs.ax
 END IF

 InRegs.ax = &H4600                        'EMM get version function
 CALL INTERRUPT(&H67, InRegs, OutRegs)
 LimVersion$=LEFT$(HEX$(OutRegs.ax),1) + "." + RIGHT$(HEX$(OutRegs.ax),1)
 PRINT TAB(10); "LIM Version "; LimVersion$; " Driver Installed"

 InRegs.ax = &H4200                  'EMM get number of pages function
 CALL INTERRUPT(&H67, InRegs, OutRegs)

 IF OutRegs.ax < 0 THEN                      'Isolate high byte of AX
         highbyte = (OutRegs.ax + 2 ^ 16) \ 256&
 ELSE
         highbyte = OutRegs.ax \ 256&
 END IF

 IF highbyte = 0 THEN
         PRINT TAB(10); "Total Number of 16K Pages Available: "; OutRegs.dx
         total& = OutRegs.dx * 16 * 1024& \ 1048576  'Convert to Megabytes
         PRINT TAB(10); "Total Expanded Memory: "; total&; " Megabytes"
 ELSE
         PRINT TAB(10); "Error Determining Number of Expanded Memory Pages"
         PRINT TAB(10); "Error Code: "; OutRegs.ax
 END IF

 DEF SEG                                'Restore original state
 IF VAL(LimVersion$) >= 4! THEN  'This only supported LIM 4.0 and later
    InRegsx.ax = &H5900  'EMM Get hardware config (Page Size) function
    InRegsx.es = VARSEG(buffer(0))
    InRegsx.di = VARPTR(buffer(0))
    CALL INTERRUPTX(&H67, InRegsx, OutRegsx)
    IF OutRegsx.ax < 0 THEN
       highbyte = (OutRegsx.ax + 2 ^ 16) \ 256&
    ELSE
       highbyte = OutRegsx.ax \ 256&
    END IF

    IF highbyte = 0 THEN
       size = buffer(0) * 16& \ 1024  'Convert paragraphs to Kilobytes
       PRINT TAB(10); "Raw Expanded Memory Page Size: "; size; " Kilobytes"
    ELSE
       PRINT TAB(10); "Error in determining Raw Page Size."
       PRINT TAB(10); "Error Code: "; OutRegsx.ax
    END IF
 ELSE
    PRINT TAB(10); "Raw Expanded Memory Page Size: 16 Kilobytes"
 END IF

 END


 109. STACK STACK Correctly Gives "Out of Memory" in QBX.EXE

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891019-160
 Last Modified: 12-DEC-1989    ArticleIdent: Q51413

 If you run a program containing the statement STACK STACK in the
 QBX.EXE environment and then attempt to edit the program, the error
 message "Out of memory" will result. The error message can be
 prevented by going to the Immediate window in QBX and executing the
 STACK statement to reset the stack size to the default. The error
 occurs because the STACK STACK statement allocates all available
 memory in the data segment for the stack. However, QBX needs to use
 part of this segment for its own purposes.

 This information applies to Microsoft BASIC PDS Version 7.00 for
 MS-DOS.


 110. Internal Format of CURRENCY Data Type in BASIC PDS 7.00

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 21-FEB-1991    ArticleIdent: Q51414

 The CURRENCY data type available in Microsoft BASIC Compiler versions
 7.00 and 7.10 for MS-DOS and OS/2 is an 8-byte signed integer scaled
 by 10,000. This allows a variable of the CURRENCY type to have a range
 of

    (2 ^ 63 -1) / 10,000  =  +922337203685477.5807

 to

    (2 ^ 63) / 10,000   =  -922337203685477.5808

 Up to 19 digits are allowed, with no more than 4 digits to the right
 of the decimal point.

 Because the CURRENCY type is scaled by 10,000, its internal
 representation is the actual value multiplied by 10,000. For instance,
 a CURRENCY variable holding the value 0.0001 will be stored as
 follows:

    HIGH BYTE                                                     LOW BYTE
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001

 As with ordinary INTEGERs, the higher byte is stored at the higher
 memory address so that once you find the address of the variable, you
 will find the low byte there, the second byte stored above, the third
 byte above that, etc. The example program below displays the
 hexadecimal machine representation for a CURRENCY data type variable
 whose value is INPUT from the keyboard.

 Sample Code:

 '******************************************************************
 '     Sample program to display machine representation of the     *
 '     CURRENCY data type (8-byte scaled INTEGER)                  *
 '******************************************************************
 CLS
 DO UNTIL INKEY$ = CHR$(27)
   PRINT "Enter a CURRENCY value.  The machine representation will be "
   PRINT "displayed in Hex"
   INPUT a@                   ' "@" is the CURRENCY data type suffix.
   address% = VARPTR(a@)      ' Get the address of the variable a@

   FOR i% = 7 TO 0 STEP -1
      PRINT HEX$(PEEK(address% + i%)); "  ";  ' Display representation
   NEXT i%                                    ' in normal Low-Byte to
                                              ' the right form.
   PRINT
   PRINT "press a key to continue, Esc to EXIT"
   SLEEP
 LOOP


 111. PDS 7.00 Alert FUNCTION Return Value Description Incorrect

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891101-66 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q51415

 The Alert FUNCTION in the WINDOW.BAS file of the User Interface (UI)
 Toolbox is incorrectly described in the documentation. On Page 553 of
 the "Microsoft BASIC 7.0: Language Reference" manual (for 7.00 and
 7.10), the "Syntax" section incorrectly shows that the Alert FUNCTION
 will return a string. The "Remarks" section and the source code in
 WINDOW.BAS correctly show that the Alert FUNCTION actually returns an
 INTEGER from 1 to 3.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The "Syntax" section of the Alert FUNCTION description reads as
 follows:

    Syntax   variablename$ = Alert(style%,text$,row1%,...etc.

 It should read as follows:

    Syntax   variablename% = Alert(style%,text$,row1%,...etc.

 The dollar sign ($) appended to "variablename" should be a percent
 sign (%) because the Alert FUNCTION returns an integer.


 112. How to Use Link Overlays in BASIC PDS 7.00 and 7.10

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891017-94 S_LINK
 Last Modified:  5-SEP-1990    ArticleIdent: Q51416

 When using the linker (LINK.EXE) to generate code overlays for
 Microsoft BASIC Professional Development System (PDS) version 7.00 or
 7.10 under MS-DOS, you must put the modules you want to overlay in
 parentheses on the LINK command line. The modules that make up one
 overlay must be compiled with the same switches. Code is the only part
 of the program that is overlaid. Data is not overlaid. Examples and
 further restrictions for using linker overlays are given below.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS (but does NOT apply to earlier BASIC compiler versions).

 Note that link overlays are not needed and not supported under OS/2
 protected mode, since OS/2 itself automatically provides a similar
 feature to support swapping of very large .EXE programs in OS/2's
 extended and virtual memory.

 The following is an example of how to produce code overlays

    LINK test1+(test2+test3)+test4+(test5)+(test6),TEST1.EXE,TEST1.MAP;

 where the following apply:

 1. test1 (TEST1.OBJ) is the main module.

 2. test2 and test3 (TEST2.OBJ and TEST3.OBJ) are separately compiled
    modules that make up one overlay.

 3. test4 (TEST4.OBJ) stays resident in memory along with the main
    module (test1) at run time and is not swapped out of memory to disk.

 4. test5 and test6 (TEST5.OBJ and TEST6.OBJ) are two separate overlays.

 5. TEST1.EXE is the executable overlaid program created by this LINK.

 6. TEST1.MAP is a text file (created by the above LINK) that tells
    you the code sizes of all overlays and procedures.

 To invoke an overlay, you call a SUB or FUNCTION in a module contained
 in that overlay, and the Overlay Manager automatically moves the
 overlay (if it is not already loaded) into DOS memory, overlaying any
 previous overlay in memory.

 You can call any module or overlay from any other module or overlay.

 Overlays provide an alternative to CHAINing when a program is too
 large to fit into memory all at once. An overlaid program is made up
 of a single .EXE file (which can be an advantage in some cases),
 unlike CHAINed programs, which are composed of several .EXE files.

 Restrictions on Using Overlays
 ------------------------------

 The restrictions on using overlays in Microsoft BASIC PDS versions
 7.00 and 7.10 for MS-DOS are as follows:

 1. Each Microsoft BASIC overlay cannot exceed 256K in code (see LINK
    .MAP for size of each overlay). You can have up to 64 overlays
    per .EXE program. This means you may be able to make .EXE programs
    up to 16 MB in code size under MS-DOS.

 2. The main module must be the first module in the LINK command line,
    and it must NOT be specified as an overlay. If you incorrectly make
    the first module in the LINK command line an overlay, the machine
    will hang when the program first loads.

 3. When you create an overlaid version of a program, make sure that
    each module contained in the program is compiled with the same
    options.

 4. You cannot use the LINK /PACKCODE or /EXEPACK option when linking a
    program that uses overlays.

 5. You cannot have a stub file as an overlay. Do not specify stub
    files (NOxxx.OBJ) in the parentheses for link overlays, or the
    program will hang. Stub files may only be specified outside
    parentheses in the LINK command line.

 Using Expanded Memory with Overlays
 -----------------------------------

 386Max (386MAX.SYS) from Qualitas, Inc. is an example of an expanded
 memory driver that can be used with BASIC PDS 7.00 and 7.10. BASIC PDS
 7.00 and 7.10 require an expanded memory driver that uses the
 Lotus-Intel-Microsoft (LIM) version 4.0 Expanded Memory Specification
 (EMS).

 If you have loaded an expanded memory driver, and if all the overlays
 can fit together at one time in expanded memory, and if each overlay
 has less than 64K of code, then overlays are loaded from expanded
 memory. Otherwise, overlays are swapped from disk, which is slower
 than loading from expanded memory.

 Assume that the overlaid program satisfies the above conditions for
 using expanded memory. Note that the overlaid modules are not loaded
 when the EXE file is first invoked. They remain on disk until the
 first overlay is called. When this occurs, all the overlaid modules
 are loaded at once from disk into expanded memory. From then on, the
 overlays are swapped from expanded memory into DOS memory, and the
 disk is no longer used for loading overlays.

 The overlay manager in BASIC 7.00 and 7.10 requests expanded memory in
 16K pages (blocks). The overlay manager only knows the size of the
 largest overlay, and must make a "best guess" at the size of the
 smaller overlays. When the overlay manager estimates how many 16K
 pages are necessary to hold all overlays at once in expanded memory,
 the estimate could be over or under the actual number of pages needed.
 If your overlays are all between 16K and 64K in size (according to the
 LINK .MAP file), and if the estimated or actual size of all overlays
 together exceeds the available expanded memory, the following
 initialization error occurs when the first overlay is called at
 run-time:

    Insufficient EMS to load overlays

 Note: This error is documented on Page 656 of the "Microsoft BASIC
 7.0: Language Reference" manual for versions 7.00 and 7.10. You will
 never see this error if all your overlays are smaller than 16K each.

 If you want to force loading overlays from disk, thus avoiding the
 possibility of this overlay initialization error in expanded memory,
 you must link with the stub file NOEMS.OBJ (with no parentheses around
 NOEMS.OBJ on the LINK command line). Alternatively, you can try
 reconfiguring expanded memory so more of it is available for BASIC
 overlays. Another alternative is to make overlays similar in size.

 DOS Memory Map When Using Overlaid .EXE Program
 ------------------------------------------------

 [Low Memory]

 * MS-DOS.
 * Main program and non-overlaid modules.
 * Contiguous overlay memory area, equal to the size of biggest overlay.
 * DGROUP (default data segment, which is shared by all routines).
 * Far heap (dynamic non-variable-length-string arrays).
 * BASIC's run-time support module if .EXE not compiled stand-alone (BC /O)

 [High Memory]

 For more information on using overlays, see the section "Linking with
 Overlays" on Pages 612-614 in the "Microsoft BASIC 7.0: Programmer's
 Guide."


 113. CURRENCY Data Type Not Available in Alternate Math (BC /FPa)

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  6-AUG-1990    ArticleIdent: Q51417

 The CURRENCY data type available in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 can be used only with
 the coprocessor/emulation math package (BC /FPi, the default). The
 CURRENCY type is not supported in the alternate math package (BC /FPa
 option). Trying to compile a program that uses CURRENCY variables with
 the alternate math package results in "Currency type illegal in
 alternate math pack" errors.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The implementation of a CURRENCY data type for alternate math would
 have delayed the release of BASIC PDS 7.00 and 7.10, keeping the
 product from developers who need the other new features. This feature
 is under review and will be considered for inclusion in a future
 release.

 The CURRENCY data type is not found in Microsoft BASIC Compiler
 versions earlier than Microsoft BASIC PDS version 7.00.

 You can declare a variable with the CURRENCY data type by appending
 the variable name with the suffix @ (the "at" sign), or you can use
 the DIM statement with the AS CURRENCY clause (DIM x AS CURRENCY).


 114. EXT.H, EXTHDR.H Files Don't Come with BASIC 6.00 or COBOL 3.00

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | B_COBOL S_QuickC S_C
 Last Modified: 15-DEC-1989    ArticleIdent: Q51603

 EXT.H and EXTHDR.H, the files necessary to write C extensions for the
 Microsoft Editor (M.EXE and MEP.EXE), are not included with the
 Microsoft Editor software for the following products:

    Microsoft BASIC Compiler Version 6.00 or 6.00b for MS-DOS and OS/2
    Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2
    Microsoft COBOL Compiler Version 3.00 or 3.00a for MS-DOS and OS/2

 As EXT.H and EXTHDR.H are included with the Microsoft C Compiler 5.10,
 the lack of EXT.H and EXTHDR.H will only affect those who are writing
 C extensions for the M.EXE or MEP.EXE editor and using Microsoft
 QuickC.


 115. Example of Gaussian Elimination; Matrix Math in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 13-DEC-1989    ArticleIdent: Q51605

 This article explains the purpose of Gaussian elimination and gives
 a code example.

 In Microsoft BASIC PDS (Professional Development System) Version 7.00
 for MS-DOS and MS OS/2, the following FUNCTION procedures perform
 Gaussian elimination:

    MatSEqnS% (for single-precision)
    MatSEqnD% (for double-precision)
    MatSEqnC% (for currency data type)

 The source code of all of these functions is provided in the MATB.BAS
 source file on one of the release disks. To use these functions in the
 QuickBASIC Extended editor, load the MATBEFR.QLB Quick library as
 follows:

    QBX /L MATBEFR.QLB

 MATFEFR.QLB and the related .LIB files are mentioned in the $INCLUDE
 file MATB.BI. MATB.BI contains DECLARE FUNCTION statements necessary
 for the matrix math routines.

 Definitions
 -----------

 1. A matrix is a two-dimensional array in BASIC.

 2. A vector is a one-dimensional array in BASIC.

 3. An identity matrix is a square array composed of 1's along the
    diagonal from upper left to lower right, with all else 0's (zeros).

 Gaussian Elimination
 --------------------

 A linear equation of n variables (unknowns) has the following form:

    a1*x1 + a2*x2 + an*xn = b

 where:

    a1 through an and b are known constants, and x1 through xn are
    variables with unknown values.

 Linear equations do not involve any products or roots of variables.
 All variables are to the first power, and don't appear as arguments
 of trigonometric, logarithmic, or exponential functions.

 A solution of a linear equation is a sequence of n numbers (s1 through
 sn) such that the equation is satisfied when we substitute x1=s1,
 x2=s2, ..., xn=sn.

 A set of multiple linear equations in the variables x1 through xn is
 called a system of linear equations. The set (vector) of constants s1
 through sn is called a solution of the system if it provides a
 solution for every equation in the system. Every system of linear
 equations has either no solutions, exactly one solution, or infinitely
 many solutions.

 A system of m linear equations in n unknowns can be written as follows
 in BASIC:

    a(1,1)*x1 + a(1,2)*x2 + ... + a(1,n)*xn = b(1)

    a(2,1)*x1 + a(2,2)*x2 + ... + a(2,n)*xn = b(2)

       ...                  ...

    a(m,1)*x1 + a(m,2)*x2 + ... + a(m,n)*xn = b(m)

 If you mentally keep track of the location of the +'s, the x's, and
 the ='s, the arrays a(m,n) and b(m) provide a shorthand notation for
 the system of linear equations. In elementary linear algebra texts,
 a(m,n) and b(m) together make what is called the "augmented matrix."

 Again, our goal is to discover the unknown values s1 through sn that,
 when assigned to variables x1 through xn, solve every equation.

 Gaussian elimination reduces the augmented matrix [the combination of
 a(m,n) and b(m)] to a matrix of reduced row-echelon form, which looks
 like a square identity matrix attached to a 1 by m vector [ b() ]. The
 vector b() contains the solution set (s1 through sn) of the system of
 linear equations.

 The Gaussian elimination functions MatSEqnS%, MatSEqnD%, and MatSEqnC%
 accept a square matrix a() and a vector b() as input arguments
 (together composing the input-augmented matrix), and give the solution
 in the one-dimensional array b(). After you invoke the function, a()
 is replaced with the identity matrix, and the solution values
 overwrite the input arguments that you had placed in b(). The n
 solution values in b(), when assigned to variables x1 through xn,
 satisfy every equation in the system.

 For more information about linear algebra, the following is an
 excellent text:

    "Elementary Linear Algebra, Second Edition", by Howard Anton,
     published by John Wiley & Sons, 1977

 Code Example
 ------------

 ' This program demonstrates Gaussian elimination to solve a set of
 ' linear equations using double-precision variables.
 ' The MATSEQND, MATSEQNS, and MATSEQNC matrix math routines are
 ' provided in the Matrix Math Toolbox in Microsoft BASIC 7.00 for
 ' MS-DOS and MS OS/2.
 '
 ' To run this program in the QuickBASIC Extended editor, load the
 ' MATBEFR.QLB Quick library as follows:
 '
 '     QBX /L MATBEFR.QLB
 '
 ' MATFEFR.QLB and the related .LIB files are documented in the INCLUDE
 ' file 'MATB.BI' but NOT in "Microsoft BASIC 7.0: Language Reference."

 DECLARE FUNCTION MatSEqnD% (A() AS DOUBLE, b() AS DOUBLE)

 ' The above DECLARE statement is all that is needed from the following
 ' include file:   REM $INCLUDE: 'matb.bi'
 DEFDBL A-Z
 OPTION BASE 1    ' Use OPTION BASE 1 for easier reference.
 DIM A(3, 3), b(3)

 ' The following system of linear equations:
 PRINT "       x +   y + 2*z = 9"
 PRINT "     2*x + 4*y - 3*z = 1"
 PRINT "     3*x + 6*y - 5*z = 0"
 ' ...can be represented in the following matrix:
 '     1  1  2  9
 '     2  4 -3  1
 '     3  6 -5  0
 ' ...which can be placed in arrays a() and b() respectively as follows:
 '     a(1,1)  a(1,2)  a(1,3)  b(1)
 '     a(2,1)  a(2,2)  a(2,3)  b(2)
 '     a(3,1)  a(3,2)  a(3,3)  b(3)
 A(1, 1) = 1
 A(1, 2) = 1
 A(1, 3) = 2
 A(2, 1) = 2
 A(2, 2) = 4
 A(2, 3) = -3
 A(3, 1) = 3
 A(3, 2) = 6
 A(3, 3) = -5
 b(1) = 9
 b(2) = 1
 b(3) = 0
 errcode% = MatSEqnD%(A(), b())
 PRINT "The following values for x, y, and z solve all three equations:"
 PRINT "x="; b(1)
 PRINT "y="; b(2)
 PRINT "z="; b(3)

 ' Here is the output, accurate to within double-precision limits:
 '    x= 1.00000000000001
 '    y= 2
 '    z= 3


 116. EXD Should Be EXP, BASIC 7.00 Page 541 "Programmer's Guide"

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr SR# S891109-123
 Last Modified:  8-JAN-1991    ArticleIdent: Q51861

 EXD should be changed to EXP in the list of transcendental operations
 affected by the NOTRNEMM.LIB stub file on Page 541 of "Microsoft BASIC
 7.0: Programmer's Guide" for 7.00 and 7.10.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 117. Example of Using NPV and IRR Financial Functions in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 14-JAN-1990    ArticleIdent: Q52068

 This article explains how to use the NPV and IRR financial functions
 in Microsoft BASIC PDS (Professional Development System) Version 7.00
 for MS-DOS and MS OS/2.

 Note that the NPV#, IRR#, and MIRR# functions are used for investments
 that are a series of nonconstant cash payments made at equal
 intervals. You pass the series of nonconstant payments in an array.
 [This contrasts with the financial functions for annuity investments
 (FV#, IPmt#, Rate#, NPer#, PV#, Pmt#, and PPmt#). In an annuity, each
 cash payment is the same constant amount, made at equal intervals.]

 The present value (PV) of a future cash receipt is the amount of money
 that, if received today, would be considered equivalent to the future
 receipt, at a given interest rate. The present value is less than the
 future receipt because you can earn interest on money received today.
 NPV (Net Present Value) compares (subtracts) the current value of a
 series of future cash flows with an amount invested today.

 NPV is useful to compare investment opportunities at a given discount
 (interest) rate. The discount rate (rate#) can be viewed as the rate
 of return you want out of your investment. If NPV is greater than or
 equal to 0, the investment equals or exceeds your interest (discount)
 rate requirement; if NPV is less than 0, the investment does not meet
 your interest rate requirement.

 The NPV#(rate#,valuearray#(),valuecount%,status%) function returns
 Net Present Value. You input the values rate#, valuearray#(), and
 valuecount% (which is the number of array elements), and get back
 status% equals 0 for success, 1 for failure.

 The IRR#(valuearray#(),valuecount%,guess#,status%) function returns
 Internal Rate of Return. IRR returns the discount rate at which NPV
 would return 0 (zero). For a given array of cash flow values, IRR can
 be thought of as an average interest rate (which compounds at each
 period). If IRR is lower than the interest rate you desire for this
 investment, then it is not a good investment.

 The first element of the input cash-flow array should usually be
 negative, indicating your initial investment. A high (positive) income
 early in the value array will make IRR higher than if the same high
 income instead occurred later in the array. This is an example of the
 time value of money.

 Please refer to an elementary accounting textbook for more information
 about these standard Accounting functions.

 Code Example
 ------------

 You can run this program in the QuickBASIC Extended environment with
 QBX /L FINANCER.QLB. To run outside this environment, you must link
 with the appropriate library (FINANCER.LIB, FINANCAR.LIB,
 FINANCEP.LIB, or FINANCAP.LIB).

 REM $INCLUDE: 'FINANC.BI
 DEFDBL A-Z
 OPTION BASE 1
 CLS
 valuecount% = 5   ' = number of cash-flow values in valuearray()
 ' Array holds cash flow values, one value per period (such as per
 ' year):
 DIM valuearray(valuecount%)
 guess = .1        ' Guess the IRR (use .1 if in doubt)

 valuearray(1) = -1000 ' 0. First value negative as initial investment.
 valuearray(2) = 100   ' 1. Return on investment after 1 period.
 valuearray(3) = 200   ' 2. (Positive value is return on investment.)
 valuearray(4) = -300  ' 3. (Negative value is additional investment.)
 valuearray(5) = 1200  ' 4. Return on investment after 4 periods.
 ' For the above values, IRR returns .0514. (5.14% return per period)
 status% = 0

 irreturn = IRR(valuearray(), valuecount%, guess, status%)
 IF status% THEN PRINT "IRR error occurred; try different guess";

 discountrate = irreturn
 netpresval = NPV#(discountrate, valuearray(), valuecount%, status%)

 'Notes for NPV#() function:
 ' If discountrate = value returned by IRR(), then NPV returns zero, as
 '    in the IRR example in the "Microsoft BASIC 7.0: Language
 '    Reference" manual, and also as in this code example.
 ' If discountrate = zero, NPV returns sum of values in valuearray().
 ' If discountrate > zero, NPV returns an amount smaller than sum of
 '    values in valuearray() due to the discount effect at each period.
 ' If discountrate < zero, NPV returns an amount larger than the sum of
 '    the values in valuearray().

 IF status% THEN PRINT "NPV error occurred"
 PRINT "IRR (fractional return on investment per period) = ";
 PRINT USING "##.####"; irreturn
 PRINT "NPV = ";
 PRINT USING "#######.##"; netpresval

 Output
 ------

 For the above values, IRR returns .0514 (5.14 percent return per
 period). NPV returns 0 (zero), since IRR returns the discount rate at
 which NPV returns 0.


 118. MatSEqn FUNCTION Correction Page 506, 7.00 Language Reference

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr SR# S891218-99
 Last Modified:  8-JAN-1991    ArticleIdent: Q52069

 The following two corrections apply to the MatSEqn FUNCTION
 (MatSEqnS%, MatSEqnD%, and MatSEqnC%) on Page 506 of the "Microsoft
 BASIC 7.0: Language Reference" manual (for 7.00 and 7.10):

 1. Insert the text marked in brackets ([]) into the first sentence in
    the Remarks on Page 506, as follows:

    The MatSEqntype% procedure solves a system of linear equations
    contained in [a one-dimensional vector and in] a square matrix...

 2. Insert the sentence marked in brackets ([]) after the fourth
    sentence in the Remarks on Page 506, as follows:

    The first matrix is the square input matrix that contains the
    coefficients for a system of simultaneous equations. [The second
    matrix is used to input the vector of constants for that system
    of simultaneous equations.]

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 For an example of using MatSEqnx (Gaussian elimination), query on
 the following words:

    Gaussian and elimination


 119. Example of PPMT and PMT Financial Functions in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 14-JAN-1990    ArticleIdent: Q52070

 This program demonstrates the PPMT and PMT financial functions in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.

 PMT returns the periodic payment for an investment. In the case of a
 loan, PMT returns the amount of the constant monthly payment (the sum
 of principal plus interest) for the loan, based upon a constant
 interest rate, the total number of payments, and the amount (present
 value) of the loan.

 PPMT is the payment on the principal for an investment at a specified
 period. (PMT minus PPMT is the payment on the interest at a specified
 period.) The sum of all PPMT values returned over the life of the loan
 equals the loan amount.

 Below is an analysis of the finances for buying and selling a house.
 The program returns average equity gain per month after the house has
 been bought and sold. You can change the initial parameters (such as
 houseval, down, rate1, sellper, apprec, etc.) to explore different
 scenarios, including a simplified inflation effect. Negative net
 equity gain per month is outgoing money; positive net equity gain per
 month is income.

 You can choose the period of time at which you sell the house and
 compare the net income or outgo per month to that of your current
 housing situation.

 Run this program with QBX /L FINANCER.QLB in Microsoft BASIC PDS
 Version 7.00 for MS-DOS. To run outside the QBX.EXE environment, you
 must link with the appropriate library (FINANCER.LIB, FINANCAR.LIB,
 FINANCEP.LIB, or FINANCAP.LIB).

 Code Example
 ------------

 REM $INCLUDE: 'financ.bi'
 DEFDBL A-Z

 ' Initialize variables:
 CLS
 houseval = 110000#     ' Purchase price of house (median for Seattle).
 apprec = 1.07#         ' Assumed yearly appreciation rate of house.
 sellper = 10# * 12#    ' Period (month) at which you choose to sell.
 down = .1#             ' Fraction of houseval paid as down payment.
 equity = down * houseval  ' Initial equity in house (10% down payment)
 pv1 = (1 - down) * houseval 'Present value of loan = 90% of houseval
 rate1 = .1025# / 12 ' Loan interest rate (10.25%) divided by 12 months
 pool = 0 ' Pool of money, if any, to earn interest & subtract payments
 poolint = 1.0057# ' Monthly interest earned on pool to get 7% yearly.
 pointsbuy = .02#  ' Assumed fees to buy loan, as fraction of houseval.
 pointsell = .07#  ' Selling fees (points) as fraction of selling price
 per = 0#           ' Month (period) counter.
 nper1 = 360#       ' # periods in loan. 30-year loan has 360 months.
 ptype% = 0#        ' 0 means payment due at end of each period.
 fv1 = 0#           ' Future value (the goal) of a loan is always zero.
 ptot1 = 0#         ' Current total of principal paid towards loan.
 in = .95#          ' 1 minus the inflation rate
 proptax = -130#    ' property taxes per month (tax deductible)
 fire = -25#        ' fire/house insurance per month
 roommate = 400#   ' Rent income from roommate (0 if none) after taxes.
 roominflate = 1.02 ' Yearly rate you increase your roommate's rent.
 tax = .8#       ' 1 minus your average yearly Tax rate (as a fraction)
 initial = pool + equity
 PRINT "Purchase price ="; houseval;
 PRINT " // Initial pool + equity = "; initial
 upfront = equity + (pointsbuy * houseval)
 PRINT "Up front cost (down payment + loan fees) ="; upfront

 ' Calculate monthly (principal+interest) payment:
 payment1 = Pmt(rate1, nper1, pv1, fv1, ptype%, status%)
 IF down < .2# THEN
    minsure = .03 * payment1 ' Monthly mortgage insurance rate (3% of
 ELSE               ' principal+interest payment). You usually must pay
    minsure = 0#    ' mortgage insurance if you paid < 20% down.
 END IF
 PRINT "monthly payment= "
 PRINT payment1; "+"; fire; "+"; proptax; "+"; minsure; "= ";
 PRINT payment1 + fire + proptax + minsure
 PRINT "not counting tax savings ("; 1 - tax; "factor ) ";
 PRINT "or roommate income ("; roommate; ")";
 PRINT "**************************************************"

 ' Add up numbers until the period (month) where you sell (sellper):
 FOR j = 1 TO sellper
    per = j
    ' Yearly rent increase:
    IF j MOD 12 = 0 THEN roommate = roominflate * roommate

    ' Calculate principal and interest amounts paid:
    principal1 = PPmt(rate1, per, nper1, pv1, fv1, ptype%, status%)

    ptot1 = ptot1 + principal1   ' total accumulated principal to date
    interest1 = payment1 - principal1
    itot1 = itot1 + interest1  'total accumulated interest paid to date
    ' Outaftertax1 and outgo values are negative:
    outaftertax1 = ((interest1+proptax)*tax) +principal1 +fire +minsure
    pool = pool + outaftertax1 + roommate  ' (outaftertax is negative)
    ' pool earns interest if positive (no interest charged if negative,
    ' assuming you make monthly house payments without borrowing):
    IF pool > 0 THEN pool = pool * poolint
    equity = equity + ABS(principal1) ' Monthly principal builds equity
 NEXT

 ' Calculate final appreciation and closing costs; and print out:
 years = sellper / 12#   ' Number of years after which you sold.
 aphouseval = houseval * (apprec ^ years) ' Appreciated house value.
 closecost = -(pointsbuy * houseval) - (pointsell * aphouseval)
 naphouseval = aphouseval - houseval  ' net appreciation on house value
 final = pool + equity + naphouseval + closecost
 in1989 = final * (in ^ years)  ' In 1989 dollars (inflation adjusted).
 PRINT
 PRINT "After"; years; " years, buy+sell closecost ="; closecost
 PRINT "total principal paid="; ptot1 + ptot2
 PRINT "total interest paid="; itot1 + itot2
 PRINT "Appreciated value of house = "; aphouseval
 PRINT "final pool+equity+apprec-close="; final
 PRINT "or"; in1989; " in 1989 dollars with"; 1 - in;"yearly inflation"
 PRINT "(which is a"; CSNG(in ^ years); " overall inflation factor)"
 PRINT
 PRINT "Net ave. equity increase per month="; (final-initial)/sellper
 PRINT"(or with inflation=";(in1989-initial)/sellper;"in 1989 dollars)"


 120. Library Naming Conventions for BASIC PDS 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891206-120
 Last Modified: 14-JAN-1990    ArticleIdent: Q52091

 The following article explains the library naming conventions used by
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.

 In Microsoft BASIC PDS Version 7.00, library names are acronyms that
 follow a standard format:

    NAMEmso.LIB
        m = Alternate (A) or Emulation (E) math package.
        s = Far (F) or Near (N) variable-length string storage.
        o = Protected (P) or Real (R) mode operating system.

 The format starts with a base NAME of several characters used to
 identify the function of the library (such as BRT70, BCL70, FINANC,
 FONTB, MATB, etc.). Next is a two- or three-character extension
 specifying support for which math package (emulation or alternate
 math), variable-length string storage (near or far), or operating
 system (real or protected mode).

 Real mode refers to the DOS Version 3.x box in MS OS/2, or to straight
 MS-DOS. Protected mode refers to MS OS/2 only.

 BASIC Run-Time Libraries
 ------------------------

    BRT70EFR.LIB, BRT70ENR.LIB, BRT70EFP.LIB, BRT70ENP.LIB
    BRT70ANR.LIB, BRT70AFR.LIB, BRT70ANP.LIB, BRT70AFP.LIB

    Format: BRT70mso.LIB
                 m = Alternate (A) or Emulation (E) math package.
                 s = Far (F) or Near (N) strings.
                 o = Protected (P) or Real (R) mode operating system.

 BASIC Stand-Alone Libraries
 ---------------------------

    BCL70EFR.LIB, BCL70ENR.LIB, BCL70EFP.LIB, BCL70ENP.LIB
    BCL70ANR.LIB, BCL70AFR.LIB, BCL70ANP.LIB, BCL70AFP.LIB

    Format: BCL70mso.LIB    (where the mso letters are defined above)

 Financial Libraries
 -------------------

    FINANCER.LIB, FINANCAR.LIB, FINANCEP.LIB, FINANCAP.LIB

    Format: FINANCmo.LIB    (where the mo letters are defined above)
    (Name is not dependent upon Far or Near string storage.)

    FINANCER.QLB is the Quick library for use in the QBX.EXE
    environment.

 Date/Time Format Libraries
 --------------------------

    DTFMTER.LIB, DTFMTAR.LIB, DTFMTEP.LIB, DTFMTAP.LIB

    Format: DTFMTmo.LIB    (where the mo letters are defined above)
    (Name is not dependent upon Far or Near string storage.)

    DTFMTER.QLB is the Quick library for use in the QBX.EXE
    environment.

 Font Libraries
 --------------

    FONTBEFR.LIB, FONTBENR.LIB, FONTBANR.LIB, FONTBAFR.LIB

    Format: FONTBmsR.LIB    (where the ms letters are defined above)
    (There is no protected mode version.)

    FONTBEFR.QLB is the Quick library for use in the QBX.EXE
    environment.

 Matrix Operations Toolbox Libraries
 -----------------------------------

    MATBEFR.LIB, MATBENR.LIB, MATBEFP.LIB, MATBENP.LIB
    MATBANR.LIB, MATBAFR.LIB, MATBANP.LIB, MATBAFP.LIB

    Format: MATBmso.LIB    (where the mso letters are defined above)

    MATBEFR.QLB is the Quick library for use in the QBX.EXE
    environment.

 User Interface Toolbox Libraries
 --------------------------------

    UITBEFR.LIB, UITBENR.LIB, UITBEFP.LIB, UITBENP.LIB
    UITBANR.LIB, UITBAFR.LIB, UITBANP.LIB, UITBAFP.LIB

    Format: UITBmso.LIB    (where the mso letters are defined above)

    UITBEFR.QLB is the Quick library for use in the QBX.EXE
    environment.

 Presentation Graphics Toolbox Libraries
 ---------------------------------------

    CHRTBEFR.LIB, CHRTBENR.LIB, CHRTBEFP.LIB, CHRTBENP.LIB
    CHRTBANR.LIB, CHRTBAFR.LIB, CHRTBANP.LIB, CHRTBAFP.LIB

    Format: CHRTBmso.LIB    (where the mso letters are defined above)

    CHRTBEFR.QLB is the Quick library for use in the QBX.EXE
    environment.

 Stub Library
 ------------

    NOTRNEMR.LIB, NOTRNEMP.LIB

    Format: NOTRNEMo.LIB
                   o = Protected (P) or Real (R) mode operating system.

    Description: A stub library file that removes all intrinsic math
                 functions including LOG, SQR, SIN, COS, TAN, ATN, EXP,
                 ^, CIRCLE statements with a start and/or stop angle,
                 and DRAW statements with A or T commands.

    (NOTRNEMR.LIB and NOTRNEMP.LIB are the only .LIB stub files in
    BASIC 7.00. For a list of .OBJ stub files, refer to Pages 540 and
    541 of "Microsoft BASIC Version 7.0: Programmer's Guide.")

 OTHER LIBRARY NAMING CONVENTIONS
 --------------------------------

 ISAM Libraries
 --------------

    PROISAMD.LIB, PROISAM.LIB

    PROISAMD.LIB gives you full ISAM support, including the data
    dictionary routines for creating and deleting indexes, tables, and
    databases. PROISAM.LIB (with no D) supports ISAM programs without
    the ability to create or delete indexes, tables, or databases.

    PROISAM.EXE and PROISAMD.EXE are the TSR (Terminate-and-Stay-
    Resident) programs that provide ISAM support in the QBX.EXE
    environment, or in .EXE programs where you don't wish to link the
    ISAM support directly to your .EXE file.

 OS/2 Function Library
 ---------------------

    Name: OS2.LIB
    Description: Used for operating system calls into MS OS/2.


 121. "Subscript out of Range in Quick Library Module: MENU" in 7.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891207-103
 Last Modified:  2-MAY-1990    ArticleIdent: Q52092

 A program that uses procedures in the User Interface Toolbox's
 WINDOW.BAS source-code file may generate the message "Subscript out
 of range in module: MENU," if either the global-array declarations
 used with MENU.BAS are not included in the program or if they are
 included in the wrong order.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS.

 When using procedures in WINDOW.BAS, you must include the global-array
 declarations used with MENU.BAS in addition to the global-array
 declarations that are specific to WINDOW.BAS.

 The MENU.BAS COMMON SHARED statements must be listed before the
 WINDOW.BAS COMMON SHARED statements or a "Subscript out of range in
 module: MENU" error occurs.

 When using procedures in WINDOW.BAS, you make the following
 global-array declarations in your program. The COMMON SHARED
 statements must be listed in the exact order shown. The order of the
 DIM statements does NOT matter.

 'COMMON SHARED statements to be used with MENU.BAS:

         COMMON SHARED /uitools/ GloMenu       AS MenuMiscType
         COMMON SHARED /uitools/ GloTitle()    AS MenuTitleType
         COMMON SHARED /uitools/ GloItem()     AS MenuItemType

 'COMMON SHARED statements WINDOW.BAS:

         COMMON SHARED /uitools/ GloWindow()   AS WindowType
         COMMON SHARED /uitools/ GloButton()   AS ButtonType
         COMMON SHARED /uitools/ GloEdit()     AS EditFieldType
         COMMON SHARED /uitools/ GloStorage    AS WindowStorageType
         COMMON SHARED /uitools/ GloWindowStack() AS INTEGER
         COMMON SHARED /uitools/ GloBuffer$()

 'DIM statements to be used with MENU.BAS:

         DIM GloTitle(MAXMENU)                 AS MenuTitleType
         DIM GloItem(MAXMENU, MAXITEM)         AS MenuItemType

 'DIM statements to be used with WINDOW.BAS:

         DIM GloWindow(MAXWINDOW)              AS WindowType
         DIM GloButton(MAXBUTTON)              AS ButtonType
         DIM GloEdit(MAXEDITFIELD)             AS EditFieldType
         DIM GloWindowStack(MAXWINDOW)         AS INTEGER
         DIM GloBuffer$(MAXWINDOW + 1, 2)


 122. BASIC 7.00 Example to Find All Available Disk Drives

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891214-80
 Last Modified: 14-JAN-1990    ArticleIdent: Q52093

 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 can change the current drive from within a BASIC
 program with the command

    CHDRIVE <drive letter>

 where <drive letter> is a string expression that is a valid drive.
 This statement, coupled with error trapping, can be used to find all
 available disk drives.

 The example program below collects a list of all the available disk
 drives and puts it into the fixed-length STRING array "Drives". This
 is done by using the CHDRIVE statement to log onto each possible drive
 (A through Z) and adding to the list only those drives that were
 successfully logged onto.

 The INTEGER variable "IsDrive%" is used to flag whether or not the
 CHDRIVE statement was successful in trying to log onto the next drive.

 If CHDRIVE is unsuccessful, BASIC will generate a "Device unavailable"
 error. This error will be trapped by the local error-handling routine,
 "DriveError", which will set "IsDrive%" to FALSE.

 If CHDRIVE is successful, "IsDrive%" will remain TRUE and the drive
 will be added to the list. The total number of available drives is
 stored in the INTEGER variable "TotalDrives%".

 Note that on a PC a legal drive name can only be a single letter
 between  "A" and "Z". Also, DOS does not distinguish between uppercase
 and lowercase letters. Therefore, in the following program we can use
 the numbers 65 through 90 whose corresponding ASCII characters are "A"
 through "Z" to circulate through all the possible drives. The counter
 variable of a FOR...NEXT loop is just right for performing this task.
 Our counter is "DriveLetter%".

 Code Example
 ------------

 CONST TRUE = -1
 CONST FALSE = 0

 DIM Drives(26) AS STRING * 1       'The list of drives.

 ON LOCAL ERROR GOTO DriveError   'If CHDRIVE unsuccessful trap error.
 TotalDrives% = 0

 FOR DriveLetter% = 65 TO 90      'ASCII "A" through "Z"
    IsDrive% = TRUE
    CHDRIVE CHR$(DriveLetter%)   'Try to log onto drive.
    IF IsDrive% THEN
       TotalDrives% = TotalDrives% + 1   'CHDRIVE was successful.
       Drives(TotalDrives%) = CHR$(DriveLetter%)   'Add drive letter.
    END IF
 NEXT DriveLetter%

 END

 DriveError: IsDrive% = FALSE   'CHDRIVE was unsuccessful.
             RESUME NEXT        'Resume at the IF statement.


 123. You Can CHAIN Only to an .EXE or .COM in BASIC PDS 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891220-87
 Last Modified: 14-JAN-1990    ArticleIdent: Q57341

 In Microsoft Basic Compiler Versions 6.00 and 6.00b and in QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS, you can CHAIN to an
 executable file that does not have the extension .EXE, and it will not
 generate an error. In BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2, the same executable file must
 have the extension .EXE or .COM to run without an error. If the
 CHAINed-to file does not have one of these two extensions, the error
 "Bad File Mode" is generated when the program is executed.

 This new extension checking is to help you CHAIN to files that are
 most likely meant to be CHAINed to.


 124. QBX May Incorrectly Parse Array Element in User-Defined TYPE

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q57501

 The QuickBASIC Extended editor (QBX.EXE), which is shipped with
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS, incorrectly parses a line of code that uses incorrect syntax
 for an array element in a user-defined TYPE. The following is an
 example:

    TYPE abc
       a(1 to 10) AS STRING * 8
    END TYPE
    DIM y AS abc
    PRINT y.a$(3)

 When you enter the last line into QBX.EXE and press the ENTER key,
 the line is interpreted (parsed) incorrectly and is displayed
 incorrectly as follows:

    3yGOTO

 If the correct line of code "PRINT y.a(3)" is entered, the code is
 interpreted correctly.

 Microsoft has confirmed this to be problem in the QBX.EXE editor in
 Microsoft BASIC PDS version 7.00. This problem was corrected in
 QBX.EXE in BASIC PDS 7.10.

 This problem relates only to QBX.EXE and does not relate to the BC.EXE
 compiler in BASIC 7.00.


 125. SCREEN Statement Correction for SCREEN 3 and 4 in PDS 7.00

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891214-90 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57343

 The "Microsoft BASIC 7.0: Language Reference" manual for Microsoft
 BASIC PDS Versions 7.00 and 7.10 incorrectly documents SCREEN modes 3
 and 4. Page 311 incorrectly states that SCREEN mode 3 supports
 Olivetti or AT&T Adapter Boards and that SCREEN mode 4 supports
 Hercules graphics capabilities.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The correct entries under the SCREEN statement for SCREEN modes 3 and
 4 are included in the QBX.EXE Microsoft Advisor online Help system and
 appear as follows:

 SCREEN 3: Hercules adapter required, monochrome monitor only
    - 720 x 348 graphics
    - 80 x 25 text format, 9 x 14 character box
    - 2 screen pages (1 only if a second display adapter is installed)
    - PALETTE statement not supported

 SCREEN 4:
    - Supports Olivetti (R) Personal Computers models M24, M240, M28,
      M280, M380, M380/C, M380/T and AT&T (R) Personal Computers 6300
      series
    - 640 x 400 graphics
    - 80 x 25 text format, 8 x 16 character box
    - 1 of 16 colors assigned as the foreground color (selected by
      the COLOR statement); background is fixed at black


 126. "Subscript out of Range in Quick Library Module: WINDOW" Error

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S891207-24 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57344

 The following COMMON SHARED statement should be added to the global
 array declarations found on Page 550 of the "Microsoft BASIC 7.0:
 Language Reference" manual (for 7.00 and 7.10) to successfully use the
 User Interface (UI) Toolbox's WINDOW.BAS source code file:

    COMMON SHARED /uitools/GloWindowStack() AS INTEGER

 The order of COMMON SHARED statements is important. The above
 statement should be inserted as follows:

    COMMON SHARED /uitools/GloWindow()      AS WindowType
    COMMON SHARED /uitools/GloButton ()     AS ButtonType
    COMMON SHARED /uitools/GloEdit()        AS EditFieldType
    COMMON SHARED /uitools/GloStorage()     AS WindowStorageType
    COMMON SHARED /uitools/GloWindowStack() AS INTEGER
    COMMON SHARED /uitools/GloBuffer$()

 If this COMMON SHARED statement is missing from a program that uses
 the WINDOW.BAS source code file, the program generates the error
 message "Subscript out of range in Quick library module: WINDOW" on
 the first call to a WINDOW.BAS procedure. This error will probably
 occur on the call to WindowInit because it must be the first
 WINDOW.BAS procedure called.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.


 127. Colored Buttons/Scroll Bars in BASIC 7.00 UI Toolbox

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891207-109
 Last Modified: 14-JAN-1990    ArticleIdent: Q57355

 The User Interface (UI) Toolbox supplied with Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 allows you to display scroll bars in windows. However, it has no
 facility for specifying foreground and background colors for them and
 always uses white and black, respectively. This limitation can be
 removed by modifying two COLOR statements in the ButtonShow procedure
 of the WINDOW.BAS toolbox file and adding a COMMON SHARED statement to
 the module-level code of that same file.

 The ButtonShow procedure of the WINDOW.BAS toolbox file is called when
 a button (which includes scroll bars) is to be displayed in a window.
 As written, the ButtonShow procedure does not allow regular buttons to
 have a different color than the window text and scroll bars are
 limited to a white foreground and black background.

 The colors of regular buttons can be specified through the use of the
 WindowColor procedure, which changes the colors used for window text.
 The colors used for window text are the same as those used for
 buttons.

 The COLOR statement used to color scroll bars is as follows:

    COLOR 0,7

 There are two of these COLOR statements in the ButtonShow procedure,
 one for horizontal scroll bars and one for vertical scroll bars. Both
 of them need to be changed to the following statement:

    COLOR ScrollBarForeground%, ScrollBarBackground%

 Here ScrollBarForeground and ScrollBarBackground are sample names for
 integer variables and may be differently named. However, they must be
 unique throughout the entire program because they will be COMMON
 SHARED between the module opening a button and the WINDOW.BAS module.
 Therefore, at the module-level code of both of those modules, insert
 the following statements:

    COMMON SHARED /ScrollBarColors/ ScrollBarForeground%
    COMMON SHARED /ScrollBarColors/ ScrollBarBackground%

 Here ScrollBarColors is an sample name for a named COMMON block and
 may be different. However, the name of the COMMON block must be the
 same in both modules and the data types of the variables must be
 integer. To prevent confusion, the same names used in the COLOR
 statements should be used in the COMMON SHARED statements.

 After the above changes have been made, you can specify what the
 foreground and background colors of each scroll bar will be by
 assigning color numbers to the variables in the named COMMON block.
 The variables do not need to be passed to the ButtonShow procedure
 because they are COMMON SHARED with the WINDOW.BAS module. The COLOR
 statement will always have access to them.

 Code Example
 ------------

 The following code fragment is an example of specifying colors for a
 scroll bar:

 'The following COMMON SHARED statements would also appear in the
 'module-level code of the WINDOW.BAS module.

 COMMON SHARED /ScrollBarColors/ ScrollBarForeground%
 COMMON SHARED /ScrollBarColors/ ScrollBarBackground%

 ScrollBarForeground% = 14   'yellow foreground.
 ScrollBarBackground% = 1    'blue background.

 'The ButtonOpen procedure will call the ButtonShow procedure,
 'which will use the values in ScrollBarForeground% and
 'ScrollBarBackground% to COLOR the scroll bar.

 CALL ButtonOpen (1, 1, "", 10, 30, 20, 30, 6)


 128. "Overflow" Accessing > 32K Array Inside User-Defined TYPE

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891113-17 buglist7.00
 Last Modified: 14-JAN-1990    ArticleIdent: Q57356

 When a program is compiled with the /D switch, the length of arrays
 inside user-defined TYPEs is limited to 32,768 bytes. The compiler
 will not generate an error if a larger array is declared inside a
 user-defined type, but accessing any element that is offset more than
 32,768 bytes into the array will cause an "Overflow" error.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2. We are researching this problem and will report new information
 here as it becomes available.

 This limitation applies only to arrays inside user-defined TYPEs, a
 new feature that was introduced in BASIC PDS 7.00 for MS-DOS and MS
 OS/2.

 The following two examples illustrate when the "Overflow" error occurs
 and when it doesn't.

 Example 1
 ---------

 When compiled with the BC /D switch, this program generates an
 "Overflow" error. This is because element 16,385 of the INTEGER array
 inside of the user-defined TYPE is being accessed. 16,385 * 2 (2 bytes
 per INTEGER) is greater than 32,768, so that element is out of bounds.

 TYPE aType
    anArray (1 TO 16385) AS INTEGER  'The compiler will not
                                     'flag this as an error -
 END TYPE                            '(16385*2) > 32768
 DIM aVariable as aType

 FOR i = 1 TO 16385
    aVariable.anArray(i) = 1   'When i = 16385 the "Overflow"
 NEXT i                        'error will be generated.

 Example 2
 ---------

 The following program does not generate an "Overflow" error. This is
 because the highest element of the INTEGER array inside the
 user-defined type being accessed is 16,384. 16,384 * 2 (2 bytes per
 INTEGER) is not greater than 32,768, so the element is not out of
 bounds.

 TYPE aType
    anArray (1 TO 16385) AS INTEGER  'The compiler will not
                                     'flag this as an error -
 END TYPE                            '(16385 * 2) > 32768
 DIM aVariable as aType

 FOR i = 1 TO 16384
    aVariable.anArray(i) = 1   'No "Overflow" error -
 NEXT i                        '16384 * 2 <= 32768.


 129. Missing Dollar Sign on a Call to Assembly Routine

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S891226-5 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57357

 On Page 372 of the "Microsoft BASIC 7.0: Language Reference" manual
 (for 7.00 and 7.10) the CALL to Makestring needs to have a dollar sign
 appended to the end of it as shown below.

 The following is incorrect:

    PRINT Makestring

 It should be the following:

    PRINT Makestring$

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 130. Incorrect Declaration of Far Procedure in Assembly; BASIC 7.10

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S891226-6 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57358

 On Page 495 of the "Microsoft BASIC 7.0: Programmer's Guide" (for 7.00
 and 7.10), the "proc far" declaring the assembly procedures as far
 should actually be just "far", not "proc far" as shown below.

 The following is incorrect:

    extrn stringassign:proc far

 It should be the following:

    extrn stringassign:far

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 131. Use "proc uses", Not "procuses" in MASM Example; BASIC 7.10

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S891226-4 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57359

 On Page 495 of the "Microsoft BASIC 7.0: Programmer's Guide" (for 7.00
 and 7.10), a space should appear between the assembly code "proc" and
 "uses", but the manual shows no space between them.

 The following is incorrect:

    addstring  procuses si di ds,s1:far ptr,s1len,s2:far ptr,s2len

 The following is correct:

    addstring  proc uses si di sd,s1:far ptr,s1len,s2:far ptr,s2len

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 132. Variable Length String Passed from BASIC PDS 7.00 to C

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891017-100
 Last Modified: 17-JAN-1990    ArticleIdent: Q57362

 The example below demonstrates how to pass a variable-length string
 from a compiled BASIC program to a C program. This information applies
 to Microsoft BASIC Professional Development System (PDS) 7.00 for
 MS-DOS and MS OS/2.

 BASIC to C Example
 ------------------

 Compile and link as follows:

 Compile:  BC /Fs/d Bastest.bas;
           QCL /AM Ctest.c /c

 Link:     LINK /noe/nod Bastest+Ctest,,,BRT70EFR+MLIBCE;

 REM ===== BASIC PROGRAM =====
 DECLARE SUB StringFar CDECL (BYVAL p1o AS INTEGER, BYVAL p1s AS
 INTEGER, SEG p3 AS INTEGER)
 CLS
 a$ = "This is a test" + CHR$(0)
 CALL StringFar(SADD(a$), SSEG(a$), LEN(a$))
 PRINT "Back from C"
 END
 /* C sub-program */
 #include <e:\qc2\include\stdio.h>
 void StringFar(a,len)
    char far *a;
     int *len;
  {
     int i;
     printf("The string is : %s \n\n",a);
     printf(" Index       Value       Character\n");
     for (i=0;i < *len; i++)
        {
          printf("  %2d          %3d
 %c\n",i,a[i],a[i]);
        };
  }


 133. How to Pass a Variable Length String from BASIC to MASM

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891017-100
 Last Modified: 17-JAN-1990    ArticleIdent: Q57363

 The example below demonstrates how to pass a variable-length string
 from a compiled BASIC program to a MASM procedure. This information
 applies to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2.

 BASIC to MASM Example
 ---------------------

 Compile and link as follows:

 Compile: BC /Fs/d basmasm.bas;
          MASM masmtest;
 Link:    LINK basmasm+masmtest,,,BRT70EFR;

 REM ==BASIC to MASM code===
 DEFINT A-Z
 DECLARE SUB printmessage (BYVAL segm, BYVAL offs)
 CLS
 a$ = "Assembly test successful" + "$"
 CALL printmessage(SSEG(a$), SADD(a$))
 LOCATE 10, 10
 PRINT "Back from assembly"
 END

 ;MASM code here
                     .Model    Medium,basic
                     .stack
                     .code
                     public    printmessage
 printmessage        proc      uses ds,segm,offs
                     mov       ax,segm
                     mov       ds,ax
                     mov       dx,offs
                     mov       ah,9
                     int       21h
                     ret
 printmessage        endp
                     end


 134. Missing FUNCTION Name in BASIC PDS 7.00 Example

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S891219-95 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57364

 There is an error on Page 494 of the "Microsoft BASIC 7.0:
 Programmer's Guide" (for 7.00 and 7.10), as shown below.

 The following is incorrect:

    C$ = (A$, LEN(A$), B$, LEN(B$))

 The following is correct:

    C$ = AddString$(A$, LEN(A$), B$, LEN(B$))

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 135. "Subprogram Not Defined" GetCopyBox, AttrBox Using GENERAL.BAS

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891219-77 docerr
 Last Modified:  1-AUG-1990    ArticleIdent: Q57365

 GetCopyBox, PutCopyBox, and AttrBox (which are all invoked in
 GENERAL.BAS) are assembly language procedures located in the UIASM.ASM
 assembler source file, in the UIASM.OBJ object file, and in the
 UITBEFR.QLB Quick library. This fact needs to be added on Pages 499,
 585-586, 589, and 591 of the "Microsoft BASIC 7.0: Language Reference"
 manual for Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10. You will need to know this when using
 GENERAL.BAS from the User Interface (UI) Toolbox as described below.

 If you are using GENERAL.BAS in QBX.EXE and get a "Subprogram not
 defined" error on a call to GetCopyBox, PutCopyBox, or AttrBox, then
 you must invoke QBX with a Quick library containing these routines,
 for example:

    QBX /L UITBEFR.QLB.

 [Also, if you are using GENERAL.BAS in QBX.EXE and get a "Subprogram
 not defined" error on a call to MouseHide (in the Box subprogram),
 then you must Load (choose Load from the File menu) the MOUSE.BAS
 source file, which contains MouseHide and the other mouse UI Toolbox
 routines.]

 This information applies to the UI Toolbox in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS.

 If you chose to have Quick libraries created when you ran SETUP.EXE
 for BASIC 7.00 or 7.10, you already have the UITBEFR.QLB Quick library
 that contains all the UI Toolbox routines. SETUP.EXE places
 UITBEFR.QLB by default in the directory where you chose to place
 .LIB files.

 Pages 534 and 535 "Microsoft BASIC 7.0: Language Reference" for
 versions 7.00 and 7.10 describe how to build UITBEFR.QLB (or subsets)
 yourself. (You can use LINK /Q to build UIASM.OBJ into a Quick library
 and use LIB.EXE to build the parallel .LIB library.)

 The three routines in UIASM.OBJ (PutCopyBox, GetCopyBox, and AttrBox)
 must always be present when using the UI Toolbox.

 Page 586 correctly describes how to make calls to AttrBox SUB. Since
 the code for AttrBox is not in the GENERAL.BAS source-code file, if
 you want to alter the code for AttrBox, you must edit the UIASM.ASM
 source file and reassemble it with Microsoft Macro Assembler (MASM).

 Documentation Correction
 ------------------------

 Pages 499 and 585-586 of the "Microsoft BASIC 7.0: Language Reference"
 manual incorrectly imply that AttrBox SUB is a procedure found in the
 GENERAL.BAS source-code file for the User Interface (UI) Toolbox.

 The AttrBox is actually an assembly language procedure located in the
 UI Toolbox object file, UIASM.OBJ (and in the UIASM.ASM source file).
 The UI Toolbox procedures require that UIASM.OBJ be included either in
 a Quick library when running inside the QBX.EXE editor or in a library
 (.LIB) that is linked to your program when running outside the
 environment (in a compiled executable .EXE form).


 136. DateSerial# Accepts Values Outside Range for Arguments

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr SR# S891227-47
 Last Modified:  8-JAN-1991    ArticleIdent: Q57366

 Page 425 of the "Microsoft BASIC 7.0: Language Reference" manual (for
 7.00 and 7.10) states that the DateSerial# function will generate an
 "Illegal function call" if values are specified outside the given
 ranges of the following:

    year%  - A year from 1753 to 2078
    month% - A month from 1 to 12
    day%   - A day from 1 to 31

 An "Illegal function call" is only generated if the year, month, and
 day arguments generate a serial number outside the valid range of
 -53,688 to 65,380. The corresponding dates for this range are January
 1, 1753, to December 31, 2078.

 The README.DOC file provided with Microsoft BASIC Professional
 Development System (PDS) Versions 7.00 and 7.10 notes this
 documentation error.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The DateSerial# function can return serial numbers for dates in the
 following range, inclusive:

    DATE:     January 1, 1753, to December 31, 2078
    SERIAL#:           -53688 to 65380

 The DateSerial# function generates an "Illegal function call" only if
 the arguments passed to it generate a serial number outside the range
 of -53,688 to 65,380. The following example uses a value outside the
 given range for the "month%" argument, but does not generate an
 "Illegal function call":

    theDate# = DateSerial#(89, 13, 1)

 The serial number returned in the above call actually corresponds to
 the date January 1, 1990. A value of 13 logically corresponds to the
 month following December. Since December is the last month of a year,
 the year value is incremented by 1, and the month value is reset to 1,
 which corresponds to January; therefore, the following two calls to
 DateSerial# return the same serial number:

    theDate# = DateSerial#(89, 13, 1)
    theDate# = DateSerial#(90,  1, 1)

 Negative numbers work in the same way. A value of "-1" for the month
 argument refers to the month of November in the previous year. The
 following to calls to DateSerial# return the same serial number:

    theDate# = DateSerial#(90, -1, 1)
    theDate# = DateSerial#(89, 11, 1)

 The following are example calls to DateSerial# that generate the
 "Illegal function call" error message since the resulting serial
 number falls outside the valid range:

    theDate# = DateSerial#(2078, 12, 32)  ->  January   1, 2079
    theDate# = DateSerial#(2078, 13,  1)  ->  January   1, 2079
    theDate# = DateSerial#(1753,  0, 31)  ->  December 31, 1752


 137. COMMON SHARED Must Be in Order in User Interface Toolbox

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891211-54
 Last Modified: 23-FEB-1990    ArticleIdent: Q57367

 When using procedures from the User Interface (UI) Toolbox's MENU.BAS
 or WINDOW.BAS, you must provide global-array declarations in your
 program. If these declarations are in the wrong order, various errors
 may occur. The proper order for COMMON SHARED declarations can be
 found at the beginning of each User Interface Toolbox .BAS file.
 Possible errors include "Subscript out of range in module...," "Far
 Heap Corrupt," or the system may hang.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 In most cases, switching the order of the COMMON SHARED statements for
 the global-array declarations generates the error "Subscript out of
 range in module..." on the first call to a procedure in MENU.BAS or
 WINDOW.BAS.

 Changing the order of certain COMMON SHARED statements results in a
 "Far Heap Corrupt" message when the program is run from the QBX.EXE
 editor. This can put the computer in an unstable memory state, which
 may cause it to hang. When the same program is run from the DOS
 command line, the program fails and gives a "Subscript out of range in
 module..." error message.

 Here is some good advice from Page 65 of the "Microsoft BASIC 7.0:
 Language Reference" manual:

    Errors caused by mismatched COMMON statements are subtle and
    difficult to find. An easy way to avoid mismatched COMMON
    statements is to place COMMON declarations in a single include
    file and use the $INCLUDE metacommand in each module.

 Code Example
 ------------

 The following code exhibits the behavior of a program that has a
 statement (COMMON SHARED /uitools/GloWindowStack() AS INTEGER) in the
 wrong order. This program generates a "Far Heap Corrupt" message and
 can hang when run from the QBX.EXE editor in either MS-DOS or in OS/2
 real mode. If this program is compiled, linked, and then run from the
 DOS command line, it generates a "Subscript out of range in module..."
 error.

    REM $INCLUDE: 'MENU.BI'
    REM $INCLUDE: 'WINDOW.BI'
    REM $INCLUDE: 'MOUSE.BI'
    REM $INCLUDE: 'GENERAL.BI'

    COMMON SHARED /uitools/GloMenu     AS MenuMiscType
    COMMON SHARED /uitools/GloTitle()  AS MenuTitleType
    COMMON SHARED /uitools/GloItem()   AS MenuItemType

    'The next statement is out of order

    COMMON SHARED /uitools/GloWindowStack() AS INTEGER
    COMMON SHARED /uitools/GloWindow() AS WindowType
    COMMON SHARED /uitools/GloButton() AS ButtonType
    COMMON SHARED /uitools/GloEdit()   AS EditFieldType
    COMMON SHARED /uitools/Storage     AS WindowStorageType
    'This is where the statement should be
    COMMON SHARED /uitools/GloBuffer$()

    DIM GloTitle(MAXMENU)              AS MenuTitleType
    DIM GloItem(MAXMENU, MAXITEM)      AS MenuItemType
    DIM GloWindow(MAXWINDOW)           AS WindowType
    DIM GloButton(MAXBUTTON)           AS ButtonType
    DIM GloEdit(MAXEDITFIELD)          AS EditFieldType
    DIM GloWindowStack(MAXWINDOW)      AS INTEGER
    DIM GloBuffer$(MAXWINDOW +1, 2)

    MenuInit
    WindowInit


 138. QBX Make Library Uses OS/2 Mode Last Used by Make EXE File

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891211-105
 Last Modified:  8-JAN-1990    ArticleIdent: Q57382

 The Make Library menu command of the QuickBASIC Extended (QBX.EXE)
 environment that comes with Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2 will compile currently loaded source modules for
 whichever OS/2 mode (real or protected) that the last Make EXE File
 menu command compiled for.

 (Note that the QBX.EXE environment runs only under OS/2 real mode or
 MS-DOS and does not itself run under OS/2 protected mode, although
 QBX.EXE can make .EXE programs that run under OS/2 protected mode.)

 The Make Library command on the Run menu of the QBX.EXE environment
 can be used to make stand-alone libraries for either real or protected
 mode operation. However, there is no option in the Make Library dialog
 box that allows you to choose which mode the modules of the library
 will be compiled for.

 The Make Library command will compile the source-code modules for
 whichever mode the last Make EXE File command compiled for. That is,
 if the OS/2 Protected Mode option in the Make EXE File dialog box was
 selected the last time you made an EXE file, then the Make Library
 command will compile the library modules for protected mode. If a real
 mode (using the DOS or OS/2 Real Mode option) EXE file was made last,
 a real mode library will be made the next time Make Library is
 invoked.

 Note that selecting a mode (protected or real) in the Make EXE File
 dialog box and then choosing the Cancel button will not cause the Make
 Library command to compile for that mode. BC.EXE must be invoked for
 the change to take effect.

 Do the following to demonstrate the problem:

 1. Invoke QBX and type the following line:

    PRINT "This will be a protected-mode program"

    Now save the program.

 2. Make the program into an executable file using the Make EXE File
    menu command. For the target environment (operation mode), select
    the OS/2 Protected Mode option. Choose the Make EXE button to make
    the executable file.

    The "/Lp" option should be one of the parameters on the BC.EXE
    command line that is displayed. This switch is used to compile for
    protected mode.

 3. When the executable has been made, the QBX environment should
    reappear on the screen. Choose the Make Library command and select
    the Make Library button to make the library.

    The "/Lp" switch should be one of the parameters on the BC.EXE
    command line that is displayed. This switch is used to compile for
    protected mode.

 4. When the QBX environment comes back on the screen, repeat Steps 2
    and 3. However, in Step 2, select the DOS Or OS/2 Real Mode option
    for the target environment. Instead of the "/Lp" switch, the "/Lr"
    switch should be one of the parameters on the BC.EXE command line
    generated by the Make EXE File and the Make Library commands.


 139. LoadFont Function Example Documentation Error in BASIC 7.00

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891211-4 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57502

 Page 524 of the "Microsoft BASIC 7.0: Language Reference" for
 Microsoft BASIC Professional Development System (PDS) Versions 7.00
 and 7.10 shows an incorrect example of how to load a font by its order
 in the font file. This documentation incorrectly states the following:

    Note that to load fonts according to their order in the font
    file, l% would take the form:

       l% = LoadFont%("n1,n3,n6")

 The code above should read as follows (where l% means L%, not to be
 confused with 1%):

    l% = LoadFont%("n1/n3/n6")

 When loading multiple fonts, each font given in the fontspec$ argument
 of LoadFont%(fontspec$) should be separated by forward slashes (the
 "/" character), not by commas.

 If the code in this documentation error is used, only the first font
 is loaded (l% contains the number "1", indicating that only one font
 is loaded).

 Code Example
 ------------

 The following code example demonstrates the documentation problem. To
 use this code example, you must start QBX.EXE with /L FONTBEFR.QLB to
 access the font routines.

 REM $INCLUDE: 'fontb.bi'
 '* Load a the Times Roman font.
 SCREEN 9
 PRINT "Registering Times Roman font."
 FontNum% = RegisterFonts("D:\BC7\FONTS\TMSRB.FON")
 PRINT "Number of fonts in the file: "; FontNum%
 PRINT "Loading fonts 4,5,6 from the Times Roman file."
 var1% = LoadFont%("N4,N5,N6")
 PRINT "Number of fonts successfully loaded"; var1%
 PRINT "value of FontErr", FontErr
 a$ = "Hello world"
 var1% = OutGText%(100, 100, a$)
 END


 140. Documentation Errors in BASIC 7.00 Presentation Graphics

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891211-2 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q57504

 This article documents several documentation errors in Chapter 6,
 "Presentation Graphics," of the "Microsoft BASIC 7.0: Programmer's
 Guide" for Microsoft BASIC Professional Development System (PDS)
 Versions 7.00 and 7.10. The errors are as follows:

 1. Page 250 details the fields in the AxisType user-defined TYPE. The
    field "Labelled" is misspelled. It should be spelled "Labeled".
    This field is spelled correctly in the definition of the AxisType
    in the CHRTB.BI $INCLUDE file.

 2. Page 251 incorrectly says to assign TicFormat to the CONSTant
    cDecFormat for decimal. There is no CONSTant named cDecFormat.
    This constant is defined as cNormFormat in the CHRTB.BI $INCLUDE
    file.

 3. Page 266 describes how to load fonts for use in Presentation
    Graphics. The following line in the example at the bottom of the
    page is incorrect:

       Env.MainTitle.Font = 3

    This line should be changed to the following:

       Env.MainTitle.TitleFont = 3


 141. "No Symbolic Information" Using Older CodeView with BASIC PDS

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891228-44
 Last Modified: 14-JAN-1990    ArticleIdent: Q57515

 If a version of Microsoft CodeView earlier than Version 2.35 is used
 on a program compiled with Microsoft BASIC Professional Development
 System (PDS) Version 7.00, the message "No symbolic information" is
 displayed within CodeView and no BASIC source code is displayed.

 BASIC PDS 7.00 is designed to use CodeView Version 2.35, which is
 included with the product.

 This information applies to the Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.


 142. Why BASIC 7.00 and 7.10 Don't Support Multiuser ISAM

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 27-JUL-1990    ArticleIdent: Q57579

 Question:

 Why is ISAM support in Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 only single-user and not multiuser? Also,
 why was ISAM support for OS/2 protected mode not available in 7.00 but
 was released in version 7.10?

 (Multiuser ISAM support refers to the ability for multiple processes,
 or users on a network, to access different records within one ISAM
 file at the same time, with locking of individual records. BASIC 7.00
 and 7.10 don't support multiuser ISAM; they only support single-user
 ISAM, where the whole ISAM file is locked during use by one program.)

 Response:

 The Microsoft BASIC Professional Development System (PDS) is a
 feature-packed product designed to satisfy the majority of needs
 expressed to us by our professional BASIC programmers. It includes the
 following:

  - Significant enhancements in performance (smaller and faster EXEs)

  - Significant enhancements in capacity (a 10- to 50-times increase in
    code and/or data space)

  - Significant enhancements in language (CURRENCY data type, static
    arrays in user-defined-TYPE records, local error handling, stack
    control, DOS file control)

  - Extras (three Excel-based libraries, three BASIC toolboxes for user
    interfaces, presentation graphics, and matrix math)

  - A new dimension added to file handling in the form of the
    high-performance ISAM database engine with a powerful, integrated
    BASIC programming interface

 As much as Microsoft wanted to include multiuser ISAM in BASIC PDS
 version 7.00 or 7.10, doing so meant holding back other features (such
 as those above) from the programmers who have expressed such a great
 need for them. Clearly, PC connectivity is growing and so will the
 need for a multiuser ISAM in BASIC. Just as Microsoft listened to
 customers in creating BASIC PDS 7.00 and 7.10, we will continue to
 listen and will make every attempt to have our future products address
 the most serious needs made known to us.

 The longer we allow the feature list for a given product release to
 grow, the longer everyone has to wait to get the feature(s) that may
 solve their immediate problem(s). If we had held BASIC 7.00 or 7.10
 off the market until multiuser ISAM was ready, no one would have had
 any of the above capacity, performance, or language features in a
 satisfactory time frame.

 Only after thorough testing did we introduce protected-mode (but still
 single-user) ISAM support in BASIC 7.10.

 Our perpetual challenge in the product release planning process is to
 find the combination of features and schedule that will best satisfy
 the needs of most of our customers.


 143. What Features Would You Want for a 1-Byte Data Type in BASIC?

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified: 17-JAN-1990    ArticleIdent: Q57580

 Some developers using Microsoft BASIC or QuickBASIC may suggest that a
 single-byte, unsigned data type should be added to BASIC. As of
 Microsoft BASIC PDS Version 7.00 or QuickBASIC Version 4.50 or
 earlier, a single-byte data type hasn't yet been implemented. If you
 support this suggestion, please send Microsoft your (customer)
 comments about what you would use this data type for and what kinds
 of operations you would like to see it support.

 For example, would you like the single-byte data type to be a fully
 implemented short integer complete with overflow checking and coercion
 to floating point or longer integers for the appropriate operations,
 or would you like to see it implemented as a simple, small, and fast
 data type with a subset of these operations? What are the ranges of
 uses that you can see for such a data type in your programs?

 We'd like to know what kinds of uses people envision for a single-byte
 data type before we consider adding the overhead to the product.

 Please send in your comments to Microsoft Product Support
 (206-454-2030) so we may forward them to the Microsoft BASIC Program
 Manager. Your input will be greatly appreciated.


 144. Microsoft Doesn't Offer Educational Edition of BASIC PDS 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 14-JAN-1990    ArticleIdent: Q57581

 Question:

 Why doesn't Microsoft offer an educational edition of BASIC PDS
 (Professional Development System) Version 7.00?

 Response:

 Microsoft instead recommends one of the following products for
 educational institutions and people who want to teach modern BASIC on
 IBM Personal Computers or compatibles:

 1. "Learn BASIC Now" by Halvorson and Rygmyr, published by Microsoft
    Press, 1989.

    This is the fastest, easiest way to learn modern QuickBASIC
    programming. The book includes a disk with the Microsoft QuickBASIC
    Interpreter (QBI.EXE), the QBI Advisor complete electronic
    reference, the QuickBASIC Express online tutorial and introduction
    to the interpreter, and dozens of sample programs. The book teaches
    BASIC programming step by step.

 2. Microsoft QuickBASIC Interpreter, Academic Edition Version 1.00,
    for IBM Personal Computers and Compatibles

    This product is entirely disk based, without a printed manual. The
    disk contains the Microsoft QuickBASIC Interpreter (QBI.EXE), the
    QBI Advisor complete electronic reference, the QuickBASIC Express
    online tutorial and introduction to the interpreter, and dozens of
    sample programs.

 The above two QuickBASIC Interpreter (QBI.EXE) products have the same
 language features found in Microsoft QuickBASIC Version 4.50 for IBM
 PCs and compatibles. (Note that the QBI.EXE interpreter environment
 has some limitations compared to QB.EXE 4.50).

 We found no compelling reason to make a special academic edition for
 BASIC PDS 7.00 since the only features in 7.00 not found in the
 existing QuickBASIC academic editions are all targeted for people
 making professional, commercial applications and are not crucial for
 teaching BASIC.


 145. BC 6.00/6.00b ERROUT.EXE Utility, "Command Failed" Error

 Product Version(s): 6.00 6.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891019-106 docerr
 Last Modified: 14-JAN-1990    ArticleIdent: Q57644

 Contrary to Pages 328 and 329 of the "Microsoft CodeView and
 Utilities: Software Development Tools for MS-DOS" manual, the
 ERROUT.EXE utility supplied with Microsoft BASIC Compiler Versions
 6.00 and 6.00b works only with .EXE or .COM files.

 When running any DOS command line other than an .EXE or .COM file,
 ERROUT fails to execute the supplied command and either hangs the
 machine or returns the following error:

    execution error U2253 : command failed

 When executing batch files or DOS commands such as TYPE and DIR, the
 above error message displays. In the case of batch files, if the .BAT
 extension is included at the end of the batch-file name, ERROUT.EXE
 may hang the machine. If the .BAT extension is not included, the above
 error message displays. (When an error output filename is supplied
 with the /f option, this same error is written to the file.)

 The first example on Page 329 of the "Microsoft CodeView and
 Utilities: Software Development Tools for MS-DOS" manual (for
 Microsoft BASIC Compiler 6.00 and 6.00b) fails since it uses the DOS
 TYPE statement. This first example should be removed. The examples
 using CL and MASM work properly since CL.EXE and MASM.EXE are .EXE
 programs.

 (The ERROUT.EXE utility is not shipped in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.)

 Syntax for ERROUT
 -----------------

 The ERROUT.EXE utility redirects standard error output generated from
 an .EXE or .COM program, using the following syntax:

    ERROUT [/f standarderrorfile] doscommandline

 Here, "standarderrorfile" is a filename to which all errors generated
 by "doscommandline" will be written when you use the /f option
 (lowercase "f"). Without the /f option, all error messages are sent to
 the console.

 No form of ERROUT works except when doscommandline is the name of an
 .EXE or .COM file.


 146. Setting COMSPEC & SHELL in OS/2; SHELL "Illegal Function Call"

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# S891218-2  B_QuickBas
 Last Modified: 14-JAN-1990    ArticleIdent: Q57645

 The following two situations might cause an "Illegal function call"
 error when attempting to SHELL under OS/2:

 1. In the OS/2 DOS 3.x compatibility box, a program can generate an
    "Illegal function call" if the COMSPEC environment variable is
    placed in the AUTOEXEC.BAT. Under OS/2, COMSPEC should be defined
    only in the CONFIG.SYS file.

 2. In an OS/2 protected mode session, "Illegal function call" on a
    SHELL can be generated if the parameter /E:xxxx is used to attempt
    to set the environment size on the CMD.EXE command interpreter. The
    CMD.EXE command interpreter will accept this parameter, but it will
    then prevent you from SHELLing another copy of CMD.EXE. To correct
    this problem, remove the COMSPEC from the AUTOEXEC.BAT file and make
    sure it is in the CONFIG.SYS. Also delete the parameter /E:xxxx
    after CMD.EXE in the CONFIG.SYS.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 under MS OS/2 real mode, to Microsoft BASIC Compiler Versions
 6.00 and 6.00b under MS OS/2 real and protected modes, and to
 Microsoft BASIC Professional Development System (PDS) 7.00 under MS
 OS/2 real and protected modes.

 To reproduce the problem, do the following:

 1. Place the following lines in the CONFIG.SYS file for OS/2:

       SET COMSPEC=C:\OS2\CMD.EXE /P /E:1024
       SET SHELL=C:\OS2\COMMAND.COM /P /E:1024

 2. Place the following statement in the OS/2 AUTOEXEC.BAT file:

       SET COMSPEC=C:\OS2\COMMAND.COM /P /E:1024

    Note: The path names to CMD.EXE and COMMAND.COM may be different on
    your system, depending on how you installed OS/2.

 3. Reboot your computer with the new settings.

 4. Do one of the following, depending on whether you are in real
    (MS-DOS) or protected mode:

    a. Load QB.EXE or QBX.EXE in real mode (DOS 3.x box) and either
       choose DOS Shell from the File menu, execute the word "SHELL"
       in the immediate window, or execute a program that contains only
       the word "SHELL." Each of these will produce the "illegal
       function  call" error in QB and QBX.EXE.

    b. Under OS/2 protected mode, execute a BASIC 6.00, 6.00b,or 7.00
       compiled program whose only statement is SHELL to show the
       problem.

 To eliminate the problem, remove the COMSPEC statement from the
 AUTOEXEC.BAT file, delete the /P /E:1024 after CMD.EXE, and reboot.

 The Command Interpreter (COMMAND.COM) Under DOS
 -----------------------------------------------

 Under DOS 3.x, 4.00, and 4.01, the COMSPEC environment variable is
 defined in the AUTOEXEC.BAT file. The SET COMSPEC= statement gives DOS
 a path for where the DOS command interpreter COMMAND.COM is located on
 the disk.

 Under DOS, a SHELL= command defined in the CONFIG.SYS file tells DOS
 the name of your command interpreter. This at first may not seem
 useful, but this feature was provided so that you can write your own
 command interpreter. You can place the name of your command
 interpreter in the SHELL= statement for DOS to load that command
 interpreter at boot time. However, most people use COMMAND.COM as
 their command interpreter in both the SET COMSPEC= and SHELL= commands
 under DOS.

 If you want to set the environment size, you can use the /E:xxx
 parameter on COMMAND.COM to increase or decrease the size available
 for environment variables and the PATH.

 The Command Interpreters (CMD.EXE and COMMAND.COM) Under OS/2
 -------------------------------------------------------------

 Under OS/2, there are two command interpreters (CMD.EXE and
 COMMAND.COM) and two parameters to SET in the CONFIG.SYS file:

 1. First, the SET COMSPEC= statement tells OS/2 where to find the OS/2
    protected mode command interpreter, which is called CMD.EXE. Unlike
    COMMAND.COM, CMD.EXE does not take the parameter /E:xxxx to set the
    environment size. OS/2 does not limit the environment size as DOS
    does with COMMAND.COM. If you use /E: on CMD.EXE, it will not cause
    an error message at boot time, but it will prevent you from
    SHELLing when in an OS/2 session.

 2. Second, the SHELL= statement tells OS/2 where to find the DOS
    compatibility box command interpreter, which is called COMMAND.COM.
    Just as in DOS, COMMAND.COM will take the parameter /E:xxxx, which
    allows you to set the environment size for the DOS box command
    interpreter. Note, however, that when you go into the DOS box, OS/2
    takes the value of the SHELL in the CONFIG.SYS and SETs the DOS box
    COMSPEC equal to that value so that normal DOS programs that need
    that information will function normally. This can be shown by
    typing the word SET at the DOS box command line. This will show
    that the COMSPEC is actually set, even though it is not in the
    AUTOEXEC.BAT file.

 Note again that both COMSPEC and SHELL are set in the CONFIG.SYS file
 under OS/2. Nothing is done in the AUTOEXEC.BAT file to specify
 information about command interpreters under OS/2.


 147. Use STACK, Not FRE("), with QBX.EXE or /Fs in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 14-JAN-1990    ArticleIdent: Q57646

 With the advent of far string support in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and OS/2, the FRE()
 function has some different properties. The following statement

    PRINT  FRE("")

 does not return the remaining default data segment (DGROUP) space when
 run in the QBX.EXE environment or when run as a program compiled with
 the /Fs (Far String) option. To obtain the remaining DGROUP space in
 these cases, you must now use the STACK function (introduced in BASIC
 7.00). For example, the following statement

    PRINT STACK

 returns the current space available in DGROUP for the STACK to be
 resized. The stack is always in DGROUP, so the new STACK function
 conveniently informs you of the total remaining space that can be used
 in DGROUP.

 This information applies to Microsoft BASIC PDS 7.00 for MS-DOS and
 MS OS/2.

 For more information on the many changes in the FRE() function in
 regard to far strings, refer to Pages 140-142 of the "Microsoft BASIC
 7.0: Language Reference" manual.


 148. Using DIR$ to Load Directory Listing into Array in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-JAN-1990    ArticleIdent: Q57671

 This article illustrates how to use the DIR$ function and load an
 MS-DOS or MS OS/2 directory listing into a BASIC string array. This
 information applies only to the Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The following sample program demonstrates use of the DIR$ function
 available in BASIC PDS 7.00 to return all the files matching a given
 filespec and store them in a BASIC string array. For more information
 on the DIR$ function, see Page 107 of the "Microsoft BASIC 7.0:
 Language Reference" manual.

 Code Example
 ------------

 DEFINT A-Z
 CONST TRUE = -1
 CONST FALSE = NOT TRUE

 NumFiles = 255             'Maximum number of filenames to hold
 Counter = 0
 Finished = FALSE
 DIM FileName$(NumFiles)

 CLS     'Enter DIR type filespec, for example "C:\*.BAS":
 INPUT "Enter filespec:"; Path$

 TempName$ = DIR$(Path$)             'Get the first filename.
 IF TempName$ = "" THEN
   PRINT "No file(s) found"
 ELSE
   FileName$(Counter) = TempName$ ' Keep getting filenames until we
   Counter = Counter + 1      ' have NumFiles worth or we get them all.
   DO
     TempName$ = DIR$
     IF TempName$ <> "" THEN FileName$(Counter) = TempName$
     Counter = Counter + 1
   LOOP WHILE TempName$ <> "" AND Counter <= NumFiles
 END IF

 IF FileName$(0) <> "" THEN    'Display filenames if we received any.
   Counter = 0
   DO
     PRINT FileName$(Counter)
     IF FileName$(Counter) = "" THEN Finished = TRUE
     Counter = Counter + 1
   LOOP WHILE Counter <= NumFiles AND NOT Finished
 END IF


 149. Menus Cannot Have Zero Items in BASIC PDS 7.00 UI Toolbox

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900108-113
 Last Modified: 14-JAN-1990    ArticleIdent: Q57672

 The User Interface (UI) Toolbox routines provided with Microsoft BASIC
 Professional Development System (PDS) Version 7.00 do not allow menus
 without menu items.

 Because of this design, it is necessary to always have menu items to
 choose from. It may be possible to alter the source for the menu
 routines (MENU.BAS) and change the functionality to add the ability
 for menus without items.

 This feature is under review and will be considered for inclusion in a
 future release.


 150. "Typed Variable Not Allowed in Expression" Using Nested Arrays

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S891220-141 buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q57709

 Microsoft BASIC Professional Development System (PDS) version 7.00
 allows static arrays as fields of user-defined TYPEs. This feature
 allows programs to have complex data structures such as nested arrays
 (a nested array is an array of user-defined-TYPE records that contain
 an array).

 However, compile-time errors occur using the ERASE statement and the
 LBOUND and UBOUND functions on an array of arrays (nested in a
 user-defined TYPE) when subscripted by means of a user-defined TYPE.
 The BC.EXE compiler gives the messages "Syntax error" and "Typed
 variable not allowed in expression." This problem occurs only when the
 code is compiled with BC.EXE, not when it is compiled with QBX.EXE.

 The array reference needed to produce the problem looks like the
 following:

    PRINT UBOUND(array2(typedvariable.field).nestedarray1)

 Microsoft has confirmed this to be a problem in BC.EXE in Microsoft
 BASIC Professional Development System (PDS) version 7.00 for MS-DOS
 and MS OS/2. This problem was corrected in BASIC PDS version 7.10.

 You can work around this problem by using a non-TYPEd variable as the
 subscript for the nested array (see the workaround example below).

 Code Example
 ------------

 The following code example illustrates the problem:

    TYPE Type1
       Array1(1 TO 1) AS INTEGER
    END TYPE
    TYPE Type2
       Number AS INTEGER
    END TYPE
    DIM Array2(1 TO 1) AS Type1
    DIM Var AS Type2
    Var.Number = 1
    PRINT LBOUND(Array2(Var.Number).Array1)
    '                   ^^^^^^^^^^ This TYPEd variable causes the error.

 The following code example shows a workaround for the problem:

    TYPE Type1
       Array1(1 TO 1) AS INTEGER
    END TYPE
    TYPE Type2
       Number AS INTEGER
    END TYPE
    DIM Array2(1 TO 1) AS Type1
    DIM Var AS Type2
    Var.Number = 1
    Var2% = Var.Number
    PRINT LBOUND(Array2(Var2%).Array1)
    '                   ^^^^^ Non-TYPEd variable will work.


 151. QB/QBX "Out of Stack Space" Using Large TYPE as SUB Parameter

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q57711

 The program below demonstrates a problem with the QuickBASIC (QB.EXE)
 and QuickBASIC Extended (QBX.EXE) editors in which the environment
 runs out of stack space when passing a large user-defined TYPE
 variable to a SUBprogram.

 Microsoft has confirmed this to be a problem in QB.EXE in Microsoft
 QuickBASIC versions 4.00, 4.00b, and 4.50 for MS-DOS; in QB.EXE
 shipped with Microsoft BASIC Compiler 6.00 and 6.00b (buglist6.00,
 buglist6.00b) for MS-DOS; and in the QBX.EXE editor that comes with
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are researching
 this problem and will post new information here as it becomes
 available.

 This problem does not occur in .EXE programs compiled with BC.EXE.

 The minimum code to duplicate this "Out of stack space" error is as
 follows:

 1. Create a TYPE that is near the size of, or larger than, the
    available stack space. (A TYPE with 2400 bytes is adequate to show
    the problem in both QB.EXE and QBX.EXE. QB.EXE has a default
    program stack size of 2K, and QBX.EXE has a default program stack
    size of 3K).

 2. DIMension an array of that TYPE. An array of one element is all
    that is necessary to reproduce the problem. The array can be
    either $DYNAMIC or $STATIC.

 3. Create a SUBprogram that takes a single element of this TYPE as a
    parameter. The SUB does not have to contain any code at all.

 4. CALL the SUB and pass one element of this array.

 5. Run the program by pressing SHIFT+F5 in the environment.

 Attempting to run this program in the editor produces an "Out of stack
 space" error followed by an "Out of memory" error before the program
 even begins to execute. The errors do NOT occur at the time of the
 CALL because the program is pushing information onto the stack. This
 can be shown by putting a breakpoint on the CALL and then attempting
 to execute the program. The CALL is never reached; the problem occurs
 during the binding and final memory allocation steps.

 This problem does not occur when the program is compiled with the
 BC.EXE compiler.

 To work around this problem, dimension the TYPEd array with DIM SHARED
 or put it in a COMMON SHARED statement.

 The following is the minimum amount of code needed to reproduce the
 problem:

    DECLARE SUB sub1 (boot AS ANY)
    TYPE rec1
      jump1 AS STRING * 2400
    END TYPE
    DIM var1(1) AS rec1
    CALL sub1(var1(1))
    END
    SUB sub1 (boot AS rec1)
    END SUB

 The following code example shows one workaround:

    DECLARE SUB sub1 ()
    TYPE rec1
      jump1 AS STRING * 2400
    END TYPE
    DIM SHARED var1(1) AS rec1
    CALL sub1
    END
    SUB sub1
    END SUB


 152. Repeated Word on Page 611 BASIC 7.0 Programmer's Guide

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr SR# S900112-170
 Last Modified: 20-JAN-1990    ArticleIdent: Q57777

 On Page 611 of the "Microsoft BASIC Version 7.0: Programmer's Guide,"
 there is a repeated word in the explanation of the stub file
 NOFLTIN.OBJ. The error is shown below.

 Page 611 states the following:

    If you link with NOFLTIN.OBJ, all numbers numbers used by INPUT,
    READ, and VAL must be legal long integers.

 It should be corrected to read as follows:

    If you link with NOFLTIN.OBJ, all numbers used by INPUT, READ,
    and VAL must be legal long integers.


 153. FORTRAN READ Statement Hangs in OS/2 If Called from BASIC

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 SR# S900103-146
 Last Modified: 17-JAN-1990    ArticleIdent: Q57795

 When running under MS OS/2, a Microsoft BASIC program LINKed with a
 FORTRAN routine that contains a READ statement will hang during
 execution. The same program compiled and linked under MS-DOS will run
 correctly.

 This problem occurs in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for OS/2 and in Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for OS/2. Microsoft is researching this problem and
 will post new information here as it becomes available.

 The following two programs will hang when run. To demonstrate these
 programs from an .EXE program, compile and link as follows with the
 BASIC compiler and Microsoft FORTRAN Optimizing Compiler Version 5.00:

    BC /O /Lp BAS;
    FL /c /FPi /Lp FOR.FOR ;
    LINK /NOE /NOD BAS FOR,,,BCOM60.LIB LLIBFE.LIB;

 Please note that the above FORTRAN library LLIBFE.LIB may be called
 LLIBFEP.LIB, depending on how you installed FORTRAN.

 Code Example
 ------------

 The following BASIC program is BAS.BAS, which calls a FORTRAN
 procedure:

    DECLARE SUB FPROG()
    DIM A%(500)
    COMMON SHARED /NMALLOC/ A%()
    PRINT "Calling FORTRAN"
    CALL FPROG
    END

 The following program is FOR.FOR, which prompts you for input and then
 should display the entered value:

       SUBROUTINE FPROG()
          INTEGER i
          WRITE (*,*) 'Please enter i'
          READ (*, *) i
          WRITE (*, *) 'This is i:', i
       END

 BAS.EXE produces the following output, and then hangs:

    Calling FORTRAN
    Please enter i


 154. QBX.EXE 7.00 Editor Black & White Only on PS/2 Model 60 & 80

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900111-148
 Last Modified: 20-JUN-1990    ArticleIdent: Q57796

 The QuickBASIC Extended (QBX.EXE) environment may have problems
 displaying colors on certain IBM PS/2 models with an out-of-date 8514
 adaptor card. QBX.EXE loads and correctly runs programs that execute
 graphics in VGA SCREEN modes 12 and 13. However, the editor itself
 comes up in gray, black, and white. The only colors available under
 Display on the Options menu are gray, black, and white.

 This problem may be corrected by contacting IBM and updating the 8514
 adaptor card (or the BIOS chip on the card).

 This information applies to the QuickBASIC Extended editor (QBX.EXE)
 in Microsoft BASIC Professional Development System (PDS) version 7.00
 for MS-DOS.

 Microsoft Product Support Services has verified this problem on a PS/2
 model 60 that has a built-in VGA with an 8514 VGA color monitor. This
 problem was reproduced under MS-DOS version 3.30, under PC-DOS version
 3.30, and under the DOS 3.x box in IBM OS/2 version 1.20.

 One customer also reported this problem on a PS/2 model 80 with an
 8514A monitor. Microsoft has not confirmed this problem on a PS/2
 model 80.

 Another customer reported that on an IBM PS/2 Model 80 (under IBM DOS
 4.00) with an 8514 video card and an 80387 coprocessor installed, the
 QBX.EXE editor displays in monochrome. However, if the coprocessor is
 disabled (SET NO87="Coprocessor Disabled"), the QBX.EXE editor
 displays the proper colors. (No TSR or device drivers were in the
 system during this test.) Microsoft has not confirmed this report.

 A customer has also reported this problem on an IBM PS/2 Model 70
 using an 8515 monitor. Microsoft has not confirmed this report.

 To demonstrate that these color problems are due to the card, do the
 following:

 1. Start QBX.EXE.

 2. Unplug the monitor from the 8514 card.

 3. Plug the monitor into the VGA on the motherboard.

 4. Unplug the monitor and plug it back into the 8514 card, and correct
    color now returns.


 155. Problems Using BASIC 7.00 with Novell Advanced NetWare 2.15

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900112-81
 Last Modified:  1-AUG-1990    ArticleIdent: Q57797

 Microsoft BASIC Professional Development System (PDS) version 7.00 has
 not been fully tested under nor is it guaranteed to run under any
 version of Novell NetWare. Below are some confirmed and unconfirmed
 cases of problems using BASIC PDS 7.00 programs with Novell NetWare.

 Confirmed QBX.EXE Hanging Report
 --------------------------------

 1. Microsoft Product Support Services performed one test that showed
    that QBX.EXE may hang under Novell Advanced NetWare version 2.15
    revision C. This test was performed on an IBM AT with a 16-bit
    Ungermann Bass network card. The test was run on a nondedicated
    Novell server. The QBX.EXE editor screen comes up, but at this
    point, the machine hangs and requires a cold reboot.

    This information applies to the QBX.EXE editor that comes with
    Microsoft BASIC Professional Development System (PDS) version 7.00
    for MS-DOS.

 Unconfirmed QBX.EXE Hanging Reports
 -----------------------------------

 1. A customer reported that QBX.EXE can hang under the following
    configuration:

       COMPAQ 386/20 or ALR 386/33 computer
       Version 2.15 Novell Advanced NetWare
       Micom Interland board NI52100TP-8
       Microsoft Mouse 7.00

    When the customer booted without the Novell drivers, or with the
    Novell drivers and without the Microsoft Mouse 7.00 driver, QBX.EXE
    worked correctly without hanging. Microsoft has not confirmed this
    information.

 2. A customer reported that QBX.EXE can hang under the following
    configuration:

       IBM PS/2 Model 50z computer
       Version 2.15 revision C Novell SFT network

 3. A customer reported that a BASIC PDS 7.00 program using the
    OPEN COM statement may hang on a workstation connected to Novell
    Advanced NetWare version 2.15 revision A. When a Quarterdeck QEMM
    version 5.00 expanded memory driver was installed, the machine
    would not hang, but instead, QEMM would return an "Exception 12"
    error. When the software for the Novell Network was removed, the
    computer would not hang, nor would it generate an Exception 12
    error with the QEMM driver loaded. Microsoft has not confirmed this
    problem. The customer reported the problem on the following
    configuration:

       Dell System 310
       Novell Advanced NetWare version 2.15 revision A
       DOS version 3.30
       80387 math coprocessor
       4 MB extended memory
       Video Seven VGA video card
       Phoenix 80386 ROM BIOS Plus version 1.10 A05
       Western Digital EtherCard Plus 16, or 3Com EtherLink card

 4. A customer reported that QBX.EXE hangs on the following
    configuration (customer did not test same program run from .EXE):

       Novell NetWare 2.15 SFT revision C
       Everex Step 386
       Version 3 AMI BIOS
       MS-DOS version 4.01

 5. A customer reported that QBX.EXE hangs on the following
    configuration (customer did not test same program run from .EXE):

     Novell SFT NetWare 286 version 2.15 revision B
     Uknown name AT 286
     1 MB RAM
     MDI Graphics Card (Hercules-compatible)
     MF-II keyboard
     MS-DOS 3.30


 156. LINK /PAC Switch in 6.00/6.00b Is Now /PACKC in BASIC PDS 7.00

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr SR# S900116-46
 Last Modified:  8-JAN-1991    ArticleIdent: Q57852

 The LINK.EXE /PACKCODE switch of the Microsoft Segmented-Executable
 Linker version 5.01.20, shipped with Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and MS OS/2, can be abbreviated with /PAC on
 the LINK command line. The same is true for the Microsoft Overlay
 Linker shipped with Microsoft QuickBASIC versions 4.00, 4.00b, and
 4.50.

 This abbreviation has changed to /PACKC in the Segmented-Executable
 Linker version 5.05 shipped with Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 On Page 589 of the "Microsoft BASIC 7.0: Programmer's Guide" (for
 versions 7.00 and 7.10) the abbreviation for /PACKCODE is incorrectly
 documented as being /PAC. It should be changed to /PACKC.

 In addition, eleven occurences of /PAC should be changed to /PACKC on
 Pages 596-597 of the "Microsoft BASIC 7.0: Programmer's Guide" (for
 versions 7.00 and 7.10).

 The /PACKCODE switch abbreviation was changed from /PAC to /PACKC
 because a new switch was added to the linker to take advantage of
 Microsoft BASIC PDS's ability to manage multiple data segments (far
 strings). The name of the new switch is /PACKDATA and is used to pack
 small data segments together. Its abbreviation is /PACKD.

 Although it is not ambiguous to have one switch abbreviated /PAC and
 another /PACKD, because the switches have similar functions, it is
 more logical for their abbreviations to have the same first 4 letters
 ("PACK") followed by a distinguishing letter ("C" or "D").


 157. BASIC 7.00 WindowDo Doesn't Trap Click in Current Window

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891113-16
 Last Modified: 20-JAN-1990    ArticleIdent: Q57853

 The WindowDo procedure of the WINDOW.BAS toolbox file that is included
 with Microsoft BASIC Professional Development System (PDS) Version
 7.00 for MS-DOS will not trap a click in the current window unless
 that click is in a button or edit field.

 To work around this limitation, open an "area" button (button type 4)
 in the current window that is exactly the same size as the current
 window. This does not make the WindowDo procedure trap clicks in the
 current window (it is only trapping a click in a button), but it
 appears so because an area button is invisible.

 The WindowDo procedure allows you to trap window events such as
 selecting buttons and edit fields, resizing, moving, or closing a
 window, and selecting a window other than the current window. However,
 WindowDo cannot trap a click in the current window itself unless the
 click occurs on a button or edit field in that window.

 For example, suppose a program opens up two windows. For simplicity,
 we will assume that there are no buttons or edit fields opened in
 either window. By default, the last window opened (window2) is the
 current window. The WindowDo procedure will trap a click in the other
 window (window1) but not in window2. This is a design limitation of
 the WindowDo procedure and is not considered a problem.

 To easily work around this situation, in the current window, open an
 area button (button type 4) that is exactly the same size as the
 current window. The WindowDo procedure is still trapping a click in a
 button, but it appears as if a click is being trapped anywhere in the
 window because the button is hidden. Type 4 buttons are invisible.

 For a detailed explanation of the WindowDo procedure, see Page 572 of
 the "Microsoft BASIC Version 7.0: Language Reference" manual. For more
 information on area buttons (button type 4), see the ButtonOpen
 procedure on Page 557 of the same manual.

 The following example program illustrates the limitation and its
 workaround:

 '$INCLUDE: 'general.bi'   'These INCLUDE, COMMON SHARED, and DIM
 '$INCLUDE: 'mouse.bi'     'statements are generally those needed
 '$INCLUDE: 'menu.bi'      'for using the User Interface Toolbox.
 '$INCLUDE: 'window.bi'

 COMMON SHARED /uitools/ GloMenu           AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle()        AS MenuTitleType
 COMMON SHARED /uitools/ GloItem()         AS MenuItemType
 COMMON SHARED /uitools/ GloWindow()       AS WindowType
 COMMON SHARED /uitools/ GloButton()       AS ButtonType
 COMMON SHARED /uitools/ GloEdit()         AS EditFieldType
 COMMON SHARED /uitools/ GloStorage        AS WindowStorageType
 COMMON SHARED /uitools/ GloWindowStack()  AS INTEGER
 COMMON SHARED /uitools/ GloBuffer$()

 DIM GloTitle(MAXMENU)           AS MenuTitleType
 DIM GloItem(MAXMENU, MAXITEM)   AS MenuItemType
 DIM GloWindow(MAXWINDOW)        AS WindowType
 DIM GloButton(MAXBUTTON)        AS ButtonType
 DIM GloEdit(MAXEDITFIELD)       AS EditFieldType
 DIM GloWindowStack(MAXWINDOW)   AS INTEGER
 DIM GloBuffer$(MAXWINDOW + 1, 2)

 CLS
 CALL WindowInit   'Initialize window and mouse routines.
 CALL MouseInit

 'Open window1. It is the current window..
 CALL WindowOpen(1, 4, 20, 20, 36, 14, 1, 14, 1, 15, FALSE, FALSE,_
                 FALSE, FALSE, 1, "Window 1")

 'Open window2, it is now the current window.
 CALL WindowOpen(2, 4, 45, 20, 61, 14, 1, 14, 1, 15, FALSE, FALSE,_
                 FALSE, FALSE, 1, "Window 2")

 CALL MouseShow        'Show the mouse cursor.

 CALL WindowDo(0, 0)   'Wait for a window event to happen.
                       'The program will not continue until window1 is
                       'clicked. This is because clicking in window2
                       '(the current window) is not trapped by the
                       'WindowDo procedure.

 'Assume window1 is the current window now.

 'Open an area button in the current window that is the same size as
 'the current window.
 CALL ButtonOpen(1, 0, "", 1, 1, 17, 17, 4)

 CALL WindowDo(0, 0)   'Wait for a window event to happen.
                       'The program will continue if either window is
                       'clicked. Clicking window2 will be trapped
                       'because it is not the current window. Clicking
                       'window1 will be trapped because there is a
                       'button (although invisible) in window1 that
                       'is the same size as window1.


 158. BASIC PDS 7.00 Supports Short-Circuit Boolean Expressions

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | B_QuickBas SR# S890703-44
 Last Modified: 20-JAN-1990    ArticleIdent: Q57866

 Microsoft BASIC Professional Development System (PDS) Version 7.00
 supports "short-circuit" optimization of Boolean expressions, as
 described below. To take advantage of this speed optimization in
 complex IF, WHILE, DO LOOP WHILE, or DO LOOP UNTIL statements, the
 quickest Boolean conditions should appear first.

 Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler Versions 6.00 and
 6.00b DON'T support short-circuit Boolean expressions.

 Boolean expressions are those expressions in BASIC that evaluate to
 true or false. In BASIC, the IF, WHILE, and DO LOOP {WHILE | UNTIL}
 statements all require Boolean expressions as part of their syntax.

 A "short-circuit" Boolean expression is a unique kind of Boolean
 expression. If a Boolean expression consists of more than one part,
 not all the parts may be evaluated. The evaluation of the expression
 may stop, or "short circuit," partway through. Consider the following
 two-part Boolean expression:

    IF <condition1> AND <condition2> THEN

 If <condition1> evaluates to false, it isn't necessary to evaluate
 <condition2>, because "false" AND "anything else" is still false.
 Therefore, we can short circuit the expression and not evaluate
 <condition2>.

 The same rule applies to the following expression:

    IF <condition1> OR <condition2> THEN

 If <condition1> is true, we do not need to evaluate <condition2>
 because "true" OR "anything else" always evaluates to true.

 Short-circuit Boolean expressions are desirable for two reasons.
 First, they allow you to optimize code by evaluating only as much of
 the Boolean expression as necessary. This can generate faster, more
 efficient code. In the examples above, if <condition2> were very
 complex, a short-circuit Boolean might speed up program execution by
 evaluating the whole expression only when absolutely necessary.
 Second, short-circuit Booleans can be used to prevent error
 conditions. In the code example below, BASIC PDS 7.00 prevents the
 "Division by zero" error in .EXE programs since it supports
 short-circuit Booleans. QBX.EXE programs in BASIC 7.00, and QB.EXE and
 .EXE programs in QuickBASIC 4.00, 4.00b, and 4.50, give the "Division by
 zero" error.

 BASIC 7.00 will short circuit IF expressions as long as doing so does
 not change the semantics of the statement. The following is an
 example:

    IF (a% < b%) OR (c! < d!) THEN PRINT

 The compiler compares a% and b%. If a% is less than b%, the compiler
 skips the floating-point comparison. On the other hand, consider the
 following statements:

    DECLARE FUNCTION Foo! (p!)
    IF (a% < b%) OR (c! < Foo!(d!)) THEN PRINT

 The compiler avoids the floating-point comparison when a% is less
 than b%, but it still calls the function Foo. This is because existing
 programs may rely on the side effects of the function Foo.

 This feature affects the best way to write code in BASIC PDS 7.00.
 Specifically, in complex IF, WHILE, DO LOOP WHILE, or DO LOOP UNTIL
 conditions, the quickest conditions should appear first.

 Code Example
 ------------

 The following program determines if a compiler supports short-circuit
 Boolean optimization for an IF statement. Since it supports
 short-circuit Booleans, BASIC PDS Version 7.00 prevents the "Division
 by zero" error in the .EXE program. QBX.EXE programs in BASIC 7.00,
 and QB.EXE and .EXE programs in QuickBASIC 4.00, 4.00b, and 4.50, give
 the "Division by zero" error.

 DEFINT A-Z
 ON ERROR GOTO errorhandle
 a = 1
 b = 1
 c = 0
 CLS
 LOCATE 10, 10

 ' In the following IF statement, b / c is not executed if
 ' short-circuit Booleans are supported because a = 1 evaluates to
 ' true, and therefore, the whole expression is true. This is
 ' because (true OR <anything>) evaluates to true.

 IF (a = 1 OR ((b / c) = 1)) THEN
    ' If this PRINTs, then short-circuit Booleans are supported.
    PRINT "This compiler supports short-circuit Booleans"
 END IF
 terminate:
 PRINT "End of program reached"
 END
 errorhandle:
    IF ERR = 11 THEN PRINT "Division by zero, Error="; ERR
    LOCATE 11, 10
    PRINT "This compiler does not support short-circuit Booleans"
    RESUME terminate     ' End the program.


 159. BUILDRTM.EXE Requires BASIC 7.00 Component Libraries; SETUP

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q57882

 The BUILDRTM.EXE utility program for Microsoft BASIC Professional
 Development System (PDS) Version 7.00 can be used to create custom
 run-time modules. For BUILDRTM to function, you must have the
 component libraries available.

 The component libraries are installed by the BASIC PDS 7.00 SETUP.EXE
 program, but are deleted unless you specify that they be maintained.
 (You are prompted to delete or keep the component libraries during the
 setup procedure).

 The following lists show the component libraries needed to use
 BUILDRTM under real mode (MS-DOS) and OS/2 protected mode (note that
 all component library files have a .LIB extension):

 Real Mode (MS-DOS) Component Libraries
 --------------------------------------

    B70OBJ.LIB    B70OBN.LIB    B70ORN.LIB    B70ROBJ.LIB   B70RORJ.LIB
    B70ROBN.LIB   B70RORN.LIB   B70ROEJ.LIB   B70ROEN.LIB   B70S.LIB
    BLIBFP.LIB    EMR.LIB       B70RLN.LIB    B70RCN.LIB

 MS OS/2 Protected Mode Component Libraries
 ------------------------------------------

    B70OBJ.LIB    B70OBN.LIB    B70ORN.LIB    B70POBJR.LIB  B70PORJ.LIB
    B70POBN.LIB   B70PORN.LIB   B70POEJ.LIB   B70POEN.LIB   B70S.LIB
    BLIBFP.LIB    EMP.LIB       B70PLN.LIB    B70PCN.LIB    OS2.LIB

 To install these libraries, run the BASIC PDS 7.00 SETUP.EXE program,
 select the libraries you want to install (real or protected mode), and
 then specify that you want to maintain the component libraries.


 160. UI Toolbox Menu Bar with Menu Past 64th Column Shows Garbage

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900112-171 buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q57883

 The User Interface (UI) Toolbox shipped with Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10
 incorrectly processes menu bars when the last menu item starts in the
 64th or higher column. The symptom of this errant behavior is that
 garbage characters are displayed on the screen after that menu is
 deselected.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS. We are researching this problem and
 will post new information here as it becomes available. A correction
 for this problem in MENU.BAS is shown below.

 To correct the source code, MENU.BAS, so that it will handle longer
 menu bars correctly, change the following IF statement (found after
 the "menuDoShowPullDown" label near the end of the MenuDo SUB)

    LEN(GloTitle(currMenu).text)

 to

    LEN(RTRIM$(GloTitle(currMenu).text))

 in both of the following places:

   IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem _
        < LEN(GloTitle(currMenu).text) THEN
     GloTitle(currMenu).rColItem = _
        GloTitle(currMenu).lColItem + LEN(GloTitle(currMenu).text)
   END IF

 Note: The underscore (_) characters above indicate line continuation
 to fit in this article. This block IF is actually on three long lines
 in the original source.

 The changed code is as follows:

   IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem _
        < LEN(RTRIM$(GloTitle(currMenu).text)) THEN
     GloTitle(currMenu).rColItem = _
        GloTitle(currMenu).lColItem + LEN(RTRIM$(GloTitle(currMenu).text))
   END IF

 This correction should be made and the libraries rebuilt to enable
 correct handling of menus beginning past the 64th column.

 The above correction is the same as for a separate article describing
 a different symptom, where the mouse-selectable area for narrow menus
 is too wide. To find this and other problems with the User Interface
 Toolbox, query in this Knowledge Base on the following keywords:

    user and interface and toolbox and buglist7.00


 161. Listbox Initialized Incorrectly in BASIC 7.00 UI Toolbox

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900109-123 buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q57884

 The ListBox FUNCTION in the User Interface (UI) Toolbox WINDOW.BAS
 file provided with Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 does not behave correctly when a list box
 is first activated. On initialization, the keyboard cursor is set on
 the OK button instead of in the list box.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS. We are researching this problem and
 will post new information here as it becomes available.

 Without the modification listed below, you must press the TAB key
 twice before using the cursor keys to move into the list box.

 To correct this behavior, the initial value of currButton (set early
 in the ListBox FUNCTION) must be changed from 2 to 0. The following
 are the statements from the ListBox FUNCTION of WINDOW.BAS adjacent to
 (and including) the incorrect statement:

    currTop = 1
    currPos = 1
    currButton = 2       '****** Need to change this to currButton = 0

    GOSUB ListBoxDrawText

 This correction should be made and the libraries rebuilt to have the
 cursor positioned properly in the list box.

 To find other problems with the User Interface Toolbox, query in this
 Knowledge Base on the following words:

    User and Interface and Toolbox and buglist7.00


 162. Disabled First Menu Malfunctions in BASIC 7.00 UI Toolbox

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900108-102 buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q57885

 The User Interface (UI) Toolbox menu routines, provided with Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS, do not behave correctly when the first menu on the line is
 disabled. In this case, the menu can still be chosen with the ALT+X
 key combination.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS. We are researching this problem and
 will post new information here as it becomes available.

 This article provides an example demonstrating the problem and the
 correction to MENU.BAS.

 Use the following command line to set up QBX for demonstrating the
 problem:

    QBX /L UITBEFR

 The following code example disables the first (only) menu, but it can
 still be selected with the ALT+X keys. To demonstrate the problem,
 press ALT, which incorrectly highlights the first menu, then press the
 DOWN ARROW, which incorrectly brings down the menu item (without a
 proper menu box).

 REM $INCLUDE: 'General.bi'
 REM $INCLUDE: 'Mouse.bi'
 REM $INCLUDE: 'Menu.bi'
 COMMON SHARED /uitools/ GloMenu AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle() AS MenuTitleType
 COMMON SHARED /uitools/ GloItem() AS MenuItemType
 DIM GloTitle(MAXMENU) AS MenuTitleType
 DIM GloItem(MAXMENU, MAXITEM) AS MenuItemType

 CLS
 MenuInit
 MenuSet 1, 0, 0, "Menu Title", 1   '*** Disable main level menu
 MenuSet 1, 1, 1, "Exit", 1
 MenuPreProcess
 MenuShow
 MouseShow

 '*** It should not be possible to select the menu. Pressing
 '*** ALT highlights the first menu and the arrow brings down
 '*** other options (with incorrect highlighting).

 WHILE NOT ((menu = 1) AND (item = 1))
    IF MenuInkey$ = "menu" THEN
       menu = MenuCheck(0)
       item = MenuCheck(1)
    END IF
 WEND

 The following IF statement is taken from the end of the MenuDoInit
 GOSUB routine near the beginning of the MenuDo SUB:

     IF lButton THEN
         mouseMode = TRUE
         currMenu = 0
         currItem = 0
     ELSE
         mouseMode = FALSE
         currMenu = 1               '****** These lines need
         currItem = 0               '****** to be changed.
         GOSUB MenuDoShowTitleAccessKeys
     END IF

 The above IF statement should be replaced with the following IF
 statement:

     IF lButton THEN
         mouseMode = TRUE
         currMenu = 0
         currItem = 0
     ELSE
         mouseMode = FALSE
         currMenu = 0               '****** Set defaults to 0
         currItem = 0               '******
         FOR m=1 TO MAXMENU         '****** Search each menu
            IF GloTitle(m).state = 1 THEN ' check state
               currMenu=m           '****** set menu for 1st state
               EXIT FOR             '****** and exit
            END IF                  '******
         NEXT                       '****** last line of changes
         GOSUB MenuDoShowTitleAccessKeys
     END IF

 This correction should be made and the libraries rebuilt to properly
 disable a menu item.

 To find any other problems with the User Interface Toolbox, query on
 the following words:

    User and Interface and Toolbox and buglist7.00


 163. Overhead for /V and /W Event Trapping Is Reduced in BASIC 7.00

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q57890

 The code overhead for BC /V is only 3 bytes per statement, and the
 code overhead for BC /W is only 3 bytes per labeled or numbered line,
 in Microsoft BASIC Professional Development System (PDS) Version 7.00
 for MS-DOS and MS OS/2.

 The overhead for these event trapping options is 5 bytes in Microsoft
 QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS, and in Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 Event trapping for the ON <event> GOSUB statements is handled by
 polling. The <event> can be COM(n), KEY(n), PEN, PLAY(), STRIG, and
 TIMER. In BASIC 6.00, 6.00b, and 7.00, you can also use ON SIGNAL and
 ON UEVENT.

 At various points in your code, as controlled by the /V and /W options
 and the <event> ON and <event> OFF statements, the compiler places a
 call instruction to a routine that checks for events. /V places the
 call on every statement in the module. /W only places the call on
 every numbered or labeled line in the module. In QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler 6.00 and 6.00b,
 this call occupies 5 bytes. In BASIC 7.00, this has been reduced to 3
 bytes per call.


 164. How BC /G2 Option Makes Smaller .EXE Code in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  2-FEB-1990    ArticleIdent: Q57891

 In Microsoft BASIC Professional Development System (PDS) Version 7.00
 for MS-DOS and MS OS/2, the BC /G2 option generates code that is
 specific to computers containing an 80286 processor chip. Code
 generated with /G2 will run on computers with 80286 and 80386 chips,
 but will not run on computers with 8086 or 8088 chips.

 When compiled with the /G2 option, a program may be zero to ten
 percent smaller. The percentage by which the size decreases is usually
 more significant than the percentage by which the speed improves.

 Note: The 80286 chip is also known as the 286, for short. The 80386 is
 also known as the 386.

 The biggest gain from the use of 286 instructions is the PUSH
 immediate instruction. This is an operation frequently used by the
 compiler. To get an idea of how many bytes you would save, compile an
 existing program with the /A option and look for sequences of the
 following:

    MOV     reg,constant
    PUSH    reg

 These will be replaced with a single PUSH instruction, saving 1 or 2
 bytes per instance.

 We provided the BC /G2 option for developers who market their
 compiled-BASIC products to customers with 286 or 386 machines.


 165. Buttons Not Allowed in Resizeable Windows in 7.00 UI Toolbox

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891108-73
 Last Modified:  2-FEB-1990    ArticleIdent: Q57924

 Resizable windows created by the WindowOpen procedure of the
 WINDOW.BAS User Interface (UI) Toolbox file are not allowed to contain
 buttons. This design of the UI Toolbox is not documented. This
 information applies to Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Microsoft BASIC PDS 7.00 comes with toolbox files that allow you to
 program windows, menus, scroll bars, edit fields, and buttons. One of
 the files, WINDOW.BAS, contains a procedure called ButtonOpen, which
 opens a button in the current window. Windows themselves can be opened
 with another procedure in WINDOW.BAS called WindowOpen.

 Among the many attributes you can specify when opening a window is
 whether or not the window can be resized. If this attribute is
 specified, making the window resizable, the ButtonOpen procedure will
 not open a button in that window. ButtonOpen doesn't report this as an
 error; it simply doesn't open the button.

 Although this design is not documented, it is obvious when examining
 the source code of the ButtonOpen procedure and is considered a
 limitation, not a problem.

 The source code of the User Interface Toolbox files (WINDOW.BAS,
 MENU.BAS, MOUSE.BAS, and GENERAL.BAS) is provided so that you can
 modify them if you want to overcome any of their inherent limitations,
 such as the one described above. This modification can be safely done
 only if you have a full understanding of every module of the User
 Interface Toolbox, which may require much time and effort.

 However, a less safe but much quicker workaround for the above
 limitation has been used successfully. (Note: This procedure has not
 been extensively tested and is not guaranteed by Microsoft to work
 properly under any circumstances.)

 To use this workaround, comment out the line "resize = TRUE" in the
 ButtonOpen procedure of the WINDOW.BAS file. It is the first and only
 line inside the first IF/END structure of the procedure. The following
 code fragment identifies the IF/END structure and the statement that
 must be commented out:

    IF MID$(WindowBorder$(GloWindow(WindowCurrent).windowType), 9, 1) =
    "+" THEN
        resize = TRUE   'Comment out this statement.
    END IF

 After commenting out the line, the ButtonOpen procedure will open
 buttons in a resizable window. However, it is your responsibility to
 make sure that any buttons opened stay within the window boundaries
 after any resizing has been done.


 166. BASIC Does Not Support 8514 VGA Text Modes in OS/2

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S891229-63
 Last Modified: 31-JAN-1990    ArticleIdent: Q57927

 Microsoft BASIC does not support the VGA-specific screen modes, such
 as 50-line mode, in MS OS/2 protected mode set up for 8514 video
 cards. If the 8514 card is set up as a VGA card only, then BASIC can
 recognize the VGA TEXT modes. BASIC offers no support for the 8514
 extended modes.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS OS/2.

 When trying to utilize VGA-specific line modes, BASIC returns an
 "Illegal Function Call" error when using an 8514 card in MS OS/2.

 The following program demonstrates the problem:

    PRINT "This line will print"
    WIDTH 80,50         ' this line gives "Illegal Function Call"
    SYSTEM

 Compile and link as follows:

    BC /LP /O TEST.BAS;
    LINK TEST;


 167. EXE Does Nothing If BC.EXE Compiled from GW-BASIC Binary Code

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q57931

 Programs saved in the Binary (the default tokenized) format in the
 GW-BASIC or BASICA Interpreter will appear to compile in BC.EXE and
 LINK into an .EXE program without error in the BASIC compilers listed
 further below. However, the resulting .EXE file created from a Binary
 GW-BASIC or BASICA source program does nothing when run -- it just
 drops back to DOS.

 The BC.EXE compiler fails to abort and give an error message when you
 mistakenly give it GW-BASIC or BASICA Binary files. Microsoft has
 confirmed this to be a problem in Microsoft BASIC Compiler versions
 6.00 and 6.00b; in Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10; and in Microsoft QuickBASIC versions
 4.00, 4.00b, and 4.50 (buglist4.00, buglist4.00b, buglist4.50). We are
 researching this problem and will post new information here as it
 becomes available.

 To correctly create an EXE file from a GW-BASIC or BASICA program, it
 must first be saved in ASCII (text) format in the GWBASIC.EXE or
 BASICA.EXE editor. The following GW-BASIC or BASICA statement will
 save TEST.BAS in ASCII format:

    SAVE "TEST",A

 Binary format is the default SAVE format in BASICA and GW-BASIC; thus,
 you must explicitly save with the A (ASCII) option before BC.EXE can
 handle the source file.

 BASICA is an interpreter shipped in the ROM of some IBM and COMPAQ
 computers. Microsoft GW-BASIC Interpreter is shipped with some
 versions of DOS, depending upon the hardware vendor or the version of
 MS-DOS.

 Additional reference words: B_QuickBas B_GWBasicI


 168. BC 6.00 User's Guide, NOVGA.OBJ Affects SCREENs 11-13, Not 3

 Product Version(s): 6.00 6.00b | 6.00 6.00b
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | docerr SR# S900121-5
 Last Modified:  2-FEB-1990    ArticleIdent: Q58019

 On Page 10 of the "Microsoft BASIC Compiler 6.0: User's Guide," Table
 3.1 incorrectly states that NOVGA.OBJ removes support for screen mode
 3 features. The chart should actually show the following:

    NOVGA.OBJ    Video Graphics Array (VGA) features (screen modes
                 11, 12, and 13) absent.

 This correction applies to the user's guide for Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 This documentation error was corrected in the documentation for
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.


 169. Can't Search on Blank String Field in BASIC 7.00 ISAM

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900119-140
 Last Modified:  2-FEB-1990    ArticleIdent: Q58020

 Blank string fields cannot be searched on with the ISAM file handler
 that comes with Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 If a search is performed on a string field (whether the field is the
 entire index or part of a combined one) and the entire field is filled
 with spaces, the record will not be found and an end-of-file condition
 will be returned.

 To work around this problem, represent blank fields by inserting some
 other character into them and searching on the presence of that
 character in the field.

 Due to the way the ISAM engine stores string fields in a database
 table, completely blank string fields cannot be found when you use the
 SEEKGT, SEEKGE, or SEEKEQ statements. This is the case whether the
 string field represents the entire index or whether it is a field
 (primary or not) included in a combined index. Also, the same behavior
 is exhibited with fields that are unique and with those that have
 duplicates.

 This characteristic of the ISAM file handler is due to the way it
 strips off leading and trailing spaces from a string field to conserve
 disk space. For example, if the string " abc " (length of 5, with one
 leading and one trailing space) is inserted into a string field with a
 length of 10, "abc" (a length of 3) is actually written to the table.
 Therefore, inserting a string consisting entirely of spaces results in
 nothing being written to the table because every character is stripped
 off.

 The best workaround for this situation is to associate a special
 character with string fields that are to be completely blank and set
 the field equal to that character. Then, in all subsequent searches on
 this field, use that character as the key.


 170. BASIC 7.00 MousePoll Gives Screen, Not Window Coordinates

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891108-92
 Last Modified:  2-FEB-1990    ArticleIdent: Q58024

 The MousePoll routine of the MOUSE.BAS file that comes with the User
 Interface (UI) Toolbox in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS returns the absolute screen
 coordinates of the mouse text cursor as well as the status of the left
 and right mouse buttons.

 Using the window routines of the WINDOW.BAS toolbox file (also
 included) does not make the MousePoll routine return coordinates that
 are relative to the top-left corner of the current window. They are
 always relative to the top-left corner of the screen. This may not be
 apparent because the documentation presents all the toolbox files as
 being part of a user-interface unit; therefore, it may appear that the
 MousePoll routine returns coordinates that are relative to the current
 window.

 Included with Microsoft BASIC PDS is a toolbox source file called
 MOUSE.BAS. There is a routine in this module called MousePoll, which
 when called returns the vertical and horizontal coordinates of the
 mouse text cursor plus the status of the left and right mouse buttons.

 The coordinates returned are absolute screen coordinates. That is, if
 the mouse cursor is at the top-left corner of the screen, the
 coordinate pair (vertical, horizontal) returned is (1,1).

 This may lead to some confusion for those who are using another of the
 toolbox source files, WINDOW.BAS. This module contains (among many
 other things) routines used to open, resize, move, and print to
 windows. When addressing locations in these windows, relative (not
 absolute) coordinates are used. That is, the top-left corner of the
 window has coordinates (1,1) even if it is not in the same position as
 the screen's top-left corner (1,1).

 Therefore, it is important to note that the MousePoll subprogram does
 not return coordinates relative to any window's top-left corner, but
 always returns coordinates relative to the screen's top-left corner.


 171. BASIC PDS 7.10 Allows Line Numbers 40 Digits Long; Correction

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900120-1 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58027

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 are enhanced to allow line numbers as
 long as 40 numbers (characters) long. However, Page 697 of Appendix A
 in the "Microsoft BASIC 7.0: Programmer's Guide" (for 7.00 and 7.10)
 incorrectly states that the largest line number possible is 65,529.

 The following code example demonstrates using large line numbers in
 BASIC PDS 7.00 and 7.10

    ON KEY(1) GOSUB 1234567890123456789012345678901234567891
    KEY(1) ON
    CLS
    PRINT "starting"
    WHILE a$ <> "q" AND a$ <> "Q"
    a$ = INKEY$
    WEND
    END

    1234567890123456789012345678901234567891
              PRINT "That is the F1 key"
              PRINT "Hit 'q' or 'Q' to quit"
              RETURN


 172. Alternate Math (BC /FPa) Won't Always Produce Smaller .EXE's

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | docerr SR# S900122-49
 Last Modified:  8-JAN-1991    ArticleIdent: Q58035

 Using alternate math (BC /FPa) does not always produce smaller
 executable files than using the emulator math library (BC /FPi) when
 compiling with Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2 and Microsoft BASIC Professional Development System
 (PDS) Versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Page 8 of the "Microsoft BASIC Compiler 6.0: User's Guide" and Page
 562 of the "Microsoft BASIC 7.0: Programmer's Guide" (for 7.00 and
 7.10) misleadingly state that "it [the alternate math library] also
 creates a smaller executable file." Page 545 of the "Microsoft BASIC
 7.0: Programmer's Guide" misleadingly states that "alternate math is
 an IEEE-compatible math package optimized for speed and size."

 Although there is an initial space savings from using the alternate
 math libraries, each individual floating-point calculation can take
 more room using the alternate math library than the equivalent code
 for the emulator math library. This means that as the code grows in
 size, the initial space savings can be lost and the program can
 actually be larger using the alternate math package.

 Note: You will only notice a savings in the size of an executable
 compiled /FPa versus /FPi if the program is also compiled with the /O
 (stand-alone) option. If you compile as non stand alone with the
 alternate math library (/FPa) option, the program will actually
 contain both math libraries -- the compiled program will contain the
 alternate math routines, while the BASIC run-time module
 (BRUN60Ax.EXE, BRUN61Ax.EXE, or BRT70Axx.EXE) will contain the
 emulator math routines.

 The small program below demonstrates the size difference when
 compiling with and without the alternate math package.

 Compile the following program in these two ways:

   BC /FPa test, test1.obj;
   BC /FPi test, test2.obj;
   LINK test1;
   LINK test2;

 Code Example
 ------------

    REM  This is TEST.BAS
    a = 6.1
    b = 5.7
    c = a * b

 The program compiled with the alternate math package (/FPa) produces
 larger code for the floating-point operation than the equivalent
 instructions using the emulator math library (/FPi). There is,
 however, an initial savings of about 4K when compiling with the
 alternate math library. In most programs, this initial savings offsets
 any extra code generated by floating-point calculation. In larger
 programs with lots of floating-point calculations, the extra code for
 each floating-point operation can actually create a larger executable
 file.


 173. "Internal Error" Using Two-Dimensional Single-Precision Array

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist7.00 fixlist7.10
 Last Modified: 21-SEP-1990    ArticleIdent: Q58039

 The code example below generates the error message "Internal Error
 near 8C54" when compiled using the BC.EXE shipped with Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS and MS
 OS/2. This problem does not occur in the QBX.EXE environment or in
 earlier compiler versions.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 version 7.00. This problem was corrected in BASIC PDS version 7.10.

 Code Example
 ------------

   DIM a (4, 4), b(4, 4)
   k% = i% + 1
   a(0, j%) = a(0, k%)
   b(0, j%) = b(0, k%)

 To work around this problem in 7.00, compile using the BC /D (Debug)
 option, or change the arrays to integer arrays or double-precision
 arrays. To cause the error, the array must be single precision,
 two-dimensional, and referenced with integer variables as shown.


 174. "Insufficient EMS to Load Overlays" at Run Time in 7.00, 7.10

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900808-19
 Last Modified:  5-SEP-1990    ArticleIdent: Q64876

 The run-time error message "Insufficient EMS to load overlays" occurs
 (if it is going to occur at all) when the first overlaid module is
 called. This error is documented on Page 656 of the "Microsoft BASIC
 7.0: Language Reference" manual for Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10. The article below
 explains in more detail why you might get this error condition.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS when using linked
 overlays.

 The "Insufficient EMS to load overlays" error message is not random.
 If you run a program on a particular machine and the error does not
 occur, the error will never occur for that program unless that
 machine's expanded memory configuration is changed. Common ways of
 changing the expanded memory configuration include the following:
 setting up a larger RAM drive in expanded memory; or moving the
 program to another machine with a different amount of free expanded
 memory.

 If a given program produces an "Insufficient EMS to load overlays"
 error on a given machine, the error will always occur for that program
 as long as the machine's expanded memory configuration and usage stay
 the same.

 When a BASIC program calls the first overlaid module, the program
 must estimate the space in expanded memory necessary to load all
 overlays at once. This estimate is based only on the following:

 1. The number of overlays
 2. The size of the largest overlay
 3. The fact that each overlay has less than 64K of code (otherwise, it
    would not be able to use expanded memory)

 The overlay manager in BASIC 7.00 and 7.10 requests expanded memory in
 16K pages (blocks). The overlay manager knows the size of only the
 largest overlay and must make a "best guess" at the size of the
 smaller overlays. When the overlay manager estimates how many 16K
 pages are necessary to hold all overlays at once in expanded memory,
 the estimate could be over or under the actual number of pages needed.
 If your overlays are all between 16K and 64K in size (according to the
 LINK .MAP file), and if the estimated or actual size of all overlays
 together exceeds the available expanded memory, the following
 initialization error occurs when the first overlay is called at
 run-time:

    Insufficient EMS to load overlays

 Note: You will never see this error if all your overlays are smaller
 than 16K each.

 If you want to force loading overlays from disk, thus avoiding the
 possibility of this overlay-initialization error in expanded memory,
 you must link with the stub file NOEMS.OBJ (with no parentheses around
 NOEMS.OBJ on the LINK command line). Alternatively, you can try
 reconfiguring expanded memory so more of it is available for BASIC
 overlays. Another alternative is to make overlays similar in size.

 To find out the size of each overlay, you must look at the .MAP file
 generated by the linker (LINK.EXE).

 References:

 For more information about how to use link overlays in BASIC 7.00 and
 7.10, search in this Knowledge Base for a separate article with the
 following words:

    How and link and overlays and expanded and memory and BASIC

 See also the section "Linking with Overlays" on Pages 612-614 in the
 "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10.


 175. INTERRUPTs Using Strings Need SSEG for Segment in QBX & BC /Fs

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | S_C H_MASM SR# S900112-133
 Last Modified:  2-FEB-1990    ArticleIdent: Q58041

 Because the QuickBASIC Extended (QBX.EXE) editor that comes with
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 uses far addresses for all strings, some CALL INTERRUPT statements
 that worked in earlier versions of Microsoft's BASIC products require
 modification for correct results.

 To correct for this behavior, change the segment passed to the
 INTERRUPT to be SSEG(stringvariable).

 This information applies to Microsoft QuickBASIC Extended (QBX.EXE)
 and to programs compiled with BC /Fs in Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 In earlier versions of Microsoft BASIC's, near strings were used.
 Because of this, the VARSEG of the string variable, or -1 in some
 cases, could be used for the segment. In BASIC PDS 7.00, you must use
 the SSEG function to return the segment of a string variable.

 The following table shows the difference in the method of assigning
 the registers for string variables:

    BASIC Versions 6.00/6.00b    BASIC PDS Version 7.00
    -------------------------    ----------------------

    inregs.DS = VARSEG(a$)       inregs.DS = SSEG(a$)   '**** SSEG
    inregs.DX = SADD(a$)         inregs.DX = SADD(a$)
    inregs.ES = -1               inregs.ES = SSEG(b$)   '**** SSEG

 In addition to INTERRUPTs, the change to far strings could also have
 the same effect on mixed-language programming with Microsoft C and
 Microsoft Macro Assembler (MASM).


 176. No Beep When Clicking Outside Modal Window of WINDOW.BAS

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900116-127 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58102

 Using a mouse to select outside a modal window created with the
 WindowOpen procedure of WINDOW.BAS does not produce a beep. This is
 contrary to Page 575 of the "Microsoft BASIC 7.0: Language Reference"
 manual (for 7.00 and 7.10), which incorrectly says:

    When a window is modal, any attempt to select outside the window
    is unsuccessful and results in a beep.

 WINDOW.BAS is a file provided with the User Interface (UI) Toolbox in
 Microsoft BASIC Professional Development System (PDS) Versions 7.00
 and 7.10 for MS-DOS.

 While a modal window is current, pressing certain keys generates a
 beep, but no beep is generated when you click outside the window with
 the mouse. The keys that generate a beep are as follows [Note: This
 list assumes a 101-key (enhanced) keyboard]:

    ESC
    UP ARROW
    DOWN ARROW
    LEFT ARROW
    RIGHT ARROW
    HOME
    END
    PGUP
    PGDN
    ENTER (on main keyboard)
    TAB
    ENTER (on numeric keypad)
    1, 2, 3, 4, 5, 6, 7, 8, 9 (on numeric keypad)


 177. Compiler Options Explained for QBX.EXE's Make EXE File Command

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 29-JAN-1991    ArticleIdent: Q58106

 The following is a complete description of the compiler options
 available when you choose the Make EXE File command from the Run menu
 in the QuickBASIC extended (QBX.EXE) environment. This information is
 also available in the "Microsoft BASIC 7.0: Language Reference" manual
 (for 7.00 and 7.10) under "appendixes," Page 608.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Although the QBX.EXE editor can run only under MS-DOS or the DOS real
 mode of MS OS/2, the Make EXE File command in QBX.EXE can use the /Lp
 option to create programs that require MS OS/2 protected mode.

 ------------------------ Make EXE File -------------------
                 ____________________________________
 EXE File Name: |____________________________________|

 This box lets you specify the name of the output .EXE file.

 ----- EXE Type -----------------------------------------
 [] Stand-Alone EXE           /O
 [] EXE Requiring BRT Module
 --------------------------------------------------------

 /O -- Substitutes the default stand-alone library for the default
 run-time library (creates a stand-alone executable file that can run
 without a BASIC run-time module). Stand-alone programs can be
 significantly larger than programs compiled to use the run-time
 module. /O is selected by default in this Make EXE File window.

 EXE Requiring BRT Module -- Makes an EXE program that requires the
 presence of BRT70XXX.EXE at run time. The XXX depends upon the /Fpi or
 /Fpa math package, near or far strings, and real or protected mode.

 ----- Speed -------------------------------------------
 [] 80x87 or Emulator Math   /Fpi
 [] Alternate Math           /Fpa
 [] Code Generation for 286   /G2
 [] Quick Call Optimization   /Ot
 -------------------------------------------------------

 /Fpi -- Causes the compiler to generate "in-line instructions" for use
 in floating-point operations. This option is the default.

 /Fpa -- Causes your program to use the alternate-math library for
 floating point operations.

 /G2 -- This option generates 80286-specific instructions (which
 actually affects size more than speed)

 /Ot -- Optimizes execution speed for SUB and FUNCTION procedures and
 DEF FN statements. To use this type of optimizing, certain conditions
 must be met. The frame size generated for SUB and FUNCTION procedures,
 and statements defined by DEF FN, depends on which of the following
 conditions exist in your code:

    For SUB and FUNCTION procedures:

    A reduced frame is generated with /Ot if no module-level handler
    exists in the code, and the /D or /Fs isn't used. A full frame is
    generated if your code uses local error handlers, calls a DEF FN or
    GOSUB statement, has returned (because of a GOSUB or other reason),
    or contains an ON event GOSUB.

    For statements defined by DEF FN:

    A full frame is generated if the /D, /Fs, /E, or /X option is used.
    In all other cases, no frame is generated if the /W or /V option is
    used. In all other cases, no frame is generated.

 ---- Target Environment --------------------------------
 [] DOS or OS/2 Real Mode     /Lr
 [] OS/2 Protected Mode       /Lp
 --------------------------------------------------------

 /Lr -- Creates a real-mode object file (the default). This makes
 .EXE programs that run in MS-DOS or the real mode (the DOS 3.x box)
 of MS OS/2.

 /Lp -- Creates a protected-mode object file (to make .EXE programs
 that run in OS/2 protected mode).

 ---- Size/Capacity -------------------------------------
 [] Far Strings                /Fs
 [] Near Strings
 [] Disable String Compression /S
 --------------------------------------------------------

 /Fs -- This option enables far-heap strings in user programs.

 Near Strings -- This option enables near (DGROUP) strings in user
 programs.

 /S -- Writes quoted strings directly to the object file instead of the
 symbol table in memory. Use this option when an "Out of memory" error
 message is generated while BC.EXE is compiling a program that has many
 string constants.

 ---- Debug ----------------------------------------------
 [] Run-Time Error Checking    /D
 [] CodeView Information       /Zi
 ---------------------------------------------------------

 /D -- Generates debugging code for run-time error checking; enables
 CTRL+BREAK. For ISAM programs, causes BASIC to write open database
 buffers to disk after every DELETE, INSERT, UPDATE, and CLOSE
 statement. You must use either /Ah or /D when you are compiling Quick
 library routines that will be loaded into QBX with the /Ea option
 (which moves arrays into expanded memory).

 /Zi -- This option adds debugging information to the object file that
 can be used by the Microsoft CodeView (CV.EXE, or CVP.EXE) debugger.

 QBX.EXE 7.10 adds an "Additional Options" field (not found in 7.00),
 which lets you specify any additional compiler options for invoking
 BC.EXE.

 There are four buttons at the bottom of the window:

 Make EXE -- This button shells out to DOS, runs BC.EXE with the
 specified options, runs LINK.EXE, creates an executable BASIC .EXE
 program, and returns to QBX.EXE.

 Make EXE and Exit -- This button transfers control to BC.EXE with the
 specified options, runs LINK.EXE, creates an executable BASIC
 .EXE program, and ends control in DOS, where you can run the .EXE.

 Cancel -- The Cancel button removes the Make EXE File window and
 returns you to the main QBX.EXE screen.

 Help -- The Help button briefly describes a few features of the Make
 EXE File window.


 178. BASIC 7.00 Wrong Integer FOR-NEXT Index Results in .EXE

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900123-121 buglist7.00 fixlist7.10
 Last Modified:  1-AUG-1990    ArticleIdent: Q58108

 In a compiled .EXE program, a FOR ... NEXT loop with an ending loop
 counter value that is a variable and with a body that contains an
 integer or long integer array assigned to a single- or
 double-precision value can PRINT an incorrect value for the loop
 counter. This problem occurs in a compiled .EXE program only, not in
 the QuickBASIC Extended environment (QBX.EXE). An example of this
 problem is shown in the program below.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS and MS
 OS/2. This problem was corrected in Microsoft BASIC PDS version 7.10.

 The program below illustrates two conditions that, when occurring
 together, can produce an undesirable effect. The root of this error is
 embedded in the BASIC compiler (BC.EXE) optimization techniques. The
 two conditions necessary to show this problem are as follows:

 1. A variable (not a constant) is used as the stop (ending) loop
    counter value on a FOR ... NEXT statement.

 2. An integer or long integer array (which is subscripted with the
    loop counter) is assigned to a single- or double-precision number.
    (This is known as "typecasting" -- a single- or double-precision
    number is typecasted to an integer or long integer.)

 The problem occurs only on the first PRINT statement in the source
 file that prints the loop counter (i%). For all loop iterations, that
 PRINT i% statement incorrectly displays the fixed value of t#, the
 ending loop value. PRINT i% statements farther down in the source code
 work correctly.

 To eliminate the problem, use one of the following workarounds:

 1. Compile with the BC /X option.

      Note: In the example below, the debug compiler option (/D) does
      not correct the problem.

 2. Use the CINT() function to convert the real number to an integer
    before assigning it to the integer or long integer array.

 3. Use a numeric constant (instead of a variable) for the ending
    value of the FOR loop counter.

 4. Compile with the BC /FPa option (instead of the default /FPi).

 Code Example
 ------------

    Dim ia%(10)            'An integer or long array shows problem.
    t# = 5                 't# can be any numeric type (!, @, #, %, or &)
    FOR i% = 1 to t#       't# is the ending value of the loop counter, i%
    PRINT i%;              'This value incorrectly prints equal to t# in .EXE
    ia%(i%) = 46.7         'A real number is typecast to an integer or
                           'long-integer value and assigned to the array
 REM ia%(i%) = CINT(46.7)  'Workaround: use CINT(46.7) in the above line.
    PRINT i%;              'This value prints correctly.
    PRINT ia%(i%)          'This value prints correctly.
    NEXT i%
    END

 Below is the (incorrect) output from this .EXE (compiled without
 BC /X):

    5   1   46.7
    5   2   46.7
    5   3   46.7
    5   4   46.7
    5   5   46.7

 The output should be as follows:

    1   1   46.7
    2   2   46.7
    3   3   46.7
    4   4   46.7
    5   5   46.7


 179. BASIC 7.00/7.10: Incorrect Results with Alternate Math Library

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q58124

 Using Microsoft BASIC Professional Development System (PDS) version
 7.00 for MS-DOS and MS OS/2, the code example below produces incorrect
 results when compiled with the alternate math library (/FPa).

 This code works correctly in the QBX.EXE environment or when compiled
 with BC /D (debug) or /X. It also works correctly when compiled with
 BC /FPa in Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS
 and MS OS/2. Dimensioning the array as double-precision also works
 around the problem.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 version 7.00. This problem was corrected in BASIC PDS 7.10.

 Code Example
 ------------

    DIM A(3)
    A(i%) = 5
    sx = A(i%)
    pr = .1 * A(i%)
    PRINT pr, sx, A(i%)

 Compile as follows:

    BC prog /o /fpa;

 Link as follows:

    LINK prog;

 The correct output from BASIC 7.10 is as follows:

    .5     5     5


 180. "Error Loading File (x.QLB)" After QBX /L x; Must Compile /Fs

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900126-5
 Last Modified: 26-FEB-1990    ArticleIdent: Q58125

 The error "Error in loading file (xxx.QLB )" occurs when loading a
 Quick library into QBX.EXE if the Quick library contains BASIC modules
 compiled without the BC /Fs (far strings) option. The BC /Fs option is
 needed because far strings are always used in the QuickBASIC Extended
 (QBX) environment.

 To create a Quick library that is usable in QBX, recompile with the BC
 /Fs option and relink (LINK /QU) to make a new Quick library.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 The necessity of using the /Fs option to make Quick libraries is
 documented on Page 617 of the "Microsoft BASIC 7.0: Programmer's
 Guide." For more information on Quick libraries, see Chapter 19,
 "Creating and Using Quick Libraries."


 181. BASIC PDS 7.00 List of Stub Files for Linking Smaller .EXE's

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900112-169
 Last Modified: 26-FEB-1990    ArticleIdent: Q58175

 Below is the list of linker stub files that come with Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2. Stub files are special object files that block the inclusion of
 certain pieces of the BASIC run-time routines in the final .EXE file
 at link time. Most stub files can reduce .EXE program size and memory
 usage.

 This list can also be found on Pages 540-541 and 610-611 of the
 "Microsoft BASIC 7.0: Programmer's Guide," and on Pages 10-12 of the
 "Microsoft BASIC 7.0: Getting Started" manual.

 BASIC 7.00 Stub Files
 ---------------------

 Filename              Description
 --------              -----------

 OVLDOS21.OBJ          DOS 2.10 support to an overlaid program. Does
                       not reduce .EXE size.

 NOCGA.OBJ             Removes support for CGA graphics (SCREEN modes 1
                       and 2).

 NOCOM.OBJ             Removes communications ("COM1:", "COM2:") device
                       support in two cases. LINK includes
                       communications support overhead only if you use a
                       string variable in place of the file or device
                       name, as in OPEN A$ FOR OUTPUT AS #1, or if you
                       use a string constant starting with COMn in an
                       OPEN statement.

 NOEDIT.OBJ            Reduces functionality of the editor provided
                       with the INPUT and LINE INPUT statements to
                       support only ENTER and BACKSPACE keys (no HOME,
                       END, etc.).

 NOEGA.OBJ             Removes support for EGA graphics (SCREEN modes
                       7, 8, 9, 10, 11).

 NOEMS.OBJ             Prevents the overlay manager from using Expanded
                       Memory Specification (EMS); instead, the BASIC
                       .EXE program is forced to swap to disk.

 NOEVENT.OBJ           Removes support for EVENT trapping. This stub
                       file is effective only if linked with the BASIC
                       run-time module (BRT70xxx.EXE); it has no effect
                       when linked into stand-alone executables.

 NOFLTIN.OBJ           Replaces the numeric parsing code with an
                       integer-only version. If you link with
                       NOFLTIN.OBJ, all numbers used by INPUT, READ,
                       and VAL must be legal long integers.

 NOGRAPH.OBJ           Removes all support for graphics statements and
                       nonzero SCREEN modes. NOGRAPH.OBJ is a superset
                       of the following stub files: NOHERC.OBJ,
                       NOOGA.OBJ, NOCGA.OBJ, NOEGA.OBJ, and NOVGA.OBJ.

 NOHERC.OBJ            Removes support for Hercules graphics SCREEN 3.

 NOISAM.OBJ            Removes ISAM support from the BASIC run-time
                       module (BRT70xxx.EXE) and is not useful for
                       stand-alone programs (compiled with BC /O).

 NOLPT.OBJ             Removes line printer support.

 NOOGA.OBJ             Removes support for Olivetti graphics (SCREEN
                       mode 4).

 NOTRNEMR.LIB          Removes support for transcendental operations,
 and NOTRNEMP.LIB      including: SIN, COS, TAN, ATN, LOG, SQR, EXP,
                       ^ (the exponential operator), a CIRCLE statement
                       with a start or stop value, and the DRAW
                       statement with the A or T commands.

 NOVGA.OBJ             Removes support for VGA (Video Graphics Array)
                       graphics (SCREEN modes 11, 12, 13).

 SMALLERR.OBJ          Reduces size of error messages displayed.

 TSCNIOxx.OBJ          Removes certain features from BASIC programs to
                       produce text-only screen I/O. There are four
                       files, depending on string type and operating
                       system mode, as follows:

                          TSCNIONR.OBJ   Near string, real mode (DOS)

                          TSCNIOFR.OBJ   Far string, real mode (DOS)

                          TSCNIONP.OBJ   Near string, OS/2 protected mode

                          TSCNIOFP.OBJ   Far string, OS/2 protected mode

                       The TSCNIOxx stub files remove all support for
                       BASIC graphics modes and graphics statements,
                       except SCREEN 0. They also remove support for
                       special treatment of control characters. The
                       TSCNIOxx stub files cannot be used with any of
                       the other graphics stub files.


 182. BUILDRTM "Unresolved External" Using OVLDOS21.OBJ; Not Allowed

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58410

 The stub file OVLDOS21.OBJ, which is shipped with Microsoft BASIC
 Professional Development System (PDS) Versions 7.00 and 7.10 for
 MS-DOS, can be linked into an .EXE program that uses an extended
 run-time module, but is not allowed to be built into an extended
 run-time module.

 The link error "L2029: Unresolved external" displays a few times if
 you attempt to use the BUILDRTM.EXE utility to place the OVLDOS21.OBJ
 file into an extended run-time module.

 The following sentences need to be added to Pages 539, 611, and 663 of
 the "Microsoft BASIC 7.0: Programmer's Reference" manual (for versions
 7.00 and 7.10):

    Note that you cannot use BUILDRTM to build the OVLDOS21.OBJ stub
    file into an extended run-time module. You can link OVLDOS21.OBJ
    into an .EXE program that uses a normal or extended run-time
    module.

 The following is a correct example to link the OVLDOS21.OBJ stub file
 for use with an extended run-time module:

 LINK import.obj+main.obj+OVLDOS21.obj+(sub1)+(sub2),main.exe,,extrtm.lib;

 The OVLDOS21.OBJ stub file shipped with BASIC PDS Version 7.00 is
 provided to support code overlays under MS-DOS Version 2.10. This stub
 file is not required if overlays are to be used on MS-DOS Versions 3.00
 and later. For more information about overlays, search for a separate
 article by querying on the following words:

    how and use and LINK and overlays and BASIC and PDS and 7.00


 183. LIM 4.0 Expanded Memory Boards/Drivers for BASIC 7.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-FEB-1990    ArticleIdent: Q58547

 Listed below are some memory boards/drivers that are within the
 specifications of the LIM 4.0 EMS (Lotus-Intel-Microsoft Version 4.0
 Expanded Memory Specification) standard for MS-DOS. One list below is
 for 80386 computers, and another list is for 80286 computers.

 This information is useful for owners of Microsoft BASIC Professional
 Development System (PDS) Version 7.00 under MS-DOS. The following
 features in BASIC PDS 7.00 can take advantage of LIM 4.0 EMS expanded
 memory: ISAM file-handling, the QBX.EXE environment, and certain
 overlaid .EXE programs.

 Below is a list of expanded memory boards and drivers for machines
 with an 80386 processor chip. (The 80386 is also known as the 386):

 Company        Address / Phone              Memory board / Driver
 -------        ---------------              ---------------------

 Above
 Software       (714) 545-1181               Above Disk

 Everex         48431 Milmont Dr.            RAM8000 / EMM.SYS
                Fremont, CA 94538
                (800) 821-0806
                (415) 498-1115

 Intel          185 Berry                    InBoard 386 AT / Driver
                Suite 306
                San Francisco, CA 94107
                (800) 538-3373
                (408) 765-4512

 Microsoft      One Microsoft Way            HIMEM.SYS
                Redmond, WA 98052
                (800) 426-9400
                (206) 882-8088

 Orchid         45365 Northport              RamQuest XT / AT
                Loop West
                Fremont, CA 94538
                (415) 683-0300

 Qualitas       7101 Wisconsin Ave.          n/a / 386MAX
                Suite 1386
                Bethesda, MD 20814
                (301) 907-6700

 Quarterdeck    150 Pico Blvd                n/a / QEMM
                Santa Monica, CA 90405
                (213) 392-9851

 Tall Trees     2585 East Bayshore Rd.       JRAM / JEMS
                Palo Alto, CA 94303
                (415) 493-1980

 Techmar        6225 Cochran Rd.             MICRORAM 386
                Solan, OH 44139              MICRORAM (PS/2)
                (216) 349-1009

 Toshiba        2441 Michelle Dr.            n/a / EMM386.SYS
                Tustin, CA 92680
                (800) 999-4273
                (714) 583-3000

 Below is a list of expanded memory boards and drivers for machines
 with an 80286 processor chip. (The 80286 also known as the 286):

 Company        Address / Phone              Memory board / Driver
 -------        ---------------              ---------------------

 Above
 Software       (714) 545-1181               Above Disk

 AST            16215 Alton Parkway          Rampage Plus XT / AT
                Irvine, CA 92718             SixPak 286 XT / AT
                (714) 863-1333

 Intel          185 Berry                    Above Board Plus / EMM
                Suite 306                    Above Board Plus 8 / EMM
                San Francisco, CA 94107
                (800) 538-3373
                (408) 765-4512

 Microsoft      One Microsoft Way            HIMEM.SYS
                Redmond, WA 98052
                (800) 426-9400
                (206) 882-8088

 Orchid         45365 Northport              RamQuest XT / AT
                Loop West
                Fremont, CA 94538
                (415) 683-0300

 Qualitas       7101 Wisconsin Ave.          n/a / MOVE'EM
                Suite 1386
                Bethesda, MA 20814
                (301) 907-6700

 Quarterdeck    150 Pico Blvd                n/a / QEMM(IBM ONLY)
                Santa Monica, CA 90405       n/a / QEMM 50/60
                (213) 392-9851

 Tall Trees     2585 East Bayshore Rd.       JRAM / JEMS
                Palo Alto, CA 94303
                (415) 493-1980

 Techmar        6225 Cochran Rd.             MICRORAM
                Solan, OH 44139              CAPTAIN 286
                (216) 349-1009

 Toshiba        2441 Michelle Dr.            n/a / EMM.SYS
                Tustin, CA 92680
                (800) 999-4273
                (714) 583-3000

 Note: The MS-DOS interrupts necessary to access LIM 4.0 expanded
 memory are documented in the following book:

    Pages 25-68 of "MS-DOS Extensions: Programmer's Quick Reference,"
    by Ray Duncan (Microsoft Press, 1989).


 184. 7.10 Correction Passing Far Variable-String Array to MASM

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900207-62 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58563

 Page 515 of the "Microsoft BASIC 7.0: Programmer's Guide" (for 7.00
 and 7.10) incorrectly shows how to pass a far variable-length-string
 array to assembly. Page 515 states the following:

    To accomplish this, BASIC could call a MASM procedure, passing it
    the address of the first string descriptor in the array:

    DECLARE SUB ChangeArray(S$)
    CALL ChangeArray(A$(1))

 This does not, in fact, pass the address of the string descriptor of
 the first array element, but rather passes the near address of the
 descriptor of a copy of the string. To pass the address of the first
 descriptor, use BYVAL and VARPTR as follows:

    DECLARE SUB ChangeArray(BYVAL offset%)
    CALL ChangeArray(VARPTR(a$(1)))

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Note that all strings in the QBX.EXE environment are always far. When
 making .EXE programs with BC.EXE, you can enable far strings with the
 BC /Fs option.

 The following code example shows the correct way to pass an array of
 BASIC variable-length far strings to assembly language:

    DECLARE SUB ChangeArray(BYVAL offset%)
    DIM a$(1 TO 10)
    FOR i% = 1 TO 10
      a$(i%) = STRING$(i%, ASC("A") + i% - 1)
      PRINT a$(i%)
    NEXT
    CALL ChangeArray(VARPTR(a$(1)))
    FOR i% = 1 TO 10
       PRINT a$(i%)
    NEXT
    END

 To use the above program, the following assembly code (taken from
 Pages 516-517 of "Microsoft BASIC 7.0: Programmer's Guide") should be
 assembled and linked with the above program, or linked into a Quick
 library (.QLB) for use in the QBX.EXE environment:

       .model medium,basic
       .data
 array       dw 100 dup(0)
       .code
 ; arraydescriptor below is the pointer to the array:
 changearray proc uses si di, arraydescriptor: near ptr
       extrn stringassign:proc
       mov   cx, 10
       mov   si, arraydescriptor
       lea   di, array
 transferin: push cx

       push  ds
       push  si
       xor   ax,ax
       push  ax
       push  ds
       push  di
       mov   ax, 10
       push  ax
       call  stringassign
       pop   cx
       add   si, 4
       add   di,10
       loop  transferin

       mov   cx,100
       lea   bx, array
 more: cmp byte ptr[bx], 0
       jz    skip
       add byte ptr[bx], 32
 skip: inc   bx
       loop  more

       mov   cx, 10
       lea   si, array + 90
 transferout:push   cx

       push  ds
       push  si
       push  cx
       push  ds
       push  di
       xor   ax,ax
       push  ax
       call  stringassign
       pop   cx
       sub   si, 10
       add   di, 4
       loop  transferout

       ret

 changearray endp
       end

 Use the following Microsoft Macro Assembler command line to assemble
 the above code:

    MASM CHGARRAY.ASM ;

 To create a Quick library from CHGARRAY.OBJ, use the following LINK
 line:

    LINK /Q CHGARRAY,,,QBXQLB;

 To use this Quick library, enter QBX.EXE with the following statement:

    QBX /L CHGARRAY

 The output for the above code example is as follows:

    A
    BB
    CCC
    DDDD
    EEEEE
    FFFFFF
    GGGGGGG
    HHHHHHHH
    IIIIIIIII
    JJJJJJJJJJ
    jjjjjjjjjj
    iiiiiiiii
    hhhhhhhh
    ggggggg
    ffffff
    eeeee
    dddd
    ccc
    bb
    a


 185. How to Use Customize Menu Command of Utility Menu in QBX.EXE

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900118-14
 Last Modified: 26-FEB-1990    ArticleIdent: Q58568

 This article explains how to use the Customize Menu command in the
 Utility menu in the QBX.EXE (QuickBASIC Extended) environment. The
 Customize Menu command allows you to add your own DOS commands
 (internal, external, or batch files) to the Utility menu. This
 provides easy access to these commands rather than having to shell out
 to DOS and type them in at the command line prompt.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 The following is a brief summary of the features of the Customize Menu
 dialog box:

 Applications List - A list of the DOS commands already included in the
                     Utility menu.

 Add button        - Adds a new command to the Applications List. For
                     details, see farther below.

 Edit button       - Edits the information associated with a command
                     already in the Applications List.

 Delete button     - Deletes a command from the Applications List.

 To Begin button   - Puts the currently selected command at the top of
                     the Applications List.

 To End button     - Puts the currently selected command at the bottom
                     of the Applications List.

 Save button       - Saves all the changes made to the Applications
                     List and closes the Customize Menu dialog box.

 Cancel button     - Cancels all the changes made to the Applications
                     List and closes the Customize Menu dialog box.

 Help button       - Provides online help for using the Customize
                     Menu command.

 The Customize Menu command in the Utility menu is a handy way to
 execute DOS-level commands from inside the QBX.EXE environment. It
 allows you to execute internal commands, external commands, and batch
 files by selecting a menu item with the keyboard or mouse. There is no
 need to shell out to DOS. When the command or batch file is finished,
 you can be prompted to "press any key to continue" or you can specify
 for QBX to reappear automatically.

 Adding, deleting, editing, and ordering commands in the Utility menu
 is very simple, and the discussion above should be adequate enough for
 every feature except the Add button, which is discussed below in
 detail.

 Add Button
 ----------

 When selected, the Add button brings up another dialog box containing
 edit fields that are used to enter information about the command to be
 added. The following is a list of the edit fields and buttons of this
 dialog box and information about each one:

 Menu Text (20 chars) - Enter the name you want displayed in the
                        Utility menu. This name will also appear in the
                        Applications List. This may or may not be the
                        name of the actual command.

 Pathname             - Enter the name of the command if it is internal
                        or the full path to the file if it is external
                        or a batch file. For example, "DIR" or
                        "C:\CHKDSK".

 Arguments            - Enter the arguments passed to the command. For
                        example, this may be "a:" if the command is
                        "FORMAT" or "/w" if the command is "DIR", etc.

 Initial Directory    - Enter the name of the directory you want the
                        command to operate in.

 Prompt Before        - Select this option if you want to be prompted
 Returning              with "press any key to continue" before control
                        is returned to QBX.

 Accelerator Key      - Select the None button if you do not want to
                        use an accelerator key or select the ALT+F
                        button if you do. The values that may be
                        entered into the box following ALT+F range from
                        2 to 10, specifying the function keys F2
                        through F10.

 OK button            - Select this button when you are satisfied with
                        the information in the dialog box. The Add
                        dialog box closes and the name of the new
                        command is added to the Applications List.
                        However, none of the changes to the Utility
                        menu are saved unless the Save button is
                        selected.

 Cancel button        - This button cancels the information entered in
                        the edit fields and closes the Add dialog box.

 Help button          - This button displays more online help.

 Below is a step-by-step example illustrating how to use the Customize
 Menu command. This example shows how to add the DOS command "DIR" to
 the Utility menu. This DIR command operates on the current directory
 and uses the "/w" parameter to display the listing in many columns
 rather than one. Also, an accelerator key (ALT+F5) is linked to the
 command for easy keyboard access and the user is prompted to "press
 any key to continue" after the DIR command is finished.

  1. Choose Customize Menu from the Utility menu. This can be done by
     holding down the ALT and U keys together, followed by the C key
     alone.

  2. The Customize Menu dialog box appears. Press the TAB key once to
     highlight the Add button and then press ENTER.

  3. Another dialog box appears, containing edit fields used to enter
     information about the command. The cursor is placed in the top
     edit field, "Menu Text (20 chars)." Type in "DIR" for this field
     and press TAB.

  4. The cursor advances to the next edit field, "Pathname". Since DIR
     is an internal command, it has no path, so you only need to enter
     the name of the command by itself, "DIR". Do this and press TAB
     again.

  5. The next edit field is "Arguments". A common argument to pass to
     the DIR command is "/w".  The "/w" argument (called a switch)
     breaks the directory listing into columns rather than listing them
     in one long column, which frequently scrolls off the screen. Type
     "/w" and press TAB.

  6. For the "Initial Directory" edit field, you can enter any valid
     pathname. Leaving this field blank causes the command to use the
     current pathname. Press TAB to leave it blank.

  7. The cursor is now placed inside the button titled "Prompt Before
     Returning." You can press SPACEBAR to toggle this button on or
     off. Toggle it on and press TAB.

  8. The cursor advances to the button titled "None". By default it is
     also selected, specifying that no accelerator key is to be defined
     for accessing the DOS command from the Utility menu. To enter an
     accelerator key, press the RIGHT ARROW. This toggles the None
     button off and the ALT+F button on. Press TAB to advance the
     cursor to the edit field following the ALT+F button and enter a 5
     (specifying F5). Press ENTER to continue.

  9. The current dialog box closes and the main Customize Menu dialog
     box reappears. You will see that "DIR" has been added to the
     Applications List. Press TAB until the Save button is highlighted,
     then press ENTER.

 10. The Customize Menu dialog box closes. You can now choose the DIR
     command from the Utility menu either by pulling down the menu and
     then choosing DIR or you can use the accelerator key sequence,
     ALT+F5. After displaying the contents of the current directory, you
     will be prompted with "press any key to continue" before control is
     returned to QBX.


 186. Token Ring Network Driver May Conflict with BASIC 7.00 Setup

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900207-50 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q58639

 A customer reported that when running the SETUP.EXE installation
 program for Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and OS/2, problems may occur if a Token Ring
 network device driver Version 1.10 has been loaded from the CONFIG.SYS
 file during a system boot. Upon removing the device driver and
 rebooting the system, everything seems to install and build correctly.

 The customer reported that the source files on the distribution disks
 were overwritten with the current system date and weren't properly
 unpacked onto the hard disk, and subsequent library and toolbox builds
 crashed because of the corrupt files used. Microsoft has not confirmed
 this information.


 187. LOCAL (Procedure) ERROR Handling Introduced in BASIC PDS 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 26-FEB-1990    ArticleIdent: Q58606

 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 offers structured error trapping and handling that
 make error handling much more flexible than in earlier versions of
 BASIC.

 In previous versions of BASIC, error handling routines existed at the
 module level. When a handler was turned on with the ON ERROR GOTO
 statement, it was active for all procedures within that module.

 With Microsoft BASIC PDS 7.00, you can now create both module-level
 and procedure-level error handlers. BASIC PDS 7.00 introduces the ON
 LOCAL ERROR GOTO statement to trap procedure-level errors. A given
 type of error can invoke different local error-handling routines,
 depending on which procedure is running. For example, you may want to
 invoke different error-handling routines for ERR code 54, "Bad File
 Mode," because the error has different meaning for different file
 operations.

 For more information, please refer to Chapter 8, "Error Handling," in
 the "Microsoft BASIC 7.0: Programmer's Guide," or see the ON ERROR
 statement "Details" in the Microsoft Advisor online Help system in the
 QBX.EXE environment.

 Error handling is the process of intercepting and dealing with errors
 that would otherwise stop your program at run time. BASIC PDS 7.00
 provides an ON [LOCAL] ERROR GOTO statement to enable the trapping of
 errors and takes the appropriate action so the program can continue
 executing. The ON ERROR GOTO statement jumps to a labeled
 error-handling  routine. The ON [LOCAL] ERROR GOTO 0 statement can be
 used to disable an error-handling routine.

 Procedure-Level Versus Module-Level Error-Handling
 --------------------------------------------------

 For many applications, procedure-level error handling is preferred
 because procedures tend to be organized by task (display, printing,
 general I/O, etc.), and errors are also task-related. Therefore,
 program organization can be simpler and more straightforward when
 related tasks and their error handlers are grouped together.

 The following is the syntax for ERROR handling:

    ON [LOCAL] ERROR { GOTO line | RESUME NEXT | GOTO 0 }

    LOCAL: The LOCAL keyword indicates an error-handling routine that
    is "local" to the procedure within which the error-handling routine
    is located. A local error-handling routine:

    -- Overrides any enabled module-level error-handling routines.

    -- Is enabled only while the procedure within which it is
       located is executing.

    GOTO <line>: Enables the error-handling routine that starts at
    <line>. Thereafter, if a run-time error occurs, program control
    branches to <line> (label or line number). The specified <line> is
    in either module-level code or in the same procedure (if the LOCAL
    keyword is used). If <line> is not found in either place, BASIC
    generates a "Label not defined" compile-time error.

    Exiting an Error-Handling Routine
    ---------------------------------

    RESUME NEXT: Specifies that when a run-time error occurs control
    goes to the statement after the statement where the error occurred;
    the ERR function can then be used to obtain the run-time error
    code.

    RESUME[0]: Returns to the statement that caused the error or the
    last call out of the error-handling procedure or module.

    RESUME <line>: Returns to the label or line number specified by
    <line>.

    ERROR ERR: Initiates a search of the invocation path for the next
    higher-level error-handling routine, if any. If no higher-level
    error handler exists, the program stops with the error reported by
    the ERR function.

    GOTO 0: Disables any enabled module-level error-handling routine
    within the current module, or disables any enabled error handler
    within the current procedure (if used together with the LOCAL
    keyword).

 Below is an example of how to use procedure-level (local) error
 handling and module-level error handling within the same module.

 This program consists of one module that contains a main program and a
 subprogram within the same module. At the module-level code, the ON
 ERROR GOTO is placed at the top of the program so that that there is a
 way to handle errors that occur in the module-level code. The
 subprogram "test" has its own local error handler. Two errors occur in
 this program; one in the module-level code (ERROR 2 "Syntax error"),
 and another in the subprogram (Error 51 "Division by zero"). Each
 error is handled independently by each error-handler routine.

 Code Example
 ------------

 'MODULE LEVEL CODE:
 DECLARE SUB test ()
 CLS
 'Enable module-level error handler:
 ON ERROR GOTO ModuleHandler
 PRINT "We are at the module-level code"

 'Call a SUBprogram procedure within the same module:
 CALL test
 PRINT "We are back at the module level"
 'Simulate an error ("Syntax Error") in the module-level code:
 ERROR 2
 PRINT "this is the end"
 END

 'Module-Level Error Handler:
 ModuleHandler:

 PRINT "You have encountered an error at the module-level code,"
 PRINT "and the program has trapped error number:"; ERR
 PRINT "Now resuming to next line..."
 'RESUME NEXT from a module-level error handler returns to the next
 'statement immediately following the one that caused the error
 '(or to the statement following the CALL to a procedure in which
 'an untrapped error occurred):
 RESUME NEXT

 'This SUB is called by the module-level code:
 SUB test
 PRINT "We are now at the procedure (local) level code."
 'Enable the local-error handler:
 ON LOCAL ERROR GOTO LocalHandler
 a! = 10
 b! = 0
 'A "Division by zero" error occurs when the following line executes:
 c! = a! / b!
 PRINT "We resumed past the statement with the division by zero error."
 PRINT "c! ="; c!

 'Place the EXIT SUB statement before the error-handling routine to
 'avoid incorrectly passing control to the local error handler:
 EXIT SUB

 LocalHandler:
 PRINT "You have encountered an error at the procedure-level code,"
 PRINT "and the program has trapped error number:"; ERR
 SELECT CASE ERR
    CASE 11
    PRINT "Error Message: Attempted to divide by zero"
 END SELECT
 PRINT "Now resuming to next line..."
 RESUME NEXT

 END SUB


 188. Bad EXE Result Assigning n Between 2 Statements Using Same n

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900207-44 buglist7.00 fixlist7.10
 Last Modified:  6-SEP-1990    ArticleIdent: Q58608

 Assigning a SINGLE-precision variable in a statement between two other
 statements that use that same variable can produce incorrect results
 in an .EXE compiled with BC.EXE in Microsoft BASIC Professional
 Development System (PDS) version 7.00 for MS-DOS and OS/2. This
 problem does not occur in the QBX.EXE (QuickBASIC Extended)
 environment. This error does not occur with the INTEGER, LONG, DOUBLE,
 or CURRENCY data types.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 version 7.00. This problem was corrected in version 7.10.

 To work around this problem in 7.00, do ONE of the following:

 1. Use the BC /X compiler option.

 2. Make an assignment to a temporary variable before the second or
    third statement.

 3. Place a line number or label on the second or third statement.

 4. Place a DEFxxx statement in the program (such as DEFDBL A-Z), or
    explicitly DIMension the variable to be some data type other than
    SINGLE precision.

 This problem does NOT occur in Microsoft BASIC Compiler version 6.00
 or 6.00b for MS-DOS and OS/2, or in Microsoft QuickBASIC version 4.00,
 4.00b, or 4.50 for MS-DOS.

 The following code example illustrates the problem and contains
 workarounds #2 and #3 in comments:

    init = p
    'temp = init      'Uncomment this line for workaround #2
    'label:           'Uncomment this line for workaround #3
    p = 200
    wrong = p
    PRINT wrong, p    'In EXE compiled without /X, this prints 0 and 200


 189. "7.0: Programmer's Guide" Error Handling Example Correction

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900207-56 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58640

 The following are two corrections to the error handling example
 program on Page 291 of the "Microsoft BASIC 7.0: Programmer's Guide"
 (for 7.00 and 7.10):

 1. In Module #1, the line "ON ERROR GOTO Handler" should be removed
    because there is no line label "Handler" in the first module.

 2. In Module #2, the line "DEFINT A-Z" should be added before the line
    "Handler:". Since the default type for variables is SINGLE,
    variables A and B would be incorrectly typed as SINGLE instead of
    as INTEGER if the DEFINT A-Z line is not inserted.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 190. BASIC 7.00 Can Assign an Array to an Array If in a TYPE

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900131-59 B_QuickBas
 Last Modified: 12-NOV-1990    ArticleIdent: Q58733

 Some languages, such as Pascal, allow you to assign one array directly
 to another, which copies all the elements from one array to another.
 Microsoft BASIC cannot do this, except in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 where you can now
 directly assign one static array to another by defining the array in a
 user-defined-TYPE variable and then assigning one variable of this
 TYPE to another.

 Using a variable of a TYPE that contains an array, you can also write
 an entire array to a file using a single PUT# statement.

 Note that in Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 for
 MS-DOS, in Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and in Microsoft BASIC PDS versions 7.00 and 7.10 for
 MS-DOS and MS OS/2, you can directly assign variables of a
 user-defined TYPE directly to one another if they are of the same
 TYPE. (LSET can be used for assignment if the record variables differ
 in TYPE.) The TYPEd variables are assigned in one simple statement,
 and each and every element of the user-defined TYPE is automatically
 copied.

 Microsoft BASIC PDS version 7.00 for MS-DOS and MS OS/2 introduces
 support for static arrays in user-defined TYPEs. In BASIC PDS 7.00 and
 7.10, you can directly assign one static array to another by defining
 the array in a user-defined-TYPE variable and then assigning one
 variable of this TYPE to another, as shown in Example 1.

 You can also write a whole array at once into a disk file, as shown in
 Example 2.

 Code Example 1
 --------------

 The following program can be used in BASIC PDS 7.00 and 7.10 to
 demonstrate the assignment of the contents of one static array to
 another. (Note that dynamic arrays cannot be placed in user-defined
 TYPEs.)

    TYPE rec1
      array1(20) AS INTEGER
    END TYPE
    DIM var1 AS rec1, var2 AS rec1
    CLS
    FOR i = 1 TO 20      ' Fill the array in var1:
      var1.array1(i) = i
    NEXT
      var2 = var1          ' Make the assignment.
    FOR i = 1 TO 20      ' Confirm that the array was copied to var2:
      PRINT var2.array1(i)
    NEXT
    END

 Code Example 2
 --------------

 The following example, compiled in BASIC PDS 7.00 or 7.10, shows how
 to write a whole array to disk at once, using just one PUT# statement:

    TYPE rec1
      array1(20) AS INTEGER
    END TYPE
    DIM var1 AS rec1, var2 AS rec1
    CLS
    FOR i = 1 TO 20      ' Fill the array in var1:
      var1.array1(i) = i
    NEXT

    OPEN "test.dat" FOR RANDOM AS #1
    PUT #1, , var1         ' write whole array to disk all at once.
    CLOSE

    OPEN "test.dat" FOR RANDOM AS #1
    GET #1, , var2      ' Reads array all at once into var2.
    FOR i = 1 TO 20     ' Print the contents of array var2:
      PRINT var2.array1(i);
    NEXT
    CLOSE


 191. Quick Libraries in BASIC 7.00 Don't Use Expanded Memory

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900207-70
 Last Modified: 27-JUL-1990    ArticleIdent: Q58658

 When using a Quick library in QBX.EXE, the programming environment
 included with Microsoft BASIC Professional Development System (PDS)
 version 7.00 or 7.10, the Quick library is always placed in
 conventional memory. If you have expanded memory (as defined in the
 LIM 4.0 EMS), QBX.EXE utilizes this expanded memory for loaded source
 code segments that are smaller than 16K; however, Quick libraries are
 always placed in conventional memory.

 Microsoft BASIC PDS 7.00 or 7.10 is the only Microsoft BASIC product
 that supports expanded memory, so this is not a consideration in
 earlier versions of Microsoft BASIC Compiler or QuickBASIC.

 Note: (LIM 4.0 EMS is an acronym for the Lotus/Intel/Microsoft version
 4.0 Expanded Memory Specification for MS-DOS.)


 192. TIMEVALUE# Function Documentation Correction in BASIC 7.00

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900208-180 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58660

 The following reference to the TIMEVALUE# function on Page 486 of the
 "Microsoft BASIC 7.0: Language Reference" manual (for 7.00 and 7.10)
 is incorrect. The second sentence in the remarks section states the
 following:

    Time can be entered as "2:24PM" or "14:24".

 This sentence should indicate a space between "2:24" and "PM" and read
 as follows:

    Time can be entered as "2:24 PM" or "14:24".

 The TIMEVALUE function is a routine in the "add-on library" included
 with Microsoft BASIC Professional Development System versions 7.00 and
 7.10 for MS-DOS and MS OS/2.


 193. ButtonOpen Incorrectly Handles Button in Resizable Window

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900202-66 buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q58673

 The ButtonOpen SUBprogram in the User Interface (UI) Toolbox (in
 WINDOW.BAS) incorrectly handles buttons in resizable windows and
 buttons with invalid states. When trying to create a button with an
 invalid state (such as state 3 for window type 2), the following
 message displays and the program stops:

    Cannot open button on window that can be re-sized.

 When you attempt to place a button in a resizable window, the above
 message is not displayed, but no button is created. In this case, the
 ButtonOpen SUB falls through without doing anything.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS. The necessary
 corrections to the WINDOW.BAS source code are listed below.

 For additional corrections to source code in the User Interface
 Toolbox, search in this Knowledge Base for the following words:

    User and Interface and Toolbox and buglist7.00

 The section of code that must be modified is at the end of the
 ButtonOpen SUB from WINDOW.BAS (Note: The underscores are used for
 display purposes only):

   IF (resize AND buttonType >= 6) OR NOT resize THEN
 ...*** not all code displayed
     IF (buttonType = 1 AND state >= 1 AND state <= 3)_
     OR (buttonType >= 2 AND buttonType <= 3 AND state >= 1 AND state <= 2)_
     OR (buttonType >= 4 AND buttonType <= 7) THEN
 ...*** not all code displayed
     ELSE
         PRINT "Cannot open button on window that can be re-sized!"
         END
     END IF
   END IF
 END SUB

 The problem with the existing code is that the ELSE clause matches the
 wrong level of the IF nesting. To modify the code to display correct
 messages, change the above code to the following:

   IF (resize AND buttonType >= 6) OR NOT resize THEN
   ...*** not all code displayed
     IF (buttonType = 1 AND state >= 1 AND state <= 3)_
     OR (buttonType >= 2 AND buttonType <= 3 AND state >= 1 AND state <= 2)_
     OR (buttonType >= 4 AND buttonType <= 7) THEN
     ...*** not all code displayed

 'The following lines have changed.
     ELSE
       PRINT "Illegal state ("; state; ") or button type ("; buttonType; ")"
       END
     END IF
   ELSE
     PRINT "Cannot open button on window that can be re-sized!"
     END
   END IF
 END SUB

 The following code examples demonstrate the two problems with the
 unmodified ButtonOpen SUB:

 Example 1
 ---------

 This first example attempts to open a button, type 2 (check box), with
 an invalid state, 3. This program displays the following incorrect
 message using the unmodified code shipped with BASIC PDS 7.00 or 7.10:

    Cannot open button on window that can be re-sized.

 After making the specified modifications to WINDOW.BAS, Example 1
 displays the following correct message:

    Illegal state ( 3 ) or button type ( 2 )

 REM $INCLUDE: 'General.bi'
 REM $INCLUDE: 'Mouse.bi'
 REM $INCLUDE: 'Menu.bi'
 REM $INCLUDE: 'Window.bi'
 COMMON SHARED /uitools/ GloMenu           AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle()        AS MenuTitleType
 COMMON SHARED /uitools/ GloItem()         AS MenuItemType
 COMMON SHARED /uitools/ GloWindow()       AS windowType
 COMMON SHARED /uitools/ GloButton()       AS buttonType
 COMMON SHARED /uitools/ GloEdit()         AS EditFieldType
 COMMON SHARED /uitools/ GloStorage        AS WindowStorageType
 COMMON SHARED /uitools/ GloWindowStack()  AS INTEGER
 COMMON SHARED /uitools/ GloBuffer$()
 '$DYNAMIC
 DIM GloWindow(MAXWINDOW) AS windowType
 DIM GloWindowStack(MAXWINDOW) AS INTEGER
 DIM GloButton(MAXBUTTON) AS buttonType
 DIM GloEdit(MAXBUTTON) AS EditFieldType
 DIM GloBuffer$(MAXWINDOW + 1, 2)
 CLS
 WindowInit
 Resize% = 0               'Not resizable
 WindowOpen 1, 3, 3, 24, 24, 7, 0, 7, 0, 7, 7, 7, Resize%, 0, 1, "test"
 buttonType% = 2              'Check box (valid states=1 and 2)
 state% = 3                   '3 is invalid state for check box
 CALL ButtonOpen(1, state%, "Foo", 10, 10, 20, 20, buttonType%)

 Example 2
 ---------

 The following example attempts to open a button in a resizable window.
 This program executes without messages using the unmodified code
 shipped with BASIC PDS 7.00 or 7.10, but no button is created.

 After making the specified modifications to WINDOW.BAS, Example 2
 displays the following correct message:

    Cannot open button on window that can be re-sized.

 REM $INCLUDE: 'General.bi'
 REM $INCLUDE: 'Mouse.bi'
 REM $INCLUDE: 'Menu.bi'
 REM $INCLUDE: 'Window.bi'
 COMMON SHARED /uitools/ GloMenu           AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle()        AS MenuTitleType
 COMMON SHARED /uitools/ GloItem()         AS MenuItemType
 COMMON SHARED /uitools/ GloWindow()       AS windowType
 COMMON SHARED /uitools/ GloButton()       AS buttonType
 COMMON SHARED /uitools/ GloEdit()         AS EditFieldType
 COMMON SHARED /uitools/ GloStorage        AS WindowStorageType
 COMMON SHARED /uitools/ GloWindowStack()  AS INTEGER
 COMMON SHARED /uitools/ GloBuffer$()
 '$DYNAMIC
 DIM GloWindow(MAXWINDOW) AS windowType
 DIM GloWindowStack(MAXWINDOW) AS INTEGER
 DIM GloButton(MAXBUTTON) AS buttonType
 DIM GloEdit(MAXBUTTON) AS EditFieldType
 DIM GloBuffer$(MAXWINDOW + 1, 2)
 CLS
 WindowInit
 Resize% = TRUE                 'Resizable
 WindowOpen 1, 3, 3, 24, 24, 7, 0, 7, 0, 7, 7, 7, Resize%, 0, 1, "test"
 buttonType% = 2
 state% = 1                     'Valid state.
 CALL ButtonOpen(1, state%, "Foo", 10, 10, 20, 20, buttonType%)


 194. MenuEvent$ Should Be MenuEvent, Page 495 BASIC 7.0 Reference

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900212-51 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58676

 On Page 495 of the "Microsoft BASIC Version 7.0: Language Reference"
 manual (for 7.00 and 7.10), the User Interface (UI) Toolbox routine
 "MenuEvent" is incorrectly referred to as "MenuEvent$". This is a
 documentation error, since the correct name is "MenuEvent".

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 MenuEvent is a SUB in the toolbox file MENU.BAS and is used to poll
 for any menu events activated by the mouse or keyboard.


 195. Limits for Nesting Arrays in TYPE Statements in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 28-FEB-1990    ArticleIdent: Q58790

 In the QBX.EXE (QuickBASIC Extended) environment for MS-DOS, you can
 have up to 16 nested-array TYPE definitions (see Code Example 1,
 below). If you exceed 16 nestings, you get a "Subscript out of range"
 error.

 In the QBX.EXE environment, nonarray nested TYPEs (see Code Example 2,
 below) can be nested until you run out of memory.

 As for the BC.EXE compiler, the limit on the number of TYPE statements
 for one module is 240 whether they are nested or nonnested TYPE
 definitions. If the number of TYPEs of all kinds exceeds 240, the
 BC.EXE compiler gives an error of "Too Many Type statements".

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 (This information does not apply to versions of Microsoft BASIC
 earlier than 7.00 because they do not support arrays in user-defined
 TYPEs.)

 Note that only static (nondynamic) arrays can be placed in TYPE
 statements in BASIC PDS 7.00.

 Code Example 1 (Arrays of Nested TYPEs)
 ---------------------------------------

 OPTION BASE 1

 TYPE test1
    a AS STRING * 1
 END TYPE

 TYPE test2
    b2(1) AS test1        'Nest it as the first TYPE
 END TYPE
 .
 .
 .
 TYPE test15
    b15(1) AS test14
 END TYPE

 TYPE test16
    b16(1) AS test15
 END TYPE

 DIM temp(1000) AS test16

 Code Example 2 (Nonarray Variables of Nested TYPEs)
 ---------------------------------------------------

 TYPE test1
    a AS INTEGER
 END TYPE

 TYPE test2
    b2 AS test1
 END TYPE

 TYPE test3
    b3 AS test2
 END TYPE
 .
 .
 .
 TYPE test237
    b237 AS test236
 END TYPE

 TYPE test238
    b238 AS test237
 END TYPE

 TYPE new
    none AS INTEGER    'Put in to see if the TYPEs had to be nested
 END TYPE

 TYPE new2
    none2 AS INTEGER
 END TYPE

 DIM temp(100) as test238


 196. DATEVALUE# Function in BASIC 7.00 Uses MM-DD-YY, Not DD-MM-YY

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58791

 The DATEVALUE# function that comes in the Date/Time Library of
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 does not interpret dates in the form of "dd/mm/yy" or "dd-mm-yy,"
 where the day number precedes the month number (dd stands for day, mm
 stands for month, and yy stands for year). Instead, the DATEVALUE#
 function interprets dates in the form of "mm/dd/yy" or "mm-dd-yy,"
 where the month number precedes the day number. For example, you get
 "Illegal Function Call" (error 5) when passing "30/12/88" or
 "30-12-88" to the DATEVALUE# function.

 Both Page 427 of the "Microsoft BASIC 7.0: Language Reference" manual
 (for 7.00 and 7.10) and also the "HELP: DateValue# Function Details"
 screen in the Microsoft Advisor online Help system in QBX.EXE
 incorrectly state that "30/12/88" is one of the acceptable formats.
 This should be changed to say that "12/30/88" ("mm/dd/yy") format is
 accepted by the DATEVALUE# function.

 Also, the "HELP: DateValue# Function Details" screen in the Microsoft
 Advisor online Help system in QBX.EXE incorrectly states: "To use
 DateValue# in the QBX environment, use the FINANCER.QLB Quick
 library." This should be changed to say the DTFMTER.QLB Quick library.
 (Page 427 of the reference manual correctly says to use DTFMTER.QLB in
 QBX.)

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 If you want to give the date before the month, you can use the name of
 the month instead of the numeric representation of the month.

 The following are not accepted ("Illegal Function Call"):

    B# = DateValue# ("30-12-88")
    B# = DateValue# ("30/12/88")

 The following are accepted (the workaround is to use the spelled
 instead of the numeric month):

    B# = DateValue# ("30-Dec-88")
    B# = DateValue# ("30/Dec/88")

 The following are accepted (but month, day, and year must be in
 order):

    B# = DateValue# ("12-30-88")
    B# = DateValue# ("12/30/88")
    B# = DateValue# ("December 30, 1988")

 DateValue# accepts dates between January 1, 1753, and December 31,
 2078.

 Complete Code Example
 ---------------------

 You can run this program with QBX /L DTFMTER.QLB, or link with the
 appropriate DTFMTxx.LIB file if making an .EXE program:

    REM $INCLUDE: 'DATIM.BI'
    d$ = "30-Dec-88"
    PRINT DateValue#(d$)   ' Prints 32507
    d$ = "12/30/88"
    PRINT DateValue#(d$)   ' Prints 32507


 197. PCOPY Can Fail from Page 0 in 43-Line Mode in SCREEN 0

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900214-56 buglist7.00 fixlist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q58792

 In Microsoft BASIC Professional Development System (PDS) version 7.00,
 when in 43-line mode in SCREEN mode 0, using a PCOPY statement to copy
 screen page 0 to some other screen page may fail. If screen page 0 is
 both the visual and active page during the PCOPY statement, it copies
 corrupt information to the other screen page. This problem occurs only
 in SCREEN mode 0 when in 43-line mode and only when PCOPYing from page
 0. It does not occur when PCOPYing from another page to page 0.
 Temporarily setting the active and/or visual page to a screen page
 other than 0 during the PCOPY corrects the problem.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 version 7.00 for MS-DOS. This problem was corrected in BASIC PDS
 version 7.10.

 The following program demonstrates the problem. A string of 3440 X's
 that fills the screen is displayed, then copied from page 0 to page 1.
 The visual page is then set to page 1 to view the information copied
 from page 0. What appears in page 1 is only a few lines of text,
 either at the top or middle of the screen. Setting either the visual
 and/or active screen page to any page other than page 0 corrects the
 problem.

    WIDTH 80, 43
    PRINT STRING$(3440, "X");
    'SCREEN , ,0, 1    'Uncommenting this line corrects the problem
    PCOPY 0, 1
    LOCATE 10, 10: PRINT " HIT ANY KEY TO SWITCH PAGES "
    SLEEP
    SCREEN , ,0, 1
    END


 198. "Unresolved External" Using Wrong Linker with BASIC 7.00, 7.10

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900130-159 S_LINK
 Last Modified:  4-SEP-1990    ArticleIdent: Q58815

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 are shipped with Microsoft
 Segmented-Executable Linker versions 5.05 and 5.10 respectively.
 Because of the newer technology used in these linkers, it is more
 important than ever to use only the linker that comes with the product
 (or a later version of the Segmented-Executable Linker) to link BASIC
 PDS programs.

 Linking BASIC PDS modules with a version of LINK.EXE earlier than
 5.05, such as the Microsoft 8086-Object Linker, can result in "L2029:
 Unresolved external" errors, such as the following:

      B$IsamSetmemDown in file(s):
    C:\BC7\LIB\BCL70ENR.LIB(..\rt\isam.asm)

      B$IsamSetmemBack in file(s):
    C:\BC7\LIB\BCL70ENR.LIB(..\rt\isam.asm)

      B$RestoreEmsState in file(s):
    C:\BC7\LIB\BCL70ENR.LIB(..\rt\isam.asm)

      B$DoIsamTerm in file(s):
    C:\BC7\LIB\BCL70ENR.LIB(..\rt\isam.asm)

      B$FIsamInited in file(s):
    C:\BC7\LIB\BCL70ENR.LIB(..\rt\isam.asm)

 These errors should not occur when linking BASIC PDS modules with
 Microsoft Segmented-Executable Linker versions 5.05 or later.

 A very common mistake is running the Linker from a directory that does
 not contain LINK.EXE and thus invoking an older linker version found
 first in your DOS PATH. You must be sure to have the correct linker
 found in your DOS PATH or in the current directory.


 199. BASIC PDS 7.10 Does Not Support ILINK.EXE Incremental Linker

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900212-106 B_BasicCom docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58816

 Page 593 of the "Microsoft BASIC 7.0: Programmer's Guide" (for 7.00
 and 7.10) incorrectly states that you can use the LINKer switch /INC,
 which sets up your .EXE file for later use with the Microsoft
 Incremental Linker (ILINK.EXE). Microsoft BASIC Professional
 Development System (PDS) Version 7.00 or 7.10 does not support the
 Incremental Linker. This is a documentation error, and the section
 "Preparing for Incremental Linking (/INC)" should be removed from Page
 593.

 ILINK.EXE is also documented on Pages 261-269 (Chapter 14) of the
 "Microsoft CodeView 2.3 and Utilities User's Guide" provided with
 Microsoft BASIC PDS 7.00 and 7.10, but ILINK.EXE is NOT shipped with
 or supported by BASIC PDS 7.00 or 7.10. The reference to BASIC on Page
 263 should be removed.

 Also, the /INC option needs to be added to the table of "Invalid LINK
 Options" on Page 590 of the "Microsoft BASIC 7.0: Programmer's Guide"
 for 7.00 and 7.10.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 ILINK.EXE is shipped with and supported by Microsoft C Version 5.10,
 QuickC Versions 2.00 and 2.01, and Microsoft Macro Assembler Version
 5.10.


 200. BASIC 7.00 "Error Loading Run-Time Module: Incompatible"

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900201-67
 Last Modified: 20-SEP-1990    ArticleIdent: Q58817

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 maintain a date and time stamp for each of their run-time
 modules (BRT70xxx.EXE and BRT71xxx.EXE). This time stamp is inherited
 by the compiled BASIC PDS program linked with a given BASIC PDS
 run-time module. (This information does NOT apply if you compile with
 the BC /O stand-alone option.)

 The result of this inheritance is that the BASIC executable .EXE
 program does not run with a run-time module other than the one it was
 linked with. Attempting to use a BASIC PDS 7.00 or 7.10 run-time
 module other than the one that the .EXE program was linked with
 results in the following error message:

    Error loading run-time module <runtime name>.EXE: Incompatible
    run-time module.

 The time stamp association between BASIC PDS 7.00/7.10 run-time
 modules and executable programs helps ensure that the run-time module
 used by the program actually contains the routines the BASIC
 executable program expects to be able to call.

 For example, assume that you have created the BASIC run-time module
 BRT70ENR.EXE and the run-time library BRT70ENR.LIB during setup, and
 you specify that you do not want to include VGA graphics support
 (which removes the VGA graphics routines by linking the NOVGA.OBJ stub
 file into your run-time module). If you were allowed to execute a
 program that was compiled by another person using a different
 BRT70ENR.LIB run-time library, and that program used VGA graphics
 routines, that program would try to call the graphics routines it
 expected to find at certain locations in the BASIC run-time
 BRT70ENR.EXE. Because the VGA graphics routines will not be present in
 your BRT70ENR.EXE run-time, the code at that location is not going to
 be the expected VGA routine, and the results of such a call are
 unpredictable.


 201. Microsoft Editor Cannot Use QuickBASIC Extended Help Files

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900209-75 s_editor S_PWB
 Last Modified:  6-SEP-1990    ArticleIdent: Q58819

 Microsoft Editor (M.EXE and MEP.EXE) version 1.20, which is included
 with Microsoft BASIC Professional Development System (PDS) version
 7.00 for MS-DOS and MS OS/2, cannot use the QuickBASIC Extended
 (QBX.EXE) Microsoft Advisor online Help system files. (The QBX.EXE
 editor environment is also included with BASIC PDS 7.00.)

 The online Help files used by QBX.EXE are of the wrong size and format
 to be used by the M.EXE or MEP.EXE editor.

 No version of the M.EXE or MEP.EXE editor can use the Microsoft
 Advisor online Help files used by QBX.EXE.

 This problem is eliminated by using PWB (Programmer's WorkBench),
 which comes with Microsoft BASIC PDS 7.10. PWB.EXE replaces the
 M.EXE/MEP.EXE editor, and improves functionality.

 The help files of QBX.EXE and PWB.EXE can be created and modified
 using HELPMAKE.EXE, the Microsoft Help File Creation Utility.


 202. Cannot Link PROISAM.LIB or PROISAMD.LIB into Quick Library

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900205-118
 Last Modified: 27-FEB-1990    ArticleIdent: Q58922

 The libraries PROISAM.LIB and PROISAMD.LIB included with Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS-DOS
 cannot be linked into Quick libraries to be used by the QuickBASIC
 Extended Environment (QBX.EXE).

 Trying to link PROISAM.LIB or PROISAMD.LIB into a Quick library
 generates the following error message:

    LINK : fatal error L4050: too many public symbols for sorting

 The terminate-and-stay-resident (TSR) programs PROISAM.EXE and
 PROISAMD.EXE are the programs that make the ISAM engine available to
 QBX. PROISAM.EXE or PROISAMD.EXE must be run prior to invoking QBX.EXE
 if you want to use ISAM statements in your BASIC program.

 PROISAMD.EXE supports all the ISAM routines. PROISAM.EXE does not
 support all of the features of ISAM because for many database
 applications certain features are not needed. It does not contain the
 "data dictionary" statements -- CREATEINDEX, DELETEINDEX, and
 DELETETABLE. It contains a restricted version of the OPEN...FOR ISAM
 statement that opens a database or table but does not create it if it
 does not already exist.


 203. CONFIG.SYS IOPL=YES to Run CodeView CVP.EXE in Protected Mode

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | S_CodeView
 Last Modified: 27-FEB-1990    ArticleIdent: Q58923

 To run the Microsoft CodeView debugger (CVP.EXE) in OS/2 protected
 mode, you must have the following line in your CONFIG.SYS file in MS
 OS/2:

    IOPL=YES

 This information applies to the Microsoft CodeView debugger (CVP.EXE)
 shipped with Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2.


 204. Must LINK 87.LIB Stub File in .OBJ List, NOT in the .LIB List

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900215-30
 Last Modified:  1-MAR-1990    ArticleIdent: Q58953

 Page 612 of the "Microsoft BASIC 7.0: Programmer's Guide" correctly
 states the following concerning the .LIB stub files (87.LIB,
 NOTRNEMR.LIB, and NOTRNEMP.LIB):

    Stub files (including the .LIB files listed) are specified in the
    <objfiles> field of LINK. You must supply the /NOE
    (/NOEXTDICTIONARY) option when linking any of the stub files.

 If you mistakenly link the 87.LIB, NOTRNEMR.LIB, or NOTRNEMP.LIB stub
 file in the .LIB area instead of the .OBJ area of the LINK.EXE command
 line, the stub file will be ignored, and no code is excluded from your
 .EXE file.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Example of Using 87.LIB Stub File
 ---------------------------------

 To remove floating-point-coprocessor emulation code from a stand-alone
 BASIC PDS 7.00 .EXE program, the 87.LIB file must be placed in the
 .OBJ area in the LINK.EXE command line, as follows:

    BC test/O;
    LINK test+87.LIB /NOE;

 The resulting .EXE program requires the presence of an 8087, 80287, or
 80387 (80x87) numeric coprocessor.

 87.LIB should be placed in the linker's objects (.OBJ) list, NOT in
 the libraries (.LIB) list. If you mistakenly link the 87.LIB file in
 the .LIB area of the LINK.EXE command line, 87.LIB is ignored, and no
 code is excluded from your .EXE file. (The resulting .EXE program will
 run on machines with or without a coprocessor.) Below is an example of
 the WRONG way to link the 87.LIB stub file:

    LINK test,,,87.LIB /NOE;

 This is wrong because the linker first searches the default BASIC
 libraries for the references it needs and only then searches your
 listed .LIB files for unresolved references (if any). For stub files
 to work, they must appear in the .OBJ area of the LINK command line to
 resolve routine references before the default library reference
 search.


 205. "R6002 - Floating Point Not Loaded" Without Math Coprocessor

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900215-15
 Last Modified: 27-FEB-1990    ArticleIdent: Q58954

 A BASIC PDS 7.00 program gives "run-time error R6002 - Floating point
 not loaded" on a machine WITHOUT a coprocessor when the BASIC run-time
 library or .EXE program is created with coprocessor-only support.
 Coprocessor-only support means that the BASIC run-time routines
 require an 80x87 (8087, 80287, or 80387) math coprocessor to run.

 The R6002 error is an initialization error that cannot be trapped in a
 BASIC program.

 Implementing coprocessor-only support in an .EXE program depends upon
 whether you compile with or without the BC /O (stand-alone .EXE)
 option, as follows:

 1. If you compile WITHOUT BC /O, BASIC programs require a run-time
    module (BRT70xxx.EXE) to be present at run time. If you want to
    build a BASIC run-time module and BRT70xxx.LIB file with
    coprocessor-only support, you must invoke the BUILDRTM.EXE utility
    with the /FPi87 switch. For example:

       BUILDRTM /LR /FPi87 /DEFAULT

    (See Page 611 of "Microsoft BASIC 7.0: Language Reference" for an
    explanation of the options of the BUILDRTM.EXE utility.) You can
    then link with your new coprocessor-only run-time module, as
    follows:

       BC test;
       LINK IMPORT+test,test,,{newlibname} /NOE;

 2. If you compile WITH the BC /O (stand-alone .EXE) option, you can
    directly link your BASIC .OBJ file with the 87.LIB stub file. For
    example:

       BC test /O;
       LINK test+87.LIB /NOE;


 206. Twice-Called String FUNCTION May Fail in QB/QBX Quick Library

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10 B_QuickBas
 Last Modified:  6-AUG-1990    ArticleIdent: Q58955

 In the QBX.EXE or QB.EXE environment, a STATIC string FUNCTION located
 in a Quick library (.QLB) that is invoked twice within the same PRINT
 or assignment statement may give incorrect results. This problem only
 exists with a STATIC string FUNCTION in a Quick library that is
 invoked twice in one statement with a plus sign (+, for string
 concatenation) connecting the two invocations. This problem can be
 worked around easily by using temporary variables and splitting the
 statement into two statements. The problem does not occur in compiled
 and linked .EXE programs.

 Microsoft has confirmed this to be a problem in the QBX.EXE
 environment shipped with Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS, in the QB.EXE
 environment shipped with Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, and in the QB.EXE environment shipped with Microsoft
 QuickBASIC versions 4.00, 4.00b, and 4.50 (buglist4.00, buglist4.00b,
 buglist4.50) for MS-DOS. We are researching this problem and will post
 new information here as it becomes available.

 Code Example
 ------------

 The following code example demonstrates the problem:

    FUNCTION Foop$(x$) STATIC
      Foop$ = x$ + "Z"
    END FUNCTION

 The module above should be compiled and built into a Quick library,
 then QBX should be started with that Quick library. Calling this
 FUNCTION twice in a row gives the incorrect results, as follows:

    DECLARE FUNCTION Foop$(x$)
    PRINT Foop$("abc")+Foop$("def")

 This example prints "defZdefZ" instead of correctly printing
 "abcZdefZ".


 207. ListBox Redefines Window 1 and Closes All Windows When Done

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900209-66
 Last Modified: 26-FEB-1990    ArticleIdent: Q58957

 The ListBox function of the WINDOW.BAS toolbox file is not designed to
 be used when other windows are already open. This is because ListBox
 redefines Window 1 and closes all windows when it is finished
 executing. This is not a problem, but a limitation of the ListBox
 function.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 This behavior of the ListBox function can be changed by modifying two
 statements, the one that opens and redefines Window 1 and the one that
 closes all the windows at the end of the function.

 The statement that opens and redefines Window 1 is as follows:

    WindowOpen 1, 4, StartRowPos, 20, StopRowPos, 0, 7, 0, 7, _
        15, 0, 0, 0, 1, 1, ""

 The number mentioned immediately after "WindowOpen" (1 in this case)
 is the handle to the window that will be opened. If Window 1 already
 exists, it will be redefined and become the modal window that is used
 by the ListBox function. This statement must be changed so that the
 next available window handle is used, not always Handle 1. The
 function for getting this handle is WindowNext. Therefore, the
 modified WindowOpen statement would be as follows:

    WindowOpen WindowNext, 4, StartRowPos, 20, StopRowPos, 0, 7, 0, 7, _
       15, 0, 0, 0, 1, 1, ""

 Now when the statement is executed, the next available window handle
 is used instead of always using Handle 1. This ensures that a window
 that is already open will not be redefined.

 The statement that closes all of the windows at the end of the
 function is as follows:

    WindowClose 0

 Passing a 0 to the WindowClose statement closes all open windows.
 Passing any other handle closes just the window with that handle. This
 statement must be changed so that only the current window (the one
 being used by ListBox) is closed. The function that returns the handle
 of the current window is WindowCurrent. Therefore, the above statement
 should be changed to the following:

    WindowClose WindowCurrent

 When the above two changes have been made to the ListBox function, it
 can safely be used with other open windows.

 The following sample program illustrates how to use the ListBox
 function. It opens a window and then a button in that window. Then it
 invokes ListBox, passing it an array of strings to display. After the
 user has finished with the list, the WindowDo procedure is invoked,
 which polls the mouse, waiting for the user to click on the button
 opened in Window 1. When it is clicked, the program ends. However, if
 the above changes have not been made to the ListBox function, Window 1
 is redefined by the window opened by ListBox. Thus, the first window
 opened disappears, along with its button. After ListBox is finished
 executing, it closes the window that it created, leaving no windows
 for the WindowDo procedure to operate on. This causes the program to
 end immediately.

 Code Example
 ------------

 'The following INCLUDE, COMMON SHARED, and DIM statements are
 'generally needed for working with the toolbox library routines.

 '$INCLUDE: 'general.bi'
 '$INCLUDE: 'mouse.bi'
 '$INCLUDE: 'menu.bi'
 '$INCLUDE: 'window.bi'

 COMMON SHARED /uitools/ GloMenu           AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle()        AS MenuTitleType
 COMMON SHARED /uitools/ GloItem()         AS MenuItemType
 COMMON SHARED /uitools/ GloWindow()       AS WindowType
 COMMON SHARED /uitools/ GloButton()       AS ButtonType
 COMMON SHARED /uitools/ GloEdit()         AS EditFieldType
 COMMON SHARED /uitools/ GloStorage        AS WindowStorageType
 COMMON SHARED /uitools/ GloWindowStack()  AS INTEGER
 COMMON SHARED /uitools/ GloBuffer$()

 DIM GloTitle(MAXMENU)           AS MenuTitleType
 DIM GloItem(MAXMENU, MAXITEM)   AS MenuItemType
 DIM GloWindow(MAXWINDOW)        AS WindowType
 DIM GloButton(MAXBUTTON)        AS ButtonType
 DIM GloEdit(MAXEDITFIELD)       AS EditFieldType
 DIM GloWindowStack(MAXWINDOW)   AS INTEGER
 DIM GloBuffer$(MAXWINDOW + 1, 2)

 DIM text$(1 TO 15)

 FOR i = 1 TO 15                  'Load string array with some
 text$(i) = STRING$(15, i + 64)   'strings. This will be the list
 NEXT i                           'passed to the ListBox function.

 CLS
 CALL WindowInit   'Initialize window routines
 CALL MouseInit    'Initialize mouse routines

 'Open window #1.
 CALL WindowOpen(1, 3, 10, 20, 70, 14, 1, 14, 1, 15, false, false,
 false, false, 1, "Window")

 'Open button #1 in window #1.
 CALL ButtonOpen(1, 1, "OK", 10, 29, 0, 0, 1)

 'Make the mouse cursor visible.
 CALL MouseShow

 'Put up the list box.
 a% = ListBox(text$(), 15)

 'Trap the clicking of the button.
 CALL WindowDo(0, 0)
 END


 208. Size and Memory Limits in QBX.EXE in BASIC PDS 7.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900215-76
 Last Modified: 26-FEB-1990    ArticleIdent: Q58960

 The QBX.EXE environment offers programming versatility, but has
 limitations to keep file size and complexity manageable. As a result,
 you may reach these limits in some situations.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The information below lists the boundaries that you may encounter in
 the QBX.EXE environment. Most of these limits also apply to the BC.EXE
 compiler. This information was taken from the Microsoft Advisor online
 Help system in QBX.EXE, under "Contents - QBX Memory and Capacity."

 ---------------------------------------------------------------
 QBX Environment Limits - Names, Strings, and Numbers
 ---------------------------------------------------------------
                               Maximum               Minimum

 Variable name length          40 characters             1
 String length                 32,767 characters         0
 Integers                      32,767               -32,768
 Long Integers                 2,147,483,647       -2,147,483,648
 Single precision numbers
                  (positive)   3.402823E+38         2.802597E-45
 Single precision numbers
                  (negative)   -2.802597E-45       -3.402823E+38
 Double precision numbers
                   (positive)
                     Maximum:
                          1.797693134862315D+308
                     Minimum:
                          4.940656458412465D-324
 Double precision numbers
                  (negative)
                     Maximum:
                         -4.940656458412465D-324
                     Minimum:
                         -1.797693134862315D+308
 Currency
                     Maximum:
                          922337203685477.5807
                     Minimum:
                         -922337203685477.5808

 ----------------------------------------------------------------
 QBX Environment Limits - Arrays
 ----------------------------------------------------------------
                                   Maximum              Minimum
 Array size (all elements)
   Static                          65,535 bytes (64 K)     1
   Dynamic                         Available memory
 Number of dimensions allowed      60                      1
 Dimensions allowed if unspecified 8                       1
 Array subscript value             32,767            -32,768

 Note: The maximum range between array subscript values is 32,767.

 -----------------------------------------------------------------
 QBX Environment Limits - Procedures and Files
 -----------------------------------------------------------------
                                   Maximum              Minimum

 Procedure size (interpreted)      65,535 bytes (64 K)     0
 Number of arguments passed        60 interpreted          0
 Nesting of include files          5 levels                0
 Module size (compiled)            65,535 bytes (64 K)     0
 DATA file numbers                 255                     1
 DATA file record number           2,147,483,647           1
 DATA file record size (bytes)     32,767 bytes (32 K)     1
 DATA file size                    Available disk space    0
 Path names                        127 characters          1
 Error message numbers             255                     1

 -----------------------------------------------------------------
 QBX Environment Limits - Editing
 -----------------------------------------------------------------
                                       Maximum         Minimum

 Text box entry                        127 chars          0
 Search for string                     127 chars          1
 Change to string                      127 chars          0
 Place markers                           4                0
 Watchpoints and/or watch expressions   16                0
 Number of lines in Immediate window    10                0
 Characters in View window on one line  255               0
 Length of COMMAND$ string              124 characters    0


 209. UI Toolbox Shortcut Keys Documentation Error in BASIC 7.00

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900220-48 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q58963

 On Page 496 of the "Microsoft BASIC 7.0: Language Reference" (for 7.00
 and 7.10) two of the procedure names under "Shortcut Keys" (for
 MENU.BAS) are incorrectly stated. ShortCutKeyDelete$ should be
 ShortCutKeyDelete and ShortCutKeyEvent$ should be ShortCutKeyEvent.
 Also on the same page, the WindowBorder function (detailed on Page 568
 of the same manual) should be added to the "Define Windows" summary
 (for WINDOW.BAS) in Table 3.5.

 This information applies to the User Interface (UI) Toolbox in
 Microsoft BASIC Professional Development System (PDS) Versions 7.00
 and 7.10 for MS-DOS.


 210. Bad Integer Output Using DEF FN, VAL, FOR-NEXT in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900217-5 buglist7.00 fixlist7.10
 Last Modified:  1-AUG-1990    ArticleIdent: Q59008

 When run as an .EXE program (compiled with BC.EXE), the program below
 gives incorrect output in Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and MS OS/2. The same program
 gives correct output when run in the QBX.EXE environment or compiled
 with the BC /D option.

 The program fails when it assigns an integer array (which is
 subscripted by a FOR...NEXT loop counter) to the VAL of a DEF FN
 string function operating on a temporary string that was assigned to
 an array element that is subscripted by the FOR...NEXT loop counter.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) version 7.00. This problem was
 corrected in BASIC PDS version 7.10.

 This problem does not occur with an .EXE compiled in QuickBASIC
 version 4.50 or earlier.

 The program below outputs "2 2" instead of "1 2" from an .EXE program.
 (The problem occurs whether compiled as a stand-alone .EXE or as an
 .EXE requiring the BRT module). This problem is corrected by doing any
 one of the following:

 1. Compiling with the BC /D option.

 2. Removing the DEFINT A-Z line.

 3. Replacing n (the ending value of the FOR...NEXT loop counter) with
    the constant 2 in the FOR...NEXT statement.

 4. Eliminating the use of the temporary (placeholder) variable t$ by
    putting s$(i) in place of it in the VAL function.

 5. Replacing d(i) with a nonarray (scalar) variable.

 Code Example
 ------------

    DEFINT A-Z
    DIM s$(1 TO 2), d(1 TO 2)
    DEF FNa$ (x$)
    FNa$ = x$
    END DEF
    CLS
    n = 2
    s$(1) = "1"
    s$(2) = "2"
    PRINT
    FOR i = 1 TO n
       t$ = s$(i)
       d(i) = VAL(FNa$(t$))
    ' One workaround is to use:   d(i) = VAL(FNa$(s$(i)))
       PRINT d(i);
    NEXT
    END


 211. "BASIC 7.0: Reference" Correction for CALL Statement Example

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900217-3 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q59073

 The corrections below apply to the Example program for the CALL
 statement (for calling BASIC procedures) on Page 32 of the "Microsoft
 BASIC 7.0: Language Reference" manual for 7.00 and 7.10:

 1. The following incorrect sentence should be changed to say "the
    24th line" instead of "the 25th line":

       The following example uses the CALL statement to call a SUB
       procedure that prints a message on the 25th line of the
       display....

 2. The following remark after the LOCATE 24,1 statement should be
    changed to say "the 24th line" instead of "the 25th line":

       LOCATE 24, 1 ' Move cursor to 25th line of display.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 212. BASIC 7.00 ISAM Cannot Store Single-Precision Numbers

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  2-MAR-1990    ArticleIdent: Q59289

 When using the ISAM file-handling feature of Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS, you
 cannot use a single-precision variable in the TYPE ... END TYPE record
 structure. To store real numbers (numbers with a decimal point), you
 must use a CURRENCY or a double-precision variable. (You may also use
 an INTEGER and a LONG integer if you do not need a number with a
 decimal point.)

 This is not a software problem, but is a design limitation of BASIC
 PDS 7.00.

 For more information on this topic, see Pages 333-334 of the
 "Microsoft BASIC 7.0: Programmer's Guide."


 213. BASIC and C, /FPa, LINK L2025 "Symbol Defined More Than Once"

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# S900202-109 S_C buglist6.00 buglist6.00b buglist7.00
 Last Modified: 18-OCT-1990    ArticleIdent: Q59321

 When linking BASIC and C, where the C routine uses math functions
 (such as SIN, COS) and was compiled with the /FPa (alternate math)
 option and where the BASIC program was compiled with the /FPa option
 and without the /O (stand-alone) option, several "L2025 Symbol defined
 more than once" errors will occur. These errors are not affected by
 /NOD or /NOE LINK options.

 Any of the following three workarounds corrects the problem:

 1. Compile the BASIC program with BC /o (stand-alone).

 2. Compile BASIC and C with (default) BC /FPi.

 3. Call all math functions from BASIC. (C can call BASIC externs to do
    math -- see below.)

 Microsoft has confirmed this to be a problem in Microsoft C Compiler
 versions 5.00 and 5.10 (buglist5.00, buglist5.10), in Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2, and in
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 The following code example causes the "symbol defined more than once"
 errors when compiled as listed. The following are the compile and link
 lines for the BASIC and C programs:

    BC /FPa testb;
    CL -c -AL -FPa test.c ;
    LINK /NOD /NOE testb+test,,,brt70anr llibcar;

 When the code below is compiled and LINKed as specified, the following
 LINK errors will occur:

    llibcar.LIB(fcall.ASM) : error L2025: __fpmath : symbol defined
       more than once

    llibcar.LIB(..\ccalle.ASM) : error L2025: __fpsignal : symbol defined
       more than once

 For more information about calling C from BASIC, search in this
 Knowledge Base using the following word:

    BAS2C

 BASIC Program, TESTB.BAS
 ------------------------

 DECLARE SUB test CDECL
 CALL test

 'Function used by C for workaround #3
 FUNCTION BasSin#(a AS DOUBLE)
    BasSin#=SIN(a)
 END FUNCTION

 C Program, TEST.C
 -----------------

 #include <stdio.h>

 extern double pascal BasSin(double near *);  // BASIC function for
                                              // workaround #3
 void test()
 {
 double d=1.2;
 printf("%f",sin(d));           // Comment this line and
 //printf("%f",BasSin(&d));     // uncomment this line for workaround #3
 }


 214. PRINT Ignored After PRINT CURRENCY Variable in QBX.EXE 7.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q59398

 The program below demonstrates a problem with executing a PRINT
 statement to produce a blank line.

 After printing a variable or array element that has been dimensioned
 as a CURRENCY data type, a blank line cannot be produced by issuing a
 successive PRINT. This problem occurs only within the QBX.EXE
 environment, and does not occur with programs compiled with BC.EXE.

 Microsoft has confirmed this to be a problem in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS. This problem was corrected in BASIC PDS
 version 7.10.

 Code Example
 ------------

    DIM A AS CURRENCY
    A = 10
    PRINT A
    PRINT
    PRINT "Where did the space go?"
    END

 Output
 ------

    10
    Where did the space go?

 Workaround Code Example
 -----------------------

 Each additional PRINT statement will correctly produce a blank line,
 as shown in the following program:

    DIM A AS CURRENCY
    A = 10
    PRINT A
    PRINT
    PRINT
    PRINT "A blank line was printed"

 Output
 ------

    10

    A blank line was printed


 215. BASIC 7.0 UEVENT Example Causes Subsequent Programs to Hang

 Product Version(s): m7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900222-46 docerr buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q59399

 The sample program for trapping a user-defined event on Pages 310-312
 of the "Microsoft BASIC 7.0: Programmer's Guide" for Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 contains
 a misprint, but even if corrected, this sample program may cause the
 computer to hang after it is run.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10. We are
 researching this problem and will post new information here as it
 becomes available.

 Page 311 of "Microsoft BASIC 7.0: Programmer's Guide" contains a
 misprint in the MASM programming example for trapping a user-defined
 event. If the code is not corrected, an "A2009: Symbol not defined"
 error will result when the code is assembled.

 The last section of code for this example reads as follows:

     RestInt  proc  uses ds
        lds dx, cs:OldVector
        mov  x, 251CH          ; <== this line contains the misprint

 To correct the code, make the following change:

     RestInt  proc  uses ds
        lds dx, cs:OldVector
        mov ax, 251CH          ; <== change "x" to "ax"

 However, even when this misprint is corrected, if the BASIC program is
 compiled so that it requires a run-time module or if the assembly code
 is put into a Quick library, running the program may cause the
 computer to hang. The problem does not occur if the BASIC program is
 compiled with the BC /O option.

 The following compiling and linking steps will reproduce the problem:

 1. Assemble the MASM code as follows:

       MASM MASMPROG.ASM;

 2. Compile the BASIC code so that it requires a run-time module (no
    /O) and enables event trapping (/V). If the program is compiled as
    a stand-alone program (with the /O option), the problem does not
    exist.

       BC BASPROG.BAS /V;

 3. LINK the program using the BASIC PDS 7.00 or 7.10 linker, as
    follows:

       LINK BASPROG.OBJ + MASMPROG.OBJ;

 4. Run the program.

 5. The computer may hang instantly or may hang after attempting to run
    another program, such as QBX.EXE.


 216. CHDIR & SHELL "CHDIR" in OS/2 Protected Mode Differs from DOS

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900226-124
 Last Modified:  9-MAR-1990    ArticleIdent: Q59400

 In OS/2 protected mode, if a BASIC program issues a CHDIR, the command
 will affect only the current BASIC process; other processes in the
 system will not be affected. However, this behavior changes when a
 SHELL statement is issued because a SHELL statement executes a copy of
 CMD.EXE. The SHELLed program is considered to be a "child process" of
 the program that issued the SHELL. If the SHELLed program executes
 OS/2's CD or CHDIR command, only the SHELLed process will be affected,
 not the currently running BASIC program that issued the SHELL. This is
 not a problem with BASIC under OS/2; it is correct behavior that is
 dictated by the design of OS/2.

 This information applies to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for OS/2 and to Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for OS/2.

 The OS/2 API function, DosChDir(), has the same effect as the BASIC
 CHDIR statement. For both of these, the currently executing BASIC
 process is changed, but the parent process (which started the BASIC
 process) is unchanged. Similar to CHDIR, the ENVIRON statement (and
 other statements that modify the OS/2 protected-mode environment) has
 no effect on the parent process.

 This is a feature of the protected mode of OS/2; child processes
 cannot affect the parent process's environment. This represents a
 notable change from DOS. In DOS, there are "programs," but not
 "processes" as in OS/2. In DOS, you cannot have multiple programs
 running simultaneously. There is only one program running and
 therefore it is reasonable to assume that any change directory command
 will change the current DOS directory for both the parent and child in
 a program. Changing the "current directory" under DOS changes it for
 the entire operating system -- the change is global. This means the
 change also takes effect for any programs run later unless the user or
 program specifically changes the current directory. In OS/2 protected
 mode where there can be many programs running at once, having one
 global working directory that could be changed by any process at any
 moment would not be reasonable.

 Code Example
 ------------

 In OS/2 protected mode, the following code example has no effect on
 the screen group that starts the EXE file, but the FILES statement
 illustrates that the directory has been changed for the current
 process:

 a$ = "\bc7"
 CHDIR a$            'This only affects the current BASIC process
                     'API Function DosChDir has same effect as CHDIR
 'SHELL "cd "+a$     'This only affects the SHELLed process. After
 FILES "*.*"         'returning from the SHELL, it has no effect.

 In DOS, either the CHDIR statement or the commented SHELL statement in
 the above program will change the directory for the DOS command line.


 217. QBX & BC /Es Option Shares Expanded Memory with Mixed Language

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900227-66 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q59402

 This article discusses the /Es (share expanded memory) option for
 QBX.EXE and BC.EXE in Microsoft BASIC Professional Development System
 (PDS) Versions 7.00 and 7.10 for MS-DOS.

 The BC /Es Option
 -----------------

 The /Es option for BC.EXE needs to be added to the list of BC options
 on Page 559 of the "Microsoft BASIC 7.0: Programmer's Guide" for
 versions 7.00 and 7.10.

 The BC /Es option is correctly described on Page 608 of the "Microsoft
 BASIC 7.0: Language Reference" (Appendix C: "Command-Line Tools Quick
 Reference") for 7.00 and 7.10. The BC /Es option is also correctly
 documented as follows in the Microsoft Advisor online Help system in
 QBX.EXE, found by choosing Contents from the Help menu, then selecting
 "BC Command Line":

    "HELP: BC Command Line"
    /Es       Allows you to share expanded memory between BASIC and
              mixed-language routine(s) that make use of expanded memory.
              Specify /Es when you are going to use a mixed-language
              routine that makes use of expanded memory.

 Note: The only way an .EXE program compiled with BC.EXE can use
 expanded memory is with ISAM file buffers, or when linked to use
 overlays, as described in a separate article found with the following
 query:

    how and LINK and overlays and BASIC and 7.00

 The QBX /Es Option
 ------------------

 QBX.EXE, the programming environment included with Microsoft BASIC
 Professional Development System (PDS) Version 7.00, can use expanded
 memory for procedures smaller than 16K.

 Note that the QBX /Es option cannot be used together with the /Ea
 option. (The QBX /Ea option lets each non-variable-length string array
 smaller than 16K use one 16K page of expanded memory.)

 By invoking QBX with the /Es switch, QBX can share expanded memory
 with mixed-language routines (in Quick libraries) that make DOS
 interrupts to access expanded memory.

 The QBX /Es switch is correctly documented on Page 626 of the
 "Microsoft BASIC 7.0: Language Reference," and in the Microsoft
 Advisor online Help system in QBX.EXE, found by choosing Contents from
 the Help menu, then selecting "QBX Command Line":

    "HELP: QBX Command Line"
    /Es      Allows you to share expanded memory between QBX and
             Quick libraries or mixed-language routines that make use
             of expanded memory. Specify /Es when you are using a
             Quick library or mixed-language routine that makes use
             of expanded memory. Do not use /Es with the /Ea option.


 218. Illegal DIM x AS STRING*<Variable> Can Hang QB.EXE or QBX.EXE

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 fixlist7.10 B_QuickBas
 Last Modified: 20-SEP-1990    ArticleIdent: Q59405

 Illegally defining fixed-length strings (DIM AS STRING * N%) with
 integer variables (N%) can in some cases cause problems inside the
 QB.EXE and QBX.EXE environments. (The length of fixed-length strings
 must be defined with constants, not variables.)

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 (buglist4.00,
 buglist4.00b, buglist4.50); in the QB.EXE environment of Microsoft
 BASIC Compiler versions 6.00 and 6.00b; and in the QBX.EXE environment
 of Microsoft BASIC Professional Development System (PDS) version 7.00
 for MS-DOS. This problem was corrected in the QBX.EXE environment of
 BASIC PDS 7.10.

 To find a related article on this topic, query in this Knowledge Base
 on the following words:

    invalid and constant and variable and fixed and length and string

 The QB.EXE environment of QuickBASIC 4.00 and 4.00b runs Examples 1
 and 2 (below) without hanging; however, it fails to flag the variable
 on the STRING * flen declaration as an error.

 In both Examples 1 and 2, getting rid of flen and defining the string
 with a constant value (x AS STRING * 82) corrects the problem. You can
 also work around the problem by making flen a CONST constant, for
 example:

    CONST flen = 82

 Also, by changing flen to a noninteger variable, the QB.EXE or QBX.EXE
 environment correctly flags the error. BC.EXE (the command-line
 compiler) always correctly flags the error.

 Example 1
 ---------

 When the following program is run inside the QuickBASIC Extended
 (QBX.EXE) 7.00 environment, the error message "INVALID CONSTANT" is
 flagged on the line "flen = 82" instead of on the DIM line:

    DEFINT A-Z
    flen = 82
    DIM x AS STRING * flen

 Example 2
 ---------

 When the following program is run in QB.EXE 4.50 or QBX.EXE 7.00, the
 computer may hang, or the error message "STRING SPACE CORRUPT" may
 display and the computer may exit back to DOS:

    DEFINT A-Z
    flen = 82
    TYPE recordtype
       x AS STRING * flen
    END TYPE
    DIM datetest AS recordtype


 219. QB.EXE/QBX.EXE "Identifier Too Long" Using User-Defined TYPE

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10 B_QuickBas
 Last Modified: 20-SEP-1990    ArticleIdent: Q59429

 Inside the QuickBASIC environment (QB.EXE or QBX.EXE), an "Identifier
 Too Long" error is incorrectly generated under the following
 circumstances:

 1. Create a user-defined TYPE (record). Give it one field with a long
    name (20 to 40 characters).

 2. DIMension a variable of that TYPE. Give the variable a long name
    (20 to 40 characters).

 3. Use the variable in some statement in the program and run the
    program.

 4. If the length of the entire identifier (record name plus the field
    name) is longer than forty characters, an "Identifier Too Long"
    error message is generated in the environment.

 This error occurs in QB.EXE and QBX.EXE, but does NOT occur with
 BC.EXE.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 (buglist4.00,
 buglist4.00b, buglist4.50); in the QB.EXE environment of Microsoft
 BASIC Compiler versions 6.00 and 6.00b; and in QuickBASIC Extended
 (QBX.EXE), the extended environment provided with Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10. We are
 researching this problem and will post new information here as it
 becomes available.

 When using TYPEd variables, both parts of the variable, the variable's
 name and its field name, are supposed to have a limit of 40
 characters. This means that the total possible length of a TYPEd
 variable when used in a statement is 80 characters.

 This problem can be worked around by either shortening the name of the
 variable, shortening the name of the field in the TYPE, or by placing
 the single variable into an array of that TYPE.

 Code Example
 ------------

 TYPE temp
   '012345678901234567890123456789; Forty characters is a legal name:
    thisisatesttoobutthisistoolong AS INTEGER
 END TYPE

 DIM thisisatest AS temp

 ' The following causes an "identifier too long" error
 ' when the entire name exceeds forty characters.
 '012345678901234567890123456789012345678901
  thisisatest.thisisatesttoobutthisistoolong = 10

 DIM thisisatest(1) AS temp

 'If you make "thisisatest" an array instead of a single type
 'variable the problem is eliminated.
 thisisatest(1).thisisatesttoobutthisistoolong = 10


 220. 3 Cases Where DIR$ Gives "Illegal Function Call" in BASIC 7.00

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q59430

 Page 107 of the "Microsoft BASIC 7.0: Language Reference" manual (for
 7.00 and 7.10) incorrectly states that you can only receive "Illegal
 Function Call" using the DIR$ function if you don't specify a
 filespec$ the first time you call DIR$.

 However, the DIR$ function returns an "Illegal Function Call" in the
 following three circumstances:

 1. Invoking DIR$ for the first time without a filespec$ parameter
    causes an "Illegal Function Call" error.

 2. If you invoke DIR$ with a filespec$ and no matching files are found
    (it returns a null string -- ""), if you then invoke DIR$ another
    time without the filespec$ parameter, you will receive an "Illegal
    Function Call" error. In other words, you must call DIR$ with a
    filespec$ until a match is found. After that, DIR$ can be called
    again with no filespec$ to get the next filename in the list of
    files found.

 3. Once the entire list of matched file names has been retrieved,
    using DIR$ without a filespec$ correctly returns a null string
    telling you that the end of the list has been reached. Invoking
    DIR$ one more time after that point generates an "Illegal Function
    Call." In other words, once you run out of files that matched your
    original filespec$, you must call DIR$ with a filespec$ again until
    another match is achieved.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The code example below demonstrates that when DIR$ is used
 incorrectly, it generates an "Illegal Function Call." If you comment
 out DIR$ after the WHILE loop, the program runs correctly.

 The DIR$ function is a new function introduced in Microsoft BASIC PDS
 7.00. It is designed to let you find files and browse through
 directories looking for files without having to use SHELL, as in
 earlier versions of BASIC. DIR$ takes a filespec$ parameter that is
 very similar to the parameters that can be passed to the DIR command
 found in MS-DOS or OS/2.

 Code Example
 ------------

    DIM test(200) AS STRING * 12
    CLS
    temp$ = DIR$("*.*")
    count = 0
    WHILE temp$ <> "" ' When it returns null,
                      ' the end of the list has been reached.
       test(count) = temp$
       count = count + 1
       PRINT temp$
       temp$ = DIR$
    WEND
    PRINT DIR$       ' If this line is left here, it will cause the error
                     ' "Illegal Function Call" to occur.
    END


 221. 7.10 Correction for OPEN COM Transfer & Receive Buffer; TB, RB

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900217-4 docerr
 Last Modified: 16-JAN-1991    ArticleIdent: Q59431

 This article corrects three documentation errors in the description
 of the Transfer Buffer (TB[n]) and Receive Buffer (RB[n]) options for
 the OPEN COM statement on page 240 of the "Microsoft BASIC 7.0:
 Language Reference" manual for BASIC PDS versions 7.00 and 7.10.

 Also, page 559 of "Microsoft BASIC 7.0: Programmer's Guide"
 incorrectly states that "the transmission buffer is allocated 128
 bytes for each communications port." This should be changed to "512
 bytes" for the default transmission buffer size.

 To illustrate the documentation corrections (listed below), consider
 the following program sequence. PROG1.EXE is started from the DOS or
 OS/2 command line. PROG1 sets the receive-buffer size to 4096 in the
 OPEN COM statement, CLOSEs the communications port, and CHAINS to
 PROG2.EXE. When PROG2 OPENs the COM port, if PROG2 does not use the RB
 parameter, the size of the receive buffer will still be 4096. This is
 true whether you compile with /O or use the BRTxxx.EXE run-time
 module.

 Note that the size of the transmit buffer (TB) in PROG1.EXE never
 affects the size of the transmit buffer in PROG2.EXE. The size of the
 transmit-buffer is not transferred across a CHAIN. (This is by
 design.)

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The following are three documentation errors in the description of the
 Transfer Buffer (TB[n]) and Receive Buffer (RB[n]) options for the
 OPEN COM statement on page 240 of the "Microsoft BASIC 7.0: Language
 Reference" manual:

 1. For the TB[n] option, the first sentence is incorrect, as follows:

       Sets the size of the receive buffer to n bytes.

    This sentence should be changed to read as follows:

       Sets the size of the transmit buffer to n bytes.

 2. For the TB[n] option, the last sentence incorrectly describes the
    default transmit buffer size, as follows:

       The default value, if n or the TB option is omitted, is the
       current receive buffer size.

    This sentence should be changed to read as follows:

       The default value, if n or the TB option is omitted, is 512
       bytes.

    (Note: The default size for the transmit buffer is 512 bytes; the
    only way to change this size is with the TB option in the OPEN COM
    statement. The transmit-buffer size is never affected by any
    receive-buffer options.)

 3. The description for the RB[n] option should be supplemented to say
    that the receive buffer size of the program currently being
    executed, if not changed by the RB in the OPEN COM statement or by
    the /C:n option on the QB or BC command line, will be the same as
    for the program from which the current program was CHAINed (if any)
    with the CHAIN statement.

 The OPEN COM statement can open the device names "COM1:" and "COM2:".


 222. Don't Use OPTION BASE 1 in UI Toolbox: "Illegal Function Call"

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900228-24
 Last Modified: 12-MAR-1990    ArticleIdent: Q59488

 When writing programs that utilize the User Interface (UI) Toolbox
 routines, it is not advisable to use the OPTION BASE 1 statement. This
 can create run-time errors, such as "Illegal function call," because
 the UI Toolbox uses index "zero" in arrays that must be in COMMON
 SHARED between your modules.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.


 223. INSTR, Documentation Correction for BASIC PDS 7.00

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900306-120 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q59562

 The following sentence describing the INSTR function on Page 138 of
 the "Microsoft BASIC 7.0: Programmer's Guide" for Microsoft BASIC
 Professional Development System (PDS) Versions 7.00 and 7.10 is
 incorrect. The second sentence under the "Searching for Strings"
 paragraph states the following:

    The INSTR(stringexpression1$, stringexpression2$) function tells
    you whether or not string2 is contained...

 This sentence should be changed to refer to stringexpresion2$ instead
 of string2, as follows:

    The INSTR(stringexpression1$, stringexpression2$) function tells
    you whether or not stringexpression2$ is contained...


 224. "Cannot Load File" Error with ISAMREPR.EXE and SHARE.EXE

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900227-52 buglist7.00 fixlist7.10
 Last Modified: 14-FEB-1991    ArticleIdent: Q59565

 If SHARE.EXE is loaded, attempting to repair an ISAM file using
 ISAMREPR.EXE results in the error:

    Cannot open 'file.mdb'

 This error occurs regardless of the version of MS-DOS being used.

 ISAMREPR.EXE is an ISAM file repair utility provided with Microsoft
 BASIC Professional Development System (PDS) version 7.00. This
 information applies only to BASIC PDS for MS-DOS.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 7.00. This problem is corrected if you use SHARE.EXE from MS-DOS
 version 4.01 and ISAMREPR.EXE from BASIC PDS version 7.10. (You must
 recompile your programs in BASIC PDS version 7.10.)

 To reproduce the problem, load SHARE.EXE, then, using the ISAM
 database file "BOOKS.MDB" provided with BASIC PDS 7.00, attempt to
 repair the file using ISAMREPR.EXE, as follows:

    C:\> SHARE

    C:\> ISAMREPR BOOKS
    Microsoft  (R)  ISAM Repair Utility   Version 1.00
    Copyright  (C)  Microsoft Corp 1989.  All rights reserved.

    ISAMREPR : Cannot open 'BOOKS.MDB'


 225. OS/2 DosFindFirst Code Example Correction; Missing Comma

 Product Version(s): 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q59723

 On Page 525 of the "Microsoft BASIC 7.0: Programmer's Guide" for
 Microsoft BASIC Professional Development System (PDS) Versions 7.00
 and 7.10, the code example given is missing a comma to delimit the
 VARSEG and SADD parameters when invoking the function DosFindFirst%.

 The incorrect syntax documented in the manual is as follows:

    x = DosFindFirst%(VARSEG(flname$) SADD(flname$), dirh,_
                     atr, buffer, bufflen, searchcount, reserved)

 The correct syntax of the CALL is as follows:

    x = DosFindFirst%(VARSEG(flname$), SADD(flname$), dirh,_
                     atr, buffer, bufflen, searchcount, reserved)

 A comma is needed between VARSEG(flname$) and SADD(flname$).


 226. List Box Width Can Be Only 14-55 Characters in 7.00 UI Toolbox

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900222-126
 Last Modified: 26-MAR-1990    ArticleIdent: Q59724

 The ListBox() function of the WINDOW.BAS toolbox file takes two
 parameters: a string array containing the list of items to be
 displayed, and an integer variable containing the number of items in
 the list.

 The header comment of the ListBox() function describes how to add a
 third parameter, an integer variable (BoxWidth%) that contains the
 desired width of the list box to be displayed. Unless this parameter
 is added, the width of the list box always defaults to 14 characters.
 However, even if this parameter is given, the width cannot be less
 than 14 or greater than 55 characters. The ListBox() function ensures
 that the width is within this range.

 This information applies to the User Interface (UI) Toolbox in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS.

 After adding the modification that allows the desired list box width
 to be specified, a sample invocation of the ListBox() function would
 be as follows

    x% = ListBox(text$(),MaxRec%,BoxWidth%)

 where:

    x%         is the array element selected from the list box
    text$()    is the string(s) to display in the list box
    MaxRec%    is the number of strings to display in the list box
    BoxWidth%  is the desired width of the list box

 If BoxWidth% is less than 14, ListBox() changes it to 14. If BoxWidth%
 is greater than 55, ListBox() changes it to 55. The statements that
 perform these checks are located toward the end of the function under
 the subroutine heading ListBoxWidthCalc:

    IF BoxWidth < 14 THEN BoxWidth = 14
    IF BoxWidth > 55 THEN BoxWidth = 55

 It is NOT recommended that you change or delete these IF statements to
 allow any list box width. If the width is too small, the OK and Cancel
 buttons may not fit in the list box. If the width is too large, the
 resulting list box may not fit on the screen.


 227. BASIC 7.00 Can Write Whole Array (in TYPE) to Disk at Once

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  3-AUG-1990    ArticleIdent: Q59734

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 introduce support for static arrays in user-defined TYPE
 definitions. This means that you can write an entire array (in a user
 TYPE record) to a disk file at once. The code example below writes an
 entire array to a RANDOM or BINARY file using a single PUT# statement.

 Note that you cannot output arrays all at once (in one PRINT# or
 WRITE# statement) to files opened with sequential access (OPEN FOR
 OUTPUT). With sequential access (OPEN FOR OUTPUT or INPUT), you must
 output or input just one array element at a time.

 You must use RANDOM or BINARY access to write a static
 nonvariable-length string array to a file all at once (as shown in the
 examples below).

 Note that in Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 for
 MS-DOS, in Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and in Microsoft BASIC PDS versions 7.00 and 7.10 for
 MS-DOS and MS OS/2, you can directly write whole records (variables)
 of a given user-defined TYPE to disk as the third argument of the PUT#
 statement. Each and every element of the user-defined TYPE record is
 automatically copied to the file. If the data is numeric and you
 output to a file OPENed with RANDOM or BINARY access, the data is
 automatically stored in numeric format (without requiring a lengthy
 FIELD statement or numeric-to-string conversion functions such as
 MKS$, MKD$, MKI$, or MKL$).

 Since an array can be an element of a record of user-defined TYPE in
 BASIC 7.00 and 7.10 (but not in earlier versions), you can write a
 whole array at once into a disk file, as shown below.

 Code Example
 ------------

 The following example, compiled in BASIC PDS 7.00 or 7.10, shows how
 to write a whole array to disk at once, using just one PUT# statement:

 TYPE rec1
   array1(20) AS INTEGER
 END TYPE
 DIM var1 AS rec1, var2 AS rec1  'DIMension var1 & var2 with TYPE rec1
 FOR i = 1 TO 20      ' Fill each element of the array:
   var1.array1(i) = i
 NEXT

 ' The following OPEN statements may OPEN FOR either RANDOM or BINARY:
 OPEN "test.dat" FOR RANDOM AS #1
 PUT #1, , var1       ' Write whole array to disk all at once.
 CLOSE

 OPEN "test.dat" FOR RANDOM AS #1
 GET #1, , var2      ' Reads array all at once into var2.
 FOR i = 1 TO 20     ' Print the contents of the array var2.array1:
   PRINT var2.array1(i);
 NEXT
 CLOSE


 228. ISAMCVT.EXE Fails to Convert db/LIB File, Try Packing First

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900312-79
 Last Modified: 26-MAR-1990    ArticleIdent: Q59765

 A customer reported that when converting db/LIB (dBASE) files to
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 ISAM files with the ISAMCVT.EXE utility, the ISAM files are not
 created correctly if the db/LIB file contains logically deleted
 records. For the process to be successful, the logically deleted
 records must be physically removed from the file. According to the
 customer, db/LIB provides a packing feature to do this.

 This information applies to Microsoft BASIC PDS 7.00 for MS-DOS.

 The utility ISAMCVT.EXE is used to convert other types of indexed
 files to BASIC's ISAM format. One of these types is db/LIB. A customer
 reported that if the db/LIB file to be converted has records in it
 that are marked for deletion, ISAMCVT.EXE either produces a corrupted
 ISAM file or does not produce one at all.

 Packing an indexed file is a method of physically removing records
 that are marked for deletion. The utility ISAMPACK.EXE is used to
 perform this function on BASIC's ISAM files. According to the
 customer, using a similar utility on a db/LIB file that has records
 marked for deletion allows ISAMCVT.EXE to successfully convert the
 file to the ISAM format.

 Microsoft has not verified this information, but it is recommended to
 pack all data files before they are converted to BASIC PDS ISAM with
 the ISAMCVT.EXE utility.


 229. Problem with MID$ Statement and MID$ Function in QBX.EXE

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900315-77 buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q60131

 Using the MID$ function as an argument of the MID$ statement can
 produce incorrect results in the QBX.EXE environment that comes with
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10, as shown in the program below.

 The problem does not occur when compiled with the BC.EXE environment
 of Microsoft BASIC PDS 7.00 and 7.10; with the BC.EXE or QB.EXE
 environment of Microsoft QuickBASIC version 4.00, 4.00b, or 4.50; or
 with the BC.EXE or QB.EXE environment of Microsoft BASIC Compiler
 versions 6.00 and 6.00b.

 Microsoft has confirmed this to be a problem in the QBX.EXE
 environment of Microsoft BASIC PDS versions 7.00 and 7.10. We are
 researching this problem and will post new information here as it
 becomes available.

 The program below should correctly output "1212345678". However, when
 run from within the QBX.EXE environment, it incorrectly outputs
 "1212121212". This behavior also occurs if a length% argument of 10 is
 used in the MID$ function. If 8 or 9 is used as the length% argument
 of the MID$ function, the correct output is produced. If the start%
 argument of the MID$ function is not taken to be 1, correct output
 displays.

 Code Example
 ------------

    A$= "1234567890"
    MID$(A$, 3) = MID$(A$, 1)
    PRINT A$

 Note: The first MID$ occurrence above is the MID$ statement, and the
 second occurrence is the MID$ function.


 230. BASIC PDS 7.00: ISAMREPR Always Adds 32K to a .MDB File

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900321-28
 Last Modified:  3-APR-1990    ArticleIdent: Q60132

 The ISAMREPR.EXE utility provided with Microsoft BASIC Professional
 Development System (PDS) Version 7.00 always adds at least 32K to an
 ISAM database file during the repair process. This is correct behavior
 for ISAMREPR and is documented on Page 384 of the "Microsoft BASIC PDS
 7.0: Programmer's Guide."

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 During the repair process, ISAMREPR allocates 32K or more of extra
 space as "work space" for use while repairing the file. This space is
 automatically added to the file at the beginning, before any deleted
 or damaged records are found during the process. For instance, if
 ISAMREPR is run twice on the same file, at least 64K will be added to
 the file, even though the repair might not have been necessary the
 first time. However, this added space is not "lost"; it is reused as
 new records or tables are added to the file.

 If the size of the file becomes unmanageable because of unused space,
 ISAMPACK.EXE can be used to remove the unused space and reduce the
 size of the file.


 231. L2025 Creating Quick Library Using Functions in SIGNAL.H

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900114-12
 Last Modified:  3-APR-1990    ArticleIdent: Q60135

 When placing a C program using the functions from SIGNAL.H into a
 Quick library for QuickBASIC (QB.EXE) or QuickBASIC Extended
 (QBX.EXE), LINK flags multiple occurrences of L2025 "Symbol defined
 more than once" in the CRT0DAT.ASM module of the C library. These
 errors are not affected by the /NOE (No Extended library search)
 option. This conflict is a limitation of Quick libraries. The SIGNAL.H
 functions work correctly when linked with a compiled BASIC program.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, QB.EXE from Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS, QBX.EXE from Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS, Microsoft QuickC Versions 1.00,
 1.01, 2.00, and 2.01, and Microsoft C Compiler Versions 5.00 and 5.10
 for MS-DOS.

 When the C code from the example below is compiled and linked into a
 Quick library as shown, the error L2025 is cited multiple times:

    QCL -c -AL signal.c ;     (QuickC)
    CL -c -AL signal.c ;      (C Compiler)

    LINK /Q signal,,,qbxqlb;      (LINK -> QLB in BC7)
    LINK /Q signal,,,bqlb45;      (LINK -> QLB in QB45)

 Code Example
 ------------

 The following code example demonstrates calling the raise() function
 from the SIGNAL.H file in C. When compiled and linked to a QLB as
 listed above, multiple L2025 errors occur:

    #include <signal.h>
    void test()
       {
       printf("SigFPE: %d\n",raise(SIGFPE));   /* Signal float error */
       }

 The following BASIC source demonstrates how to call the above C
 routine:

    DECLARE SUB test CDECL ()
    CALL test

 The above BASIC program compiles and links correctly to an EXE despite
 the fact that it fails to create a usable QLB file. The BASIC compile
 and link lines are as follows:

    BC testsig;
    LINK /NOE testsig+signal;

 The working EXE produces the following output:

    SigFPE: -1


 232. Near Strings Hotkey in Make EXE Dialog Box Does Not Toggle

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900319-29 buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q60136

 In the QBX.EXE editor, the Near Strings hotkey (ALT+N) in the Make EXE
 File dialog box does not move the option marker to the Near Strings
 option -- only the cursor is moved to the option. The arrow keys must
 be used to change this option.

 All other hotkeys -- ALT+F for Far Strings, ALT+A for Alternate Math
 and so on -- move the option marker to the desired option. Only the
 Near Strings hotkey (ALT+N) does not.

 To work around this problem, use the arrow keys to move to the Near
 Strings option. (The arrows can be used for any of the choices.)

 Microsoft has confirmed this to be a problem in the QBX.EXE
 environment that comes with Microsoft BASIC Professional Development
 System (PDS) version 7.00. This problem was corrected in QBX.EXE in
 BASIC PDS 7.10.


 233. WIDTH Syntax Correction; WIDTH Parameter Is Required

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900315-50 docerr B_QuickBas
 Last Modified: 15-JAN-1991    ArticleIdent: Q60137

 The following WIDTH statement syntax (taken from the documentation
 listed further below) incorrectly indicates that both "screenwidth%"
 and  ", screenheight%" are optional:

    WIDTH [screenwidth%][, screenheight%]

 According to the above syntax description, "WIDTH" with no parameters
 is a legal statement; however, WIDTH with no arguments correctly
 causes the following error in the QBX.EXE environment:

    Expected: # or LPRINT or expression or ,

 The syntax description for the WIDTH statement should be corrected to
 read as follows:

    WIDTH {screenwidth% | , screenheight% | screenwidth%, screenheight%}

 Note that screenwidth% is measured in columns, and screenheight% is
 measured in lines.

 This correction applies to the WIDTH statement on page 449 of the
 "Microsoft QuickBASIC 4.0: Language Reference" for 4.00 and 4.00b; on
 page 409 of the "Microsoft BASIC 7.0: Language Reference" manual for
 BASIC PDS 7.00 and 7.10; to the WIDTH statement in the QBX.EXE
 Microsoft Advisor online Help system from Microsoft BASIC Professional
 Development System (PDS) version 7.00; and in the QB.EXE QB Advisor
 online Help system from Microsoft QuickBASIC version 4.50.

 This documentation error has been corrected in the QBX.EXE online Help
 in BASIC PDS 7.10.

 The following section of the QBX.EXE online Help system defines the
 notation used for syntax description (in all of the above products):

 [optional item]      Items inside square brackets are optional; you
                      do not have to use them in the statement.

 {choice1 | choice2}  Braces and a vertical bar indicate a choice
                      between two or more items. You must use one of
                      the items in the statement unless the braces
                      are enclosed in square brackets.


 234. Explanation and Example of the NMAKE.EXE Utility

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900314-143
 Last Modified: 20-JUL-1990    ArticleIdent: Q60138

 Microsoft's NMAKE.EXE is a program-maintenance utility. It saves time
 by automating the process of updating project files. NMAKE compares
 the modification dates for one set of files, the target files, to
 those of another file type, the dependent files. If any of the
 dependent files have changed more recently than the target files,
 NMAKE executes a specified series of commands.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and MS OS/2.

 The main purpose of NMAKE is to help you update applications quickly
 and simply. However, it can execute any command, so it is not limited
 to compiling and linking. NMAKE can also make backups, move files, and
 do many other project management tasks.

 NMAKE works by comparing the times and dates of two sets of files,
 which are called "targets" and "dependents":

  - A target file is a file that you want to create, such as an
    executable file.

  - A dependent file is a file used to create a target, such as a BASIC
    source file.

 When you run NMAKE, it reads a "description file" that you supply. The
 description file consists of one or more blocks. Each block lists a
 target, the target-dependents, and the command that builds the target.
 If any dependent has changed more recently than the target, NMAKE
 updates the target by executing the command listed in the block.

 You can invoke NMAKE with the following two options:

 1. Specify options, macro definitions, and the names of targets to be
    built on the DOS or OS/2 command line.

 2. Specify options, macro definitions, and the names to be built in a
    command file, and give the filename on the DOS command line.

 NMAKE accepts a number of command-line options, which are described in
 detail in the Microsoft programmer's guide in Chapter 20.

 NMAKE reads a description file (text file, saved as text only with
 line breaks) to determine what to do. The description file may contain
 any number of description blocks.

 For example, if you have the following three source files that are
 part of the same program

    MAIN.BAS
    FILE1.BAS
    FILE2.BAS

 and if the files through the program-development process need to be
 updated, you would use NMAKE. First, you create the description file
 that will contain the description blocks, as follows:

 #####################COMPILE.MAK##########################

     ALL: Sample.exe
     main.obj: main.bas      #target : dependent
        BC main.bas;         #command field: any DOS command
     file1.obj: file1.bas        #line
        BC file1.bas;
     file2.obj: file2.bas
        BC file2.bas;
     files.lib: file1.obj file2.obj
        LIB files.lib file1.obj + file2.obj

     sample.exe: main.obj files.lib
        LINK main.obj + files.lib, sample.exe;

 ##########################################################

 Then, you invoke NMAKE. The syntax for invoking NMAKE is as follows:

    NMAKE  COMPILE.MAK

 Code Example
 ------------

 MAIN.BAS
 --------

 PRINT "We are in the Main Program"
 CALL file1
 CALL file2
 PRINT "We are DONE!!"

 FILE1.BAS
 ---------

 PRINT "We are in FILE1.BAS "
 SUB file1
   PRINT "We are in the sub of file1.bas"
 END SUB

 FILE2.BAS
 ---------

 PRINT "We are in FILE2.BAS"

 SUB file2
   PRINT "We are in the sub of file2.bas"
 END SUB


 235. LEN Function Returns Wrong Length in LEFT$ in OPEN Statement

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900319-95 buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q60139

 The LEN function in Microsoft BASIC Professional Development System
 (PDS) version 7.00 may return an incorrect string length when used
 within a string function in an OPEN statement. This occurs only when
 the program is compiled with the Far Strings (BC /Fs) option, and
 doesn't occur in the QuickBASIC Extended (QBX.EXE) environment or when
 the program is compiled without the Far Strings option (in other
 words, compiled with the BC.EXE default near strings).

 To work around this problem, use a temporary variable for the result
 of the LEN function and use that result in the string function.

 Microsoft has confirmed this to be a problem with BC /Fs in Microsoft
 BASIC Professional Development System (PDS) version 7.00. This problem
 was corrected in BASIC PDS 7.10.

 This problem occurs because the compiler incorrectly assumes that the
 length will be the first 2 bytes of the descriptor when LEN is used in
 a string function in the OPEN statement. This assumption is correct
 for near strings, but the far string descriptor is different and the
 length must be retrieved in a different manner.

 Code Example
 ------------

 The following are the compile and link lines that reproduce the
 problem in the code example:

    BC LENTEST /Fs;
    LINK LENTEST;

 The following code example OPENs the wrong file on the first OPEN
 statement:

    ' LENTEST.BAS
    tmp$ = "TEST.12X"
    l% = LEN(tmp$)        'Temporary for work-around

    'This should incorrectly create a file named 'TEST.12X'
    OPEN LEFT$(tmp$, LEN(tmp$) - 1) FOR RANDOM AS #1
    CLOSE #1

    'For a workaround, use temporary variable (l%) for LEN(tmp$) and
    'you will get 'TEST.12'
    OPEN LEFT$(tmp$, l% - 1) FOR RANDOM AS #1
    CLOSE #1

 Both OPEN statements in the above code example should open "TEST.12",
 but the first OPEN actually opens "TEST.12X" because the string length
 is returned incorrectly and is thus too large. Subtracting 1 from this
 larger value still leaves the full string to be returned from LEFT$.


 236. HELPMAKE ":p" Option Does Not Work Correctly

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist7.00 buglist7.10 s_utility
 Last Modified: 21-SEP-1990    ArticleIdent: Q60141

 When using the HELPMAKE.EXE utility (for modifying the online Help
 system of QBX.EXE environment), the ":p" command does not work as
 described on Page 681 of the "Microsoft BASIC 7.0: Programmer's
 Guide." The ":p" is described as setting a screen break for the Help
 environment. If ":p" is used, the Help environment behaves as if it
 were not used.

 Microsoft has confirmed this to be a problem with HELPMAKE in
 Microsoft Professional Development System (PDS) versions 7.00 and 7.10
 for MS-DOS. We are researching this problem and will post new
 information here as it becomes available.

 A workaround for this problem is to use the ":ln" command, which is
 also described on Page 681 of the "Microsoft BASIC 7.0: Programmer's
 Guide" for BASIC PDS 7.00 and 7.10. The ":ln" command specifies the
 size of the help window, where "n" is the number of lines. If this
 command is used, the size of the window is n + 1. If you want
 something to show up on the next page, you must have n + 1 number of
 lines before the next page. If this option is not used, the size of
 the window will default to the number of lines in the Help screen + 1,
 with 19 being the maximum number of lines.

 For any of the ":" commands described on Page 681 to take effect,
 HELPMAKE must be invoked with the /Ac option as described on Page 673.

 Note: HELPMAKE.EXE is the Microsoft Help File Maintenance Utility.
 HELPMAKE version 1.04 is shipped with BASIC PDS 7.00, and HELPMAKE
 version 1.05 is shipped with BASIC PDS 7.10.


 237. Configuring M.EXE to Epsilon Format

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900322-11
 Last Modified: 11-JUL-1990    ArticleIdent: Q60142

 This article describes the correct way to set up the Microsoft M
 Editor (M.EXE) to simulate the Epsilon editor environment. The Epsilon
 editor is a text editing utility published by Lugaru Software, which
 emulates EMACS-type editors running on larger computers.

 This article applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 In the BIN directory that Setup installs on the hard drive, there is a
 file called EPSILON.INI. This file contains the keystroke assignments
 necessary to reconfigure the M.EXE Editor. To get this field
 recognized, do one of the following:

 1. Rename the file to TOOLS.INI.

 2. Copy this file into your current TOOLS.INI file.

 Then, make sure that your DOS INIT variable is set to the directory
 that your TOOLS.INI file is located in; for example:

    SET INIT=D:\BC7\BIN

 At the top of the EPSILON.INI file is the clause [M MEP]. This clause
 tells the computer that the following commands should be issued when a
 program called M.EXE or a program called MEP.EXE is executed. If you
 have changed the name of your M Editor, this label should be changed
 to include the current name of the editor.


 238. /FPa, /Lp, and Near Strings Disabled with Quick Library

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900321-16
 Last Modified: 17-JAN-1991    ArticleIdent: Q60143

 If QBX.EXE is invoked with the /L option to load in a Quick library,
 the following compiler options will be disabled when the Make EXE File
 command is chosen from the Run menu:

    Alternate Math        /FPa
    OS/2 Protected Mode   /Lp
    Near Strings

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 A Quick library must be compiled using 80x87 or Emulator Math (/FPi),
 DOS or OS/2 real mode (/Lr), and Far Strings (/FS). Therefore, even if
 BASIC 7.00 or 7.10 is installed to support the Alternate Math library,
 OS/2 protected mode, and Near Strings, these compiler options cannot
 be selected from the Make EXE File menu option when a Quick library is
 loaded.


 239. CHAINing with Additional Variables in COMMON Causes Hang

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q60147

 In a compiled BASIC program, CHAINing from a program that has a
 DYNAMIC variable-length string array in COMMON to a program that has
 an additional variable in COMMON whose length is greater than 530
 bytes will cause the program to either terminate and display an
 "Unprintable Error" message or hang, depending on the version of BASIC
 compiler being used.

 This problem does not occur in the QB.EXE or QBX.EXE editors or when
 the /Fs compiler option is used with Microsoft BASIC Professional
 Development System (PDS) versions 7.00 or 7.10.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b and 4.50; in Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and OS/2; and in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS and OS/2. We are researching this
 problem and will post new information here as it becomes available.

 With BASIC PDS 7.00 or 7.10, the "Unprintable Error" message displays.
 In the other BASICs listed above, the program hangs.

 To duplicate the problem, the following conditions must be met:

 1. The first program must have a dynamic variable-length string array
    in COMMON.

 2. The first program must assign a value to an element of the array.

 3. The second program must have an additional COMMON variable (not in
    the first program's COMMON) with a length greater than 530 bytes.
    This can be either a fixed-length string or a user-defined TYPE.

 4. The second program must assign a value to the additional variable.

 5. Both programs must be compiled with near strings (no /Fs).

 Similarly, to work around the problem, any of the following methods
 can be used:

 1. Make the array $STATIC (DIM before COMMON in both programs).

 2. Put the additional COMMON variable in the COMMON block for the
    first program as well.

 3. Compile both programs with the Far Strings (/Fs) option in BASIC
    PDS 7.00 or 7.10.

 When the programs below are compiled for OS/2 protected mode, the
 problem is almost identical. The only difference in protected mode is
 the size of the additional variable in the COMMON block. The process
 will hang whenever the additional COMMON variable is greater than 20
 bytes (instead of 530 as in DOS). Besides the length of the COMMON
 variable, the conditions and the workarounds (listed above) apply to
 both OS/2 protected mode and DOS (and OS/2 real mode).

 Code Example #1
 ---------------

 The following program CHAINs to Code Example #2, which produces the
 "Unprintable Error" in BASIC PDS 7.00 or 7.10 and hangs in the other
 BASIC versions listed above when compiled as shown:

 'FIRST.BAS compile and LINK lines:
 '    BC FIRST;
 '    LINK FIRST;
 'NOTE: Compiling with the Far Strings option (/FS) corrects problem.

 'DIM VarStrArray(0) AS STRING      'Static array works correctly.
 COMMON VarStrArray() AS STRING
 'More COMMON variables can be added to both without changing
 ' problem.
 COMMON FixStr AS STRING * 531      'Full COMMON in both files works.
 DIM VarStrArray(0) AS STRING       'Dynamic array (any size) fails.
 VarStrArray(0) = "Test"            'Must assign a value to array.
 PRINT "Chaining FIRST->SECOND"
 CHAIN "SECOND"
 END

 Code Example #2
 ---------------

 The following is the CHAINed program, which will terminate and produce
 the "Unprintable Error" or hang (depending on the version of BASIC
 being used) when compiled as shown:

 'SECOND.BAS compile and LINK lines:
 '    BC SECOND;
 '    LINK SECOND;
 'NOTE: Compiling with the Far Strings option (/FS) corrects problem.

 'DIM VarStrArray(0) AS STRING  'Static array works correctly.
 COMMON VarStrArray() AS STRING 'Must be Dynamic string array.
 'More COMMON variables can be added to both without changing problem.
 COMMON FixStr AS STRING * 531  'Must be fixed STRING with LEN > 530

 PRINT "In SECOND"
 FixStr = "Test"                'Assignment to new COMMON var required.
 END


 240. No Space Needed in "/O MY.SRC" in HELPMAKE, Programmer's Guide

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q60220

 Page 673 in the "Microsoft BASIC 7.0: Programmer's Guide" (for
 versions 7.00 and 7.10) incorrectly shows a space between "/O" and
 "MY.SRC" in the following example for decoding a Help database:

    HELPMAKE /V /D /O MY.SRC MY.HLP > MY.LOG

 Using this syntax gives the error ":fatal error H1100: cannot open
 file." The correct syntax is as follows:

    HELPMAKE /V /D /OMY.SRC MY.HLP > MY.LOG

 The sample syntax given on the bottom of Page 672 shows the "/O"
 option as it should be used.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 241. How to Run the CHRTDEMO.BAS Example Program

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900329-119
 Last Modified: 11-APR-1990    ArticleIdent: Q60422

 The CHRTDEMO.BAS example program requires several additional files to
 run properly. If any of these files is not loaded in the QBX.EXE
 environment, the "Subprogram not defined" error occurs. If any of the
 files are left out when LINKing, the "Unresolved external" LINK error
 occurs.

 The steps to set up the files to run CHRTDEMO (for either the QBX.EXE
 environment or as an EXE program) are documented in the banner
 comments at the beginning of CHRTDEMO.BAS.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 The following table shows the files required to run the CHRTDEMO
 example program and in which Quick library the modules are contained
 (Note: Assembly modules are contained in each QLB):

    Source File    CHRTBEFR.QLB   UITBEFR.QLB
    -----------    ------------   -----------

    CHRTDEMO.BAS
    CHRTDEM1.BAS
    CHRTDEM2.BAS
    CHRTB.BAS            X
    FONTB.BAS            X
    CHRTASM.ASM          X              X
    FONTASM.ASM          X              X
    UIASM.ASM            X              X
    WINDOW.BAS                          X
    MENU.BAS                            X
    MOUSE.BAS                           X
    GENERAL.BAS                         X

 In addition to the files listed above, expanded memory [with an LIM
 4.0 EMM (Expanded Memory Manager)] is required to run in the QBX.EXE
 environment. In EXE form, the program will run without EMS (expanded
 memory support).

 When running the CHRTDEMO program, you must first enter data through
 the dialog box for the Data option of the View menu. When the program
 begins, the Chart option of the View menu is gray, since there are no
 series to chart. If a chart is requested without data entered in any
 series, the following dialog box message appears:

    No data in series.

 When entering the data, the Series name and Category labels are the
 same for the entire chart, but you must enter a different set of data
 for each series. Thus, the numbers entered in the Values column apply
 only to the currently selected Series. If an unnamed Series is
 selected, the values will be lost when OK is chosen to close the
 dialog box. When OK is chosen with data in an unnamed series, the
 following dialog box message appears:

    Series without names will be deleted upon exit.

 The following banner comment from CHRTDEMO.BAS describes the steps
 (and memory requirements) to run the CHRTDEMO program in either the
 QBX.EXE environment or as an EXE program:

 ' This demo program uses the Presentation Graphics and User
 ' Interface toolboxes to implement a general purpose charting
 ' package.
 '
 ' It consists of three modules (CHRTDEMO.BAS, CHRTDEM1.BAS, and
 ' CHRTDEM2.BAS) and one include file (CHRTDEMO.BI). It requires
 ' access to both the Presentation Graphics and User Interface
 ' toolboxes.
 '
 ' EMS is needed to load and run the demo under QBX. If you do not
 ' have EMS, refer to the command line compile instructions below,
 ' which will allow you to run the demo from the DOS prompt. Running
 ' the demo under QBX requires access to the Presentation Graphics
 ' and User Interface toolboxes. This can be done using one of two
 ' methods:
 '
 '   1. One large Quick library covering both toolboxes can be created.
 '      The library "CHRTDEM.LIB" and Quick library "CHRTDEM.QLB" are
 '      created as follows:
 '
 '         BC /X/FS chrtb.bas;
 '         BC /X/FS fontb.bas;
 '         LIB chrtdem.lib+uitbefr.lib+fontasm+chrtasm+fontb+chrtb;
 '         LINK /Q chrtdem.lib, chrtdem.qlb,,qbxqlb.lib;
 '
 '      Once created, start QBX with this Quick library and load the
 '      demo's modules (CHRTDEMO.BAS, CHRTDEM1.BAS and CHRTDEM2.BAS).
 '
 '   2. Either the Presentation Graphics or User Interface Quick Library
 '      may be used alone provided the other's source code files
 '      are loaded into the QBX environment. If CHRTBEFR.QLB is
 '      is used, then WINDOW.BAS, GENERAL.BAS, MENU.BAS, and MOUSE.BAS
 '      must be loaded. If UITBEFR.QLB is used, then CHRTB.BAS and
 '      FONTB.BAS must be loaded. Once a Quick Library is specified and
 '      all necessary source files are loaded, load the program
 '      modules (CHRTDEMO.BAS, CHRTDEM1.BAS and CHRTDEM2.BAS).
 '
 ' To create a compiled version of the chart demo program, perform the
 ' following steps:
 '
 '   BC /X/FS chrtb.bas;
 '   BC /X/FS fontb.bas;
 '   LIB chrtdem.lib + uitbefr.lib + fontasm + chrtasm + fontb
 '                   + chrtb;
 '   BC /X/FS chrtdemo.bas;
 '   BC /FS chrtdem1.bas;
 '   BC /FS chrtdem2.bas;
 '   LINK /EX chrtdemo chrtdem1 chrtdem2, chrtdemo.exe,, chrtdem.lib;
 '
 ' "CHRTDEMO" can now be run from the command line.


 242. Unresolved External Making Quick Library from CHRTB.BAS

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900402-93 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q60425

 The CHRTB.BAS file contains BASIC source code for the Presentation
 Graphics Toolbox Chart Routines.

 At the beginning of this file, there are instructions for creating a
 library and Quick library that contain the charting routines found in
 CHRTB.BAS. However, numerous unresolved external link errors (L2029)
 will be produced unless alterations are made to these instructions.

 This documentation error occurs in the CHRTB.BAS file in Microsoft
 BASIC Professional Development System (PDS) Versions 7.00 and 7.10 for
 MS-DOS.

 Since CHRTB.BAS makes calls to routines found in the Fonts Toolbox,
 FONTB.OBJ and FONTASM.OBJ must be included when making a library or
 Quick library out of CHRTB.BAS. These two files were mistakenly
 omitted from the instructions found in the CHRTB.BAS file.

 The correct method of creating a library and Quick library containing
 the charting routines found in CHRTB.BAS is as follows:

    BC /X /FS chrtb.bas
    BC /X /FS fontb.bas
    LIB chrtb.lib +chrtb+chrtasm+fontb+fontasm+qbx.lib;
    LINK /Q chrtb.lib, chrtb.qlb,,qbxqlb.lib;

 If the charting routines are going to be used in conjunction with the
 User Interface Toolbox source code (GENERAL.BAS, WINDOW.BAS, MENU.BAS,
 and MOUSE.BAS), the library should instead be created in the following
 manner:

    LIB chrtb.lib +chrtb+chrtasm+uiasm+fontb+fontasm+qbx.lib;


 243. TSCNIOxx.OBJ Stub Files Remove COLOR Border Parameter

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900327-66
 Last Modified: 20-APR-1990    ArticleIdent: Q60851

 When a Microsoft BASIC Professional Development System (PDS) Version
 7.00 program is linked with one of the TSCNIOxx.OBJ stub files, most
 graphics statements and functions are stubbed out. When a program that
 has been linked in this manner attempts to use the "border" parameter
 syntax of the COLOR statement, the run-time error "Feature
 unavailable" should be generated. This is because the border parameter
 syntax support is contained in the graphics portion of the BASIC
 run-time module and this is removed, or stubbed, during LINK time.

 The syntax for the COLOR statement that applies here is as follows:

    COLOR [foreground][,background][,border]

 This statement is only supported on a CGA graphics adapter in SCREEN 0.


 244. Passing Far Strings to C Using StringAddress and StringLength

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900328-95
 Last Modified: 19-APR-1990    ArticleIdent: Q60852

 Programs compiled with the /Fs option, functions and procedures
 (compiled with /Fs) in a Quick library, and programs designed to run
 under the QuickBASIC Extended (QBX.EXE) environment now need to handle
 strings passed to non-BASIC routines differently.

 The following program demonstrates how to pass a variable-length far
 string to a Microsoft C function using the BASIC run-time routines
 StringAddress and StringLength. These routines are necessary to obtain
 the string's far address and length.

 Code Example
 ------------

 '----------- Here is the file TESTB.BAS
 DECLARE SUB TestC CDECL (A$)
 A$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + CHR$(0)
                 'Add Hex 0 at the end for the C printf function
 CLS : PRINT : PRINT
 PRINT "BASIC: "; A$
 PRINT "Len: "; LEN(A$)
 PRINT
 CALL TestC(A$)
 LOCATE CSRLIN + 3
 PRINT "Back in BASIC"
 SYSTEM

 /* ---------- Here is the file TESTC.C
 extern char far * pascal StringAddress(long near *);
 extern int pascal StringLength(long near *);

 void TestC (long near * Desc)
 {
   int  len;
   char far *segadd;

   len = StringLength( Desc );
   segadd = StringAddress( Desc );
   printf("C: %s\n", segadd);
   printf("Len: %i\n", len);
 }

 Compile and link options, as follows:

    BC /o TESTB;
    CL -c -AM TESTC.C
    LINK /noe TESTB TESTC;

 The output should from this program should be as follows:

    BASIC: ABCDEFGHIJKLMNOPQRSTUVWXYZ
    Len: 27

    C: ABCDEFGHIJKLMNOPQRSTUVWXYZ
    Len: 27

    Back in BASIC


 245. Floating-Point Bench Marks: QB vs BC6 vs PDS, /FPi vs /FPa

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900403-121 B_QuickBas
 Last Modified: 19-APR-1990    ArticleIdent: Q60858

 This article provides some informal benchmarks for various versions of
 Microsoft BASIC. It demonstrates the speed differences between them
 using certain mathematic operations with different versions of BASIC
 and different math packages. The data listed below was generated on a
 Wyse 386 16 MHz PC without a coprocessor.

 This information applies to Microsoft QuickBASIC Version 4.50,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2,
 and Microsoft BASIC Professional Development System (PDS) Version 7.00
 for MS-DOS and OS/2.

 The emulator (/FPi) is a math package that uses software to emulate
 the floating-point coprocessor functions as closely as possible when a
 coprocessor is not present. The alternate math package (/FPa) is
 another method of emulating the coprocessor functions. The main
 difference is that the emulator always uses an 80-bit temporary work
 area (to emulate the coprocessor's 80-bit register), whereas the
 alternate math package uses a smaller temporary storage area for most
 operations. The alternate math package can generate significantly
 faster code, but at a loss of precision for floating-point
 calculations.

 QuickBASIC uses only the emulator math (EM) package (/FPi). The
 alternate math package is not available with QuickBASIC, but is
 available with BASIC compiler 6.00 and 6.00b and BASIC PDS 7.00.

 The following table gives the times for the various operations in the
 program listed below (these operations were performed 10,000 times on
 a 386/16 MHz):

    10,000        PDS 7.00       BC 6.00b       BC 6.00       QB 4.50
    Operations  /FPi    /FPa   /FPi    /FPa   /FPi    /FPa   (EM only)
    ----------  ------------   ------------   ------------   ---------

    empty loop   3.19   1.87   3.91    1.21   3.94    1.22   3.56
    J#=I#+I#     4.53   1.84   5.78    1.84   5.78    1.85   5.15
    J#=I#*I#     4.72   2.03   5.97    2.12   5.91    2.03   5.19
    J#=I#^2     33.91   3.68  46.32    3.81  45.47    3.72  42.31
    J#=I#^.5    33.93  29.34  46.50   30.57  45.66   29.47  42.63
    J#=SQR(I#)   5.57   3.25   6.84    3.40   6.71    3.28   6.00
    J#=COS(I#)  16.87  15.90  31.44   16.22  31.47   16.15  29.94

 Please note the following about the above table:

 1. Any exponents are slow in the emulator. Equivalent multiplication
    is much faster for small cases.

 2. Fractional exponents are almost as slow with the alternate math
    package as the emulator. The times for other noninteger exponents
    are similarly slow with the alternate math package. Note that SQR
    is much faster than raising to the .5 exponent.

 3. BASIC PDS 7.00 greatly improves the emulator speed for many of the
    operations (COS, exponentiation) over previous versions. Since the
    alternate math package doesn't have the same factor of improvement,
    the emulator runs closer to the alternate package for many
    operations in BASIC PDS 7.00.

 4. The time of execution for most operations using /FPa in PDS 7.00 is
    40-60 percent of the time with /FPi in PDS 7.00.

 Code Example
 ------------

 The following code example demonstrates the times of various
 operations using the different versions of BASIC:

    'Compile and link lines for emulator (only mode for QuickBASIC):
    '
    ' BC /O BENCH.BAS;
    ' LINK BENCH;
    '
    'Compile and link for alternate math in BASIC compiler and PDS:
    '
    ' BC /O /FPa BENCH.BAS;
    ' LINK BENCH;
    orig = TIMER
    FOR I# = 1 TO 10000
    NEXT
    PRINT "Empty loop:"; TIMER - orig

    orig = TIMER
    FOR I# = 1 TO 10000
    J# = I# + I#
    NEXT
    PRINT "J#=I#+I#:"; TIMER - orig

    orig = TIMER
    FOR I# = 1 TO 10000
    J# = I# * I#
    NEXT
    PRINT "J#=I#*I#:"; TIMER - orig

    orig = TIMER
    FOR I# = 1 TO 10000
    J# = I# ^ 2
    NEXT
    PRINT "J#=I#^2: "; TIMER - orig

    orig = TIMER
    FOR I# = 1 TO 10000
    J# = I# ^ .5
    NEXT
    PRINT "J#=I#^.5: "; TIMER - orig

    orig = TIMER
    FOR I# = 1 TO 10000
    J# = SQR(I#)
    NEXT
    PRINT "J#=SQR(I#):"; TIMER - orig

    orig = TIMER
    FOR I# = 1 TO 10000
    J# = COS(I#)
    NEXT
    PRINT "J#=COS(I#): "; TIMER - orig
    END


 246. Vectored Fonts Not Usable in BASIC PDS 7.00

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900408-2 bit map
 Last Modified: 21-SEP-1990    ArticleIdent: Q60859

 The font files MODERN.FON, SCRIPT.FON, and ROMAN.FON from Microsoft
 Windows/286 and Microsoft Windows/386 cannot be used with the
 Microsoft BASIC Professional Development System (PDS) version 7.00 or
 7.10 font toolbox.

 The "Microsoft BASIC 7.0: Language Reference" manual correctly states
 on Page 518 that the font toolbox supplied with BASIC PDS 7.00 works
 with any standard Windows bitmap .FON file. However, the files
 MODERN.FON, SCRIPT.FON, and ROMAN.FON are vectored fonts, not
 bitmapped fonts. The BASIC PDS font toolbox will use the rest of the
 fonts supplied with Windows/286 or Windows/386 without any problem.

 The difference between bitmapped and vectored fonts is that bitmapped
 fonts are fixed in size and shape. To get a different-sized font, you
 must use a different bitmap for each character. Vectored fonts, also
 called scalable or resizeable fonts, are actually made up of
 instructions for drawing the different characters. As a result, you
 can easily resize the figures.

 The same .FON files are supplied with Windows/286 and Windows/386.

 The message "Bad Font File" will be generated by the BASIC PDS font
 toolbox if it cannot use a specific font.


 247. CommandKeySet Subprogram Should Be ShortCutKeySet

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900410-29 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q60860

 Page 549 of the "Microsoft BASIC 7.0: Language Reference" (for 7.00
 and 7.10) incorrectly refers to the CommandKeySet SUBprogram where it
 should refer to the ShortCutKeySet SUBprogram.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) Versions 7.00 and 7.10 for MS-DOS.


 248. Problem When Using Integer Array and FOR Loop in BASIC 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900411-147 buglist7.00 fixlist7.10
 Last Modified:  1-AUG-1990    ArticleIdent: Q60965

 The code example below shows a case where using an integer variable
 for a FOR loop-counter can produce incorrect results in a compiled
 BASIC program. The program must have the following elements to
 reproduce the problem:

 1. The program must contain a simple FOR loop (not nested, etc.).

 2. The FOR loop must contain a call to the INT function.

 3. The upper bound of the FOR loop must be specified with a
    variable, not a literal.

 4. The loop-counter variable and upper-bound variable must be
    integers.

 The code example below demonstrates these conditions and prints out
 the value of the loop counter each time it loops. In a compiled BASIC
 program, this example always prints the upper bound of the loop
 counter.

 Microsoft has confirmed this to be a problem in the BC.EXE compiler
 that comes with Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS and MS OS/2. This problem was corrected in
 BASIC PDS version 7.10.

 This problem does not occur in QBX.EXE (the QuickBASIC extended
 environment that comes with BASIC PDS 7.00). This problem also does
 not occur in the BC.EXE or QB.EXE environments that come with
 QuickBASIC versions 4.00, 4.00b, or 4.50.

 Any of the following workarounds corrects the problem:

 1. Compile with the BC /X option.

 2. Compile with the BC /FPa option.

 3. Change the DEFINT statement to DEFtype, where "type" is anything
    but INT (integer).

 4. Change the upper bound on the FOR-LOOP to a literal.

 Code Example
 ------------

 DEFINT A-Z                    'Change to something other than INT
                               'or remove the line
 DIM test(4)
 temp = 4
 FOR k = 1 TO temp             'Use 4 instead of temp.
    PRINT k                    'In a compiled program, this line
                               'always prints the upper bound
                               'of the FOR-LOOP.
    test(k) = INT(1.0)         'Remove the INT function CALL.
 NEXT k

 The following is the output in the QBX.EXE environment (correct):

    1
    2
    3
    4

 The following is the output from a compiled 7.00 .EXE program
 (incorrect):

    4
    4
    4
    4


 249. QBX.EXE 7.10 Expanded Memory Usage Better Than 7.00; 32K Table

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900228-5
 Last Modified: 10-AUG-1990    ArticleIdent: Q60968

 The QuickBASIC Extended environment (QBX.EXE) can use up to 16 MB
 (megabytes) of Lotus-Intel-Microsoft (LIM) 4.0 expanded memory
 under MS-DOS. If the expanded memory is available, QBX.EXE
 automatically stores in it SUBs, FUNCTIONs, and module-level code
 units that are no greater than 16K in size. If QBX.EXE is invoked with
 the /Ea switch, arrays that are no greater than 16K in size are also
 stored in expanded memory.

 In QBX.EXE in BASIC PDS version 7.00, the memory is allocated in 16K
 pages; for example, a 2K procedure consumes 16K and wastes 14K (16K
 minus 2K) of expanded memory. Also, when one or more SUBs or FUNCTIONs
 are stored in expanded memory, QBX.EXE makes a one-time allocation of
 32K (two 16K pages) in expanded memory as overhead for its own
 internal tables.

 QBX.EXE in BASIC PDS version 7.10 is enhanced so that memory is
 allocated in 1K pages; for example, a 1K procedure or array takes up
 1K, thus using expanded memory much more efficiently than in QBX.EXE
 7.00.

 This article applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Examples of Expanded Memory Usage in QBX.EXE 7.00
 -------------------------------------------------

 As an example for BASIC PDS 7.00, suppose QBX.EXE is run on a machine
 for which FRE(-3) reports that 2720K of expanded memory is available.
 When the first module-level statement is entered, FRE(-3) would then
 return 2704K, 16K less. When the first SUB or FUNCTION is created
 after that, FRE(-3) would return 2656K, 48K less -- 16K for the SUB or
 FUNCTION itself and 32K for QBX.EXE's internal tables.

 When SUBs, FUNCTIONs, module-level code units, or arrays (if /Ea is
 used) are deleted, QBX.EXE deallocates the expanded memory they were
 using. The tables, however, will not be deallocated unless New Program
 is chosen from the File menu.

 In 7.00, a single-element integer array takes the same expanded memory
 space (16K) as an array with 8192 elements. Likewise, a SUB with a
 single PRINT statement takes the same space (16K) as a large SUB with
 hundreds of statements. (This is no longer true in 7.10, where
 expanded memory usage is more efficient.)

 To use expanded memory to its best potential in the QBX.EXE 7.00
 environment, you should try to make your SUBs as close to the 16K
 limit as possible without exceeding it. (This is not necessary in
 7.10.) The size of the SUBs (in kilobytes) is listed in the View Subs
 (F2) dialog box to the right of each SUB.

 Likewise, arrays in QBX.EXE 7.00 will use expanded memory more
 efficiently if they are dimensioned to be just under the 16K page
 size. (This is not necessary in 7.10.)

 References:

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 offer expanded memory support under the Lotus-Intel-Microsoft
 version 4.0 Expanded Memory Specification (LIM 4.0 EMS) for code and
 data in the QBX.EXE environment under MS-DOS. Earlier versions do not
 offer any expanded memory support. LIM 4.0 EMS support is discussed in
 the "Microsoft BASIC 7.0: Getting Started" manual and in the
 "Microsoft BASIC 7.1: Getting Started" manual.

 To be compatible with BASIC PDS 7.00 or 7.10, the expanded-memory
 device driver must observe the LIM 4.0 EMS.


 250. NMAKE Example Using ALL, Pseudotarget and Macros

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900319-89
 Last Modified: 14-MAY-1990    ArticleIdent: Q60969

 NMAKE works by comparing the dates and times of two sets of files,
 which are called "targets" and "dependents." A target is a file that
 you want to create, such as an executable file. A dependent is a file
 used to create a target, such as a BASIC source file. If any dependent
 has changed more recently than the target, NMAKE updates the target by
 executing the command listed in the block.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and MS OS/2.

 The pseudotarget is a name that serves as a "handle" for building a
 group of files or executing a group of commands. In the following
 example, ALL is the pseudotarget. After ALL, you would list all the
 EXE files that you want to create with this NMAKE file.

 Inference rules are templates that NMAKE uses to generate files with a
 given extension. When NMAKE encounters a description block with no
 commands, it looks for an inference rule that specifies how to create
 the target from the dependent files, given the two file extensions.
 Inference rules eliminate the need to put the same commands in several
 description blocks. In this example, the inference rules are to
 compile BASIC source files with no options and also to link the files
 with no linker options. If you wanted to specify compiler options (for
 example, /W, /X, etc.), you must include the command line "BC
 myprog.bas /X ;" in your description block for myprog.obj :
 myprog.bas.

 The OBJS statement in the description block for mymain2 is called a
 macro. Macros provide a convenient way to replace a string in the
 description file with another string. This statement is telling NMAKE
 that MYLIB.LIB is made up of these object files. The "!" on the LIB
 command is a repetition modifier that tells NMAKE to repeat the
 command as many times as it needs for dependents that are out of date
 with respect to the target. If both members of the library were
 updated, they would both be compiled and the library would be
 incrementally updated. The following commands would be executed:

    lib mylib.lib -+ libsub.obj ;
    lib mylib.lib -+ libsub2.obj ;

 The library could also contain modules written in assembler or C. You
 would need to add an assemble or C compile line, either as an
 inference rule or specifically to the module's description block. For
 example, the inference rules for a C compile and a MASM assemble would
 be as follows:

    .c.obj:
       cl /c $?

    .asm.obj:
       masm $? ;

 The following is a sample NMAKE description file, MYMAKE.MAK, which
 compiles and links two programs. The first is a main module and a
 subprogram, and the second is a main module with a library containing
 two members. To execute the description file, type the following:

    NMAKE MYMAKE.MAK

 Code Example
 ------------

 #----------------MYMAKE.MAK-------------------

 #----------pseudotarget

 ALL : mymain.exe mymain2.exe

 #----------inference rules

 .BAS.OBJ:
    BC $< ;

 .OBJ.EXE:
    LINK $** ;

 #----------mymain description block

 # target : dependent
 mymain.obj : mymain.bas  # (these will use inference rules
 mysub.obj : mysub.bas    #  to compile and link)
 mymain.exe : mymain.obj mysub.obj

 #----------mymain2 description block

 mymain2.obj : mymain2.bas
     BC mymain2.bas /X ;    # (this command used for compile)

 libsub.obj : libsub.bas    # (these will use the inference
 libsub2.obj : libsub2.bas  #  rules for compiling)

 OBJS = libsub.obj libsub2.obj

 mylib.lib : $(OBJS)
       !lib mylib.lib -+ $?;

 mymain2.exe : mymain2.obj mylib.lib   # (this uses inference
                                       #  rule for linking)


 251. BASIC PDS 7.00 Not Compatible with C PDS Version 6.00

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# S900415-6 B_QuickBas S_C S_QuickC
 Last Modified: 18-OCT-1990    ArticleIdent: Q61337

 Microsoft BASIC Professional Development System (PDS) version 7.00,
 QuickBASIC version 4.50, and earlier versions of BASIC are not
 compatible with Microsoft C Professional Development System version
 6.00 or Microsoft QuickC version 2.50 or 2.51. You must obtain BASIC
 PDS 7.10 to be compatible with these versions of C and QuickC.

 Below are some of the LINK L2025 errors that can occur when you LINK
 an incompatible BASIC version with Microsoft C PDS version 6.00:

    E:\C600\LIB\MLIBCE.LIB(chkstk.asm) : error L2025: STKHQQ : symbol
     defined more than once

    E:\C600\LIB\MLIBCE.LIB(chkstk.asm) : error L2025: __aaltstkovr :
     symbol defined more than once

    E:\C600\LIB\MLIBCE.LIB(chkstk.asm) : error L2025: __chkstk :
     symbol defined more than once

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC PDS version 7.00 for MS-DOS
 and MS OS/2.

 A separate article, found by querying in this Knowledge Base using the
 following words, describes which specific Microsoft language compiler
 versions are designed to be linked together:

    BASIC and C and QuickC and calling and linked and modules

 For more specific information about how to do mixed-language
 programming with Microsoft C and Microsoft BASIC, query in this
 Knowledge Base on the following word:

    BAS2C

 Microsoft C PDS version 6.00 and Microsoft QuickC versions 2.50 and
 2.51 use different start-up and heap management code than previous
 versions of C and QuickC. Since the BASIC libraries must be put first
 on the LINK line, the BASIC libraries supply alternate start-up, heap,
 and low-level I/O code for the LINKed C routines. These alternate
 routines are specific to the versions of C available when the BASIC
 products shipped.

 Each version of BASIC is tested and designed to work with the versions
 of Microsoft C and QuickC currently on the market when the BASIC
 package is released. Incompatibilities caused by new releases of C and
 QuickC are resolved whenever an updated BASIC product ships.

 To find a separate article in this Knowledge Base that describes the /Gh
 option (which makes C 6.00 use the C 5.10 libraries, for Microsoft
 Windows 2.x compatibility), as mentioned in the C 6.00 README.DOC
 file, query on the following words:

    /Gh and 6.00 and 5.10 and C and library and compatibility

 However, BASIC PDS 7.00 and QuickBASIC 4.50 (and earlier versions) are
 not compatible with routines compiled with C 6.00, even when the C
 6.00 /Gh option is used.


 252. Docerr in MenuSet and MenuSetState in UI Toolbox of PDS 7.00

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900412-65 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q61338

 Pages 546 and 547 of the "Microsoft BASIC 7.0: Language Reference" for
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 incorrectly state that the subroutine MenuSetState treats -1
 as a legal value for the parameter state%. The lowest legal value for
 state% is 0. This is the scope of the MenuSetState routine. The
 MenuSet subroutine should be called to remove an item from a menu.

 The MenuSet subroutine, on Pages 545 and 546 of the same manual, is
 also documented incorrectly because the lowest legal value of MenuSet
 is actually -1, not 0. To make a menu item or menu title disappear,
 you must call MenuSet with state% equal to -1.


 253. Problem When Using IMP with a Variable and a Literal

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10 B_QuickBas
 Last Modified: 21-SEP-1990    ArticleIdent: Q61339

 The code example below using the IMP logical-implication operator
 incorrectly prints -1 when compiled with the BC.EXE environment of
 Microsoft BASIC Professional Development System (PDS) version 7.00 or
 7.10. When executed in the QBX.EXE (QuickBASIC Extended) environment,
 the correct answer of 0 (zero) prints.

 The only workaround is to change the -1 to a variable or change i% in
 the PRINT statement to a 0 (zero).

 Microsoft has confirmed this to be a problem in the BC.EXE environment
 of Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2; in the BC.EXE environment of
 Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 (buglist4.00,
 buglist4.00b, buglist4.50) for MS-DOS; and in the BC.EXE environment
 of Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2. We are researching this problem and will post new information
 here as it becomes available.

 For your information, the following definition of IMP is taken from
 the Microsoft Advisor online Help system in QBX.EXE:

 HELP: IMP Operator
 ------------------

    result = numeric - expression1 IMP numeric - expression2

 The logical-implication operator, IMP, compares corresponding bits in
 numeric-expression1 and numeric-expression2, and then sets the
 corresponding bit in the result according to the following table:

    Bit in first expression   Bit in second expression   Bit in result
    -----------------------   ------------------------   -------------
                 1                          1                    1
                 1                          0                    0
                 0                          1                    1
                 0                          0                    1

 Code Example
 ------------

    DEFINT A-Z
    i% = 0
    PRINT -1 IMP i%

 If a variable is used in the place of the -1 or the i% is replaced
 with a 0, then this program prints the correct answer of 0.

 Note that the constant -1 is stored internally (in two's complement
 signed binary integer format) with all 16 bits set equal to 1 (on).
 The constant 0, when stored in an integer variable, is stored with all
 16 bits set equal to 0 (off).


 254. CodeView Does Not Support the BASIC CHAIN Statement

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# S900415-4 B_QuickBas S_CodeView CV CVP
 Last Modified:  4-SEP-1990    ArticleIdent: Q61341

 Versions 2.20, 2.30, 2.35, and 3.10 of the Microsoft CodeView debugger
 do not support the BASIC CHAIN command. When a program is CHAINed in
 BASIC, CodeView executes the entire CHAINed-to program and will not
 allow it to be single-stepped through.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The CHAIN command is unique to BASIC and is not supported by the
 CodeView debugger. CodeView is a mixed-language source code debugger
 supplied with BASIC compiler versions 6.00 and 6.00b and BASIC PDS
 versions 7.00 and 7.10. CodeView is NOT shipped with QuickBASIC 4.00,
 4.00b, or 4.50 for MS-DOS.

 The following table lists which versions of CodeView are shipped with
 which versions of BASIC:

    BASIC Version      Is Shipped with CodeView Version
    -------------      --------------------------------

    6.00               2.20
    6.00b              2.30
    7.00               2.35
    7.10               3.10

 Note: CV.EXE is the CodeView utility for MS-DOS. CVP.EXE is the
 CodeView utility for MS OS/2.


 255. Description for L2043 in BASIC PDS 7.00 Manual Incorrect

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S900415-3
 Last Modified:  8-JAN-1991    ArticleIdent: Q61342

 Page 689 of the "Microsoft BASIC 7.0: Language Reference" for
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 incorrectly states for LINKer error message L2043 that the
 module QUICKLIB.OBJ was missing. This should be changed to say that
 the module QBXQLB.LIB was missing.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS.

 The description on Page 689 for the LINKer error message L2043 is
 incorrectly given as follows:

    L2043    Quick Library support module missing

             The required module QUICKLIB.OBJ was missing.

             The module QUICKLIB.OBJ must be linked when creating a
             Quick library.

 The correct explanation is as follows:

    L2043    Quick Library support module missing

             The required module QBXQLB.OBJ was missing.

             The module QBXQLB.OBJ must be linked when creating a
             Quick library.


 256. ON ERROR GOTO 0 in BASIC PDS Won't Give Error Line's Address

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900415-2
 Last Modified: 15-JAN-1991    ArticleIdent: Q61343

 Because of new flexibility added to the ON ERROR GOTO handling in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10, the address given when an .EXE program aborts from within an
 error handler may not be the actual address of the line that produced
 the error.

 If error trapping is turned on, an error occurs, and an ON ERROR GOTO
 0 or ERROR ERR statement is used in the error handler to abort the
 program, then the address of the ON ERROR GOTO 0 or ERROR ERR line
 displays when the program stops. This behavior differs from .EXE
 programs compiled in previous versions of BASIC (including QuickBASIC
 4.x and BASIC compiler 6.00 and 6.00b), which return the address of
 the line that originally caused the error.

 This information applies to .EXE programs compiled in Microsoft BASIC
 PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Because BASIC PDS versions 7.00 and 7.10 allow errors generated in a
 module's error handler to be trapped in another module's error
 handler, the compiler must generate the address of the ON ERROR GOTO
 0 (or ERROR ERR) line. Otherwise, if the error were transferred to
 another error handler that did a RESUME NEXT, the program would not
 resume to the error handler, but to the user code (because that is the
 address the compiler would have passed to it). This leaves the error
 handler still on the stack. If this occurred multiple times, the
 program would eventually run out of stack space.

 Note that the QB.EXE interpreter environment found in QuickBASIC 4.x
 and BASIC compiler 6.00/6.00b treats an ON ERROR GOTO 0 in an error
 handler as if it were an ERROR ERR, causing QB.EXE to stop the program
 and flag the error on the ON ERROR GOTO 0 line. However, the BC.EXE
 compiler in these products goes to the extra work of making .EXE
 programs that report the error back where the error originally
 occurred.

 The following program, ERR.BAS, when compiled using BC.EXE from BASIC
 PDS version 7.00 or 7.10, will abort with an error and display the
 address of the ON ERROR GOTO 0 line. Compile and LINK as follows:

    BC /x ERR.BAS,,ERR.LST;
    LINK ERR ;

 The following is ERR.BAS:

    ON ERROR GOTO handler
    y = 0
    x = 1/y
    END

    handler:
       ON ERROR GOTO 0
       RESUME

 In BASIC PDS version 7.00 or 7.10, when the program aborts, the
 following error message is given (note: the address given will be
 different on different machines):

    Division by zero in line 0 of module ERR      at address 23E5:0066

 Looking at the following listing file (ERR.LST) produced by the
 compiler shows that the address given when the program stops in error
 is that of the ON ERROR GOTO 0 line:

    0030   0006
    0030   0006            ON ERROR GOTO handler
    003A   0006            y = 0
    0046   000A            x = 1/y
    0057   000E            end
    005C   000E            handler:
    005C   000E               ON ERROR GOTO 0
    0066   000E               RESUME
    006B   000E
    008E   000E

 The address given (0066) shows as the RESUME statement. This is
 because the error occurs at the end of the ON ERROR GOTO 0 statement,
 which is the starting address of the RESUME statement line. In .EXE
 programs compiled in versions of BASIC earlier than 7.00, the address
 given was of the actual line that the error occurred on (the line at
 address 0046: x = 1/y).

 The address given in a program without ON ERROR trapping active is
 still the address of the actual error line, x = 1/y, in BASIC 7.00 and
 7.10 (and earlier versions of BC.EXE).


 257. Differences Between FormatX$ Functions & PRINT USING Statement

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900305-84
 Last Modified: 27-JUL-1990    ArticleIdent: Q61345

 This article demonstrates the differences between the FormatX$
 Add-On-Library (DTFMTxx.LIB) functions and the BASIC PRINT USING
 statement, specifically in the case of the "#" character.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2. FormatX$
 refers to the Add-On-Library functions FormatI$, FormatL$, FormatS$,
 FormatD$, and FormatC$ found in BASIC PDS 7.00 and 7.10.

 In the PRINT USING statement, the # sign is used in the string
 identifier to specify a digit placeholder. If there isn't a digit in
 that location, a space is put in its place. In the FormatX$ functions,
 the # is also a placeholder. However, if there isn't a digit, the
 location is not padded with a space.

 The FormatX$ functions can be invoked from within the QB.EXE
 environment by installing the DTFMTER.QLB Quick library. These
 functions can be invoked from .EXE programs by linking in the
 appropriate DTFMTxx.LIB library.

 The FUNCTION declarations necessary for the FormatX$ functions are
 contained in the FORMAT.BI include file, which can be included in your
 source file as follows:

    REM $INCLUDE:'FORMAT.BI'

 The syntax for the FormatX$ function(s) is as follows

    FORMATx$ (Variable, fmt$)

 where:

 1. "x" is the first letter of the data type being manipulated:

       Data Type           Syntax
       ---------           ------

       Integer             FORMATI$
       Long integer        FORMATL$
       Single precision    FORMATS$
       Double precision    FORMATD$
       Currency            FORMATC$

 2. "Variable" is the variable to be manipulated.

 3. "fmt$" is a string expression defining the output format.

 The format for the PRINT USING statement is as follows

    PRINT USING fmt$; Variable [,Variable2...][,|;]

 where:

 1. "fmt$" is a string expression defining the output format.

 2. "Variable" is an expression(s) to be manipulated.

 3. "," or ";" are optional output choices to print next output
    immediately following. (Note that PRINT USING does not support
    "print zones.")

 The following code example demonstrates the difference in the #
 operand in the fmt$ argument for FORMATX$ versus PRINT USING:

    ' $INCLUDE: 'FORMAT.BI'
    A = 123.456
    B = 88.99

    ' ------  PRINT USING STATEMENTS:
    PRINT USING "#####.##";A
    PRINT USING "######.###";B
    PRINT

    ' ------  FORMATX$ STATEMENTS:
    PRINT FORMATS$(A,"#####.##")
    PRINT FORMATS$(B,"######.###";B
    END

 The output will resemble the following:

      123.46
        88.990

    123.46
    88.99


 258. Dynamic Array Using INT in FOR Loop Returns Bad Results

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900409-113 buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q61346

 Assigning values to a dynamic array using the INT function in a FOR
 loop that contains a variable for the maximum index can produce
 incorrect results when compiled. The problem seems to be an addressing
 problem where all array values contain the result of the last
 computation.

 Microsoft has confirmed this to be a problem in the BC.EXE environment
 of Microsoft BASIC Professional Development System (PDS) version 7.00.
 This problem was corrected in BASIC PDS 7.10. This problem does not
 occur in the QBX.EXE editor in 7.00, or in earlier versions of
 Microsoft QuickBASIC or Microsoft BASIC Compiler.

 Any of the following workarounds will correct this problem:

 1. Compile with the BC /D compiler option.
 2. Use a static array.
 3. Use a temporary variable for the function value.
 4. Use a literal to define the FOR loop.

 Code Example
 ------------

 The following code example demonstrates the problem:

    'Compile and link lines:
    '
    ' BC FORARRAY;               NOTE: The BC /D compiler option
    '                                  corrects the problem.
    ' LINK FORARRAY;
    DEFINT A-Z                   'Any numeric type shows problem.
    n = 1                        'n=1 is required for FOR upper index.
    DIM a(n)                   'Array must be dynamic to show problem.
    a(0) = 1
    a(1) = 2
    FOR i = 0 TO n               'Variable n required to cause problem.
       a(i) = INT(a(i))          'INT or FIX functions cause problem.
       PRINT a(i)       'Incorrectly prints 2 for each iteration; it
                        'should have printed 1, then 2.
    NEXT
    END

 When compiled without /D, the above program displays the following
 incorrect results:

    2
    2

 When run in the QBX.EXE editor or compiled with /D option, the above
 program displays the following correct results:

    1
    2


 259. BASIC PDS 7.00 "Program Memory Overflow" with Too Many CONST

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900329-74
 Last Modified: 27-JUL-1990    ArticleIdent: Q61349

 When used with the /V switch, the BC.EXE compiler that comes with
 Microsoft BASIC Professional Development System (PDS) version 7.00
 produces a "Program memory overflow" error when compiling a program
 that has approximately 680+ CONSTants. The compiler can still have up
 to 13K "bytes free" of compiler workspace when reporting this error.

 "Program memory overflow" also occurs when compiling the TEST1.BAS
 program generated below using 756+ CONSTants with the BC /Fs (far
 strings) option.

 The CONST limits are improved in BASIC PDS version 7.10, which can
 handle significantly more CONSTants than BASIC 7.00.

 The error message "Program memory overflow" is misleading because
 normally the compiler only gives that error when more than 64K of code
 has been generated for the module being compiled. This error
 represents a limitation of the compiler. This error is generated when
 the number of CONSTants that can be included in a BASIC module has
 been exceeded.

 The "Program memory overflow" error above is due to the amount of
 internal overhead that the compiler sets aside to do its work with
 CONSTants. The error message is not generated because of a lack of
 compiler workspace. In this case, 13K "bytes free" is a valid number.
 There is actually 13K of compiler workspace free. A different
 limitation has been encountered -- the number of CONSTants BC.EXE can
 handle.

 The BC.EXE in QuickBASIC version 4.50 and the BC.EXE compiler in BASIC
 versions 6.00b and 7.10 will successfully compile a program with over
 1000 CONSTants.

 Illustration
 ------------

 To demonstrate the limitation in 7.00, use the FIRST.BAS program below
 to create the BASIC program TEST1.BAS with "n" number of CONSTants.
 For example, a TEST1.BAS program created with approximately 650
 CONSTants will compile with no errors in BASIC PDS 7.00. A program
 with 680+ CONSTants compiled with BC /V gives "Program-memory
 overflow" in BASIC PDS 7.00.

 As a comparison to versions earlier than 7.00, if you create a
 TEST1.BAS program with 1000 CONSTants, it will compile correctly with
 BC.EXE 4.50 and BC.EXE 6.00b (which have a greater capacity for
 CONSTants than 7.00).

 As a comparison to 7.10, in TEST1.BAS created below, 7.10 can handle
 1100 CONSTants when compiled BC /V (but 1200 CONSTants gives "Program
 memory overflow"). In TEST1.BAS created below, 7.10 can handle 2100
 CONSTants when compiled BC /Fs (but 2200 CONSTants gives "Compiler out
 of memory, 0 bytes free"). BASIC 7.10 can thus handle many more
 CONSTants than 7.00.

 FIRST.BAS
 ---------

 FIRST.BAS prompts you for a number, and then creates another BASIC
 program, TEST1.BAS, with that many CONSTants. Compile the resulting
 TEST1.BAS with BC /V or /Fs to test for compiler limitations.

    DEFINT A-Z
    CLS
    INPUT "How many CONSTants to you want in the file: ", Num%
    OPEN "test1.bas" FOR OUTPUT AS #1
    beg$ = "CONST p"
    equals$ = " ="
    FOR i = 1 TO Num%
       constant$ = beg$ + LTRIM$(RTRIM$(STR$(i))) + equals$ + STR$(i)
       PRINT #1, constant$
    NEXT
    CLOSE
    PRINT "File 'test.bas' successfully created"
    END


 260. Disk vs. RAM Memory of Stand Alone vs. Run Time in BASIC PDS

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900407-1 docerr
 Last Modified: 15-JAN-1991    ArticleIdent: Q61350

 There is an apparent contradiction, which needs clarification, at the
 top of page 566 in the "Microsoft BASIC 7.0: Programmer's Guide" for
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10. Page 566 first states, "Stand-alone programs require more
 disk space than those requiring the run-time module." Then it states,
 "Stand-alone programs do have the following advantages, however:
 Stand-alone programs always require less memory than their run-time
 equivalents."

 The first statement means to say that one stand-alone program requires
 more disk space than one equivalent run-time program if you do not
 count the size of the run-time module. The second statement means to
 say that stand-alone programs always require less memory in RAM than
 their run-time equivalents (counting the run-time module).

 One stand-alone program requires less RAM or disk memory than its
 run-time equivalent if you count the size of the run-time module.
 However, with a large enough number of .EXE programs, the combined
 stand-alone programs require more disk storage space than the combined
 run-time equivalents, which share one run-time module.


 261. LPRINT Followed by BLOAD or BSAVE Gives "File Already Open"

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900417-59 buglist7.00 fixlist7.10
 Last Modified: 13-AUG-1990    ArticleIdent: Q61403

 Performing an LPRINT statement prior to a BLOAD or BSAVE statement
 causes a "file already open" error to occur on the BLOAD or BSAVE
 statement if the program is run from the QBX.EXE environment or if it
 is compiled with the BC /Fs (Far Strings) option.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS and MS
 OS/2. It does not occur in earlier BASIC versions. This problem was
 corrected in Microsoft BASIC PDS version 7.10.

 The program below demonstrates this problem. To generate the "file
 already open" error, run this program from the QBX.EXE environment or
 compile it with the Far Strings option.

 The following is a list of workarounds for this problem:

 1. Open the printer as a device and send output to the printer using
    the PRINT #<file number> statement instead of the LPRINT statement.

 2. Issue a CLOSE statement after the LPRINT statement.

 3. For an executable program, compile the program with the Near
    Strings option.

 Code Example
 ------------

    CLS
    PRINT "hello"
    DEF SEG = &HB800          'points to the segment at the screen buffer
    BSAVE "picture", 0, 4000  'save the screen in the file named picture
    DEF SEG                   'restore default segment
    LPRINT "bob"
    DEF SEG = &HB800
    BLOAD "picture", 0        '**file already open error occurs here
    DEF SEG


 262. NOFLTIN.OBJ: Hex Numbers Not Allowed with INPUT, READ, or VAL

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900409-55
 Last Modified: 21-SEP-1990    ArticleIdent: Q61406

 When you LINK the stub file NOFLTIN.OBJ into a program compiled with
 the /O switch, or into a custom run-time module built with
 BUILDRTM.EXE, the numeric parsing code will be replaced with an
 integer-only version.

 If you link with NOFLTIN.OBJ, all numbers used by INPUT, READ, and VAL
 must be within the range of legal long integers.

 Although it seems that a number represented in hexadecimal should fall
 into the category of "legal long integers," it does not. A program
 that INPUTs, READs, or uses the VAL function on a hexadecimally
 represented integer will either generate an error or return incorrect
 results. Hexadecimal number parsing is also eliminated with the
 NOFLTIN.OBJ stub file.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The following is an explanation of what happens when a program linked
 with the NOFLTIN.OBJ stub file uses either the INPUT, READ, or VAL
 commands on a hexadecimal number:

    INPUT - returns a "Redo from start"
    READ  - returns "Syntax error in module <module name>"
    VAL   - returns a value of 0


 263. Machine Hangs When BASIC PDS 7.00 Tries to Call QuickC 2.00

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900405-131 buglist7.00 S_QuickC
 Last Modified: 11-MAY-1990    ArticleIdent: Q61674

 When CALLing Microsoft QuickC version 2.00 from Microsoft BASIC
 Professional Development System (PDS) version 7.00, the machine hangs
 if a single- or a double-precision number is passed to the C routine
 and a comparison of that single- or double-precision number is then
 performed in the C routine.

 To work around this problem, do one of the following:

 1. CALL QuickC from QuickBASIC version 4.50 or from Microsoft BASIC
    Compiler versions 6.00 or 6.00b.

 2. Use Microsoft C Compiler version 5.10 instead of QuickC.

 3. Pass an integer or a long integer to QuickC instead of the
    floating-point number.

 The program below demonstrates the problem.

    Compile and LINK Instructions
    -----------------------------

       BC Basside.bas ;
       QCL /AM /c Cside.c ;
       LINK Basside + Cside,,,BRT70ENR.lib + MLIBCE.LIB ;

    Code Example
    ------------

    ' Here is the BASIC Code

    DECLARE SUB Mycfun CDECL (temp#)

    CLS
    PRINT "On the basic side"
    INPUT "Enter the double precision number "; one#
    CALL Mycfun(one#)
    LOCATE 10, 10
    PRINT "Enter any key to end"
    SLEEP
    CLS
    END

    ' Here is the C code

    #include <c:\qc2\include\stdio.h>

    void Mycfun( double *testdoub)
    {
      printf("I am in the C routine  %lf \n",*testdoub);
     if ((*testdoub) > 2000.0)
      {
         printf ("In the then \n");
      }
      else
      {
         printf("In the else \n");
      };

    printf ("Returning to BASIC \n");

    }


 264. Slow Printing from BASIC to Network Printer Under OS/2

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900122-142
 Last Modified: 10-MAY-1990    ArticleIdent: Q61438

 BASIC prints very slowly to a networked printer under OS/2 when
 compared to the same printing under DOS or the OS/2 DOS box. The
 printing speed is the same under OS/2 versions 1.00, 1.10, and 1.20.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS OS/2.

 The following code, PTEST.BAS, demonstrates the slow printing speeds
 under OS/2. Compile and LINK the program as follows:

    BC /O PTEST.BAS ;
    LINK PTEST ;

 The following is the program PTEST.BAS:

    start = TIMER
    FOR x = 1 TO 50
       LPRINT "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLM:";x
    NEXT
    PRINT "Final time: "; TIMER - start

 The following is the output from a 386 machine running at 16Mhz with
 the print spooler disabled:

    Operating System     Printer          Time (seconds)
    ----------------     -------          ----

    OS/2                 Network            64
    DOS box              Network             6
    DOS 4.01             Network             4
    OS/2                 Direct             46
    DOS                  Direct             46

 Note: The direct connect times are longer because the printer has no
 spooler, and therefore, the computer must wait for the printer to
 print each line. Also, a similar C routine prints at normal speed
 under OS/2.


 265. TEXTCOMP in BASIC PDS 7.00 Must Have PROISAM Loaded

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900420-97
 Last Modified:  1-MAY-1990    ArticleIdent: Q61439

 When invoking the function TEXTCOMP in Microsoft BASIC Professional
 Development System (PDS) version 7.00, you must have PROISAM.EXE or
 PROISAMD.EXE in memory. If you do not have one of the PROISAM.EXE
 files in memory, you will get a "Feature Unavailable" error when you
 try to invoke the function.

 This information only applies to Microsoft BASIC Professional
 Development System (PDS) version 7.00 for MS-DOS.

 The TEXTCOMP function is in the ISAM terminate-and-stay-resident
 program (TSR) because it needs the international sorting tables, which
 are also in the ISAM TSR, to perform its comparison.

 To load TSR and QBX from DOS, type:

    C:\>PROISAM
 or
    C:\>PROISAMD

 Then type the following:

    C:\>QBX

 Code Example
 ------------

    areequal% = TEXTCOMP ("this is a test","this is a test too")


 266. "Illegal Function Call" CHAINing to Stand Alone, /Fpa, or /Fs

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# S900416-144 B_QuickBas
 Last Modified: 20-SEP-1990    ArticleIdent: Q61483

 Attempting to CHAIN from an EXE that requires a run-time module to a
 stand-alone EXE causes the run-time error "Illegal Function Call" on
 the CHAIN statement.

 This error message does not occur when CHAINing in the reverse
 direction (from a stand-alone EXE to an EXE that requires a run-time
 module), or when CHAINing between identical EXE types (both stand
 alone, or both run time), or when using the RUN statement instead of
 CHAIN.

 "Illegal Function Call" also occurs when CHAINing from an EXE that
 requires a run-time module to an EXE compiled with a different math
 package (/Fpa versus /Fpi; found only in BC.EXE 6.00, 6.00b, 7.00, or
 7.10) or compiled with a different string option (/Fs far strings
 versus near strings; found only in Microsoft BASIC Professional
 Development System (PDS) version 7.00 or 7.10).

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC PDS versions 7.00
 and 7.10 for MS-DOS and MS OS/2.

 When transferring control to an EXE with a different run-time module,
 the RUN statement is the preferred method. RUN makes no attempt to
 preserve any values on the transfer, whereas CHAIN tries to maintain
 COMMON variables. The CHAIN statement should be used only when
 transferring control to another BASIC program that uses the same BASIC
 run-time library as the one being CHAINed from.

 Code Example
 ------------

 The following code example produces an "Illegal Function Call" on the
 CHAIN statement when the two programs are compiled as indicated:

    'A.BAS
    'Compile and link lines:
    '   BC A;
    '   LINK A;
    CHAIN "B"         'RUN does not cause the error
    END

    'B.BAS
    'Compile and link lines:
    '   BC /o B;
    '   LINK B;
    PRINT "In Program B"


 267. Maximum Number of ISAM Files Open at Once in BASIC 7.00/7.10

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900408-3
 Last Modified:  6-FEB-1991    ArticleIdent: Q61485

 The number of ISAM tables that you can have open at one time is
 determined by the number of database files that you have open. (See
 table below.)

 The maximum number of database files that you can have open at once is
 4 files. However, this is not the maximum number of tables you can
 have open at once. The maximum number of tables that you can have open
 at once is 13 tables in 1 database file, 10 tables in 2 database
 files, 7 tables in 3 database files, or 4 tables in 4 database files.

 Attempting to open more than the maximum allowed number of tables or
 database files at once gives error 67, "Too many files."

 A database file in Microsoft BASIC Professional Development System
 (PDS) version 7.00 or 7.10 is created with the default extension .MDB
 and contains the physical data for each table plus the indexes used to
 define and point to the data.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and 7.10 for MS OS/2.

 The ISAM engine in Microsoft BASIC PDS 7.00 and 7.10 has a maximum
 number of 16 pointers or ISAM handles that it can use with ISAM files.
 These are NOT the same as DOS file handles.

 Each file still takes one DOS file handle for its first open, but it
 doesn't need any additional DOS file handles for additional tables
 opened in the same database file.

 Each database file takes four ISAM handles on its initial open: one
 handle for the file, one for the indexes, one for the data, and one
 for the initial table. Each additional table referenced in an already
 opened database takes only one additional ISAM handle and no more DOS
 handles. This is because ISAM handles that point to the same file,
 indexes, and data already exist.

 As a result, the number of tables that you can have open at once is
 determined by the number of database files you are using. The
 following table gives the combinations of databases (.MDBs) and
 additional ISAM tables that you can have open at one time:

             Maximum Number of ISAM Files and Tables

    ---------------------------------------------------------
    # of .MDBs (files):  |    1         2        3        4
                         |
    # of additional      |
    tables in already    |    12        8        4        0
    opened .MDBs:        |
                         |
    Total tables:        |    13        10       7        4
                         |
                         |
    Total ISAM handles:  |    16        16       16       16
    ---------------------------------------------------------

 Therefore, if you have all of your tables in only 1 database file, you
 can open a total of 13 tables at once. However, if you open tables in
 4 database files, you can open only those 4 tables at once.

 This information is taken from page 388 of the "Microsoft BASIC 7.0:
 Programmer's Guide" for versions 7.00 and 7.10 (Chapter 10, "Database
 Programming with ISAM").


 268. SSEGADD Example Requires Large Model (/AL) for C Routine

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900501-79 docerr S_C S_QuickC
 Last Modified: 11-MAY-1990    ArticleIdent: Q61675

 The SSEGADD example on Page 351 of the "Microsoft BASIC 7.0: Language
 Reference" manual requires that the C routine (printmessage) be
 compiled with the large memory model (/AL). The following compile
 lines should be added for the C routine:

    For C 5.00 and 5.10
    -------------------

      CL -AL printmsg.c ;

    For QuickC 1.00, 1.01, 2.00, and 2.01
    -------------------------------------

      QCL -AL printmsg.c ;

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00.

 In general, routines written in C (or other languages) need to be
 compiled either for the medium memory (/AM) or the large memory (/AL)
 model. The model size affects the default pointer type (near or far).

 When the SSEGADD example is compiled for medium model, the program
 runs without error, but the wrong data is displayed. This is because
 the printf() function is expecting a near pointer (offset in the data
 segment) and printmessage is accepting a far pointer (segment and
 offset). If you use the large memory model, printf() expects a far
 pointer, and the program runs correctly.


 269. EMS Corrupt in QBX When 386MAX Loaded with the Noframe Option

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900430-50
 Last Modified: 11-MAY-1990    ArticleIdent: Q61679

 The error "EMS Corrupt" occurs when running QBX.EXE with 386MAX using
 the "noframe" option for 386MAX. This option causes 386MAX to not use
 any page frames in base memory. QBX.EXE does not support this method
 of expanded memory management.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00.


 270. QBX ISAM Capitalizes the Field Names of a Table in an .EXE

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900508-29
 Last Modified: 22-MAY-1990    ArticleIdent: Q62055

 Microsoft BASIC Professional Development System (PDS) version 7.00
 ISAM behaves in a slightly different manner in the QBX.EXE environment
 than when compiled. In a compiled program, when a database is created,
 the ISAM engine capitalizes all field names in the TYPE used to create
 the table. In the QBX.EXE environment, the ISAM engine leaves field
 names in whatever case they were coded in. This slight difference in
 behavior of the ISAM engine should not cause any problems in ISAM.
 BASIC variable names are not case sensitive. This includes the
 variable names used to create and access ISAM tables and indexes.

 This information applies to Microsoft BASIC PDS version 7.00 for MS-DOS.

 The following program displays this behavior. Run the program in the
 QBX.EXE environment, then use the ISAMPACK.EXE utility on the file the
 program creates. ISAMPACK.EXE displays the structure of the database
 as it repairs the file. It also shows the case on all tables, fields
 in the table, and indexes. Compile the program, run it, and use
 ISAMPACK to display the database structure again. This shows the
 difference in the case of the field names.

 This difference occurs no matter how ISAM is used. ISAM can be used
 in four different ways: PROISAM(d) TSR with or without the run-time
 module; linked directly into the program itself; or linked into the
 run-time module. All forms of accessing the ISAM engine behave the
 same way.

 Code Example
 ------------

     TYPE table
         Field1      AS LONG
         Field2      AS LONG
         Field3      AS LONG
     END TYPE
     ' Check if the table already exists. If so, delete it.
     IF (DIR$("db1.mdb") <> "") THEN
         DELETETABLE "db1.mdb", "Table1"
     END IF
     OPEN "db1.mdb" FOR ISAM table "Table1" AS 1
     CREATEINDEX 1, "Idx", 1, "Field1", "Field2", "Field3"
     CLOSE
     END


 271. Description of EM-Management Switches for BASIC PDS 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900503-164
 Last Modified: 22-MAY-1990    ArticleIdent: Q62056

 This article describes the purpose and use of the Microsoft BASIC
 Professional Development System (PDS) version 7.00 switches that allow
 you to configure the use of expanded memory (EM). Especially important
 is the description of the /Es switch and its relationship to the other
 EM switches.

 This information applies to Microsoft BASIC PDS 7.00 for MS-DOS and MS
 OS/2.

 Saving and Restoring the EM State
 ---------------------------------

 By default, QBX.EXE and programs compiled with BC.EXE 7.00 perform
 only the minimum saving and restoring of the EM state necessary to
 allow the program to work properly. This assumes that no third-party
 code using EM is present. To get more than this minimal amount of EM
 save and restore, you must specify /Es upon loading QBX.EXE or when
 compiling programs with BC.EXE. This is by design. If BASIC always
 saved and restored the EM state, the save and restore operations would
 significantly affect the speed of ISAM and quick library (QLB)
 calling. The purpose of the /Es switch is to allow programs to use
 third-party code that uses EM. The trade-off is a degradation in
 speed.

 Table of EM Switches and Where You Can Use Them
 -----------------------------------------------

    Use With     Switch Name   Switch Purpose
    --------     -----------   --------------

    QBX only     /Ea           Arrays > 512 bytes but < 16K in
                               EM. Default: no arrays in EM.

    QBX only     /E:n          n = amount in kilobytes of EM QBX
                               will use. 0 means QBX uses no EM.
                               Default: use all available EM.

    QBX and BC   /Es           Enable EM state save/restore.

    PROISAM(D)   /Ie:n         Reserves n kilobytes of EM for
                               other applications (Such as QBX).
                               ISAM will use only 1.2 MB of EM
                               maximum.

 Examples: Use of the Switches, Their Effects, and How They Interact
 -------------------------------------------------------------------

 QBX /E:0

    * This switch causes QBX.EXE to disable use of EM for code storage.

    * If the program has ISAM using EM, it is assumed that no
      third-party code that is accessing EM is present. With /E:0, the
      default for QBX.EXE is not to save and restore the EM state on
      ISAM use. This maximizes the speed of ISAM performance.

 QBX /E:0 /Es

    * Save and restore operations occur on any ISAM statement or QLB
      call. Use this combination if you are loading QLBs that use EM
      and ISAM using EM is being used as well.

 QBX /E:N and N Is Nonzero

    * The EM state on QLB calls is not saved and restored.

    * ISAM calls will be saved and restored when both QBX.EXE and ISAM
      are sharing EM.

    * It is assumed there are no QLBs using EM.

 QBX /Es or QBX /E:N /Es

    * This switch forces QLB calls and ISAM statements to be saved and
      restored.

    * This switch would be used if you are using QBX.EXE and calling
      QLB routines that access EM.

 BC with No EM-Management Switches, No Overlays, No ISAM

    * The EM state is not saved or restored.

    * Third-party routines accessing EM should work correctly.

 BC with Overlays That Will Load from EM

    * EM will be used by compiled code in the overlays.

    * The default is to save and restore EM on all ISAM statements in a
      program that uses overlays.

    * This could still cause problems if third-party library routines
      that use EM are called.

 BC /Es with Overlays and ISAM

    * EM will be saved and restored on ISAM statements.

    * Always use /Es when doing mixed-language calls to routines
      that use EM as well.

 BC /Es Without EM Overlays, but With ISAM

    * /Es always saves and restores ISAM statements when ISAM is using
      EM.

    * You would use this switch if the program uses ISAM, if ISAM is
      using EM, and if there are mixed-language CALLs to routines that
      use EM.

    * Note: /Es will not cause ISAM statements to be saved and restored
      if ISAM is NOT using EM.


 272. Multiple Duplicate Definition L2025 with Graphics Stub Files

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900329-130
 Last Modified: 22-MAY-1990    ArticleIdent: Q62058

 Linking a Microsoft BASIC Professional Development System (PDS)
 version 7.00 program with the NOGRAPH.OBJ stub file and any of the
 other graphics stub files (NOEGA.OBJ, NOOGA.OBJ, NOVGA.OBJ, or
 NOHERC.OBJ) produces multiple "L2025 symbol defined more than once"
 error messages. This is because the NOGRAPH object module is a
 superset of the other NOxxx.OBJ graphics files. If you use NOGRAPH,
 you remove all graphics support and should not use any of the other
 NOxxxx.OBJ graphics stub files. The individual NOxxx.OBJ graphics stub
 files contain a subset of the stub routines in the NOGRAPH.OBJ stub
 file. When you try to link them both, you are trying to include the
 same routines twice, and therefore, the linker generates L2025,
 telling you that the same stub routine is being linked in twice.

 NOGRAPH.OBJ should be used by itself. If you want to stub out all
 graphics support, link with NOGRAPH.OBJ and no other stub file.
 However, if you want VGA support but not EGA, HERC, or OGA, link your
 program with NOEGA, NOHERC, and NOOGA, but not with NOVGA and NOGRAPH.

 This information applies to Microsoft BASIC PDS 7.00 for MS-DOS and MS
 OS/2.


 273. WHEREIS.BAS Problem Under MS-DOS 4.00 and 4.01

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas
 Last Modified: 25-MAY-1990    ArticleIdent: Q62202

 The sample program WHEREIS.BAS searches for the location of a specific
 file on disk. WHEREIS uses the BASIC SHELL statement to perform a DOS
 DIR command and redirects the results to a file that WHEREIS.BAS later
 scans for the file it is searching for.

 Under MS-DOS versions 4.00 and 4.01, the WHEREIS.BAS program SHELL
 command does not function correctly. The path specification string
 passed to the DOS DIR command from WHEREIS ends with a blackslash
 character, resulting in a DIR command something like the following:

    DIR C:\QB45\x\

 This form of the DIR command returns a list of files in the QB45
 directory when used under MS-DOS 3.x and earlier. Under MS-DOS 4.00
 and 4.01, this command fails with the error message "Invalid
 directory." Removing the trailing backslash allows the DIR command to
 operate under MS-DOS 4.00 and 4.01.

 To correct WHEREIS.BAS to operate under MS-DOS 4.00 and 4.01, you need
 to add several lines to the ScanDir SUBprogram in WHEREIS.BAS.

 In the original version of WHEREIS.BAS, line 12 of the ScanDir SUB
 reads as follows:

    SHELL "DIR " + PathSpec$ + " > " + TempSpec$

 To remove the trailing backslash from the string PathSpec$, replace
 the line above with the following:

    StripPath$ = PathSpec$

    IF RIGHT$(StripPath$,1) = "\" AND LEN(StripPath$) > 1 THEN
      StripPath$ = LEFT$(StripPath$, LEN(StripPath$) - 1)
    END IF

    SHELL "DIR " + StripPath$ + " > " + TempSpec$


 274. ADAPTER.BAS Needs SLEEP Statement When Compiled

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900504-3
 Last Modified: 29-MAY-1990    ArticleIdent: Q62203

 The sample program APAPTER.BAS included with Microsoft BASIC
 Professional Development System (PDS) version 7.00 must have the SLEEP
 statement added to the code after the call to the SUBprogram so that
 the message that states what video modes are supported on the monitor
 is displayed when the program is compiled.

 This information applies to Microsoft BASIC PDS 7.00 for MS-DOS and
 OS/2.

 ADAPTER.BAS works correctly when compiled, except that the message
 displayed at the end of the program that states what video modes are
 supported by the monitor is displayed and then erased. This is due to
 the statement "SCREEN 0, 0", which sets the screen mode back to mode 0
 following the test. This problem is related to the second parameter,
 0, which is the "Color switch" parameter. When anything in the video
 mode changes, the screen is erased. When the message is displayed in
 the compiled program, the program ends and the screen mode is set back
 to composite color monitor mode. A color switch parameter of 0 in the
 SCREEN statement sets it to noncolor. By removing the color switch
 parameter or setting it to 1, ADAPTER.BAS will work correctly.

 ADAPTER.BAS works in the environment because the SCREEN mode is not
 reset until you respond to the "Press any key to continue" message.
 This can be demonstrated in the compiled program by placing a SLEEP
 statement following the CALL to the SUBprogram Adapter and leaving the
 SCREEN 0, 0 statement as is.

 Code Example
 ------------

   -------ADAPTER.BAS-----------

   DECLARE SUB Adapter ()
   DEFINT A-Z
   Adapter
   SLEEP
   END


 275. LINK L1083 "Cannot Open Run File" on Novell Network

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900423-82
 Last Modified: 18-OCT-1990    ArticleIdent: Q62206

 A customer reported that when linking a program in Microsoft BASIC
 Professional Development System (PDS) version 7.00 on a workstation
 running Novell NetWare ELS Level I or Level II, you may get LINKer
 error L1083, "cannot open run file." Another customer reported the
 problem on Novell NetWare Advanced 286 version 2.15. This problem does
 not occur when the network software is not installed, according to the
 customers.

 The problem seems to occur only if there already is an .EXE file on
 disk with the same base name as the .OBJ file that was being linked.
 When the old .EXE file is deleted, the LINK command functions
 successfully. Microsoft has not tested or confirmed this information.

 Microsoft BASIC PDS 7.00 and 7.10 have not been tested under, and are
 not guaranteed to work under, any version of Novell NetWare.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS.

 The customer encountered this problem on both a workstation and server
 machine with the following configurations:

    286 12-MHz Clone
    Novell ELS Level 1 version 2.0 A
    (9/15/87)

 or

    Novell ELS Level 2 version 2.15
    DOS version 3.30
    Hercules video card


 276. Calling API Function to Get All Available Drives

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900517-71
 Last Modified:  7-JUN-1990    ArticleIdent: Q62214

 Microsoft BASIC Compiler versions 6.00 and 6.00b and Microsoft BASIC
 Professional Development System (PDS) version 7.00 protected mode
 programs can call the OS/2 API function DosQCurDisk() to get all the
 available logical drives. DosQCurDisk() requires the following
 parameters:

    Parameter   Description
    ---------   -----------

    PTR WORD    Receives current drive code (1 = A, 2 = B, etc.)

    PTR DWORD   Receives logical drive bitmap (logical drives A-Z
                correspond to bits 0-25; a bit is set if a
                logical drive exists)

 The first parameter is not important in getting the available drives,
 but it is worthy to note that for API functions, a WORD (2 bytes) has
 a BASIC type of INTEGER. Likewise, a DWORD (4 bytes) has a BASIC type
 of LONG. Since the specification requires pointers to these data
 items, the DECLARE statement for DosQCurDisk() uses the SEG keyword for
 each of the parameters. This causes 4-byte addresses of the parameters
 to be passed instead of 2-byte addresses, which is the default because
 BASIC uses the medium-memory model. Also, API functions return an
 error code, so for BASIC to retrieve this code, you must declare
 DosQCurDisk() as a FUNCTION.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and Microsoft BASIC (PDS) version 7.00 for MS OS/2.

 For more information on calling OS/2 API functions from Microsoft
 BASIC Compiler versions 6.00 and 6.00b, see Page 21 of the "Microsoft
 BASIC Compiler 6.0: User's Guide" included with the product.

 For more information on calling OS/2 API functions from Microsoft
 BASIC PDS version 7.00, see Page 523 of the "Microsoft BASIC 7.0:
 Programmer's Guide" included with the product.

 For more information on DosQCurDisk(), see Page 547 of "Advanced OS/2
 Programming," by Ray Duncan (Microsoft Press, 1989).

 To see a BASIC PDS 7.00 sample program that finds all the available
 drives in DOS or OS/2 real mode, query in this Knowledge Base on the
 word "chdrive".

 The following sample program (LOGICAL.BAS) reports all the available
 logical drives.

 To compile the program, use the following:

    bc logical /lp;

 To link the program for BASIC 6.00 and 6.00b, use the following:

    link /nop logical,,,doscalls;

 To link the program for BASIC 7.00, use the following:

    link /nop logical,,,os2;

 Code Example
 ------------

 ' This declaration was taken from the include file
 BSEDOSFL.BI.

 DECLARE FUNCTION DosQCurDisk% (SEG CurrentDrive AS INTEGER,_
                                SEG DriveBitmap  AS LONG)

 ' CurrentDrive% receives the current drive code (A=1, B=2,
 ' etc.). DriveBitmap& receives a bitmap of each logical
 ' drive's availability.
 ErrorCode% = DosQCurDisk% (CurrentDrive%, DriveBitmap&)

 IF ErrorCode% THEN

    PRINT "An error occurred, the code is";ErrorCode%

 ELSE

    PRINT "The following drives are available:";

    ' Bit% is used to circulate through bits 0-25 (drives A-Z)
    ' of DriveBitmap&.  If (DriveBitmap& AND 2^Bit%) = 2^Bit%,
    ' then bit Bit% of DriveBitmap& is set and the
    ' corresponding logical drive is available.
    FOR Bit% = 0 to 25
       IF (DriveBitmap& AND 2^Bit%) = 2^Bit% THEN
          PRINT " ";CHR$(Bit% + 65);
       END IF
    NEXT Bit%

 END IF

 END


 277. QBX Hangs Using KEY with Two or More Characters, Then INPUT$

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 fixlist7.10 SR# S900517-71
 Last Modified: 29-JAN-1991    ArticleIdent: Q62216

 The program below hangs in the QBX.EXE environment of Microsoft BASIC
 Professional Development System (PDS) version 7.00. The problem occurs
 when you specify two or more characters in the KEY statement's string
 to specify a softkey and follow that with an INPUT$ statement. After
 you run the program in the QBX.EXE environment, press the softkey, and
 press an additional key, the program hangs after it ends with the
 "Press any key to continue" message.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 version 7.00. This problem is corrected in BASIC PDS version 7.10.

 This is only a problem in the QBX.EXE environment. This program works
 correctly when it is compiled to an .EXE program (with either the Near
 Strings or Far Strings option).

 To work around this problem in BASIC 7.00, do any of the following:

 1. Use the INPUT statement (or INKEY$ function in a loop) instead of
    the INPUT$ function.

 2. Use only one character in the string for the KEY statement.

 The following code sample demonstrates this problem:

    KEY 10, "*" + CHR$(13)   ' Any two or more characters produce problem.
    my$ = INPUT$(1)          ' Press F10 then additional key as input.
    print my$


 278. EXEHDR.EXE Switch Omissions in 7.00/7.10 Manual

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900517-206 docerr
 Last Modified: 15-JAN-1991    ArticleIdent: Q62217

 The EXEHDR documentation on page 347 of the "Microsoft CodeView and
 Utilities User's Guide" for Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 mentions only the /v (verbose)
 option and omits many additional EXEHDR options. This manual also
 unnecessarily documents the EXEMOD utility (on pages 307-311), which
 is an older version of EXEHDR. EXEMOD is not shipped with BASIC PDS
 7.00 or 7.10 because EXEHDR contains all of EXEMOD's functionality.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS and MS OS/2.

 The full list of EXEHDR options can be displayed by typing EXEHDR /?
 at the DOS prompt. The options are as follows:

    Usage: EXEHDR [options] <file-list>
    Valid options are:

       /?
       /HEAP:(0H - ffffH)
       /HELP
       /MAX:(0H - ffffH)
       /MIN:(0H - ffffH)
       /NEWFILES
       /NOLOGO
       /PMTYPE:(PM | VIO | NOVIO | WINDOWAPI |
                   WINDOWCOMPAT | NOTWINDOWCOMPAT)
       /RESETERROR
       /STACK:(0H - ffffH)
       /VERBOSE

 Note: The hex values are listed in assembly notation (for example,
 ffffH). Hex values should actually be input with C notation using the
 "0x" prefix instead of the "H" suffix (for example, ffffH -> 0xffff).
 The values can also be entered in decimal notation without prefixes or
 suffixes.

 If the assembler notation for hex values is used with EXEHDR, the
 following errors will occur:

    EXEHDR: error U1110: malformed number FFFFH
    EXEHDR: error U1115: option /MAX:FFFFH ignored


 279. OS/2 API Function to Get Current Drive

 Product Version(s): 6.00 6.00b 7.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900517-70
 Last Modified:  7-JUN-1990    ArticleIdent: Q62218

 Microsoft BASIC Compiler versions 6.00 and 6.00b and Microsoft BASIC
 Professional Development System (PDS) version 7.00 protected mode
 programs can call the OS/2 API function DosQCurDisk() to get the
 currently selected drive. DosQCurDisk() requires the following
 parameters:

    Parameter   Description
    ---------   -----------

    PTR WORD    Receives current drive code (1 = A, 2 = B, etc.)

    PTR DWORD   Receives logical drive bitmap (logical drives A-Z
                correspond to bits 0-25; a bit is set if a
                logical drive exists)

 The second parameter is not important in getting the current drive,
 but it is worthy to note that for API functions a DWORD (4 bytes) has
 a BASIC type of LONG. Likewise, a WORD (2 bytes) has a BASIC type of
 INTEGER. Since the specification requires pointers to these data
 items, the DECLARE statement for DosQCurDisk() uses the SEG keyword for
 each of the parameters. This causes 4-byte addresses of the parameters
 to be passed instead of 2-byte addresses, which is the default because
 BASIC uses the medium-memory model. Also, API functions return an
 error code; therefore, for BASIC to retrieve this code, it must
 declare DosQCurDisk() as a FUNCTION.

 The DECLARE statements for almost every API function are located in
 include files that come with BASIC 6.00 and 6.00b and BASIC PDS 7.00.
 To modify the DECLARE statement, you just have to include the right
 file. See the PACKING.LST file included with the product for a
 description of these include files.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and Microsoft BASIC PDS version 7.00 for MS OS/2.

 For more information on calling OS/2 API functions from Microsoft
 BASIC Compiler versions 6.00 and 6.00b, see Page 21 of the "Microsoft
 BASIC Compiler 6.0: User's Guide" included with the product.

 For more information on calling OS/2 API functions from BASIC PDS
 version 7.00, see Page 523 of the "Microsoft BASIC 7.0: Programmer's
 Guide" included with the product.

 For more information on DosQCurDisk(), see Page 547 of "Advanced OS/2
 Programming," by Ray Duncan (Microsoft Press, 1989).

 Note that BASIC PDS version 7.00 supports the function "CURDIR$",
 which can also be used to get the currently selected drive. However,
 using this method requires some string parsing, so although the code
 is smaller, it may be slower.

 The sample program below (GETDRIVE.BAS) reports the currently selected
 drive.

 To compile the program, use the following:

    bc getdrive /lp;

 To link the program for BASIC 6.00 and 6.00b, use the following:

    link /nop getdrive,,,doscalls;

 To link the program for BASIC 7.00, use the following:

    link /nop getdrive,,,os2;

 Code Example
 ------------

 ' This declaration was taken from the include file
 ' BSEDOSFL.BI

 DECLARE FUNCTION DosQCurDisk% (SEG CurrentDrive AS INTEGER,_
                                SEG DriveBitmap  AS LONG)

 ' CurrentDrive receives the current drive code (A=1, B=2,
 ' etc.)
 ' DriveBitmap receives a bitmap of each logical drive's
 ' availability

 ErrorCode% = DosQCurDisk% (CurrentDrive%, DriveBitmap&)

 IF ErrorCode% THEN
    PRINT "An error occurred, the code is";ErrorCode%
 ELSE
    PRINT "The current drive is "; CHR$(CurrentDrive% + 64)
 END IF

 END


 280. TSCNIOxx.OBJ Stub Files Remove Screen 0 Page-Switching

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900423-7
 Last Modified: 20-JUN-1990    ArticleIdent: Q62260

 If you link the stub file TSCNIOxx.OBJ to your BASIC object module,
 any attempt to change the visual or active page to any page other than
 Page 0 generates the error "Feature Removed." The run-time routines
 responsible for handling page switching are included in those run-time
 routines stubbed out by TSCNIOxx.OBJ. This information applies to
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS and MS OS/2.

 The TSCNIOxx.OBJ stub file is used to remove all graphics support that
 is automatically inserted in your program at link time so that you may
 generate smaller EXE files.

 For more information on this and other stub files, query on the
 following words:

    smaller and stub and EXE

 The sample code below reproduces the error "Feature Removed."

 Compile and link as follows:

    BC scrntest.bas /o ;
    LINK scrntest + tscionr.obj,,,bcl70enr.lib /noe ;

 Code Example
 ------------

    CLS
    PRINT "Switching pages"
    SLEEP
    SCREEN 0, , 1, 1        'This line will generate the Feature.
                            'Removed error because it tries to switch
                            'pages in Text mode.


 281. Problem with SCREEN 0 Paging on CGA in QB.EXE & QBX.EXE

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900517-177 B_QuickBas buglist7.00 buglist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q62270

 Paging through the active and visible pages of SCREEN 0 does not work
 correctly on a CGA monitor in the QBX.EXE or QB.EXE environment  This
 problem occurs only when single-stepping through a program and setting
 breakpoints to view the output of the various pages. Machines equipped
 with EGA or VGA video adapters do not demonstrate this problem.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 QuickBASIC version 4.50 (buglist4.50) and in the QBX.EXE environment
 of Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10. We are researching this problem and will post new
 information here as it becomes available.

 This problem does not occur in QuickBASIC versions 4.00 and 4.00b.

 The following code example demonstrates the problem in QB.EXE or
 QBX.EXE. Step through the program using the F8 key. After the PRINT
 statement, press the F4 function key to view the output screen. The
 screen will not be updated on a CGA monitor.

 Code Example
 ------------

    DEFINT A-Z
    DO UNTIL INKEY$ <> ""
       SCREEN 0, 0, x, x
       CLS
       PRINT "SCREEN MODE 0, PAGE"; x
       x = x + 1          ' Press F4 key to view the output screen
       IF x = 8 THEN x = 0
    LOOP


 282. Incorrect Results When Compiling with Near Strings

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900517-165
 Last Modified:  1-JUN-1990    ArticleIdent: Q62456

 A program compiled with the Near Strings option (without /Fs) may
 produce incorrect results when the program uses a combination of the
 following:

 1. The LEN function on a variable length string
 2. Integer division
 3. String concatenation

 The same program will run correctly when run from the QBX.EXE
 environment or when compiled with Far Strings (with /Fs).

 Microsoft has confirmed this to be a problem in the BC.EXE 7.00
 compiler provided with Microsoft BASIC Professional Development System
 (PDS) version 7.00 for MS-DOS and MS OS/2. We are researching this
 problem and will post new information here as it becomes available.
 This problem does not occur in earlier versions of Microsoft BASIC
 Compiler (BC.EXE).

 This problem results from incorrect optimization by the BC.EXE 7.00
 compiler. You can disable these optimizations by either compiling with
 the /X compiler switch or by including line numbers in the area of the
 program where the error occurs.

 The following steps reproduce the problem:

 1. Use the LEN function on a variable-length string.

 2. Take the number returned by the LEN function and perform integer
    division on that number.

 3. Reassign a concatenated string to the variable-length string
    mentioned in step 1.

 4. Again, use the LEN function on the variable-length string and
    perform integer division on that result.

 If the program is compiled with Near Strings, the result of the
 calculation in Step 4 will be incorrect.

 The program below demonstrates the problem. The second PRINT statement
 should display a value of 9; however, if the program is compiled with
 Near Strings, a 0 will be displayed instead. The value returned by
 LEN(a$) is correct, but when integer division is performed on this
 value, an incorrect result is produced.

    PRINT LEN(a$) \ 2
    a$ = "concatenate " + "strings"
    PRINT LEN(a$) \ 2        'the value printed here is incorrect
    END

 Listed below are four different methods to work around the problem:

 1. Compile the program with /X or include line numbers in the area
    of the program where the problem occurs. Both of these actions
    disable some of the compiler optimizations that are the cause
    of this problem.

 2. Do not use integer division. Instead, perform regular division
    and then use the INT function to get the desired result, as in the
    following example:

       PRINT INT(LEN(a$) / 2)
       a$ = "concatenate " + "strings"
       PRINT INT(LEN(a$) / 2)
       END

 3. Avoid string concatenation, as follows:

       PRINT LEN(a$) \ 2
       a$ = "concatenate strings"  'assign a$ to 1 string instead of
                                   'using concatenation
       PRINT LEN(a$) \ 2
       END

 4. Assign the string that was created by concatenating strings to
    another string variable. Then, perform the LEN function on the
    new string, as in the following example:

       PRINT LEN(a$) \ 2
       a$ = "concatenate " + "strings"
       b$ = a$                'insert this line
       PRINT LEN(b$) \ 2      'and perform the rest of the
                              'calculations on b$
       END


 283. ISAM INSERT with Duplicate Key Incorrectly Allocates Record

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist7.00 buglist7.10
 Last Modified:  8-AUG-1990    ArticleIdent: Q62460

 When you specify a unique key with CREATEINDEX using Microsoft BASIC
 Professional Development System (PDS) version 7.00 ISAM, inserting
 records with duplicate keys causes a trappable error (run-time error
 86). However, the ISAM engine still inserts one record into the ISAM
 file per attempt to insert a duplicate key record. The records
 inserted with the duplicate keys are marked as deleted. The BASIC
 function LOF, which returns the total number of records in a BASIC PDS
 7.00 ISAM file, will show the actual number of successful writes to
 the file, showing that the records written with duplicate keys are not
 valid. Since these records are marked as deleted, using the ISAMPACK
 utility will remove the records and reduce the file to its appropriate
 size.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS. We are researching this problem and will post new information
 here as it becomes available.

 The sample program below demonstrates the problem. If you execute the
 code below, a record will be inserted into the ISAM file, and then 999
 more attempts will be made to insert that record. Since the program
 specifies unique keys in the CREATEINDEX statement, run-time error 86,
 "Duplicate key," will occur. The program will trap the "Duplicate key"
 error and resume execution. When the program terminates, the LOF
 function will show there is only one legitimate record in the file.
 The file size, however, will be approximately 1.6 MB. Using
 ISAMPACK.EXE on the ISAM file created by the program will reduce the
 file to 64K in size.

 To execute the program below, you must load the BASIC PDS 7.00 or 7.10
 ISAM support by executing the PROISAMD.EXE TSR (terminate-and-stay-resident)
 program. After PROISAMD has been loaded, you can execute the program
 within the QBX.EXE environment.

 Code Example
 ------------

 'WARNING: Even though this program only successfully
 '         writes one ISAM record, it creates a 1.6 MB file.
 TYPE NewRec
    AString AS STRING * 8
 END TYPE

 40 ON ERROR GOTO errorhandler
 50 DIM NewBuf AS NewRec
 60 OPEN "output.mdb" FOR ISAM NewRec "NewRec" AS #1

 70 CREATEINDEX #1, "X", 1, "AString"    '* Specify unique key *

 80 NewBuf.AString = "ABCDEFGH"
 90 FOR i = 1 TO 1000
 100     INSERT #1, NewBuf      '* Causes 999 "Duplicate key" errors *
 110    PRINT i
 120 NEXT
 130 PRINT "Size of database (should be 1): "; LOF(1)
 135 DELETEINDEX #1, "X" ' Delete the index so the program
                         ' can be run over.
 140 END

 errorhandler:
 150     SELECT CASE ERR
             CASE 86: PRINT "duplicate key attempted":
             RESUME NEXT
         CASE ELSE
             CLS
             PRINT "An error occurred. The number is: "; ERR
             PRINT "It occurred on line: "; ERL
             DELETEINDEX #1, "X"
             END
         END SELECT


 284. Must Load PROISAM or PROISAMD to Use ISAM Utilities

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900509-65
 Last Modified:  8-AUG-1990    ArticleIdent: Q62770

 As stated on Page 389 of the "Microsoft BASIC 7.0: Programmer's Guide"
 for versions 7.00 and 7.10, when using the ISAM utilities ISAMIO,
 ISAMCVT, or ISAMPACK, you must have the ISAM support installed.

 Depending on how you ran SETUP.EXE, the ISAM utilities ISAMIO.EXE,
 ISAMCVT.EXE, and ISAMPACK.EXE are built either to run as stand-alone
 programs or to require the terminate-and-stay-resident (TSR) form of
 ISAM (PROISAMD.EXE). SETUP always installs the ISAMREPR.EXE (ISAM
 repair) utility to run as a stand-alone program. For more information
 about how SETUP installs the ISAM utilities, search for a separate
 article in this Knowledge Base with the following words:

    how and SETUP and builds and ISAMIO

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The following table describes what each of the ISAM utilities does:

    Utility Name        Use
    ------------        ---

    ISAMREPR            Repairs or rebuilds database

    ISAMCVT             Converts other ISAM file types to the ISAM
                        format used by BASIC PDS 7.00

    ISAMPACK            Rotates all deleted records to the end of the
                        ISAM file, and if a 32K section is marked for
                        deletion, it decreases the size of the data
                        file by 32K

    ISAMIO              Converts to or from simple ASCII text files and
                        ISAM files


 285. Record Number for PUT/GET Statement Can Be a Long Integer

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900319-92 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q62771

 Pages 147 and 280 in the "Microsoft BASIC 7.0: Language Reference"
 and Page 110 in the "Microsoft BASIC 7.0: Programmer's Guide"
 incorrectly state that when specifying the record number in a GET/PUT
 statement for a random file or the position number for a binary file,
 the record or position number should be an integer.

 The explanation for the GET/PUT statement should describe the record
 or position number as being either an integer or a long integer.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The correct syntax for the GET/PUT statement is as follows:

   {GET|PUT} [#]filenumber% [, [recordnumber&] ] [, [variable] ]

 When accessing a random file, "recordnumber&" represents the number of
 the record to be read or written. When accessing a binary file,
 "recordnumber&" represents the byte position of where the reading or
 writing starts.

 The online Help for BASIC PDS 7.00 and 7.10 correctly describes the
 record number as "recordnumber&". The following documentation,
 however, incorrectly describes the record number as "recordnumber%":

 1. Page 110 of the "Microsoft BASIC 7.0: Programmer's Guide" for
    7.00 and 7.10

 2. Pages 147 and 280 of the "Microsoft BASIC 7.O: Language Reference"
    manual for 7.00 and 7.10

 By specifying the recordnumber variable as "recordnumber&" instead of
 "recordnumber%", it is inferred that the record number variable may
 either be of type INTEGER or LONG INTEGER.

 Using recordnumber% would suggest that the largest possible record
 number to be 32,767. Since the largest possible record number is
 2,147,483,647, the record number should be described as recordnumber&.


 286. OPEN New Table with PROISAM Causes "Feature Unavailable"

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900312-94 docerr
 Last Modified: 15-JAN-1991    ArticleIdent: Q62772

 Page 234 of "Microsoft BASIC 7.0: Language Reference" (for versions
 7.00 and 7.10) incorrectly states that the error generated when
 attempting to OPEN a new ISAM table or database with the PROISAM TSR
 loaded will produce a "File not found" error message. The correct
 error message produced is actually "Feature Unavailable."

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Note: The PROISAM TSR (or library) allows existing databases and
 tables to be accessed, but does not allow dynamic allocation of
 databases and tables. The PROISAMD TSR (or library) is required to
 dynamically allocate databases and tables.


 287. Overflow Error OPENing ISAM File with TYPE > 255 Elements

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900518-75 buglist7.00 buglist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q62773

 An "Overflow" error will occur when OPENing a file FOR ISAM with a
 TYPE containing a large number of elements. This number is 255 for
 INTEGERs, LONGs, and fixed-length STRINGs, and 239 for DOUBLEs and
 CURRENCYs. This problem occurs in both the QBX.EXE environment and
 compiled EXEs.

 To work around the problem, limit the number of elements in the main
 type by combining some elements in a nested type or arrays.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS. We are researching this problem and will post new information
 here as it becomes available.

 Code Example
 ------------

 The following program fragment (the majority of TYPE is left out for
 space reasons) demonstrates the problem. The "Overflow" error will
 occur on the OPEN statement:

 TYPE BigType
   I1 AS INTEGER
   I2 AS INTEGER
   I3 AS INTEGER
                           <... I4-I250>
   I251 AS INTEGER
   I252 AS INTEGER
   I253 AS INTEGER
   I254 AS INTEGER
   I255 AS INTEGER        '255 for INTEGER/LONG/STRING*n
 END TYPE                 '239 for DOUBLE/CURRENCY

 OPEN "BigType" FOR ISAM BigType "BigType" AS #1  'Overflow error
                                                  'here
 CLOSE

 To use the workaround listed above, the TYPE BigType should be made of
 nested types, such as the following:

 TYPE NestType
   A AS INTEGER
   B AS INTEGER
   C AS INTEGER
   D AS INTEGER
   E AS INTEGER
 END TYPE

 TYPE NewBigType
   I(1 TO 250) AS INTEGER
   N AS NestType
 END TYPE


 288. Using PC-DOS 3.00 and QBX.EXE Will Give SHELL Problems

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900522-12 buglist7.00 buglist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q62774

 When using QuickBASIC Extended (QBX.EXE) version 7.00 or 7.10 under
 PC-DOS version 3.00, if you first generate a PC-DOS "Bad command or
 file name" error on a SHELL statement, then any subsequent uses of the
 SHELL statement with any parameter will result in the "Bad command or
 file name" error until you restart QBX.EXE. To work around this
 problem, you can either use QuickBASIC version 4.50, or upgrade to
 either MS-DOS or a newer version of PC-DOS, or compile the program and
 run it outside of the environment with the near strings option
 (without /Fs).

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 under
 PC-DOS 3.00. We are researching this problem and will post new
 information here as it becomes available.

 This problem does not occur in Microsoft QuickBASIC versions 4.00,
 4.00b, or 4.50, or in Microsoft BASIC Compiler versions 6.00 or 6.00b
 under PC-DOS.

 The following code example demonstrates the problem:

 Code Example
 ------------

    SHELL "Errorxyz"      ' This will cause the first "Bad command or
                          ' file name" error.
    SHELL "CLS"           ' This is supposed to work but it gives a "bad
                          ' command or file name" error


 289. FRE(-1) Decreases with Repeated Use of DEF FNa$ in QBX.EXE

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900520-2 buglist7.00 fixlist7.10
 Last Modified:  2-NOV-1990    ArticleIdent: Q62813

 Repeated use of a DEF FN function to return a string in the QBX.EXE
 environment causes far heap memory to decrease as shown in the
 following program. This does not occur with a compiled .EXE program or
 if a FUNCTION procedure is used in place of the DEF FN function.

 Microsoft has confirmed this to be a problem in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS. This problem was corrected in BASIC PDS 7.10.

 To work around the above problem, use a BASIC FUNCTION procedure in
 place of the DEF FN function.

 This problem does not occur with any version of Microsoft QuickBASIC
 (QB.EXE) or any version of Microsoft BASIC Compiler (BC.EXE).

 Microsoft QuickBASIC versions 4.00 and later and Microsoft BASIC
 Compiler versions 6.00 and later have a method of implementing
 functions that is much more straightforward than DEF FN. These
 products allow true FUNCTION procedures to be created, much like the
 functions available in Pascal and C. A BASIC FUNCTION...END FUNCTION
 block is a procedure that allows you to return a value to the calling
 subprogram, but in all other respects is the same as a SUB...END SUB
 subprogram procedure. Using a FUNCTION procedure instead of DEF FN
 avoids the DEF FN problem described in this article.

 The following code example demonstrates the problem when run in the
 QuickBASIC Extended environment (QBX.EXE) that comes with BASIC PDS
 7.00.

 Code Example
 ------------

 DEF FNa$ = "This is a test string."
 FOR i% = 1 TO 100
   PRINT FRE(-1)   ' Show available far heap.
   PRINT FNa$
 NEXT

 Output
 ------

  179376
 This is a test string.
  179344
 This is a test string.
  179328
 This is a test string.
  179296
 This is a test string.


 290. "Not Enough Memory on Exec" When Using RUN with ISAM File Open

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900525-29 buglist7.00 fixlist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q62815

 From within the QBX.EXE environment or a compiled program, an attempt
 to execute a RUN statement while there are open ISAM files results in
 the run-time error R6007, "Not enough memory on EXEC." The RUN
 statement is documented as having the ability to close all files;
 therefore, this error should not occur.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS. This
 problem was corrected in BASIC PDS version 7.10.

 To work around the problem in version 7.00, CLOSE all ISAM files
 before executing a RUN statement.

 The following code example demonstrates the problem:

 Code Example
 ------------

 TYPE testtype
   test AS INTEGER
 END TYPE
 OPEN "test.dat" FOR ISAM testtype "runexe" AS #1
 'CLOSE        'If this line is put in, the program will run correctly
 RUN "test"


 291. REPAIR.EXE Should Be ISAMREPR.EXE in BASIC 7.00 Error Guide

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S900601-15
 Last Modified:  8-JAN-1991    ArticleIdent: Q62818

 In the "Microsoft BASIC 7.0: Language Reference" manual for Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10,
 the error "Database needs repair" at the top of Page 639 incorrectly
 refers to the file REPAIR.EXE for use in repairing ISAM files. The
 correct name for this file is ISAMREPR.EXE.

 The error message summary om Page 639 should be changed read as
 follows:

    An OPEN FOR ISAM statement attempted to open a file that is in
    need of repair. You may want to use the ISAMREPR.EXE utility
    to recover (restore physical integrity to) the database.


 292. In SUB, Variable-Length Near String Array Element Losing Value

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900603-3 buglist7.00 fixlist7.10
 Last Modified:  2-NOV-1990    ArticleIdent: Q62820

 A program compiled with the Near Strings option (without BC /Fs) may
 lose the value of a variable-length string array element under the
 specific conditions described in this article.

 The same program will run correctly when run from the QBX.EXE
 environment or when compiled with the Far Strings option (with BC
 /Fs).

 Microsoft has confirmed this to be a problem with the BC.EXE 7.00
 compiler provided with Microsoft BASIC Professional Development System
 (PDS) version 7.00 for MS-DOS and MS OS/2. This problem was corrected
 in BASIC PDS 7.10.

 This problem does not occur in earlier versions of Microsoft BASIC
 Compiler (BC.EXE).

 Here is a description of the conditions under which the problem occurs
 (as shown in Examples 1 and 2):

 Two variable-length string arrays are dimensioned. Array "A" may be
 dimensioned either dynamically or statically. Array "B" must be
 dimensioned dynamically. Array "B" will lose a value even though the
 program never changes it. A string value is assigned to an element in
 array "B" and this array element is passed as a parameter to a SUB.
 Array "A" is passed to the same SUB either through a parameter list or
 by using SHARED in the DIM statement. Inside the SUB, an element in
 array "A" is directly assigned to a string value returned by the
 RTRIM$, LTRIM$, LEFT$, MID$, or RIGHT$ function. Array "B" is not
 assigned any values in the SUB. But when control is returned to the
 main-level code (or calling procedure), the string value that was
 assigned to an element in array "B" is lost.

 The following two examples exhibit the problem. Both examples pass an
 element in B$() as a parameter variable. In the first example, array
 A$() is declared globally in a DIM SHARED statement. In the second
 example, A$() is passed as a parameter to the SUB.

 Example 1
 ---------

 DECLARE SUB TheSub (temp$)
 REM $DYNAMIC
 DIM SHARED A$(1)
 DIM B$(1)
 B$(1) = "bas"
 PRINT B$(1)
 CALL TheSub(B$(1))
 PRINT B$(1)         'There is no longer anything in B$(1).
 END

 SUB TheSub (temp$)
      A$(1) = RTRIM$("   bob    ")
 END SUB

 Example 2
 ---------

 DECLARE SUB TheSub (temp1$(), temp2$)
 REM $DYNAMIC
 DIM A$(1), B$(1)
 B$(1) = "bas"
 PRINT B$(1)
 CALL TheSub(A$(), B$(1))
 PRINT B$(1)        'There is no longer anything in B$(1).
 END

 SUB TheSub (temp1$(), temp2$)
      temp1$(1) = RTRIM$("   bob    ")
 END SUB

 To work around the problem, alter the program with any one of the
 following choices:

 1. Compile with the Far Strings option (BC /Fs).

 2. Statically dimension the array that loses its value.

 3. Remove the RTRIM$ statement.

 4. Assign a temporary string variable to the string returned by
    RTRIM$, then assign this temporary variable to the desired element
    in array "B".

 The next program is an example of using workaround 4 described above:

 DECLARE SUB TheSub (temp$)
 REM $DYNAMIC
 DIM SHARED A$(1)
 DIM B$(1)
 B$(1) = "bas"
 PRINT B$(1)
 CALL TheSub(B$(1))
 PRINT B$(1)         'B$(1) now contains the correct value.
 END

 SUB TheSub (temp$)
      dummy$ = RTRIM$("   bob    ")  'Use a temporary string variable
      A$(1) = dummy$                 'to work around the problem.
 END SUB


 293. BOOKLOOK "...Forgot ISAM TSR" Despite PROISAM.EXE Being Loaded

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900531-18
 Last Modified: 20-JUN-1990    ArticleIdent: Q62829

 The BOOKLOOK sample program from Microsoft BASIC Professional
 Development System (PDS) version 7.00 displays the misleading error
 message, "You forgot to load the ISAM TSR program," when the file
 BOOKS.MDB is not in the current directory, even though PROISAM.EXE is
 loaded.

 To correct for this error, run BOOKLOOK from the directory that
 contains BOOKS.MDB, or run PROISAMD.EXE instead of PROISAM.EXE.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00.

 The message is shown this way because this is the message printed
 whenever a "Feature Unavailable" error (ERR=73) occurs in BOOKLOOK's
 error handler. BOOKLOOK is made to run with BOOKS.MDB already created;
 therefore, the only reason "Feature Unavailable" would occur in that
 case is if the PROISAM TSR is not loaded.

 PROISAM.EXE allows you to access existing ISAM files, but does not
 allow you to create files, tables, or indexes. To do this, you must
 use PROISAMD.EXE. This explains why loading PROISAMD instead of
 PROISAM corrects the error with BOOKLOOK.


 294. X=(-1*W)^2 Gives "Division by Zero" on 386 with 387; BASIC 7.1

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist7.00 buglist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q62830

 Executing the following line of code on a 80386 machine equipped with
 an 80387 math coprocessor results in a "Division by zero" error:

    X = (-1 * W) ^ 2

 The "Division by zero" error occurs in both the QBX.EXE environment
 and within a compiled .EXE in Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10. The error occurs only on 80386
 computers with 80387 coprocessors.

 Microsoft has confirmed this to be a problem with Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available. This problem does not occur
 with other Microsoft BASIC products.

 The following are two workarounds for the above problem:

 1. Use the DOS command SET NO87=NONE to disable BASIC's use of the 387
    coprocessor. The program will then execute correctly. Note that
    disabling BASIC's use of the coprocessor usually slows program
    execution.

 2. Change the line of code into two lines, using a temporary variable
    to hold the value of (-1 * W), as follows:

       TEMP = (-1 * W)
       X = TEMP ^ 2


 295. 7.00 CREATEINDEX Example Gives "No Current Record" at Run-Time

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S900606-48
 Last Modified:  8-JAN-1991    ArticleIdent: Q62832

 Running the sample program on Page 73 of the "Microsoft BASIC 7.0:
 Language Reference" manual returns a run-time error of 85, "no current
 record," on the RETRIEVE statement.

 The code should be changed as shown below for the program to run
 correctly.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The sample program found on Page 73 uses a file called BOOKS.MDB, the
 sample ISAM file that SETUP copies to your disk. However, in this
 program, the user-defined type, BookRec, does not match the record
 structure used in BOOKS.MDB. Also the program specifies a table name
 that does not exist in BOOKS.MDB.

 The user-defined type, BookRec, should be defined as follows:

    TYPE BookRec
       IDNum AS DOUBLE
       Price AS CURRENCY
       Edition AS INTEGER
       Title AS STRING * 50
       Publisher AS STRING * 50
       Author AS STRING * 36

 In addition, the table name should be defined as "BookStock" instead
 of "BooksStock".

 The corrected program is as follows:

 DEFINT A-Z
 TYPE BookRec                   'altered user-defined type
    IDNum AS DOUBLE
    Price AS CURRENCY
    Edition AS INTEGER
    Title AS STRING * 50
    Publisher AS STRING * 50
    Author AS STRING * 36
 END TYPE

 DIM Library AS BookRec
 DIM msgtxt AS STRING

 CONST Database = "BOOKS.MDB"
 CONST TableName = "BookStock" 'TableName = BookStock (not BooksStock)
 TableNum = FREEFILE

 OPEN Database FOR ISAM BookRec TableName AS TableNum
 CREATEINDEX TableNum, "A", 0, "Author"
 CREATEINDEX TableNum, "I", 1, "IDNum"
 CREATEINDEX TableNum, "T", 0, "Title"
 CREATEINDEX TableNum, "C", 0, "Price"
 SETINDEX #1, "A"
 CLS : LOCATE 13, 30
 PRINT "choose a key:"
 PRINT SPC(9); "move to:"; TAB(49); " order by: X "
 PRINT : PRINT SPC(9); "F - first record"; TAB(49); "A - Author"
 PRINT : PRINT SPC(9); "L - last record"; TAB(49); "I - ID number"
 PRINT : PRINT SPC(9); "N - next record"; TAB(49); "T - Title"
 PRINT : PRINT SPC(9); "P - previous record"; TAB(49); "C - Cost"
 PRINT : PRINT SPC(9); "Q - Quit"; TAB(49); "X- no order"
 LOCATE 3, 1: PRINT TAB(37); Books; ""
 PRINT STRING$(80, "-");
 VIEW PRINT 5 TO 10

 MOVEFIRST TableNum
 DO
     CLS
     RETRIEVE TableNum, Library
     PRINT "Author:   "; Library.Author;
     PRINT TAB(49); "ID #"; Library.IDNum
     PRINT "Title:      "; Library.Title
     PRINT "Publisher: "; Library.Publisher
     PRINT "cost:     "; Library.Price
     PRINT SPC(30); msgtxt
     PRINT STRING$(64, "-")
     IF GETINDEX$(TableNum) = "" THEN
          PRINT STRING$(15, "-");
     ELSE
          PRINT "index in use: "; GETINDEX$(TableNum);
     END IF

      validkeys$ = "FLNPQATICX"
      DO
          keychoice$ = UCASE$(INKEY$)
      LOOP WHILE INSTR(validkeys$, keychoice$) = 0 OR keychoice$ = ""
      msgtxt = ""

      SELECT CASE keychoice$
      CASE "F"
          MOVEFIRST TableNum
      CASE "L"
          MOVELAST TableNum
      CASE "N"
          MOVENEXT TableNum
          IF EOF(TableNum) THEN
              MOVELAST TableNum
              BEEP: msgtxt = "** at last record **"
          END IF
      CASE "P"
          MOVEPREVIOUS TableNum
          IF BOF(TableNum) THEN
              MOVEFIRST TableNum
              BEEP: msgtxt = "** at first record **"
          END IF
     CASE "Q"
          EXIT DO
     CASE ELSE
          VIEW PRINT
          LOCATE 13, 59: PRINT keychoice$;
          VIEW PRINT 5 TO 10
          IF keychoice$ = "X" THEN keychoice$ = ""
          SETINDEX TableNum, keychoice$
          MOVEFIRST TableNum
      END SELECT
 LOOP

 VIEW PRINT
 DELETEINDEX TableNum, "A"
 DELETEINDEX TableNum, "I"
 DELETEINDEX TableNum, "T"
 DELETEINDEX TableNum, "C"
 CLOSE
 END


 296. No Array Bounds Checking for Arrays in TYPEs in BC 7.00 .EXE

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr SR# S900521-23
 Last Modified: 12-JUN-1990    ArticleIdent: Q62833

 In Microsoft BASIC Professional Development System (PDS) version 7.00,
 the run-time error checking code inserted by the BC /D compiler switch
 does not perform array bounds checking for arrays embedded inside
 user-defined TYPEs. However, this checking is performed inside the
 QBX.EXE environment. This is not a problem with the BC.EXE compiler
 but a design limitation. The overhead required for the check would
 cause speed degradation and a size increase for an .EXE file.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and MS OS/2.

 The BC /D compiler switch (Run-time error checking) inserts array
 bounds checking in a module. Whenever an access on an array is
 attempted with an illegal subscript, the message "Subscript out of
 range" is generated. Without /D, this type of error goes undetected
 under DOS and will most likely result in the corruption of other data.
 It can also cause corruption of code or possibly even parts of the
 operating system itself, which could cause unpredictable results,
 including hanging the machine. Under OS/2, an error of this type would
 cause a protection violation and abort the program. The /D switch
 performs array bounds checking on arrays that are NOT embedded in
 user-defined TYPEs, but won't for arrays that ARE embedded in types.
 However, in the QBX.EXE environment, the checking is done for all
 arrays.

 For example, the following program generates a "Subscript out of
 range" error in the QBX.EXE environment, but does not when compiled
 with the /D switch:

    TYPE aType
       Array (1 TO 100) AS INTEGER
    END TYPE

    DIM aVar as aType

    aVar.Array(1000) = 1000   '1000 as a subscript is out of range


 297. "Out of Stack Space" with ON ERROR, REDIM, GOSUB, Then ERASE

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist7.00 buglist7.10 SR# S900603-4
 Last Modified:  6-AUG-1990    ArticleIdent: Q62892

 When compiled with the Far Strings option (BC /FS) and run as a .EXE
 program, the program below results in the message "Out of stack space
 in line 4." This problem does not occur when the program is run in the
 QBX.EXE environment or when it is compiled with the Near Strings
 option and run. It also does not occur when lines 1 and 9 are removed,
 when line 4 is removed, or when the number of arrays erased is
 decreased by one or more.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 Code Example
 ------------

    1 ON ERROR GOTO 9
    2 FOR i% = 1 TO 100
    3   REDIM a$(1), b$(1), c$(1)
    4   GOSUB 8
    5   ERASE a$, b$, c$
    6 NEXT i%
    7 END
    8 RETURN
    9 RESUME


 298. BASIC 7.00 SETMEM Example Uses malloc/free; Should Be halloc

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900607-93 docerr
 Last Modified:  8-JAN-1991    ArticleIdent: Q63003

 The example for the SETMEM() function on Page 333 of the "Microsoft
 BASIC 7.0: Language Reference" manual (for 7.00 and 7.10) incorrectly
 uses the C malloc() and free() functions to allocate and free memory
 instead of the correct halloc() and hfree() functions.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 To be able to free memory for BASIC to reallocate, it is necessary to
 use the heap functions [halloc() and hfree()] instead of normal memory
 allocation functions. If SETMEM() is used to reallocate memory for
 BASIC after using free(), no memory will be reallocated. With hfree(),
 the memory will be returned for use with BASIC.

 For more information on using SETMEM() with C functions, query on the
 following keywords:

    SETMEM and halloc

 Code Example
 ------------

 The corrected C code for the SETMEM() example is as follows:

 void far cfunc(bytes)
 int bytes;
 {
     char *halloc();
     char *workspace;

     /* Allocate working memory (halloc) using amount BASIC freed. */
     workspace=halloc((unsigned) bytes, 1);

     /* Working space would be used here. */

     /* Free memory (hfree) before returning to BASIC */
     hfree(workspace);
 }

 Note: The C code must be compiled using the huge model (/AH).


 299. "Unknown Symbol" Setting Breakpoint on Label in CodeView 3.00

 Product Version(s): 6.00 6.00b 7.00 | 6.00 6.00b 7.00
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | SR# S900606-93 B_QuickBas S_CodeView
 Last Modified: 20-JUN-1990    ArticleIdent: Q63009

 When debugging a BASIC program in Microsoft CodeView, a breakpoint
 can be set on a BASIC label by typing the following command

    BP <label>

 where <label> is any valid BASIC label. In CodeView versions 2.x, this
 command works whether or not the program is started. In CodeView
 version 3.00, the program must have started executing before this
 command will work. If the program has not been started, CodeView 3.00
 generates the error message "Unknown symbol."

 This information applies to programs run under CV.EXE and CVP.EXE
 versions 2.x and 3.00 when compiled with the BC.EXE compiler that
 comes with QuickBASIC versions 4.00, 4.00b, and 4.50, with Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2, or with
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS and MS OS/2.

 Breakpoints can also be set in four other ways. Each of the following
 methods can be used before the program is actually started:

 1. Use the following command

       bp .<line>

    where <line> is the line number that CodeView displays next to the
    label (not a BASIC line number). This works whether or not the
    program is started.

 2. Use the mouse to double-click the line you want to break on.

 3. Position the cursor on the line you want to break on and then
    choose Set Breakpoint from the Watch menu.

 4. Position the cursor on the line you want to break on and then press
    the F9 key.


 300. Cannot Display Array Pointer or Full BASIC Array with CodeView

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# S900606-86 B_QuickBas S_CodeView
 Last Modified:  5-SEP-1990    ArticleIdent: Q63010

 The BC.EXE compiler in QuickBASIC versions 4.00, 4.00b, and 4.50, in
 Microsoft BASIC Compiler versions 6.00 and 6.00b, and in Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 can
 create programs that will run under Microsoft CodeView versions 2.x
 and 3.00. However, arrays or arrays in TYPEd records give "?CANNOT
 DISPLAY" for the CodeView commands ?, ??, or w?. This is not a problem
 with either the BASIC compiler or CodeView, but represents a
 limitation of debugging BASIC programs in CodeView.

 This information applies to programs run under CV.EXE and CVP.EXE 2.x
 and 3.00 when compiled with the BC.EXE compiler that comes with
 QuickBASIC versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and Microsoft BASIC
 PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 In CodeView, the ? command is used to display an expression. The ??
 command is used to graphically view a variable in a dialog box. ??
 will expand a variable, such as a TYPEd record, to show the fields and
 the value currently assigned to each field.

 This limitation also applies to the CodeView 3.00 command ??, where
 the graphical display (??) can expand the elements of an array. For
 example, an array in C (int intarray[10];) can be displayed as a far
 pointer with ? and expanded to its elements with ??. With CodeView 2.x
 and C version 5.10, the ?? command won't display the elements of a C
 array, but will display the far pointer value that is the array's
 address.


 301. LINK /F of Overlaid BRT70xx Program Causes "Invalid Runtime"

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900615-62 buglist7.00 fixlist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q63040

 LINK-overlaid programs using the BRT70xxx.EXE run-time module from
 Microsoft BASIC Professional Development System (PDS) version 7.00
 should not be LINKed with the /F (/FARCALLTRANSLATION) option. When
 this is done, a CALL to an overlay causes an attempt to reload the
 run-time module. This results in an "Invalid runtime module" message
 and, in most cases, the machine hangs.

 To work around this problem, LINK without the /F option or compile
 for a stand-alone .EXE (with the BC /O option).

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 version 7.00. This problem does not occur in BASIC PDS 7.10.

 The /F (/FARCALLTRANSLATION) LINK option is described on Page 241 of
 the "Microsoft CodeView 2.3 and Utilities User's Guide" for Microsoft
 BASIC PDS version 7.00 for MS-DOS. Using this option may produce a
 slight gain in speed and size of executables by translating far calls
 to near calls. However, attempts to optimize overlaid calls cause a
 problem with the run-time module. Thus, /F should not be used with an
 overlaid program that is using the run-time module.

 Code Example
 ------------

 The following programs (which are separate .BAS source files)
 compose a simple overlaid program that demonstrates the problem:

 CALLOVL.BAS
 -----------

 INPUT "Call overlay (Y/N)? ",i$
 IF ((i$ = "Y") OR (i$ = "y")) THEN CALL test
 END

 OVL.BAS    **** NOTE: This is a file separate from the above file!
 -------

 SUB test
   PRINT "in overlay"
 END SUB

 The following are the compile and LINK lines to demonstrate the
 problem with the above separate modules:

    BC CALLOVL;
    BC OVL;
    LINK /F CALLOVL+(OVL);

 These programs can be run properly if either /O is added to each BC
 command line or the /F is omitted from the LINK line.


 302. Overlaid Modules Loaded into EM Only When 1st Overlay Called

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900608-158
 Last Modified:  5-SEP-1990    ArticleIdent: Q63161

 When using expanded memory with an overlaid program, the overlaid
 modules are not loaded when the EXE file is invoked. They remain on
 disk until the first overlay is called. When this occurs, all the
 overlaid modules are loaded from disk into expanded memory. From then
 on, the overlays are swapped to and from expanded memory and the disk
 is no longer needed for that purpose.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10.

 For more information about using linker overlays in BASIC PDS 7.00 and
 7.10, search for a separate article in this Knowledge Base with the
 following words:

    LINK and overlays and expanded and memory and BASIC

 To demonstrate this characteristic of BASIC overlays, boot up with an
 Lotus/Intel/Microsoft (LIM) version 4.0 Expanded Memory Specification
 (EMS) device driver and compile and link the three modules below as
 follows:

    bc main;
    bc overlay1;
    bc overlay2;

    link main+(overlay1)+(overlay2);

 MAIN.BAS
 --------

    '* Note: The disk activity will be most obvious if this test
    '        is run on a floppy drive.
    PRINT "MAIN"
    PRINT "HIT ANY KEY TO LOAD OVERLAYS INTO EMS"
    SLEEP
    CALL ovl1
    PRINT "OVERLAYS LOADED"
    PRINT "HIT ANY KEY TO CALL SECOND OVERLAY"
    PRINT "THERE SHOULD BE NO DISK ACTIVITY IF YOU HAVE EMS"
    SLEEP
    CALL ovl2
    PRINT "HIT ANY KEY TO END THE PROGRAM"
    SLEEP
    END

 OVERLAY1.BAS
 ------------

    SUB ovl1
       PRINT "OVERLAY1"
    END SUB

 OVERLAY2.BAS
 ------------

    SUB ovl2
       PRINT "OVERLAY2"
    END SUB

 When run, the resulting EXE file (MAIN.EXE) produces the following
 output:

    MAIN
    OVERLAY1
    OVERLAY2

 However, before "OVERLAY1" is displayed, there will be disk activity
 while the code for overlay1 is loaded into the overlay area of
 conventional memory (for execution) and overlay2 is loaded into
 expanded memory. To see this clearly, run MAIN.EXE from a floppy
 drive. When overlay2 is called, there will be no disk activity because
 it will be swapped in from expanded memory.

 Note that this is not a problem with BASIC PDS 7.00 or 7.10, but a
 feature of the overlay manager. However, it can present a speed
 problem for applications that rely on the quickness of swapping from
 expanded memory for the first-called overlay. To work around this,
 make the first executable statement in your program a CALL to an
 additional overlay with no code in it. When it is called, all the
 other overlays will be loaded into expanded memory. The functionality
 and speed of the application will remain intact while the difference
 in EXE size and load time will be minimal.

 For example, the module MAIN.BAS above would be modified as follows:

    CALL loadovls
    PRINT "MAIN"
    CALL ovl1
    CALL ovl2
    END

 The subprogram "loadovls" (meaning "load overlays") would be coded as
 the following:

    SUB loadovls
    END SUB

 When loadovls is called, the code for overlay1 and overlay2 will be
 loaded into expanded memory. This eliminates the disk activity between
 the display of "MAIN" and "OVERLAY1".


 303. When Out of Memory in QBX 7.00, Instant Watch Reruns Program

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 buglist7.10 SR# S900606-88
 Last Modified:  6-AUG-1990    ArticleIdent: Q63195

 Trying to set an Instant Watch variable on a large variable-length
 string in QBX.EXE can cause QBX to restart the program from the
 beginning if the program is almost out of memory. When the program is
 almost out of memory, QBX fails to add the watch and instead reruns
 the program.

 Microsoft has confirmed this to be a problem with the QBX.EXE
 environment that comes with Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS. We are researching
 this problem and will post new information here as it becomes
 available.

 To reproduce the problem, the following conditions must be duplicated:

 1. There must be less than 15K of memory free. Use PRINT FRE(-1) to
    show this.

 2. Create a large string, such as the following:

       a$=STRING$(10000,62)

 3. Stop the program just after the string is assigned. For instance,
    step through the program with the F8 key, or put a breakpoint on
    the line after you create the string.

 4. Move the cursor back up to the string variable.

 5. Press SHIFT+F9 to set an Instant Watch.

 6. If QBX allows you to set the watch, either decrease the amount of
    free memory, or keep setting Instant Watches on the same variable.
    Eventually, QBX will fail to add the watch, and will rerun the
    program from the beginning.

 Code Example
 ------------

 Use the above steps to reproduce the problem with the code below. The
 following code was used to reproduce this problem on a machine where
 CHKDSK.COM showed 508,200 bytes free:

    REM $DYNAMIC
    CLEAR
    REDIM array1(19000) AS DOUBLE
    PRINT
    a$ = STRING$(10000, 33)
    PRINT a$       ' Stop the program here. Move the cursor to a$.
    PRINT FRE(-1)  ' Press SHIFT+F9 several times.
    PRINT
    PRINT
    PRINT
    PRINT
    PRINT
    PRINT


 304. Using PWB with Both BASIC PDS 7.10 and C PDS 6.00

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900618-153 S_C S_PWB
 Last Modified:  6-SEP-1990    ArticleIdent: Q63197

 The Programmer's WorkBench (PWB) is designed as a multilanguage,
 project-oriented development environment for MS-DOS and MS OS/2.

 The key to each language's interface into PWB is the .HLP files and
 the .MXT files for MS-DOS and the .PXT files for MS OS/2. The .HLP
 files are the help files for each language product. The .MXT and .PXT
 files are PWB extensions for each language that define menus and
 dialog boxes for each compiler. Thus, to use PWB with both BASIC and
 C, you must copy the PWBC.MXT file (for MS-DOS) or PWBC.PXT file (for
 MS OS/2) into the directory containing the BASIC PWB.EXE file, and SET
 the HELPFILES environment variable to find both the C and BASIC help
 files.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.10 and to Microsoft C PDS version 6.00 for
 MS-DOS and MS OS/2.


 305. Main Module Must Be First BASIC File in Program List for PWB

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900618-147 S_PWB PWB
 Last Modified:  5-SEP-1990    ArticleIdent: Q63198

 The main module in a multiple-module program must be listed as the
 first BASIC source file in the Program List for PWB.EXE (the
 Programmer's WorkBench) to properly make the EXE file. If a
 supporting module is listed first, its module-level code (virtually
 nonexistent in most cases) is treated as the main entry point. This
 produces an EXE that is approximately the correct size, but does
 nothing.

 To convert a given module in the Program List to the main module,
 choose that module in the Edit Program List dialog and choose the To
 Top Of List button.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.10 for MS-DOS and MS OS/2.

 For example, to make a Program List containing everything necessary
 for the UIDEMO example program, UIDEMO.BAS must be listed at the
 beginning of the BASIC files list. The incorrect and correct orders
 are demonstrated below.

 The following order of files does NOT create a working UIDEMO.EXE:

    GENERAL.BAS
    MENU.BAS
    MOUSE.BAS
    UIDEMO.BAS
    WINDOW.BAS
    UIASM.OBJ
    QBX.LIB

 The above order does not work because GENERAL is taken as the main
 module. Since GENERAL.BAS has no executable statements at the module
 level, the program does nothing when run.

 The correct order must have UIDEMO.BAS first:

    UIDEMO.BAS
    GENERAL.BAS
    MENU.BAS
    MOUSE.BAS
    WINDOW.BAS
    UIASM.OBJ
    QBX.LIB


 306. BUILDRTM with PROISAM(D) Must Have OBJ and LIB in Export List

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900620-71
 Last Modified: 17-JAN-1991    ArticleIdent: Q63268

 To build ISAM support into a custom run-time module (instead of using
 ISAM from the separate TSR program), you must specify in BUILDRTM's
 Export List file both the object (.OBJ) and library (.LIB) forms of
 your chosen ISAM library (PROISAM or PROISAMD). If either the object
 or library form is left out of the Export List file, LINK.EXE flags
 numerous occurrences of L2025 ("Symbol defined more than once") and
 L2029 ("Unresolved external").

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The following Export List file (arbitrarily named ISAM.EXP) shows the
 files that need to be specified to put PROISAMD into a custom run-time
 module:

    # ISAM.EXP
    #OBJECTS
    PROISAMD.OBJ
    # (specify additional OBJs here)
    #LIBRARIES
    PROISAMD.LIB

 The command line to build the custom run-time module specified by the
 above Export List file is as follows:

    BUILDRTM /LR ISAMRUN ISAM.EXP

 This BUILDRTM command outputs three files: IMPORT.OBJ and ISAMRUN.LIB
 (used to resolve LINK references to your custom run-time module) and
 ISAMRUN.EXE (your custom run-time module).

 To LINK the above run-time module to a BASIC program, use the
 following LINK command:

    LINK IMPORT.OBJ+yourfile.OBJ,yourfile.EXE,,ISAMRUN.LIB;

 For more information about using BUILDRTM.EXE, see Chapter 21,
 "Building Custom Run-Time Modules," in the "Microsoft BASIC 7.0:
 Programmer's Guide" for 7.00 and 7.10.


 307. B_OVREMAP in 7.00 Programmer's Guide Should Be B_OVLREMAP

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900613-56 docerr
 Last Modified: 16-JAN-1991    ArticleIdent: Q63422

 Page 613 of "Microsoft BASIC 7.0: Programmer's Guide" (for versions
 7.00 and 7.10) incorrectly refers to the B_OVREMAP routine. This
 routine (contained in the BASIC run-time) is actually named
 B_OVLREMAP.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The B_OVLREMAP routine is used to remap the overlays in expanded
 memory after the state has changed. To use this from a BASIC program,
 you must map the name to a usable SUB name using the ALIAS keyword in
 the DECLARE SUB line.

 Code Example
 ------------

 The following code example demonstrates the use of the B_OVLREMAP
 routine:

    DECLARE SUB OvlReMap ALIAS "B_OVLREMAP"
    SHELL             'Do something to expanded memory in the SHELL
    CALL OvlReMap     'Remap overlays in expanded memory after SHELL
    END


 308. How to Set Up Programmer's WorkBench (PWB) for BASIC PDS 7.10

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900702-109 s_pwb
 Last Modified:  5-SEP-1990    ArticleIdent: Q63623

 The following information applies to Microsoft BASIC Professional
 Development System (PDS) version 7.10 for MS-DOS and MS OS/2.

 To successfully begin using the Programmer's WorkBench (PWB.EXE), you
 must make several changes in your environment, as follows:

 1. The file NEW-VARS.BAT (a batch file for MS-DOS) or NEW-VARS.CMD (a
    command file for MS OS/2) must be executed before using PWB.EXE.
    These files are located in the BC7\BIN directory (for MS-DOS) or
    BC7\BINP directory (for MS OS/2) if the default directory names
    were chosen during setup. The information in these files can be
    added directly to your AUTOEXEC.BAT (for MS-DOS) or CONFIG.SYS (for
    MS OS/2), as shown in the "More Information" section below.

 2. The file TOOLS.PRE must be renamed to TOOLS.INI or appended to an
    existing TOOLS.INI. The TOOLS.INI must be in the directory
    specified by the environment variable INIT. The TOOLS.PRE file is
    located in the BC7\BINP directory if the default directory names
    were chosen during setup.

 3. For MS OS/2, the LIBPATH environment variable must contain the
    directory where BASIC's run-time DLLs are stored. These files are
    located in the BC7\BINP directory if the default directory names
    were chosen during setup.

 4. To use Microsoft C with PWB.EXE in interlanguage calling, the file
    PWBC.MXT (for MS-DOS) or PWBC.PXT (for MS OS/2) must be unpacked
    and copied from the distribution disks to the directory containing
    PWB.EXE. PWB.EXE is located in the BC7\BIN directory (for MS-DOS)
    or the BC7\BINP directory (for MS OS/2) if the default directory
    names were chosen during setup. To find the disk PWBC.MXT or
    PWBC.PXT is located on, look in the PACKING.LST file on DISK 1 of
    the distribution disks.

 5. After any changes have been made to the AUTOEXEC.BAT file or
    CONFIG.SYS file, your machine must be rebooted.

 The following is more information about requirements 1 through 4
 above:

 1. The information in the NEW-VARS.BAT or NEW-VARS.CMD files can be
    added directly to your AUTOEXEC.BAT (for MS-DOS) or CONFIG.SYS (for
    MS OS/2).

    To avoid LINK and compile problems, make sure the directory for
    PWB.EXE comes first in your PATH.

    The following lines must be added to (or modified if the
    environment variables already exist) your AUTOEXEC.BAT file (for
    use with MS-DOS):

       set PATH=c:\bc7\bin;c:\bc7\binb;
       set LIB=c:\bc7\lib;
       set INCLUDE=c:\bc7\src;
       set HELPFILES=c:\bc7\help;

    The following lines must be added to (or modified if the
    environment variables already exist) your CONFIG.SYS file (for
    use with MS OS/2):

       set PATH=c:\bc7\binp;c:\bc7\binb;
       set LIB=c:\bc7\lib;
       set INCLUDE=c:\bc7\src;
       set HELPFILES=c:\bc7\help;

 2. The environment variable for INIT should resemble the following if
    your TOOLS.INI file is in the directory called INIT:

       SET INIT=C:\INIT;

    To append TOOLS.PRE to TOOLS.INI, use the following command:

       COPY TOOLS.INI + \BC7\BINB\TOOLS.PRE

 3. A sample LIBPATH after using the default setup for MS OS/2 and
    Microsoft BASIC PDS 7.10 is as follows:

       LIBPATH=C:\OS2\DLL;C:\;C:\BC7\BINP;

 4. To unpack the files PWBC.MXT and PWBC.PXT, the commands are as
    follows:

       UNPACK A:PWBC.MX$ PWBC.MXT
       UNPACK A:PWBC.PX$ PWBC.PXT


 309. "Permission Denied" If SHELL to 7.00 .EXE Using ISAM from TSR

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900702-42 buglist7.00 buglist7.10
 Last Modified:  2-NOV-1990    ArticleIdent: Q63782

 If you SHELL from one program that uses ISAM to another ISAM program
 that uses the PROISAM.EXE or PROISAMD.EXE terminate-and-stay-resident
 (TSR) program, a "Permission Denied" error occurs when the OPEN
 statement is executed in the child (SHELLed) process (see Example 2
 below). This problem does not occur when ISAM support is linked into
 the .EXE programs instead of using the TSR program.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10. We are
 researching this problem and will post new information here as it
 becomes available.

 To work around this problem, use a CHAIN statement instead of SHELL,
 or LINK ISAM support to your .EXE instead of using the ISAM TSR
 program.

 In addition, SHELLing to the ISAM utilities (ISAMIO.EXE, ISAMCVT.EXE,
 ISAMREPR.EXE, or ISAMPACK.EXE) may generate unusual error messages,
 because they are not designed to be SHELLed; this is not a software
 problem but is a design limitation. For example, ISAMPACK.EXE fails
 with the message "Unknown error number." A workaround is shown below
 in Example 1.

 Note that the SETUP.EXE program for BASIC PDS 7.00 and 7.10 lets you
 choose one of the following four ISAM support options for compiled
 .EXE programs:

 1. ISAM Routines in TSR
 2. ISAM Routines in LIB, Support Database Creation and Access
 3. ISAM Routines in LIB, Support Database Access Only
 4. No ISAM support

 Only Option 1 creates PROISAM.EXE and PROISAMD.EXE TSR programs that
 can be used with BASIC compiled .EXE programs. The TSR program created
 in Option 1 can also be used in QBX.EXE. Options 2 and 3 create
 PROISAM.EXE and PROISAMD.EXE TSR programs that CANNOT be used in
 compiled .EXE programs, and that can only be used by QBX.EXE and the
 ISAM utilities (ISAMIO.EXE, ISAMCVT.EXE, ISAMREPR.EXE, and
 ISAMPACK.EXE). Options 2 and 3 create .LIB libraries for linking ISAM
 support into your .EXE programs. The fourth SETUP option does not copy
 any ISAM-related files onto your computer.

 A problem occurs whenever a SHELLed (child) process attempts to access
 the PROISAM or PROISAMD TSR program. Specifically, the problem occurs
 when you SHELL to an ISAM utility (which requires the TSR program --
 see Example 1), or SHELL to a BASIC .EXE program that requires the
 ISAM TSR (see Example 2).

 Example 1
 ---------

 Because the ISAM utilities (ISAMIO.EXE, ISAMCVT.EXE, ISAMREPR.EXE, or
 ISAMPACK.EXE) require the ISAM TSR program, the best way to work
 around the SHELLing problem is to link the BASIC .EXE (the parent
 process that executes the SHELL) to the ISAM .LIB, and then SHELL to
 an MS-DOS batch (.BAT) file that loads the TSR program, executes the
 ISAM utility, and then unloads the TSR program. The following is an
 example of this type of batch file:

    REM  Start PACK.BAT
       PROISAMD
       ISAMPACK isamfile.dat
       PROISAMD /D
    REM  End PACK.BAT

 Example 2
 ---------

 The following program (when SHELLed to itself or any other program
 that OPENs any ISAM file) will cause a "Permission Denied" error in
 the SHELLed copy:

    ' ISAMTEST.BAS
    TYPE test
      x AS INTEGER
    END TYPE
    OPEN "test" FOR ISAM test "test" as #1
    CLOSE #1
    INPUT "Do you want to shell?", a$
    IF a$="Y" THEN SHELL "ISAMTEST"    ' Put the name of this .EXE here.
    END

 Compile and link this program as follows:

    BC ISAMTEST.BAS;   (BC compile options don't affect the problem)
    LINK ISAMTEST;

 To duplicate the problem, run the PROISAM.EXE or PROISAMD.EXE TSR
 program, then run the above program. To work around the problem, link
 ISAM support to the program instead of using the ISAM TSR program, or
 use CHAIN instead of SHELL.

 Note that if you chose the "ISAM routines in TSR" option during
 SETUP.EXE and also retained component files during SETUP.EXE, there is
 a special way to LINK ISAM support into your stand-alone .EXE program,
 as described in a separate article, which can be found by using the
 following query in this Knowledge Base:

    LINK and ISAM and component and even and SETUP and TSR


 310. In 7.00 UI Toolbox, WindowOpen Must Start at Row 3, Column 2

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900706-34
 Last Modified: 10-JAN-1991    ArticleIdent: Q63797

 When using the WindowOpen SUBprogram from the User Interface (UI)
 Toolbox in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10, coordinates for the upper left-hand window
 location must be below row 2 and to the right of column 1.

 The reason for this is that the coordinates that you are giving
 represent the location of the first printable text space on the
 screen, not the actual upper left-hand corner of the window.
 Therefore, there has to be room for the window border to be drawn
 around the box.

 If you try to display a window with an upper left-hand coordinate of 1
 for col1%, or 1 or 2 for row1%, no window will be displayed on the
 screen and no error will display.

 Code Example
 ------------

 'The main body of code consists of the initialization routines that
 'allow the use of the User Interface (UI) Toolbox. The $INCLUDE files
 'contain the necessary TYPE definitions and SUB declarations. The
 'COMMON SHARED statements contain the necessary global variables for
 'communicating with the UI Toolbox routines.

 REM $INCLUDE: 'window.bi'
 REM $INCLUDE: 'mouse.bi'
 REM $INCLUDE: 'menu.bi'
 REM $INCLUDE: 'general.bi'

 COMMON SHARED /uitools/ glomenu AS MenuMiscType
 COMMON SHARED /uitools/ glotitle() AS MenuTitleType
 COMMON SHARED /uitools/ gloitem() AS MenuItemType
 COMMON SHARED /uitools/ glowindow() AS windowtype
 COMMON SHARED /uitools/ globutton() AS buttontype
 COMMON SHARED /uitools/ gloedit() AS editfieldtype
 COMMON SHARED /uitools/ glostorage AS windowstoragetype
 COMMON SHARED /uitools/ glowindowstack() AS INTEGER
 COMMON SHARED /uitools/ globuffer$()

 DIM glotitle(MAXMENU) AS MenuTitleType
 DIM gloitem(MAXMENU, MAXITEM) AS MenuItemType
 DIM glowindow(MAXWINDOW) AS windowtype
 DIM globutton(MAXBUTTON) AS buttontype
 DIM gloedit(MAXEDITFIELD) AS editfieldtype
 DIM glowindowstack(MAXWINDOW) AS INTEGER
 DIM globuffer$(MAXWINDOW + 1, 2)

 CLS

 'Windowinit and Menuinit initialize all of the necessary
 'variables for use with the UI Toolbox routines.

 MenuInit
 windowinit

 'The following windowopen statement will not create a window on the
 'screen, because the second parameter must be greater than 2, and the
 'third parameter must be greater than 1:
 '             /----- 2nd parameter must be greater than 2.
 '             v
 windowopen 1, 2, 1, 20, 20, 15, 0, 15, 0, 6, 0, 0, 0, 0, 2, "test #1"
 '                ^----- 3rd parameter must be greater than 1.

 SLEEP
 'The following windowopen statement correctly opens a window
 'that will have the minimum possible upper left-hand corner
 'coordinates:

 windowopen 2, 3, 2, 10, 20, 15, 0, 15, 0, 6, 0, 0, 0, 0, 2, "test #2"


 311. 7.00 UI Toolbox MENU.BAS Correction, Narrow Menu Selectability

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 buglist7.10
 Last Modified:  2-NOV-1990    ArticleIdent: Q63799

 The User Interface (UI) Toolbox provided in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10
 incorrectly allows a mouse cursor to choose a menu option from outside
 the confines of a narrow pull-down menu.

 Microsoft has confirmed this to be a problem in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS. The correction is provided below.

 To correct this problem, the source code of MENU.BAS can be changed to
 correctly choose items in a narrow pull-down menu. Change the
 following IF statement found in the SUB MenuDo near the line label
 "menuDoShowPullDown:". (When you load MENU.BAS into the QBX.EXE
 editor, this label is at line number 650, and the IF statement is
 located at line 660.)

 Change the following line

      LEN(GloTitle(currMenu).text)
 to
      LEN(RTRIM$(GloTitle(currMenu).text))

 in both of the following places:

      IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem _
                < LEN(GloTitle(currMenu).text) THEN
           GloTitle(currMenu).rColItem = GloTitle(currMenu).lColItem _
                + LEN(GloTitle(currMenu).text)
      END IF

 Note: The underscore characters (_) above indicate line-continuation
 characters. The block IF statement actually appears as three lines in
 the original source code of MENU.BAS.

 The changed code is as follows:

      IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem _
                < LEN(RTRIM$(GloTitle(currMenu).text)) THEN
           GloTitle(currMenu).rColItem = GloTitle(currMenu).lColItem _
                + LEN(RTRIM$(GloTitle(currMenu).text)
      END IF

 To enable correct handling of narrow pull-down menus, this change
 should be made and the libraries rebuilt as follows:

      BC /X/FS MENU.BAS;

      LIB UITB -+MENU;     [Note: UITB.LIB is the library that
                                  GENERAL.BAS outlines how to build.]

      LINK /Q UITB.LIB,UITB.QLB,,QBXQLB.LIB;

 The correction in this article is the same as for a different symptom
 described in a separate article, where garbage characters appear after
 selecting a menu at or to the right of the 64th column. To find this
 and other problems with the UI Toolbox, query in this Knowledge Base
 on the following words:

    user and interface and toolbox and buglist7.00


 312. Illegal RESUME NEXT Hangs QBX After ON LOCAL ERROR RESUME NEXT

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900615-135 buglist7.00 buglist7.10
 Last Modified:  6-AUG-1990    ArticleIdent: Q63811

 QBX.EXE hangs if an illegal RESUME NEXT statement is encountered in an
 IF statement inside a SUB where the statement ON LOCAL ERROR RESUME
 NEXT is active. This problem does not occur in a compiled and linked
 .EXE program.

 Microsoft has confirmed this to be a problem with QBX.EXE in Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS. We are researching this problem and will post new information
 here as it becomes available.

 The problem can be worked around by knowing and not programming
 illegal "RESUME without error" conditions.

 Instead of hanging the program below, the QBX environment should
 return an Error 20 ("RESUME without error"), which means that there is
 no active error-handling routine from which to RESUME. Error 20 should
 then have been automatically handled by the ON LOCAL ERROR RESUME NEXT
 statement (which does a valid RESUME NEXT).

 A RESUME NEXT statement by itself is only valid when it is within an
 error-handling routine that was an object of an ON [LOCAL] ERROR GOTO
 <linelabel> statement. When the program below is compiled and linked
 into an EXE, the .EXE does not hang, and it correctly returns and
 handles error 20.

 Code Example
 ------------

 The following code example hangs QBX.EXE on the indicated line. Note
 that this program shows illegal usage of the second RESUME NEXT, which
 should have produced error 20. When run as an .EXE program, this code
 successfully returns error 20 and handles the error correctly with the
 local error handler:

 CALL test
 SUB test
   ON LOCAL ERROR RESUME NEXT
   ERROR 1
   ' The following RESUME NEXT is a programming error:
   IF ERR = 1 THEN RESUME NEXT   '*** This line hangs in QBX.EXE
   ' The above statement correctly causes error 20 ("RESUME without
   ' error") in a .EXE program, and ERR now returns 20 and prints as
   ' follows:
   PRINT "This is next line after programming error 20, and ERR= "; ERR
   PRINT "Now ending subprogram"
 END SUB


 313. How to LINK PROISAMD.LIB to .EXE Even If SETUP "ISAM in TSR"

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900706-104
 Last Modified:  6-SEP-1990    ArticleIdent: Q63834

 The following technique gives you the setup configuration with the
 greatest flexibility of choice for ISAM support (as either a TSR
 [terminate-and-stay resident] program or linkable .LIB) in compiled
 .EXE programs.

 If you chose "ISAM Routines in TSR" (instead of "ISAM Routines in
 LIB") when you ran SETUP.EXE, then to make a standalone .EXE program
 (that uses ISAM) that does not require the PROISAMD.EXE or PROISAM.EXE
 TSR program, you must LINK with the PROISAMD.OBJ and PROISAMD.LIB
 component libraries in the linker's object list. This technique
 requires that you choose to retain component libraries when you run
 SETUP.EXE.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 under MS-DOS. This also applies to
 version 7.10 under MS OS/2.

 With BASIC PDS 7.00, there are four SETUP.EXE options for installing
 ISAM support for compiled .EXE programs:

 1. ISAM Routines in TSR
 2. ISAM Routines in LIB, Support Database Creation and Access
 3. ISAM Routines in LIB, Support Database Access Only
 4. No ISAM support

 Only Option 1 creates PROISAM.EXE and PROISAMD.EXE TSR programs that
 can be used with BASIC compiled .EXE programs. The TSR program created
 in Option 1 can also be used in QBX.EXE. Option 1 is the default since
 it consumes the least disk space.

 Options 2 and 3 create PROISAM.EXE and PROISAMD.EXE TSR programs that
 CANNOT be used in compiled .EXE programs and that can only be used by
 QBX.EXE and the ISAM utilities (ISAMIO.EXE, ISAMCVT.EXE, ISAMREPR.EXE,
 and ISAMPACK.EXE). If you choose Option 2 or 3 and you want ISAM
 support in your .EXE program, you must link to the ISAM .LIB files
 instead of using the TSR support for ISAM.

 SETUP Option 4 does not copy any ISAM-related files onto your
 computer.

 You may want to have the option of creating .EXE programs with full
 ISAM support provided either in the TSR program or linked from
 libraries. This can be accomplished by choosing Option 1 ("ISAM
 Routines in TSR") and LINKing with PROISAMD.OBJ and PROISAMD.LIB in
 the object list, as follows:

    LINK /NOE ISAMPROG.OBJ+PROISAMD.OBJ+PROISAMD.LIB;

 The following are some important notes about the above LINK command
 line:

 1. The NOExtended library search option (/NOE) is necessary to prevent
    "Symbol Defined More than Once (L2025)" errors.

 2. Both object (PROISAMD.OBJ) and library (PROISAMD.LIB) files are
    required to LINK properly.

 3. The PROISAMD.OBJ is normally deleted with component libraries by
    SETUP.EXE. You must choose to retain component libraries when you
    run SETUP.EXE to retain this necessary file.

 4. PROISAMD.LIB must be specified in the object list instead of the
    library list on the LINK command line, as shown. (When LINKing a
    library in the object list, all object files contained in that
    library are LINKed into the EXE, as opposed to only the routines
    that are not otherwise resolved.)

 5. ISAMPROG.BAS must be compiled with the BC /O (standalone) option.
    If you don't compile with BC /O, then the LINK error L2029
    "Unresolved external" error will occur for 'b$IsamRtmUsed' and
    'B$DOS3CHECK'.

 Code Example
 ------------

 The following code example would normally require the PROISAMD.EXE TSR
 program (when the "ISAM Routines in TSR" option is chosen during
 SETUP), but using the LINK line given below, the TSR program is not
 necessary.

 Compile and link as follows:

    BC ISAMPROG /O;
    LINK /NOE ISAMPROG.OBJ+PROISAMD.OBJ+PROISAMD.LIB;

 ' Name this source file as follows: ISAMPROG.BAS
 TYPE test
   x AS INTEGER
 END TYPE
 OPEN "ISAMFILE" FOR ISAM test "table" AS #1
 CLOSE #1
 END


 314. Incorrect SEEK in Example in BASIC 7.00 Language Reference

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900712-2 docerr
 Last Modified: 15-JAN-1991    ArticleIdent: Q63901

 On page 323 of the "Microsoft BASIC 7.0: Language Reference" manual,
 the example for the SEEK statement (on the 6th line from the bottom)
 incorrectly shows that the process for backing up a file is as
 follows:

    SEEK #1, SEEK(1) - LEN(RecordVar)

 This statement is the correct method for backing up one record
 position in a binary file. In a binary file, the SEEK function refers
 to a byte in the file. Therefore, to move forward or backward a
 record, you would increment or decrement by the number of bytes in
 each record of the file.

 However, because the file in the SEEK example on page 323 is a RANDOM
 access file, a SEEK function refers to each record in the file, not to
 each byte in the file. Thus, the statement should be corrected to read
 as follows:

    SEEK #1, SEEK(1) - 1

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 315. How to Scroll Text in BASIC Protected Mode Program Using API

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900710-57
 Last Modified: 17-JAN-1991    ArticleIdent: Q63956

 This article describes how protected mode BASIC programs compiled with
 Microsoft BASIC Compiler versions 6.00 and 6.00b or Microsoft BASIC
 Professional Development System (PDS) version 7.00 or 7.10 can scroll
 text on the screen by calling the OS/2 API functions VioScrollUp(),
 VioScrollDn(), VioScrollLf(), and VioScrollRt(). A full example of
 using these routines is provided below.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS OS/2.

 BASIC 6.00 and 6.00b and BASIC PDS 7.00 and 7.10 can directly call
 OS/2 API functions by linking with the appropriate library. This
 library is called DOSCALLS.LIB for BASIC 6.00 and 6.00b and OS2.LIB
 for BASIC PDS 7.00 and 7.10.

 The API functions VioScrollUp(), VioScrollDn(), VioScrollLf(), and
 VioScrollRt() all require the following parameters:

    Parameter   Description
    ---------   -----------

    WORD        y (row) coordinate of upper left corner
    WORD        x (column) coordinate of upper left corner
    WORD        y (row) coordinate of lower right corner
    WORD        x (column) coordinate of lower right corner
    WORD        Number of lines or columns to scroll
    PTR WORD    Contains character (lower byte) and attribute
                (upper byte) used to fill blanked lines or columns
    WORD        Video handle (0 = default)

 The first four parameters specify the rectangle in which the scrolling
 is to take place. Any area outside this rectangle is not scrolled. The
 sixth parameter specifies the character and attribute to use for the
 new lines or columns created behind the scrolling text. Note that a
 WORD in BASIC is an INTEGER, and any parameters preceded by the word
 "PTR" must be passed using the SEG clause in the DECLARE statement;
 BYVAL is used otherwise. The default for BASIC is to pass by reference
 (not BYVAL).

 The following program (SCROLL.BAS) displays a message on the screen
 and allows you to scroll the message up, down, left, or right using
 the cursor keys. Note that this example uses only the cursor keys on
 the numeric keypad, not the extended cursor keys. Any part of the
 message that is scrolled off the screen is lost. Press the ESC key to
 terminate execution.

 To compile and link the program, enter the following lines at the OS/2
 command prompt:

    bc scroll /v ;
    link scroll;

 Code Example
 ------------

 'SCROLL.BAS
 DEFINT A-Z

 'Declarations for OS/2's Vio scroll functions.
 DECLARE FUNCTION VioScrollUp (BYVAL Y1      AS INTEGER,_
                               BYVAL X1      AS INTEGER,_
                               BYVAL Y2      AS INTEGER,_
                               BYVAL X2      AS INTEGER,_
                               BYVAL Lines   AS INTEGER,_
                               SEG   FillNew AS INTEGER,_
                               BYVAL Handle  AS INTEGER)

 DECLARE FUNCTION VioScrollLf (BYVAL Y1      AS INTEGER,_
                               BYVAL X1      AS INTEGER,_
                               BYVAL Y2      AS INTEGER,_
                               BYVAL X2      AS INTEGER,_
                               BYVAL Lines   AS INTEGER,_
                               SEG   FillNew AS INTEGER,_
                               BYVAL Handle  AS INTEGER)

 DECLARE FUNCTION VioScrollRt (BYVAL Y1      AS INTEGER,_
                               BYVAL X1      AS INTEGER,_
                               BYVAL Y2      AS INTEGER,_
                               BYVAL X2      AS INTEGER,_
                               BYVAL Lines   AS INTEGER,_
                               SEG   FillNew AS INTEGER,_
                               BYVAL Handle  AS INTEGER)

 DECLARE FUNCTION VioScrollDn (BYVAL Y1      AS INTEGER,_
                               BYVAL X1      AS INTEGER,_
                               BYVAL Y2      AS INTEGER,_
                               BYVAL X2      AS INTEGER,_
                               BYVAL Lines   AS INTEGER,_
                               SEG   FillNew AS INTEGER,_
                               BYVAL Handle  AS INTEGER)

 Y1 = 0    'Set the coordinates of the window scrolling area to define
 X1 = 0    'the whole screen (assuming 25 rows and 80 columns).
 Y2 = 24
 X2 = 79

 Lines    = 1       'Scroll one line at a time.
 FillNew  = 20010   'Fill the new lines/columns with yellow asterisks
                    'on a red background.
 Handle   = 0       'Specifies the default OS/2 screen group.

 CLS                 'Clear screen and display the message to scroll.
 LOCATE 12, 30
 PRINT "Use arrows on numeric keypad to scroll."
 PRINT "Hit Esc to quit."

 ON KEY(11) GOSUB UpArrow      'Setup event handlers for key trapping.
 ON KEY(12) GOSUB LeftArrow    'Keys 11-14 are the arrow keys on the
 ON KEY(13) GOSUB RightArrow   'numeric keypad.
 ON KEY(14) GOSUB DownArrow

 KEY(11) ON   'Turn key trapping on.
 KEY(12) ON
 KEY(13) ON
 KEY(14) ON

 DO UNTIL INKEY$ = CHR$(27)   'Loop until the ESC key is pressed.
 LOOP
 END

 'Event handlers for key traps.
 UpArrow:    E = VioScrollUp (Y1, X1, Y2, X2, Lines, FillNew, Handle)
             RETURN

 LeftArrow:  E = VioScrollLf (Y1, X1, Y2, X2, Lines, FillNew, Handle)
             RETURN

 RightArrow: E = VioScrollRt (Y1, X1, Y2, X2, Lines, FillNew, Handle)
             RETURN

 DownArrow:  E = VioScrollDn (Y1, X1, Y2, X2, Lines, FillNew, Handle)
             RETURN


 316. BEGINTRANS Example "Invalid Columnname" for Address

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900626-73 docerr
 Last Modified:  1-AUG-1990    ArticleIdent: Q64100

 The BEGINTRANS example on Pages 23-25 of the "Microsoft BASIC 7.0:
 Language Reference" manual for versions 7.00 and 7.10 incorrectly uses
 "Address" in the Borrower TYPE declaration when trying to OPEN the
 BOOKS.MDB sample database. The example should use "Street" instead.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10.

 The BEGINTRANS example gives the error message "Invalid column name"
 because it tries to OPEN the BOOKS.MDB database (an ISAM file), which
 actually uses "Street" as a column name instead of "Address."

 The following lines of the code example should be changed as follows:

 Page 23
 -------

 The following line

    Address AS STRING * 50        'Address

 should read as follows:

    Street AS STRING * 50         'Street address

 Page 24
 -------

 The following line

    PRINT LEFT$(People.Address, 25); "  ";

 should read as follows:

      PRINT LEFT$(People.Street, 25); "  ";


 317. Description of Expanded Memory Switches for BASIC PDS 7.10

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900503-164
 Last Modified: 15-JAN-1991    ArticleIdent: Q64101

 This article describes the purpose and use of the switches that allow
 you to configure use of expanded memory (according to the LIM 4.0
 Expanded Memory Specification [EMS]) in BASIC PDS 7.00 and 7.10.
 Especially important is the description of the /Es switch and its
 relationship to the other expanded memory switches.

 This information applies to Microsoft BASIC Professional Development
 System versions 7.00 and 7.10 for MS-DOS.

 Saving and Restoring the Expanded Memory State
 ----------------------------------------------

 By default, QBX.EXE and programs compiled with BC.EXE 7.00 or 7.10
 will only perform the minimum saving and restoring of the expanded
 memory state necessary to allow the program to work properly. This
 assumes that no third-party code using expanded memory is present. To
 get more than this minimal amount of expanded memory saving/restoring,
 you must specify /Es upon loading QBX or when compiling programs with
 BC.EXE. This is by design. If BASIC always saved and restored the
 state of expanded memory, the save/restore operations would have a
 significant speed impact on ISAM and on Quick library (.QLB) calling.
 The purpose of the /Es switch is to allow programs to use third-party
 code that uses expanded memory. The trade-off is a degradation in
 speed.

 Table of Expanded Memory Switches and Where You Can Use Them
 ------------------------------------------------------------

    Use With    Switch Name    Switch Purpose
    --------    -----------    --------------

    QBX only    /Ea            Arrays > 512 bytes but < 16K in
                               expanded memory. Default: No arrays in
                               expanded memory.

    QBX only    /E:n           n = amount in kilobytes of expanded
                               memory QBX will use. 0 means QBX uses no
                               expanded memory. Default: Use all
                               available expanded memory.

    QBX and BC  /Es            Enable saving/restoring of expanded
                               memory state.

    PROISAM(D)  /Ie:n          Reserves n kilobytes of expanded memory
                               for other applications (such as QBX).
                               ISAM will only use 1.2 megabytes of
                               expanded memory maximum.

 Examples: Use of Switches, Their Effects, and How They Interact
 ---------------------------------------------------------------

 QBX /E:0
 --------

 - Causes QBX to disable use of expanded memory code storage.

 - If the program has ISAM using expanded memory, it is assumed there
   is no third-party code accessing expanded memory. With /E:0, the
   default for QBX is not to save/restore the expanded memory state on
   ISAM use. This maximizes the speed of ISAM performance.

 QBX /E:0 /Es
 ------------

 - Save/restore operations occur on any ISAM statements or QLB calls.
   You would use this combination if you are loading QLBs that use
   expanded memory and you are also using ISAM that is using expanded
   memory.

 QBX /E:N and N Is Nonzero
 -------------------------

 - The expanded memory state is not saved/restored on QLB calls.

 - Save/restore operations occur on ISAM calls when both QBX and ISAM
   are sharing expanded memory.

 - It is assumed there are no QLBs using expanded memory.

 QBX /Es or QBX /E:N /Es
 -----------------------

 - Forces save/restore operations on QLB calls and ISAM statements.

 - This would be used if you are using QBX and calling QLB routines that
   access expanded memory.

 BC with No Expanded Memory Management Switches, No Overlays, No ISAM
 --------------------------------------------------------------------

 - The expanded memory state is not saved/restored.

 - Third-party routines accessing expanded memory should work
   correctly.

 BC with Overlays That Will Load from Expanded Memory
 ----------------------------------------------------

 - Expanded memory will be used by compiled code in the overlays.

 - The default is to save/restore expanded memory on all ISAM
   statements in a program that uses overlays.

 - This could still cause problems if third-party library routines that
   use expanded memory are called.

 BC /Es with Overlays and ISAM
 -----------------------------

 - Expanded memory will be saved/restored on ISAM statements.

 - Always use /Es when making mixed-language calls to routines that use
   expanded memory as well.

 BC /Es Without Expanded Memory Overlays, but with ISAM
 ------------------------------------------------------

 - /Es always causes save/restore operations on ISAM statements when
   ISAM is using expanded memory.

 - You would use this switch if the program uses ISAM, ISAM is using
   expanded memory, and there are mixed-language CALLs to routines
   that use expanded memory.

   Note: /Es will not cause save/restore operations on ISAM statements
   if ISAM is NOT using expanded memory.


 318. BASIC 7.0 Documentation Correction for Compiling OS/2 Programs

 Product Version(s): 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900719-162 docerr
 Last Modified:  1-AUG-1990    ArticleIdent: Q64102

 The second sentence in the "Compiling OS/2 Programs" section on Page
 527 of the "Microsoft BASIC 7.0: Programmer's Guide" manual for
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 incorrectly states the following:

    For protected-mode programs, make sure to specify the /LP option
    to LINK.

 This sentence should refer to the BASIC compiler (BC.EXE) instead of
 to the BASIC linker (LINK.EXE), as follows:

    For protected-mode programs, make sure to specify the /LP option
    to compile with BC.EXE.


 319. CURRENCY Variable of User-Defined TYPE Cannot Use @ Symbol

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900717-156 buglist7.00 buglist7.10
 Last Modified: 27-JUL-1990    ArticleIdent: Q64103

 A field in a user-defined TYPE ... END TYPE statement must be defined
 with the "AS VariableType" form. When accessing the variable in the
 program, however, the variable can be referred to with or without the
 appropriate type symbol (for example, % for integer, & for long,
 etc.). However, a variable of type CURRENCY defined in a user-defined
 TYPE cannot be referred to in this manner. If the currency symbol (the
 @ sign) is used when accessing the field, the error message "Equal
 sign missing" is returned by the BC.EXE compiler. No error occurs when
 this format is used in the QBX.EXE environment.

 Microsoft has confirmed this to be a problem with the BASIC compiler
 (BC.EXE) in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS and OS/2. We are researching this
 problem and will post new information here as it becomes available.

 To reproduce this problem, no special compiler directives are
 necessary. Use the following command to generate the error:

    BC BasicProgramName ;

 The compiler error and output are as follows:

     me(1).a@ = 12
            ^  Equal sign missing

 Sample Code
 -----------

 TYPE mytype
   a AS CURRENCY
   b AS INTEGER
   c AS LONG
   d AS SINGLE
   e AS DOUBLE
   f AS STRING * 20
 END TYPE

 DIM me AS mytype
 COMMON SHARED me() AS mytype

 REDIM me(10)  AS mytype
 me(1).a@ = 12     REM  Remark this line to avoid the compiler error
                   REM  or remove the currency symbol (@).
 me(1).b% = 12
 me(1).c& = 12
 me(1).d! = 12
 me(1).e# = 12
 me(1).f$ = "12"
 PRINT me(1).a, me(1).b, me(1).c
 PRINT me(1).d, me(1).e, me(1).f


 320. GET from COM1 or COM2 Fails to Get Correct Data -- Use INPUT$

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900710-87 buglist7.00 buglist7.10
 Last Modified:  1-AUG-1990    ArticleIdent: Q64108

 The GET statement fails to read the correct information from a
 communications port (COM1, COM2) with Microsoft BASIC Professional
 Development System (PDS) version 7.00. Characters are removed from the
 buffer, but the values read in are not the correct values sent across
 the port.

 To work around this problem, use the INPUT$ function to read the data
 from the COM port.

 Microsoft has confirmed this to be a problem with Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS and OS/2. We are researching this
 problem and will post new information here as it becomes available.

 This problem does NOT occur in Microsoft QuickBASIC version 4.50 or
 earlier or in Microsoft BASIC Compiler version 6.00b or earlier.

 Code Example
 ------------

 The following program attempts to read characters from COM1 using both
 GET and INPUT$:

    DIM a AS STRING * 1, b AS STRING * 1
    OPEN "COM1:300,n,8,1" FOR RANDOM AS #1
    GET #1, , a
    b = INPUT$(1, 1)
    PRINT a, b
    END

 In QuickBASIC 4.50, both the GET and INPUT$ statements return the
 correct values, but in BASIC PDS 7.00 and 7.10, only INPUT$ returns
 the correct data while GET returns meaningless data.


 321. 7.0 Manual Correction for BASIC Calling C Passing a Far String

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900719-55 docerr
 Last Modified:  1-AUG-1990    ArticleIdent: Q64109

 Page 501 of the "Microsoft BASIC 7.0: Programmer's Guide" for versions
 7.00 and 7.10 shows an incorrect example of passing a far string to C.
 The error is in the BASIC code. The C code is correct.

 The BASIC code needs to be changed in the following two places on Page
 501:

 1. The incorrect fourth line of the example is as follows (where the
    underscore means to place the statement all on one line):

       DECLARE FUNCTION addstring$(SEG s1$,BYVAL_
               s1length,SEG s2$,BYVAL s2length)

    and should be changed to read as follows (where the underscore
    means to place the statement all on one line):

       DECLARE FUNCTION addstring$ CDECL_
              (BYVAL s1offset%, BYVAL s1segment%, BYVAL s1length%,_
               BYVAL s2offset%, BYVAL s2segment%, BYVAL s2length%)

    In other words, to create a C far pointer, you have to pass the
    segment followed by the offset and pass this BYVAL so it will be
    pushed on the stack.

 2. The incorrect tenth line is as follows:

       C$ = addstring$(A$, LEN(A$), B$, LEN(B$))

    and should be changed to read as follows (where the underscore
    means to place the statement all on one line):

       C$ = addstring$(SSEG(A$), SADD(A$), LEN(A$), SSEG(B$),_
                       SADD(B$), LEN(B$))

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 For more information on passing parameters between BASIC and C, query
 in the Knowledge Base or in the Software/Data Library on the word
 BAS2C.


 322. PRINT USING Doesn't Work in UI Toolbox Window; Use FormatX$

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900717-4
 Last Modified: 27-JUL-1990    ArticleIdent: Q64185

 The WindowPrint subroutine included in the User Interface (UI) Toolbox
 allows you to print text strings inside a window that was defined with
 the WindowOpen UI subroutine. However, the WindowPrint subroutine does
 not allow you to print numbers or formatted numbers the same way a
 PRINT USING statement does. To print numbers or formatted numbers, you
 must first use the FormatX$ functions, available in the BASIC PDS
 Add-on Library DTFMTxx.LIB. The string of numbers formatted with
 FormatX$ can then be printed with the WindowPrint subroutine.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The term FormatX$ actually refers to the functions FormatI$, FormatL$,
 FormatS$, FormatD$, and FormatC$. For more information on the FormatX$
 functions, query in this Knowledge Base on the word "FormatX$".

 To use the FormatX$ functions with the User Interface Toolbox in the
 QBX.EXE environment, you must first create a Quick library (a .QLB
 file) containing the code for both the User Interface routines and
 also the FormatX$ routines. Here are two methods to do this:

 Method 1
 --------

 To create the Quick library from provided .LIB libraries, combine the
 libraries into a new library as follows

    LIB UITFMT.LIB+UITBEFR.LIB ;
    LIB UITFMT.LIB+DTFMTER.LIB ;

 then create the new Quick library (UITFMT.QLB) as follows:

    LINK /Q UITFMT.LIB, UITFMT.QLB,,QBXQLB.LIB ;

 Note that the first LIB command line above creates UITFMT.LIB. LIB.EXE
 creates UITFMT.LIB automatically since UITFMT.LIB did not previously
 exist. The second LIB command line appends DTFMTER.LIB to UITFMT.LIB.

 To invoke QBX.EXE (the QuickBASIC Extended environment) with the
 UITFMT.QLB Quick library (created in Method 1 above), use the
 following command:

    QBX /L UITFMT.QLB

 Method 2
 --------

 To create the .QLB file from the original .OBJ files, use the
 following LINK command:

    LINK /q WINDOW.OBJ+MENU.OBJ+MOUSE.OBJ+GENERAL.OBJ+UIASM.OBJ+
                         QBX.LIB+DTFMTER.LIB,UIFMT.QLB,,QBXQLB.LIB;

 Note: In the preceding LINK line, you must use DTFMTER.LIB, where "E"
 stands for Emulator math package, and "R" stands for DOS real mode.
 Quick libraries used in QBX.EXE cannot be compiled for Alternate math
 or protected mode.

 To invoke QBX.EXE (QuickBASIC Extended) with the UIFMT.QLB Quick
 library (created in Method 2 above), use the following command:

    QBX /L UIFMT.QLB

 To use the UI Toolbox routines and the FormatX$ routines in an
 executable (.EXE) program, you must link to the UITFMT.LIB (created in
 Method 1 above) to your program, or separately link the DTFMTxx.LIB
 and UITBxxx.LIB libraries (shipped by Microsoft) into your program.

 The following code sample gives an example of using the FormatS$
 function to convert a single-precision number into a dollar amount,
 and then print the result in a UI Toolbox window:

 Code Sample
 -----------

 DEFINT A-Z
 REM $INCLUDE: 'window.bi'
 REM $INCLUDE: 'mouse.bi'
 REM $INCLUDE: 'menu.bi'
 REM $INCLUDE: 'general.bi'
 REM $INCLUDE: 'format.bi'

 COMMON SHARED /uitools/ glomenu AS menumisctype
 COMMON SHARED /uitools/ glotitle() AS menutitletype
 COMMON SHARED /uitools/ gloitem() AS menuitemtype
 COMMON SHARED /uitools/ glowindow() AS windowtype
 COMMON SHARED /uitools/ globutton() AS buttontype
 COMMON SHARED /uitools/ gloedit() AS editfieldtype
 COMMON SHARED /uitools/ glostorage AS windowstoragetype
 COMMON SHARED /uitools/ glowindowstack() AS INTEGER
 COMMON SHARED /uitools/ globuffer$()

 DIM glotitle(maxmenu) AS menutitletype
 DIM gloitem(maxmenu, maxitem) AS menuitemtype
 DIM glowindow(MAXWINDOW) AS windowtype
 DIM globutton(MAXBUTTON) AS buttontype
 DIM gloedit(MAXEDITFIELD) AS editfieldtype
 DIM glowindowstack(MAXWINDOW) AS INTEGER
 DIM globuffer$(MAXWINDOW + 1, 2)

 CLS
 MenuInit
 windowinit

 windowopen 1, 3, 3, 20, 40, 7, 0, 7, 0, 15, 0, 0, 0, 0, 1, "Format Example"
 ' Set the variable name:
 a! = 123.34

 ' Convert the variable to a string:
 b$ = STR$(a!)

 'convert the variable to a formatted string:
 x$ = formats$(a!, "$0000.00")

 ' Print out the results:

 windowprint 1, "The unformatted variable is:"
 windowprint 1, b$
 windowprint 1, "The formatted variable using the"
 windowprint 1, "form '$0000.00':"
 windowprint 1, x$


 323. How to Simulate Bound Executables with BASIC 6.00 - 7.10

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# S900724-5
 Last Modified: 27-JUL-1990    ArticleIdent: Q64210

 Although Microsoft BASIC Compiler versions 6.00 and 6.00b and
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 can create protected and real mode
 programs, they cannot create bound programs. A bound program is one
 that can run both in protected mode and real mode (DOS). However,
 there is a way to simulate the functionality of a bound program by
 creating a real mode version of the program and then linking the
 protected mode version with a module-definition file containing the
 STUB statement. The procedure for doing this is described below.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2 and Microsoft BASIC PDS versions 7.00 and
 7.10 for MS-DOS and MS OS/2.

 The STUB statement adds a DOS versions 3.x (real mode) executable file
 to the beginning of the protected mode program being created by
 LINK.EXE. The syntax of the STUB statement is the following:

    STUB 'filename'

 Here, filename is the name of a real mode executable file. This real
 mode stub is invoked whenever the program is executed under DOS 2.x or
 DOS 3.x (or the DOS compatibility box of OS/2). By default, the linker
 adds its own standard stub that terminates after displaying a message
 similar to the following:

    This program cannot run in DOS mode.

 You can use the STUB statement to replace this standard stub with a
 real mode program that exactly emulates the behavior of a protected
 mode version, thus simulating a bound executable.

 The following is an example of the steps necessary to do this. This
 example uses the following two BASIC source files:

    REALMODE.BAS
    ------------

    PRINT "This program has the same output in protected and real modes."

    PROTMODE.BAS
    ------------

    PRINT "This program has the same output in protected and real modes."

 Here are the steps:

 1. Create a real mode version of the program as you normally would.
    For our example, the following two commands accomplish this:

       bc /Lr realmode.bas;
       link realmode.obj;

 2. Create a module-definition file containing the STUB statement. You
    can do this with any text editor. Make sure the file is saved as an
    ASCII text file. For our example, the module-definition file
    (PROTMODE.DEF) would look like this:

       STUB 'REALMODE.EXE'

 3. Create the protected mode version of the program, linking with the
    module-definition file created in Step 2. Compile the program as
    you normally would, but when linking, include the name of the
    module-definition file in the fifth link parameter. The compile
    and link commands for our example would be as follows:

       bc /Lp protmode.bas;
       link protmode.obj,,,,protmode.def;

 When PROTMODE.EXE is run from a protected mode session, the following
 will be the output:

    This program has the same output in protected and real modes.

 When PROTMODE.EXE is run from a DOS (real mode) session, REALMODE.EXE
 will be executed instead of PROTMODE.EXE. Remember that REALMODE.EXE
 is appended to the beginning of PROTMODE.EXE, so it is not necessary
 to have a copy of REALMODE.EXE in the current directory. The output
 will be the same as if PROTMODE were run from a protected mode
 session:

    This program has the same output in protected and real modes.


 324. LINK "Stack Plus Data Exceed 64K"; 7.00 BC /Fs Forces /S

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  6-AUG-1990    ArticleIdent: Q64424

 In Microsoft BASIC Professional Development System (PDS) version 7.00
 for MS-DOS and MS OS/2, the BC /Fs (Far Strings) option forces the
 compiler to also perform a /S. If you use many quoted strings in your
 program, this BC /S option places extra overhead in the .OBJ file
 that could (in some cases) overload the linker and give a "Stack plus
 data exceed 64K" error (L2041) at LINK time. Compiling without /Fs
 (using near strings) will not force /S, and the program may then LINK
 without the L2041 error.

 BASIC PDS version 7.10 is enhanced so that the BC /Fs option no longer
 forces an automatic /S option. This enhancement can help avoid the
 "Stack plus data exceed 64K" error as in the above case when you need
 to compile with the /Fs option.

 BC /S Option
 ------------

 The BC /S option helps you only at compile time. You only need to use
 the BC /S option when you get an "Out of memory" error message at
 compile time due to too many quoted string constants in the source
 program. Compiling with BC /S increases DGROUP usage at link time, in
 some cases contributing to the cause of the linker error "Stack plus
 data exceed 64K." Compiling with BC /S normally does not affect the
 size or speed of the final linked .EXE program.

 BC /Fs Option
 -------------

 The BC /Fs (Far Strings) option gives you more space for
 variable-length string variables at the cost of increasing the size
 and slowing the speed of .EXE programs.


 325. ISAMIO.EXE /I Imports ASCII Text File into BASIC ISAM File

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900531-47
 Last Modified:  6-AUG-1990    ArticleIdent: Q64495

 You can convert an ASCII text file into a Microsoft BASIC Professional
 Development System (PDS) ISAM database table by using the ISAMIO.EXE
 utility with the /I (Import) option. This article describes how to use
 the ISAMIO /I option.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 under MS-DOS.

 The syntax for importing (converting) an ASCII file into an ISAM
 database using the ISAMIO utility is as follows:

    ISAMIO /I ASCIIFIL.TXT DATBASE.MDB TABLNAME SPECFIL.TXT [options]

 ASCIIFIL.TXT can have two formats. It can appear in a fixed-width
 format where certain data appears in fixed columns of the file. The
 ISAMIO /F option is required for a file of this type. The file can
 also be comma delimited with string data enclosed in double quotation
 marks. In this format, blank spaces should not be used between the
 fields and the commas. If blank spaces are inserted between the commas
 and the data, an "Unable to Parse column xx of line xx" error may
 occur.

 The DATBASE.MDB and TABLNAME are names of the ISAM database and table
 into which the ASCII file is to be imported. If DATBASE.MDB or
 TABLNAME doesn't already exist, PROISAMD support must be available to
 create them. A related ISAMIO.EXE error message is as follows:

    ISAM command is not available" (in 7.00 or 7.10)

 This error message displays when PROISAM capability is currently
 installed but PROISAMD capability is needed (to create a new ISAM
 database or table). To avoid this error, do one of the following:

 1. If you ran SETUP.EXE with the "ISAM Routines in TSR" option, load
    PROISAMD.EXE instead of PROISAM.EXE.

 2. If you ran SETUP with "ISAM Routines in LIB, Support Database
    Access Only" option, run SETUP again and choose "ISAM Routines in
    LIB, Support Database Creation and Access."

 If the database and table already exist and you use the ISAMIO /A
 (Append) option, you can use either PROISAM or PROISAMD.

 SPECFIL.TXT is the file that ISAMIO uses to specify the data type and
 size for each column of a table. Each line of the file relates to a
 column of the table. The format is as follows:

    [fixedwidthsize,][type,[size],[columnname]]

 The fields in SPECFIL.TXT can be separated by spaces or commas. The
 "fixedwidthsize" field is valid only if the /F option is used. It just
 specifies the size of the field to read from ASCIIFIL.TXT.

 The "type" field in SPECFIL.TXT is one of the indexable ISAM data
 TYPEs. In the case of arrays, user-defined TYPEs, and strings longer
 than 255 characters, the "type" field must be specified as binary. If
 the "type" field is specified as variabletext (vt) or variablestring
 (vs), the "size" field must appear. The "size" field for string data
 tells ISAMIO the size of the field to put the string data into. The
 "size" field can be smaller, which truncates input data, or larger,
 which allows a larger string to be input later. These two types are
 the same except that variabletext (vt) is case insensitive while
 variablestring (vs) is case sensitive. Note that BASIC PDS' use of
 string data is case insensitive (that is, all comparisons made are
 case insensitive). Therefore, even if variablestring is specified, it
 is converted to variabletext.

 The "columnname" field in SPECFIL.TXT is any valid ISAM column name,
 but it is ignored if the /C option is used.

 The ISAMIO options that you can use for importing a file (/I) are /C,
 /F, and /A. The following table describes these options:

 Option     Description
 ------     -----------

 /A         Tells ISAMIO that you are importing ASCIIFIL.TXT and
            appending it to an existing table (TABLNAME). If /A is
            specified, column names cannot appear in ASCIIFIL.TXT
            (the /C option), only data. If you use the /A and /C
            options together, the following error message displays:

               APPEND & COLUMN_NAMES conflicts

            The SPECFIL.TXT file cannot appear on a command line that
            contains the /A option. ISAMIO uses the format of the
            existing table that is being appended to. If SPECFIL.TXT
            is specified along with the /A option, the following error
            message displays:

               APPEND and specfile conflicts

            If the table does not exist within the specified database
            (DATBASE.MDB), ISAMIO displays the following error message:

               Can't Open Table "TABLNAME"

 /C         Tells ISAMIO that the ISAM table's column names should be
            taken from the first line of ASCIIFIL.TXT. These column
            names need to be separated by a space, comma, or any
            combination thereof. If a column name is not consistent
            with the ISAM naming convention, ISAM displays the error
            message "Invalid Name." If this option is not specified
            when importing a new table, ISAMIO looks at SPECFIL.TXT
            for the column names. If ISAMIO doesn't find a column name
            in SPECFIL.TXT, it displays an error message that tells
            you that you must specify a column name in SPECFIL.TXT.

 /F         Tells ISAMIO that the text to be imported is of a
            fixed-width format (already in columns of a certain
            length). The size of the fixed-width format must be
            specified in the first column of SPECFIL.TXT. If the /F
            option is not used, the data in the fields of ASCIIFIL.TXT
            are assumed to be delimited by commas, with string data
            enclosed in double quotation marks. If you use /F and one
            of the fields is shorter than the specified length, you
            will receive the error message "Unable to parse column xx
            of line xx," where "column" refers to the column of a
            table.

 Depending on how you ran SETUP.EXE, the ISAMIO.EXE utility will be
 built either to run as a stand-alone program or to require the
 terminate-and-stay-resident (TSR) form of ISAM. A separate article,
 found by querying in this Knowledge Base on the following words,
 discusses this topic:

    SETUP and builds and ISAMIO

 When you run ISAMIO and receive one of the following error messages,
 you must install the PROISAM.EXE or PROISAMD.EXE TSR program if you
 are running MS-DOS; if you are running OS/2, you must put PROISAM.DLL
 or PROISAMD.DLL in your LIBPATH:

    ISAMIO: ISAM TSR is not loaded" (in 7.00 under MS-DOS)
    ISAMIO : error: ISAM DLL not found" (in 7.10 under MS-DOS or OS/2)

 The following are some examples of importing different ASCII files:

 Example 1
 ---------

 The contents of ASCIIFIL.TXT are as follows:

    CustomerName  Address  CustomerNumber
    Huck Finn   1606 Crest Dr. 3490
    Joe Henry   893 S. Scenic   5620
    Billy Bob   143 Maple St    0894

 The contents of SPECFIL.TXT are as follows (where BASIC PDS ISAM treats
 vt and vs the same way):

    12,vt,20
    16,vs,16
    4,integer

 Invoke ISAMIO.EXE in MS-DOS as follows:

    ISAMIO /I ASCIIFIL.TXT CUSTOMER.MDB TABLE1 SPECFIL.TXT /C/F

 Example 2
 ---------

 The contents of ASCIIFIL.TXT are as follows:

    "Huck Finn","1606 Crest Dr.",3490
    "Joe Henry","893 S. Scenic",5620
    "Billy Bob","143 Maple St",0894

 The contents of SPECFIL.TXT are as follows:

    12,vt,20,CustomerName
    16,vs,16,Address
    4,integer,CustomerNumber

 Invoke ISAMIO.EXE in MS-DOS as follows:

    ISAMIO /I ASCIIFIL.TXT CUSTOMER.MDB TABLE2 SPECFIL.TXT

 Example 3:  Appending a File to an Existing ISAM Table
 ------------------------------------------------------

 The following example shows how to append an ASCII file to an existing
 ISAM table:

 The contents of APENDFIL.TXT are as follows:

    "John Doe","1387 Main Blvd.",2490

 Note that a SPECFIL.TXT file is not used when appending a file to the
 ISAM table. Invoke ISAMIO.EXE as follows:

    ISAMIO /I APENDFIL.TXT CUSTOMER.MDB TABLE2 /A

 For more information on how to use ISAMIO, see Pages 389-391, Chapter
 10, "ISAM Utilities," of the "Microsoft BASIC 7.0: Programmer's Guide"
 for versions 7.00 and 7.10.


 326. SETUP Builds ISAMIO, ISAMCVT, ISAMPACK as Stand Alone or Not

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-AUG-1990    ArticleIdent: Q64496

 Depending on how you run SETUP.EXE, the ISAM utilities ISAMIO.EXE,
 ISAMCVT.EXE, and ISAMPACK.EXE are built either to run as stand-alone
 programs or to require the terminate-and-stay-resident (TSR) form of
 ISAM.

 SETUP always installs the ISAMREPR.EXE (ISAM repair) utility to run as
 a stand-alone program.

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 provides the following four SETUP.EXE options for installing
 ISAM support for DOS (or OS/2 real mode):

 1. ISAM Routines in TSR
 2. ISAM Routines in LIB, Support Database Creation and Access
 3. ISAM Routines in LIB, Support Database Access Only
 4. No ISAM support

 SETUP Option 1 builds ISAMIO.EXE, ISAMCVT.EXE, or ISAMPACK.EXE
 utilities that require the TSR form of ISAM (PROISAM.EXE or
 PROISAMD.EXE). Option 1 is the default because it consumes the least
 disk space.

 SETUP Options 2 and 3 create stand-alone ISAM utilities (ISAMIO.EXE,
 ISAMCVT.EXE, ISAMREPR.EXE, and ISAMPACK.EXE), which do not require the
 presence of the ISAM TSR programs (PROISAM.EXE or PROISAMD.EXE). If
 you choose Option 3 instead of 2, the ISAM utilities will not be able
 to create or delete any ISAM databases or tables, they will just be
 able to add and delete records for existing databases or tables.

 SETUP Option 4 does not copy any ISAM utilities, TSR programs, or any
 other ISAM-related files onto your computer.

 Because BASIC PDS 7.10 introduces ISAM support under OS/2 protected
 mode, it provides the following two additional SETUP options:

 1. ISAM Routines in DLL
 2. No ISAM Support

 The protected mode ISAM SETUP choices (above) do not affect how
 ISAMIO.EXE, ISAMCVT.EXE, ISAMREPR.EXE, or ISAMPACK.EXE are built,
 since these ISAM utilities run only under MS-DOS (and not under OS/2).

 Reference:

 For more information, see Pages 389-399, Chapter 10, "ISAM Utilities,"
 of the "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and
 7.10.


 327. How to Use Named, Shared Memory Segments in OS/2 BASIC Program

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900730-92
 Last Modified: 17-AUG-1990    ArticleIdent: Q64589

 Microsoft BASIC Compiler versions 6.00 and 6.00b and Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 can
 create OS/2 protected mode programs that use named, shared memory
 segments. Named, shared memory segments are areas of memory used for
 interprocess communications (IPC). Their use involves calling three
 different OS/2 API functions. Below are two sample BASIC programs that
 demonstrate the use of named, shared memory segments.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS OS/2.

 Named, shared memory segments can be used to communicate between
 processes. Their names have the following form:

    \SHAREMEM\name.ext

 ".ext" is optional. The size of the segment can be up to 65,536 bytes.
 After the segment is allocated, it can be read from and written to
 using PEEK and POKE, which examine and set (respectively) a 1-byte
 address location. Typically, one process (called the "creator") will
 allocate the segment and other programs (called "obtainers") will
 obtain the address (selector) to it. The minimum OS/2 API functions
 that need to be called to use named, shared memory segments are the
 following:

 For the Creator
 ---------------

 Function       Description
 --------       -----------

 DosAllocShrSeg()   Allocates a named, shared memory segment of up to
                    65,536 bytes and returns a selector for it.

 For the Obtainers
 -----------------

 Function       Description
 --------       -----------

 DosGetShrSeg()     Obtains a selector to a named, shared memory segment
                    that was allocated by DosAllocShrSeg().

 For Both the Creator and Obtainers
 ----------------------------------

 Function       Description
 --------       -----------

 DosFreeSeg()       Releases the selector to the segment. When all
                    selectors by all processes have been released, the
                    segment is reclaimed by OS/2.

 For more information on named, shared memory segments and other IPC
 methods, see Chapter 13, "Interprocess Communication," of "Advanced
 OS/2 Programming" by Ray Duncan (Microsoft Press, 1989).

 The following are two sample programs that demonstrate the use of
 named, shared memory segments. To compile the programs, enter the
 following commands at the OS/2 command prompt:

    bc creator;
    bc obtainer;

 How the programs are linked depends on which version of BASIC is being
 used. This is because in BASIC 6.00 and 6.00b, the name of the OS/2
 API functions import library is DOSCALLS.LIB. In BASIC PDS 7.00 and
 7.10, the name is OS2.LIB. The link lines are as follows:

 For BASIC 6.00 and 6.00b:  link creator,,,doscalls;
                            link obtainer,,,doscalls;

 For BASIC PDS 7.00 and 7.10:  link creator,,,os2;
                               link obtainer,,,os2;

 CREATOR.BAS
 -----------

 'CREATOR.BAS allocates a named, shared segment and writes the letters
 'of the alphabet to bytes 0 through 25 of the segment. It then waits
 'until byte 0 of the segment becomes 255 before releasing its selector
 'and terminating.
 DECLARE FUNCTION DosAllocShrSeg% (BYVAL SegmentSize%,
                                   BYVAL NameSegment%,_
                                   BYVAL NameOffset%, SEG Selector%)
 DECLARE FUNCTION DosFreeSeg%     (BYVAL Selector%)

 'Attempt to allocate the segment.
 SegmentName$ = "\SHAREMEM\SPIKE" + CHR$(0)
 ErrorCode%   = DosAllocShrSeg% (26, VARSEG(SegmentName$),_
                                 SADD(SegmentName$), Selector%)

 'Check if an error occurred.  If not, make the segment current.
 IF ErrorCode% <> 0 THEN
    PRINT "Error";ErrorCode%;" allocating segment"
    BEEP
    END
 ELSE
    DEF SEG = Selector%
 END IF

 FOR ASCII% = 65 TO 90         'Write the letters A through Z to bytes
    POKE ASCII% - 65, ASCII%   '0 through 25 of the segment.
 NEXT ASCII%

 PRINT "Waiting for data to be read..."   'When OBTAINER.BAS is done
 DO UNTIL PEEK(0) = 255                   'reading, it will put a 255
 LOOP                                     'in byte 0 of the segment.

 ErrorCode% = DosFreeSeg% (Selector%)   'Free the segment selector.
 END

 OBTAINER.BAS
 ------------

 'OBTAINER.BAS obtains a selector to the segment created by
 'CREATOR.BAS and reads bytes 0 through 25, display their contents. It
 'then POKEs a 255 into byte 0 of the segment so CREATOR.BAS will
 'terminate. Lastly, it releases its selector to the segment and
 'terminates itself.
 DECLARE FUNCTION DosGetShrSeg% (BYVAL NameSegment%,
                                 BYVAL NameOffset%, SEG Selector%)
 DECLARE FUNCTION DosFreeSeg%   (BYVAL Selector%)

 'Attempt to get a selector for the segment.
 SegmentName$ = "\SHAREMEM\SPIKE" + CHR$(0)
 ErrorCode%   = DosGetShrSeg% (VARSEG(SegmentName$),_
                               SADD(SegmentName$), Selector%)

 'Check if an error occurred.  If not, make the segment current.
 IF ErrorCode% <> 0 THEN
    PRINT "Error";ErrorCode%;" getting segment"
    BEEP
    END
 ELSE
    DEF SEG = Selector%
 END IF

 FOR Offset% = 0 TO 25
    PRINT CHR$(PEEK(Offset%));" ";   'Display bytes 0 to 25 of the
 NEXT Offset%                        'named, shared memory segment.

 POKE 0, 255                            'Signal CREATOR.BAS to end and
 ErrorCode% = DosFreeSeg% (Selector%)   'release the segment selector.
 END


 328. EMS40.SYS Is Valid LIM 4.0 Driver for EM Use in BASIC PDS

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900717-157 EMS40
 Last Modified:  5-SEP-1990    ArticleIdent: Q64591

 EMS40.SYS is a device driver that emulates the Lotus/Intel/Microsoft
 (LIM) Expanded Memory Specification (EMS) version 4.0. This software
 permits AT-class machines with extended memory to adapt their extended
 memory (defined by XMS) to expanded memory (defined by EMS). This
 driver is compatible with Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 and can map BASIC PDS source code
 segments less than 16K in size to the expanded memory of the machine.

 EMS40.SYS is freeware and it is available for downloading from the PC
 MagNet bulletin board. Although the source code is also available on
 MagNet, EMS40.SYS is already compiled and ready to use. Much of the
 information in this article comes from the "readme" file also
 available on MagNet.

 EMS40.SYS can be installed as a driver specified in your CONFIG.SYS
 file with the syntax shown below. The drive and path should be
 specified so the system can find the driver during machine boot-up.
 Once installed, EMS40.SYS cannot be removed from memory without
 rebooting the computer.

    DEVICE=[LogicalDriveName:\][path\]EMS40.SYS [xxx]

 The optional "xxx" parameter allows you to specify the amount of
 extended memory in kilobytes (K) to be used as expanded memory by
 EMS40.SYS. If the "xxx" parameter is omitted, the default value is
 384K. By setting "xxx: to a smaller value than that of the extended
 memory installed, space can be reserved for extended memory programs,
 such as HIMEM.SYS.

 EMS40.SYS maps extended memory into four contiguous 16K pages in
 conventional DOS memory and permits access to memory in situations
 that otherwise could result in a "Memory Full" error. EMS40.SYS is not
 as fast as a dedicated LIM 4.0 EMS board and driver, but it implements
 (within the limitations of software emulation) all 28 functions
 specified in the LIM 4.0 EMS. It does not attempt, however, to emulate
 the DMA functions included in Function 28, Alternate Map Register Set.


 329. QBX.EXE Color Loss & Hang on VGA on Tecmar BIOS 1.02; 1.11 OK

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBAS
 Last Modified: 17-OCT-1990    ArticleIdent: Q64899

 Several customers have reported that when running QBX.EXE from
 Microsoft BASIC Professional Development System (PDS) version 7.00 or
 7.10 on a machine with a Tecmar ROM BIOS version 1.02 or 1.04, if a
 VGA screen is being used, the environment loses color and the system
 eventually hangs or reboots itself.

 Tecmar is researching this problem and will provide a free upgrade to
 Tecmar ROM BIOS version 1.11. To obtain this free upgrade, call Tecmar
 technical support at (800) 344-4463.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.


 330. An Alternative If ISAMCVT Fails on IBM BASIC 2.0 ISAM Database

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900801-41
 Last Modified:  5-SEP-1990    ArticleIdent: Q64934

 ISAMCVT.EXE is a utility provided with Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for the purpose of
 converting files created with other database-management systems,
 including IBM BASIC Compiler version 2.00, to the Microsoft ISAM
 format.

 You can also convert the database using the REBUILD.EXE utility
 provided in IBM BASIC Compiler version 2.00. IBM's REBUILD can be used
 to strip the header information off the IBM ISAM data (.DAT) file. The
 file can then be read in as a random access file and written out to a
 Microsoft BASIC PDS 7.00 or 7.10 ISAM database.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 For more information on the ISAMCVT.EXE utility, see Pages 391-393 of
 the "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and
 7.10.

 This article contains the sample program CONVERT.BAS, which reads,
 with random access, the file created by the REBUILD utility with the
 /S option and writes the information out to a Microsoft BASIC PDS 7.00
 or 7.10 ISAM database. Please note that this process does not save
 indexes, so they will have to be rebuilt.

 When an IBM BASIC 2.00 ISAM file is created, two files are actually
 created: an index file with a .KEY extension, and a data file with the
 .DAT extension. The .DAT file has a structure very similar to a random
 access file except for the additional header information, known as the
 "data dictionary." The data dictionary can be removed by using the
 REBUILD utility with the /S option. The syntax is as follows:

    REBUILD SOURCE.DAT, TARGET.DAT /S;

 The "Single-key" switch (/S) tells REBUILD to copy the source file
 (the BASIC 2.00 data file) into the target file, removing the data
 dictionary and any free space. No key file is built. The format of the
 target file is a random access file with an additional 3-byte field
 added to the beginning of each record. When reading the random file
 into a BASIC 7.00 or 7.10 program, the TYPE...END TYPE statement must
 be formatted the same way as the corresponding FIELD statement used in
 the IBM BASIC 2.00 program, with the additional 3-byte field at the
 beginning of each record. For example:

 Used in BASIC 2.00 Program       Corresponding BASIC 7.00, 7.10 Declaration
 --------------------------       ------------------------------------------

     FIELD #1, _                    TYPE BASIC20Rec
      25 as Name$, _                      Basic2Index AS STRING * 3
      30 as Address$, _                   Name AS STRING * 25
      4 as Zip$, _                        Address AS STRING * 30
      1 as Sex$, _                        Zip AS STRING * 4
      2 as Age$, _                        Sex AS STRING * 1
      4 as Income$                        Age AS STRING * 2
                                          Income AS STRING * 4
                                    END TYPE

 Now you need to set up a TYPE...END TYPE statement to write the
 appropriate information to an ISAM database or to another random
 access file. This is to mask the BASIC 2.00 index off from the record.
 You will have to dimension a variable or array of each type and assign
 each of the individual fields, ignoring the 3-byte Basic2Index field.
 For example:

      TYPE BASIC70Rec
            Name AS STRING * 25
            Address AS STRING * 30
            Zip AS DOUBLE        '7.00/7.10 ISAM doesn't support SINGLE
            Sex AS STRING * 1
            Age AS INTEGER
            Income AS DOUBLE     '7.00/7.10 ISAM doesn't support SINGLE
      END TYPE

      DIM OldRec AS BASIC20Rec
      DIM NewRec AS BASIC70Rec
                .
                .
                .
      NewRec.Name = OldRec.Name
      NewRec.Address = OldRec.Address
      NewRec.Zip = CVS(OldRec.Zip)
      NewRec.Sex = OldRec.Sex
      NewRec.Age = CVI(OldRec.Age)
      NewRec.Income = CVS(OldRec.Income)

 Note that if floating-point values in records were written to the
 file, you will need to convert them by invoking the QBX environment
 with the /MBF option. This is because IBM BASIC Compiler 2.00 uses the
 Microsoft Binary Format (MBF) for floating-point numbers, and
 Microsoft BASIC PDS 7.00 and 7.10 use the IEEE format. For example:

    QBX /MBF

 For more information on the ISAM utilities, query in this Knowledge
 Base on the following words:

    ISAM and BASIC and UTILITY

 Code Example
 ------------

 'Below is CONVERT.BAS, the sample program that converts the sample ISAM
 'file "MAIL.DAT" found on the IBM BASIC Compiler 2.00 disks. MAIL.DAT
 'is rebuilt to the file "MAIL2.DAT" when the following command is typed
 'at the DOS prompt:
 '
 '   REBUILD MAIL.DAT, MAIL2.DAT /S;
 '
 'The file is then read as a random file and each record is inserted
 'into the database "CUSTOMER.MDB". For this example, invoke QBX.EXE
 'with the /MBF option and load the PROISAMD.EXE TSR program.

 DEFINT A-Z

 '  Record description of data file MAIL2.DAT after REBUILD utility is
 '  used:

 TYPE BASIC2Rec
      Basic2Index AS STRING * 3  'This is the 3-byte index from REBUILD
      Name AS STRING * 25        'First and last name
      Address AS STRING * 30     'Address
      Zip AS STRING * 4          'Zip, SINGLE written to file using
                                 'MKS$
      Sex AS STRING * 1          'Sex
      Age AS STRING * 2          'Age, INTEGER written to file using
                                 'MKI$
      Income AS STRING * 4       'Income, SINGLE written to file using
                                 'MKS$
 END TYPE

 TYPE BASIC7Rec
       Name AS STRING * 25      'First and last name
       Address AS STRING * 30   'Address
       Zip AS DOUBLE            'Zip, note the conversion process below
       Sex AS STRING * 1        'Sex
       Age AS INTEGER           'Age, note the conversion process below
       Income AS DOUBLE         'Income, note the conversion process
                                'below
 END TYPE

 DIM OldCust AS BASIC2Rec
 DIM NewCust AS BASIC7Rec

 OPEN "MAIL2.DAT" FOR RANDOM AS #1 LEN = LEN(OldCust)
 OPEN "CUSTOMER.MDB" FOR ISAM BASIC7Rec "TABLE1" AS #2
 CLS
 i = 0
 DO WHILE NOT EOF(1)
  i = i + 1
  GET #1, i, OldCust           'Get the old record

      'Assign the corresponding fields, ignoring the 3-byte index:

  NewCust.Name = OldCust.Name
  NewCust.Address = OldCust.Address
  NewCust.Zip = CVS(OldCust.Zip)        'Convert MBF to SINGLE
                                        'and assign into DOUBLE
  NewCust.Sex = OldCust.Sex
  NewCust.Age = CVI(OldCust.Age)        'Convert MBF to INTEGER
  NewCust.Income = CVS(OldCust.Income)  'Convert MBF to SINGLE
                                        'and assign to DOUBLE

      'Insert the array element into the ISAM database:

  INSERT #2, NewCust

 LOOP

 PRINT "The file is loaded into the database"   'tell user that the
                                                'file is loaded
 PRINT "Number of records read: "; i; "  hit key to continue"
 SLEEP

 SETINDEX #2
 MOVEFIRST #2                'Print out the database, to verify that
 DO WHILE NOT EOF(2)         'the information is there.
       RETRIEVE #2, NewCust

       PRINT
       PRINT NewCust.Name
       PRINT NewCust.Address
       PRINT NewCust.Zip
       PRINT NewCust.Sex
       PRINT NewCust.Age
       PRINT NewCust.Income
       MOVENEXT #2
 LOOP


 331. ISAM Benchmark of PDS 7.10 Versus 7.00, FoxPro, and Btrieve

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | fast faster slow slower quick
 Last Modified:  5-DEC-1990    ArticleIdent: Q64979

 The following article gives a benchmark comparison of ISAM file speed
 in Microsoft BASIC Professional Development System (PDS) version 7.10
 versus the following products: BASIC PDS version 7.00, Fox Software's
 FoxPro version 1.0, and Novell's Btrieve version 5.0c.

 These performance comparisons are taken from the Microsoft press
 release document (for BASIC PDS 7.10) dated July 24, 1990.

 ISAM DATABASE SPEED COMPARISONS
 -------------------------------

 The benchmark suites used by Microsoft for performance testing and
 comparison are similar to those used by Software Digest at National
 Software Testing Laboratories (NSTL) for benchmarking of relational
 databases. All benchmark tests below were performed on a COMPAQ 386
 20e with a 110 MB hard disk and 640K of conventional memory under
 MS-DOS.

 The following four files ("tables" in BASIC PDS) were used: two files
 (tables) with three indexed columns and 1000 records; one file (table)
 with three indexed columns and 10000 records; and one file (table)
 with two indexed columns and 10000 records. Each record (in each
 file/table) contained 10 text columns plus one integer column, for a
 total of 122 characters per record. The total database size for the
 four files (tables) was 6 megabytes in both BASIC PDS and Novell
 Btrieve. A disk unfragmentation utility was run to compact the
 databases before performing the benchmarks.

 BASIC PDS 7.10 Versus 7.00
 --------------------------

 All tests ran using 64K of ISAM buffer space.

                                                        PDS 7.10 Improvement
 Item                               PDS 7.00  PDS 7.10  Percent over PDS 7.00
 ----                               --------  --------  ---------------------

 Average Individual Record Search   1.4        1.3         8%
 Group Record Search On Index       6.3        5.6        13%
 Group Record Search w/o an Index  14          9.9        41%
 Subtotal 100 Groups/Short Field   34.8       20.7        68%
 Two-File Join with Subtotals     203.2      131.4        55%
 3-File Join w/ Hi Record Return  220.9      173.7        27%
 Three-File Join with Subtotaling 154.1       62.1       148%
 4-File Join w/ Lo Record Return   82.8       39.9       108%
 Two-File, Many to Many Join        5.6        3.1        81%

 Mean Speed Improvement of 61 percent BASIC PDS 7.10 over PDS 7.00

 Microsoft BASIC PDS 7.10 Versus FoxPro 1.0 (from Fox Software)
 --------------------------------------------------------------

 These tests ran using maximum buffer space available in 640K
 conventional memory.

                                                          PDS 7.10 over
 Item                               FoxPro 1.0  PDS 7.10  FoxPro, in Percent
 ----                               ----------  --------  ------------------

 Average Individual Record Search   1.5          1.3        15%
 Group Record Search On Index       4            4.4        -9%
 Group Record Search w/o Index      7.5          9         -17%
 Subtotal 100 Groups/Short Field   22.1         20.2         9%
 Two-File Join with Subtotals      34.3         30.8        11%
 3-File Join with Hi Record Return 72.1         46.4        55%
 Three-File Join with Subtotaling  44.9         34.2        31%
 4-File Join with Lo Record Return 30.3         32.1        -6%
 Two-File, Many to Many Join        4.7          3.1        52%

 Mean Speed Improvement of 16 percent BASIC PDS 7.10 over FoxPro

 BASIC PDS 7.10 Versus Novell's Btrieve 5.0c
 -------------------------------------------

 These tests were run using a maximum buffer space of 64K in Btrieve.

                                                        PDS 7.10 over
 Item                           Btrieve 5.0c  PDS 7.10  Btrieve, in Percent
 ----                           ------------  --------  -------------------

 Average Individual Record Search    0.8       1.3       -38%
 Group Record Search On Index        4.3       5.6       -23%
 Group Record Search w/o an Index   19.9       9.9       101%
 Subtotal 100 Groups/Short Field    64.3      20.7       211%
 Two-File Join with Subtotals      400       131.4       204%
 3-File Join w/ Hi Record Return   288       173.7        66%
 Three-File Join with Subtotaling  235.9      62.1       280%
 4-File Join w/ Lo Record Return   110        39.9       176%
 Two-File, Many to Many Join        15.3       3.1       394%

 Mean Speed Improvement of 152 percent BASIC PDS 7.10 over Btrieve


 332. QBX.EXE "Out of Data Space" for Variable-Length String Array

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  4-SEP-1990    ArticleIdent: Q65034

 The 4-byte string descriptor for each variable-length string resides
 in DGROUP (the 64K near heap) regardless of the compiler string option
 (near or far).

 When using the far strings option (BC /Fs option, or running within
 QBX.EXE), only the contents (not the 4-byte descriptors) of the
 variable-length string are stored in the far segments. Large string
 arrays (near or far) can quickly fill up DGROUP with string
 descriptors, as shown in the examples below.

 This article illustrates how you can get both "Out of Data Space" and
 "Out of Memory" messages in QBX.EXE using an empty variable-length
 string array (dynamic or static) that fills up DGROUP with 4-byte
 string descriptors.

 This article also illustrates how, from a compiled .EXE program, you
 can get an "Out of String Space" message at run time when allocating
 dynamic variable-length string arrays and how you can get a "LINK :
 Fatal error L2041: Stack plus data exceed 64K" message at LINK time
 when allocating static variable-length string arrays, due to filling
 up DGROUP with 4-byte string descriptors.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Code Example 1 (Static Array)
 -----------------------------

 This example shows size limits using a static array of variable-length
 strings.

 This DIM gives "Out of Data Space" followed by "Out of Memory" in
 QBX.EXE before the PRINT can be executed. The string descriptors (4
 bytes per string-array element) are using up all the memory in DGROUP.

    PRINT "This never prints in QBX.EXE"
    DIM b$(12000)    ' Note:  DIM b$(11000) works without error.

 If you compile this program with BC /Fs to a .EXE program, you can
 specify up to about DIM b$(14000) without error. DIM b$(15000) gives
 the LINK.EXE error "LINK : Fatal error L2041: Stack plus data exceed
 64K" because DGROUP is filled up with string descriptors.

 Code Example 2 (dynamic array)
 ------------------------------

 This example shows size limits using a dynamic array of
 variable-length strings.

 The following program gives "Out of Data Space" followed by "Out of
 Memory" at run time in QBX.EXE when the program reaches REDIM
 A$(12000). From a compiled .EXE program, an "Out of String Space"
 message occurs at REDIM A$(16000) or larger, again because DGROUP is
 filled up with string descriptors.

 Note that each string element has 2 additional bytes of overhead per
 element in the far heap segment (even for this array that is empty of
 any string contents).

 CLS
 FOR j = 5 TO 16
 REDIM a$(j * 1000)
 PRINT "DIM a$("; j * 1000; ")"; " Far string segment usage="; FRE(a$)
 ' STACK returns the space available in DGROUP:
 PRINT "DGROUP available="; STACK
 NEXT

 References:

 See Pages 719-720, "Variable Storage and Memory Use," and also Chapter
 11, "Advanced String Storage," in the "Microsoft BASIC 7.0:
 Programmer's Guide" for BASIC PDS versions 7.00 and 7.10.


 333. "Error During Run-Time Initialization" Mixing Near/Far Strings

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-SEP-1990    ArticleIdent: Q65082

 When you link separate modules together to make an .EXE program, all
 the modules must have been compiled with the same string option (near
 or far strings).

 If you LINK modules or libraries together and some were compiled with
 and some without the BC /Fs (far strings) option, the .EXE program can
 hang in version 7.00, or can give the following error message at run
 time in version 7.10:

    Error during run-time initialization

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Combining string options can cause unpredictable results in the .EXE
 program at run time. After the possible hang in 7.00, a warm boot
 (CTRL+ALT+DEL) may not work. To reboot, you may have to turn the
 computer off, then back on.

 To avoid this problem, only LINK routines that were compiled with the
 same string option (BC /Fs or no /Fs).

 Also, remember that the QBX.EXE environment of BASIC PDS 7.00 and 7.10
 only supports far strings, not near strings. In other words, all BASIC
 object modules linked into a Quick library (.QLB file) for use in
 QBX.EXE must be compiled with the BC /Fs option.

 What Are Far Strings?
 ---------------------

 The contents of far strings are stored in the far heap, and the
 contents of near strings are stored in near heap (the 64K DGROUP
 segment).

 Note that the BC /Fs (far strings) option affects only the storage
 location of variable-length string variables. The far strings option
 does NOT affect fixed-length string variables. (Also, fixed-length
 strings do NOT have a string descriptor.)

 Every variable-length string variable (or array element) has a 4-byte
 string descriptor. The 4-byte string descriptor for each
 variable-length string always resides in DGROUP (the 64K near heap)
 regardless of the compiler string option (near or far).

 References:

 See Pages 719-720, "Variable Storage and Memory Use," and also
 Chapter 11, "Advanced String Storage," in the "Microsoft BASIC 7.0:
 Programmer's Guide" for BASIC PDS versions 7.00 and 7.10.

 Code Example 1
 --------------

 Compile the following program with the BC /Fs option, as follows:

    BC TEST1/Fs;

 REM  TEST1.BAS
 CALL TEST

 Compile the following program with BC and no options, as follows:

    BC TEST2;

 REM  TEST2.BAS
 SUB TEST STATIC
 PRINT "This is a test"
 END SUB

 Link as follows:  LINK TEST1+TEST2;

 Now run TEST1.EXE. If compiled in BASIC 7.00, the program may display
 random garbage on the screen and hang. If compiled in BASIC 7.10, the
 program will give the error message "Error during run-time
 initialization."

 Code Example 2
 --------------

 Compiling and linking any program in BASIC PDS 7.10 as follows gives
 "Error during run-time initialization" when you run the BASFILE.EXE
 program:

    BC /Fs basfile.BAS;
    LINK basfile.OBJ,,,BRT71ENR.LIB;

 Note that "ENR" in BRT71ENR.LIB refers to "E" for IEEE math, "N" for
 near strings, and "R" for MS-DOS (real) mode.


 334. QBX Incorrectly Initializes Array in TYPE with OPTION BASE 1

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 buglist7.10 SR# S900205-152
 Last Modified:  4-SEP-1990    ArticleIdent: Q65083

 QBX.EXE may not correctly initialize programs with OPTION BASE 1 and
 arrays in user-defined TYPEs during their initial loading. The array
 in the type is treated as a zero-based array instead of a one-based
 array. This problem is corrected by saving the file or editing either
 the OPTION BASE 1 line or the TYPE statement. This behavior does not
 occur when the program is compiled with BC.EXE.

 Microsoft has confirmed this to be a problem with the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS. We are researching this problem and
 will post new information here as it becomes available.

 Code Example
 ------------

 The following code example will give incorrect results (a length of 3
 and a lower bound of 0) on the initial run of the program, but after
 saving the file (without reloading), or after editing either of the
 indicated lines, the program runs correctly (giving a length of 2 and
 a lower bound of 1):

    OPTION BASE 1                      'Editing here corrects error
    TYPE ArrayType
         Array(2) AS STRING * 1        'Editing here also corrects
    END TYPE
    DIM varArrayType AS ArrayType
    PRINT LEN(varArrayType)               'Should be 2 (incorrectly 3)
    PRINT LBOUND(varArrayType.Array)      'Should be 1 (incorrectly 0)
    END


 335. OS/2 BASIC Program to Get Machine Configuration; DosDevConfig

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900820-52
 Last Modified:  4-SEP-1990    ArticleIdent: Q65103

 A protected mode BASIC program can call the OS/2 API function
 DosDevConfig() to find out machine-configuration information, such as
 how many printers are attached, how many serial ports and floppy disk
 drives are available, whether or not a math coprocessor is present,
 and the type of primary display adapter (monochrome or color). Below
 is a sample program demonstrating this.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS OS/2.

 DosDevConfig() takes the following parameters:

    Parameter   Description
    ---------   -----------

    PTR BYTE    Receives machine information

    WORD        Type of information needed
                0 = Number of printers attached
                1 = Number of serial ports available
                2 = Number of floppy disk drives available
                3 = Check math coprocessor (returns 1 = present, 0 = not)
                4 = PC Submodel type
                5 = PC model type
                6 = Primary display adapter type (returns 0 = monochrome,
                    1 = color)

    WORD        Reserved by OS/2, must be set to 0

 BASIC 6.00 and 6.00b and BASIC PDS 7.00 and 7.10 can directly call
 OS/2 API functions by linking with the DOSCALLS.LIB (for 6.00 and
 6.00b) or OS2.LIB (for 7.00 and 7.10) libraries. Note that a BYTE in
 BASIC has a type of STRING * 1, and a WORD has a type of INTEGER.
 Also, data items preceded by PTR can be passed using the SEG keyword
 in the DECLARE statement; otherwise, BYVAL is used.

 For more information on DosDevConfig(), see Pages 509-510 of "Advanced
 OS/2 Programming" by Ray Duncan (Microsoft Press, 1989).

 The following sample program (MACHINFO.BAS) displays configuration
 information about the machin, namely, how many printers are attached,
 how many serial ports and floppy disk drives are available, whether or
 not a math coprocessor is present, and the type of primary display
 adapter (monochrome or color). Note that a printer does not have to be
 online to be "attached."

 To compile the program, enter the following at the OS/2 command
 prompt:

    bc machinfo;

 The LINK command line for BASIC 6.00 and 6.00b is as follows:

    link /nop machinfo,,,doscalls;

 The LINK command line for BASIC PDS 7.00 and 7.10 is as follows:

    link /nop machinfo,,,os2;

 MACHINFO.BAS
 ------------

 DEFINT A-Z

 TYPE InfoType
    Info AS STRING * 1
 END TYPE

 DECLARE FUNCTION DosDevConfig% (SEG InfoVar AS InfoType,_
                                 BYVAL InfoNeeded%, BYVAL Reserved%)

 DIM InfoVar AS InfoType   'Will receive configuration information.

 'Get number of printers attached.
 ErrorCode% = DosDevConfig% (InfoVar, 0, 0)
 PRINT "There are" CVI(InfoVar.Info + CHR$(0)) " printers attached."

 'Get number of serial ports available.
 ErrorCode% = DosDevConfig% (InfoVar, 1, 0)
 PRINT CVI(InfoVar.Info + CHR$(0)) " serial ports are available."

 'Get number of floppy disk drives available.
 ErrorCode% = DosDevConfig% (InfoVar, 2, 0)
 PRINT CVI(InfoVar.Info + CHR$(0)) " disk drives are available."

 'Check if math coprocessor is available.
 ErrorCode% = DosDevConfig% (InfoVar, 3, 0)
 IF InfoVar.Info = CHR$(1) THEN
    PRINT "A math coprocessor is present."
 ELSE
    PRINT "A math coprocessor is not present."
 END IF

 'Get the type of primary display adapter (color or mono).
 ErrorCode% = DosDevConfig% (InfoVar, 6, 0)
 IF InfoVar.Info = CHR$(1) THEN
    PRINT "The primary display adapter is color."
 ELSE
    PRINT "The primary display adapter is monochrome."
 END IF

 END


 336. How to Call VioPopUp() from a Protected Mode BASIC Program

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900812-3
 Last Modified:  4-SEP-1990    ArticleIdent: Q65105

 A protected mode BASIC program that is running in a background session
 can temporarily seize control of the screen and interact with the
 user, regardless of which session is currently in the foreground. This
 is accomplished by calling the OS/2 API function VioPopUp(). Below is
 a sample program that demonstrates how to do this.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS OS/2.

 VioPopUp() takes two parameters:

    Parameter   Description
    ---------   -----------

    PTR WORD    Contains option flags for pop-up
        WORD    Video handle (0 = default)

 If bit 0 of the first parameter is set, VioPopUp() will wait until a
 pop-up is available. If bit 0 is cleared, VioPopUp() will return
 immediately with an error if a pop-up is not available.

 If bit 1 of the first parameter is set, the pop-up will be
 transparent. This means that if the display is already in a text mode,
 no mode change will occur and the screen contents and cursor position
 will not be disturbed. Also session switching will be disabled. If the
 display is not in a text mode, the pop-up will have no special effect
 on any other process.

 If bit 1 of the first parameter is cleared, the pop-up will be
 nontransparent. This means that the display will be put into an
 80-by-25 text mode, the screen cleared, and the cursor placed into the
 upper-left corner. Also, session switching will be disabled.

 During a pop-up, all other processes run normally except that they
 can't interact with the user or modify the physical display. Any
 attempt to perform these actions is blocked until the process in
 pop-up mode calls the API function VioEndPopUp(). When this happens,
 the pop-up process reverts to the background, the process that was in
 the foreground when the pop-up occurred regains its status, and the
 physical display is restored.

 Microsoft BASIC 6.00 and 6.00b and Microsoft BASIC PDS 7.00 and 7.10
 can directly call OS/2 API functions by linking with the DOSCALLS.LIB
 (for 6.00 and 6.00b) or OS2.LIB (for 7.00 and 7.10) libraries. Note
 that a WORD in BASIC has a type of INTEGER. Also, data items preceded
 by PTR can be passed using the SEG clause in the DECLARE statement of
 the function; otherwise, BYVAL is used.

 For more information about VioPopUp() and VioEndPopUp(), see Pages
 113-115 of "Advanced OS/2 Programming" by Ray Duncan (Microsoft Press,
 1989).

 The following sample program generates a pop-up, displays a message
 while in the pop-up, and then ends the pop-up. Before doing so, it
 lets the user choose the type of pop-up (transparent or
 nontransparent) and then emits five delayed beeps to allow the user to
 switch sessions.

 To compile the program, enter the following at the OS/2 command prompt:

    bc popup;

 The command line for linking the program with BASIC 6.00 or 6.00b is
 as follows:

    link /nop popup,,,doscalls;

 The command line for linking the program with BASIC PDS 7.00 or 7.10
 is as follows:

    link /nop popup,,,os2;

 POPUP.BAS
 ---------

 DECLARE FUNCTION VioPopUp%    (SEG Flags%, BYVAL Handle%)
 DECLARE FUNCTION VioEndPopUp% (BYVAL Handle%)

 'Loop until the user chooses a valid option.
 DO UNTIL (Flags% = 1) OR (Flags% = 3)

    'Prompt the user for an option.
    INPUT "Transparent (1) or Nontransparent (2) pop-up"; Flags%

    'Setting bit 0 tells OS/2 to wait until a pop-up is available.
    'Bit 1 is set for transparent mode, cleared for nontransparent.
    SELECT CASE Flags%
    CASE 1
       Flags% = 3
    CASE 2
       Flags% = 1
    CASE ELSE
       PRINT "Invalid option!"
       BEEP
    END SELECT

 LOOP

 FOR I% = 1 TO 5   'Delay so user has time to switch sessions.
    BEEP
    SLEEP 1
 NEXT I%

 ErrorCode% = VioPopUp% (Flags%, 0)   'Start the pop-up.

 COLOR 13, 1                          'Display a colored message on the
 LOCATE 12, 36                        'the screen.
 PRINT "Surprise!"

 LOCATE 25, 35
 PRINT "Hit any key";                 'Wait until a key is pressed.
 WHILE INKEY$ = ""
 WEND

 ErrorCode% = VioEndPopUp% (0)        'End the pop-up and the program.
 END


 337. "Out of Stack Space" Using RETURN <linenumber> for SUB Event

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | B_QuickBas
 Last Modified:  4-SEP-1990    ArticleIdent: Q65177

 If an event occurs in a procedure (SUB or FUNCTION), then returning
 from event-handling with the RETURN <linenumber> statement always
 leaves unrecoverable information on the stack, which can lead to the
 error message "Out of Stack Space" after many trapped events.

 This behavior is a result of violating the following design rule: to
 correctly restore (pop) the stack after handling an event, you must
 always return to the procedure level where the event occurred. This
 applies to all events trapped with the ON <event> GOSUB statement
 (where <event> includes COM, KEY, PEN, PLAY, TIMER, STRIG, and
 others).

 RETURN <linenumber> or <linelabel> is only designed to return from
 events that occur at the module-level (main-level) code. This
 correctly pops the stack.

 You must use RETURN without the <linenumber> or <linelabel> option if
 you want to RETURN to a SUB or FUNCTION procedure where an event was
 trapped. This correctly pops the stack.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2; to
 Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2; and to Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS.

 To demonstrate the "Out of stack space" message, run the following
 program and hold down the ESC key, which will be trapped in a loop
 until the error occurs. The "Out of stack space" error occurs because
 this program incorrectly allows events in the SUB to be handled by the
 RETURN <linelabel> instead of an ordinary RETURN.

 Code Example
 ------------

 DECLARE SUB test ()
 ' This is an example where the RETURN <linenumber>
 ' statement gives you "Out of Stack Space" (after about 53 ESC key
 ' trap iterations in QBX.EXE, or 118 if compiled in BC.EXE) when the
 ' event (pressing the ESC key) is trapped in a SUB procedure.
 KEY 15, CHR$(0) + CHR$(1)    ' Trap ESC key
 ON KEY(15) GOSUB escape
 KEY(15) ON
 PRINT "now in main"
 again:
   CALL test
   PRINT "Done"
 END
 escape:
   j = j + 1
 ' The FRE(-2) function returns a value decreased at each iteration by
 ' the number of bytes of stack (associated with the SUBprogram) that
 ' were lost:
   PRINT j; "ESC key was pressed. Continue in main. FRE(-2)="; FRE(-2)
   KEY(15) ON   ' <-- Must say KEY(15) ON here or else the
                '   RETURN <linelabel> statement will leave the
                '   ON KEY(15) GOSUB trap still active, which does an
                '   implied KEY(15) STOP. If the key had been trapped
                '   in the main program, then RETURN <linelabel> would
                '   work normally, and you wouldn't have to use
                '   KEY(15) ON here.
   RETURN again

 SUB test STATIC
 PRINT "Now in SUB"
 WHILE INKEY$ = "": WEND
 PRINT "You pressed some key other than ESC."
 END SUB

 References:

 The following is taken from Page 296 (under the "RETURN Statement") of
 "Microsoft BASIC 7.0: Language Reference" for versions 7.00 and 7.10:

    RETURN with a line label or line number can return control to a
    statement in the module-level code only, not in procedure-level
    code.

 The following is taken from Page 227 (under the heading "ON event
 Statement") of "Microsoft BASIC 7.0: Language Reference" for versions
 7.00 and 7.10:

    The RETURN linenumber or RETURN linelabel forms of RETURN can be
    used to return to a specific line from the trapping routine. Use
    this type of return with care, however, because any GOSUB, WHILE,
    or FOR statements active at the time of the trap remain active.
    BASIC may generate error messages such as NEXT without FOR. In
    addition, if an event occurs in a procedure, a RETURN linenumber or
    RETURN linelabel statement cannot get back into the procedure
    because the line number or label must be in the module-level code.

 The above information is accurate, but it should be added that if an
 event occurs in a procedure (SUB or FUNCTION), then returning from
 event-handling with the RETURN <linenumber> statement leaves
 unrecoverable information on the stack, which eventually leads to the
 error message "Out of Stack Space" after many trapped events.


 338. "Redo from Start" for Correct INPUT in QB and BASIC PDS

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | B_QuickBas buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified:  4-SEP-1990    ArticleIdent: Q65194

 Normally, the INPUT statement correctly gives a "Redo from start"
 message if you mistakenly type a string as input when a number is
 expected. However, the INPUT statement incorrectly gives the error
 message "Redo from start" when all of the following conditions
 coincide:

 1. The program is using the INPUT "prompt", <variable list> form of
    the INPUT statement.

 2. The variable being INPUT is a single-precision element of a
    $DYNAMIC array.

 3. The program does NOT contain error trapping, was NOT compiled
    with BC /X, and does NOT have line numbers.

 The INPUT statement will also incorrectly display a question mark (?)
 prompt under the above conditions. The problem occurs in executable
 (.EXE) programs compiled with BC.EXE, but does not occur in the QB.EXE
 or QBX.EXE environment.

 Microsoft has confirmed this to be a problem with QuickBASIC versions
 4.00, 4.00b, and 4.50 (buglist4.00, buglist4.00b, buglist4.50); with
 Microsoft BASIC Compiler versions 6.00 and 6.00b; and with Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 This problem can be easily worked around in any one of the following
 ways:

 1. Compile the program with BC /X.

 2. Include ON ERROR GOTO error-trapping in the program.

 3. Include a line number on the line where the INPUT occurs.

 4. Use the following format to prompt the user:

       PRINT "prompt message";
       INPUT "", <variable list>

 5. Use a static array instead of a dynamic array.

 Code Example:
 ------------

 The example below demonstrates this problem. Compile and link the
 program as follows:

    BC INPUT.BAS ;
    LINK INPUT ;

 When you run this program and correctly enter a number (such as 3.21
 or 0) or press ENTER alone, the program incorrectly gives a "Redo from
 start" message. You must press CTRL+C or CTRL+BREAK to stop the
 program.

    ' $DYNAMIC
    DIM z(4)
    i% = 1
    z(i%) = 0
    INPUT "Input a real number: ", z(i%)
    END


 339. Must Use BYVAL at Both Ends When CALLing 7.10 SUB or FUNCTION

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900820-85
 Last Modified:  4-SEP-1990    ArticleIdent: Q65287

 When passing parameters by value to a BASIC SUBprogram or FUNCTION
 procedure, you must use the BYVAL attribute from both the calling end
 and the receiving end.

 By itself, using BYVAL in the SUB or FUNCTION statement (at the
 receiving end) isn't enough to tell the SUB or FUNCTION to pass by
 value. If you don't also use the BYVAL attribute in the CALL statement
 or the DECLARE statement, then by default BASIC will pass by reference
 and push only the address of the variable on the stack. If you
 mistakenly use BYVAL only at the calling end or only at the receiving
 end, then an incorrect value will be passed.

 This information only applies to Microsoft BASIC Professional
 Development System (PDS) version 7.10, since passing parameters to
 BASIC SUBprograms and FUNCTIONS with the BYVAL attribute was first
 introduced version 7.10.

 Note for Versions Earlier Than 7.10: In Microsoft BASIC PDS version
 7.00, in Microsoft BASIC Compiler versions 6.00 and 6.00b, and in
 QuickBASIC versions 4.00, 4.00b, and 4.50, you could not DECLARE or
 CALL a BASIC routine with parameters having the BYVAL attribute, since
 BYVAL could be used only for parameters of non-BASIC routines (such as
 C or Macro Assembler).

 NOTE: If you create a program in an editor outside the QBX.EXE
 environment without DECLARE statements at the top of the program,
 DECLARE statements will not automatically be added to your code. As a
 result, a SUB statement that contains a formal parameter with the
 BYVAL attribute (at the receiving end) will have no BYVAL declaration
 at the calling end. Instead of specifying BYVAL in a DECLARE
 statement, you can specify BYVAL in the CALL statement.

 Code Example: Incorrect Way to Pass by Value
 --------------------------------------------

 The program below, written in an editor outside of the QBX.EXE
 environment, will pass the offset of the variable A& to the
 SUBprogram, although the SUBprogram is expecting the actual value
 contained in A&. This happens because each end of the call to the
 SUBprogram acts blindly on the information that it has. The call to
 TestPass blindly assumes that it is passing a value by reference,
 which is the default. It therefore passes the offset (in this case
 3030) of the variable A& to the SUBprogram TestPass. The SUBprogram
 TestPass is expecting to receive the value of the variable A&, as is
 dictated by the BYVAL attribute in the SUB statement. The program
 therefore prints 3030 (the offset) on the screen, instead of the
 constant 2 (the value).

 CALL TestPass (2&)  'Notice no declaration of BYVAL in CALL or
                     'DECLARE, so default is pass (send) by reference.
 SUB TestPass(BYVAL A&)  'BYVAL in SUB says to pass (receive) by value.
     B& = A&
     PRINT A&        ' Prints 3030, the offset of A&.
 END SUB

 Correct Way to Pass by Value, Using BYVAL in DECLARE and SUB
 ------------------------------------------------------------

 DECLARE SUB TestPass(BYVAL A&)
 ' BYVAL in the above DECLARE means to pass (send) by value.
 CALL TestPass (2&)
 SUB TestPass(BYVAL A&)  'BYVAL in SUB means pass (receive) by value.
     B& = A&
     PRINT A&      ' prints 2, the value (contents) of A&
 END SUB

 Another Correct Way to Pass by Value, Using BYVAL in CALL and SUB
 -----------------------------------------------------------------

 CALL TestPass (BYVAL 2&)  'BYVAL in CALL means pass (send) by value.
 SUB TestPass(BYVAL A&)    'BYVAL in SUB means pass (receive) by value.
     B& = A&
     PRINT A&      ' prints 2, the value (contents) of A&
 END SUB

 References
 ----------

 The following is taken from the README.DOC file for BASIC 7.10:

    In version 7.10, BASIC supports the use of the BYVAL keyword
    in CALL, DECLARE, SUB, and FUNCTION statements for BASIC
    procedures. You can use BYVAL to pass parameters by value
    rather than by reference (the default). It is no longer
    necessary to enclose parameters in parentheses to emulate
    passing by value. For more information and an example of using
    BYVAL in BASIC procedures, see the online Help for the DECLARE
    statement (BASIC procedures). For specifics on using BYVAL with
    CALL, see the online Help for the CALL statement (BASIC
    procedures).


 340. BASIC Program to Read COBOL BCD (COMP-3) Numbers

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# S900828-36 B_COBOL
 Last Modified:  2-JAN-1991    ArticleIdent: Q65323

 Below is a BASIC program that reads a data file created by Microsoft
 COBOL containing binary-coded-decimal (COMP-3) numbers. This is
 accomplished by reading in the file one byte at a time, interpreting
 those bytes according to the binary-coded-decimal (BCD) format, and
 performing calculations based on those interpretations to generate
 equivalent BASIC double-precision floating-point numbers.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The information about binary-coded-decimal numbers and the COMP-3
 format applies to Microsoft COBOL Compiler versions 3.00 and 3.00a for
 MS-DOS and MS OS/2, and to Microsoft COBOL Professional Development
 System version 4.00 for MS-DOS and MS OS/2.

 Microsoft COBOL 3.00, 3.00a, and 4.00 support a data type commonly
 referred to as binary-coded-decimal (BCD) format. The syntactical name
 for this data type in COBOL is COMP-3.

 The bytes used to store a COMP-3 number can contain two base-10 digits
 each. The high nibble (4 bits) stores one digit of the number and the
 low nibble (4 bits) stores the next digit to the right. That is, the
 high nibble stores a digit whose place in the number has a power of 10
 that is one greater than that of the digit in the low nibble.
 Moreover, the first byte used to store the number will contain the
 digit with the highest power of 10; subsequent bytes will hold digits
 that have successively lesser powers of 10. (Note: There are two
 nibbles in every byte.)

 A special case is made for the last byte, where the high nibble stores
 the last digit in the number, and the low nibble stores the sign of
 the number. The low nibble will contain 15 if the number is unsigned,
 12 for positive, and 13 for negative. Also, if the number of nibbles
 needed for digits plus the sign nibble will not fill a whole number of
 bytes, the high nibble of the byte storing the first digit is set to
 0.

 As an example, here is a binary representation of how the number 69
 (signed positive) would be stored:

    +---------- First Byte ---------+--------- Second Byte ---------+
    |                               |                               |
    +- High Nibble -+- Low Nibble --+- High Nibble -+- Low Nibble --+
    |               |               |               |               |
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    |               |               |               |               |
    +------ 0 ------+------ 6 ------+------ 9 ------+-- Positive ---+

 Below is a BASIC program (BCDTODBL.BAS) that converts the COMP-3
 numbers in a COBOL data file to BASIC's double-precision numbers. The
 program reads in each byte of the file sequentially, interpreting it
 as either a pair of digits or a digit and a sign. The program knows
 that it has read all the digits in a number when the low nibble of the
 last byte read contains a sign value (12, 13, or 15). When this
 happens, the program circulates through all the digits accumulated for
 the number and multiplies each by its associated power of 10. The
 result of this iterative calculation is assigned to a double-precision
 floating-point number. Finally, one more calculation is performed on
 the number so that it will contain the amount of decimal places
 specified by the user.

 Following the BASIC program is a COBOL program (WRITEBCD.CBL) that
 creates a file containing a user-specified amount of COMP-3 signed
 numbers. To compile and link the program in COBOL 3.00 or 3.00a, enter
 the following commands from the DOS or OS/2 prompt:

    cobol writebcd;
    link writebcd;

 The compile lines for COBOL Professional Development System (PDS)
 version 4.00 are as follows:

    cobol writebcd;
    link writebcd,,,coblib cobapi;

 The BASIC program can be run or compiled from within the QB.EXE or
 QBX.EXE environments. See your BASIC documentation for information on
 using the QB.EXE or QBX.EXE environments.

 BCDTODBL.BAS
 ------------

 DIM Digits%(15)       'Holds the digits for each number (max = 16).
 DIM BASICeqv#(1000)   'Holds the BASIC equivalent of each COMP-3 number.

 'Clear the screen, get the filename and the amount of decimal places
 'desired for each number, and open the file for sequential input:
 CLS
 INPUT "Enter the COBOL data file name: ", FileName$
 INPUT "Enter the number of decimal places desired: ", Decimal%
 OPEN FileName$ FOR INPUT AS #1

 DO UNTIL EOF(1)   'Loop until the end of the file is reached.
    Byte$ = INPUT$(1, 1)   'Read in a byte.
    IF Byte$ = CHR$(0) THEN  'Check if byte is 0 (ASC won't work on 0).
       Digits%(HighPower%) = 0       'Make next two digits 0. Increment
       Digits%(HighPower% + 1) = 0   'the high power to reflect the
       HighPower% = HighPower% + 2   'number of digits in the number
                                     'plus 1.
    ELSE
       HighNibble% = ASC(Byte$) \ 16      'Extract the high and low
       LowNibble% = ASC(Byte$) AND &HF    'nibbles from the byte. The
       Digits%(HighPower%) = HighNibble%  'high nibble will always be a
                                          'digit.
       IF LowNibble% <= 9 THEN                   'If low nibble is a
                                                 'digit, assign it and
          Digits%(HighPower% + 1) = LowNibble%   'increment the high
          HighPower% = HighPower% + 2            'power accordingly.
       ELSE
          HighPower% = HighPower% + 1 'Low nibble was not a digit but a
          Digit% = 0                  '+ or - signals end of number.

          'Start at the highest power of 10 for the number and multiply
          'each digit by the power of 10 place it occupies.
          FOR Power% = (HighPower% - 1) TO 0 STEP -1
          BASICeqv#(E%)=BASICeqv#(E%) + (Digits%(Digit%) * (10^Power%))
          Digit% = Digit% + 1
          NEXT

          'If the sign read was negative, make the number negative.
          IF LowNibble% = 13 THEN
             BASICeqv#(E%) = BASICeqv#(E%) - (2 * BASICeqv#(E%))
          END IF

          'Give the number the desired amount of decimal places, print
          'the number, increment E% to point to the next number to be
          'converted, and reinitialize the highest power.
          BASICeqv#(E%) = BASICeqv#(E%) / (10 ^ Decimal%)
          PRINT BASICeqv#(E%)
          E% = E% + 1
          HighPower% = 0
       END IF
    END IF
 LOOP
 CLOSE   'Close the COBOL data file, and end.

 WRITEBCD.CBL
 ------------

       $SET ANS85
        IDENTIFICATION DIVISION.
        PROGRAM-ID.  WriteBCD.

        ENVIRONMENT DIVISION.
        INPUT-OUTPUT SECTION.
        FILE-CONTROL.
            SELECT BCDFile ASSIGN TO "BCD.DAT".

        DATA DIVISION.
        FILE SECTION.
        FD BCDFile.
        01 BCDNumber      PIC S9(5) COMP-3.

        WORKING-STORAGE SECTION.
       *   Holds the number of COMP-3 items to write to the file.
        01 TotalNumbers   PIC 99 COMP-5.

        PROCEDURE DIVISION.

       *   Get the number of COMP-3 items to write to file.
           DISPLAY "Enter the number of items to write:".
           ACCEPT TotalNumbers.

       *   Open the COMP-3 file for sequential output and write each
       *   number out to the file as the user enters it.
           OPEN OUTPUT BCDFile.
           PERFORM TotalNumbers TIMES
              ACCEPT BCDNumber
              WRITE BCDNumber
           END-PERFORM.

       *   Close the COMP-3 file and end.
           CLOSE BCDFile.


 341. EOF in 7.00 Returns "Nonzero" for TRUE, But 4.50 Returns -1

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900822-29 B_QuickBas
 Last Modified:  4-SEP-1990    ArticleIdent: Q65396

 The EOF function has changed slightly from QuickBASIC versions 4.50
 and earlier to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and later. In QuickBASIC, the EOF function will return 0
 (zero) for FALSE and -1 for TRUE. In BASIC PDS 7.00, EOF still returns
 0 for FALSE, but it returns "nonzero" for TRUE. This means that EOF
 will return a positive or negative number other than 0 if the end of
 the file has been reached or if you are at the "end" of an ISAM table.
 Previous QuickBASIC programs that hard coded a check for -1 will have
 to be changed to check for a nonzero value. Since 0 is equivalent to
 FALSE and nonzero evaluates to TRUE in BASIC, this is an easy change
 to make. For instance, you do not need to check "IF EOF = -1 THEN
 GOSUB foo"; instead, you can use "IF EOF THEN GOSUB foo". This second
 check will work in any version of Microsoft BASIC.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2. This
 article documents a change from Microsoft QuickBASIC 1.00, 1.01, 1.02,
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, and from Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2.


 342. BC /R Makes UBOUND and LBOUND Incorrect for Multi-DIM Array

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | B_QuickBas buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified:  4-SEP-1990    ArticleIdent: Q65402

 The UBOUND and LBOUND functions return the upper and lower bounds of
 an array. However, if a program is compiled using the BC /R compiler
 option, which stores multidimensional arrays in row major order, the
 UBOUND and LBOUND functions return incorrect dimension bounds for
 multidimensional arrays.

 Microsoft has confirmed this to be a problem with the BC /R option in
 QuickBASIC versions 4.00, 4.00b, and 4.50 (buglist4.00, buglist4.00b,
 buglist4.50) for MS-DOS; in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and OS/2.
 Microsoft is researching this problem and will post new information
 here as it becomes available.

 Note that by default (without the /R option), BC.EXE stores arrays in
 column major order, and the UBOUND and LBOUND functions return correct
 values. Note also that the /R switch cannot be used within QBX.EXE;
 therefore, QBX.EXE can only store arrays in column major order. UBOUND
 and LBOUND work correctly in QBX.EXE.

 For more information on using the BC /R compiler switch, query in this
 Knowledge Base on the following words:

    MULTIDIMENSIONAL AND COLUMN AND ROW AND MAJOR

 Although the array is stored differently in memory by the /R compiler
 option, the upper and lower bounds of each dimension do not change.
 Therefore the values returned by UBOUND and LBOUND for a given
 dimension are supposed to be the same compiling with or without BC /R.

 When a program is compiled with the BC /R switch, the UBOUND and
 LBOUND (for a given dimension) incorrectly return the bounds for the
 opposite dimension. For example, in a two-dimensional array, if you
 request the UBOUND and LBOUND values for the first dimension, the
 values returned will incorrectly be those of the second dimension.
 Requesting the UBOUND and LBOUND values for the second dimension
 incorrectly gives you the bounds for the first dimension.

 In an odd-dimensioned array, UBOUND and LBOUND return correct bounds
 for the middle dimension, but incorrect bounds for all other
 dimensions when compiled BC /R. For example, in a three-dimensional
 array, UBOUND and LBOUND for the first dimension incorrectly return
 bounds for the third dimension; UBOUND and LBOUND for the third
 dimension incorrectly return bounds for the first dimension; but
 UBOUND and LBOUND for the second dimension correctly return bounds for
 the second dimension.

 Code Example
 ------------

 The following program example demonstrates the problem:

 DIM A(-1 TO 1, -2 TO 2)     ' DIMensions A() as a 2-dimensional array.
    ' Print lower and upper bound of first dimension:
 PRINT LBOUND(A, 1), UBOUND(A, 1)
    ' Print lower and upper bound of second dimension:
 PRINT LBOUND(A, 2), UBOUND(A, 2)

 Output when compiled without BC /R (correct):

    -1      1
    -2      2

 Output when compiled with BC /R (incorrect):

    -2      2
    -1      1


 343. LINK Creating Temporary File Can Hang on 3Com 3+ Open Network

 Product Version(s): 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900824-163 B_QuickBas
 Last Modified:  4-SEP-1990    ArticleIdent: Q65403

 A customer reported that when using LINK.EXE version 5.10 (the linker
 that comes with Microsoft BASIC Professional Development System [PDS]
 version 7.10) on a workstation running on a 3Com 3+ Open network, the
 computer may hang if the linker needs to generate a .TMP file.

 If you set the TMP environment variable to a directory on the
 workstation's own hard drive, the linker should function correctly.

 This information applies to Microsoft BASIC PDS version 7.10 and
 LINK.EXE version 5.10. The problem does not occur when using Microsoft
 BASIC PDS version 7.00 and LINK.EXE version 5.05.

 Please note that Microsoft BASIC PDS 7.10 is designed to support only
 the IBM PC-NET and MS-NET compatible networks.

 When the linker does not have enough room to work correctly in memory,
 it will write a temporary file to disk and display the message:

    Temporary file .\xxxxxxxx has been created

 This customer reported that without a TMP environment variable set,
 the linker attempted to write the temporary file on the server
 machine, which hung his computer. After he added the TMP environment
 variable and assigned it a path to a directory on the workstation's
 own hard drive, the computer did not hang. The TMP environment
 variable can be set by either typing a line such as the following at
 the DOS prompt or by putting it into your AUTOEXEC.BAT file:

    TMP=C:\directory name

 The problem only occurred when the workstation was running under DOS.
 While running under OS/2 version 1.20, the problem did not occur.

 The customer encountered this problem on a workstation with the
 following configuration:

    386 Clone
    3Com 3+ Open Network version 1.1e
    DOS 4.01


 344. Solve BASIC 6.0 "Unresolved External" with OS/2's DOSCALLS.LIB

 Product Version(s): 6.00 6.00b
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900821-150
 Last Modified:  4-SEP-1990    ArticleIdent: Q65404

 When you are creating Microsoft BASIC Compiler versions 6.00 and 6.00b
 protected mode programs that make calls to OS/2 API functions, the
 DOSCALLS.LIB library must be linked in. This library allows the linker
 to resolve external references to the API functions.

 However, the DOSCALLS.LIB that comes with BASIC will not allow the
 linker to resolve references to all of the API functions. This version
 of DOSCALLS.LIB was designed to support only a subset of them. The
 linker can use the DOSCALLS.LIB that comes with OS/2 to resolve those
 external references to API functions that are not supported by the
 BASIC version of DOSCALLS.LIB.

 This information applies to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2.

 If an API function is not supported by the BASIC version of
 DOSCALLS.LIB, the linker will generate an "Unresolved external" error
 if it finds a call to it in an object file. To remedy the situation,
 the program must be linked with the OS/2 version of DOSCALLS.LIB. This
 version of DOSCALLS.LIB is usually placed in the main OS/2 directory
 (C:\OS2, for example) by the OS/2 installation program.

 Note that Microsoft BASIC Professional Development System versions
 7.00 and 7.10 for MS OS/2 use a library named OS2.LIB (instead of
 DOSCALLS.LIB) to resolve external references to API functions. OS2.LIB
 provides support for all API functions, so linking with the OS/2
 version of DOSCALLS.LIB should never be necessary in BASIC PDS 7.00
 and 7.10.


 345. 7.10 Memory Lost If Reassign $DYNAMIC String Array to STRING$

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900816-176 buglist7.00 buglist7.10
 Last Modified: 26-DEC-1990    ArticleIdent: Q65478

 In a compiled .EXE file, assigning a $DYNAMIC variable-length-string
 array element directly to a BASIC intrinsic string function (such as
 STRING$) creates an internal temporary string that may fail to be
 deallocated. Repetitive reassignments can cause "Out of String Space"
 or "Out of Memory" errors. This article documents this problem with
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 and shows two examples of the problem.

 Microsoft has confirmed this to be a problem with BASIC PDS versions
 7.00 and 7.10 for MS-DOS and MS OS/2. This problem does not occur in
 the QBX.EXE environment, or in earlier versions of Microsoft BASIC
 Compiler or QuickBASIC. We are researching this problem and will post
 new information here as it becomes available.

 The problem can occur for dynamic variable-length-string array element
 assignments of the form A$(x)=STRING$(n). But this form of assignment
 may not give the problem in some cases, such as in Code Example 1
 where A$(x)=STRING$(n) appears within a FOR...NEXT loop.

 Any one of the following code modifications works around the problem:

 1. Use a $STATIC array instead of a $DYNAMIC array,

 -or-

 2. First assign a temporary variable such as temp$ to the BASIC
    string function (STRING$), then assign the array element to temp$:

    temp$=STRING$(12000)
    A$(1)=temp$
    temp$=""

 -or-

 3. Use the CLEAR statement to erase the memory wasted by the
    internal temporary string (but CLEAR also erases all other
    variables).

 -or-

 4. In some cases, surrounding the assignment with a FOR...NEXT
    structure may eliminate the problem, such as in Code Example 1.

 This problem is not affected by any compiler options that limit
 optimizations (BC /D, /X, etc.). The problem occurs with both near and
 far strings (BC /Fs, /Fn).

 Code Example 1
 --------------

 The following code example shows one case (in a FOR...NEXT block) that
 reclaims memory properly and three cases that fail to return the
 string memory. In the cases that fail, the a$()=SPACE$() statement
 fails to release an amount of string space equal to the length of the
 string assigned (due to an internal unreleased temporary string).
 Repeated assignments will decrease string memory until string memory
 eventually runs out.

 Compile and LINK as follows (compile and LINK options do not affect
 the problem):

    BC STRING;
    LINK STRING;

 REM $DYNAMIC
 CLS
 DIM a$(10)
   PRINT "FRE(a$(1)) at start of program: ", FRE(a$(1))

   PRINT "Case #1: memory recovered if string deallocated in FOR loop."
   PRINT "For loop works fine -- memory restored"
   FOR i% = 12000 TO 0 STEP -12000
     a$(1) = SPACE$(i%)
     PRINT "Free during FOR loop: ", FRE(a$(1))
   NEXT

   PRINT "Case #2: Prompt user for size of string."
   INPUT "Input big number (try 12000):", big%
   a$(1) = SPACE$(big%)   'Both A$(1) & internal string consume memory:
   PRINT "FRE(a$(1)) after allocation: ", FRE(a$(1))
   INPUT "Input a small number (0):", small%
   a$(1) = SPACE$(small%) 'Internal temporary string still wastes memory:
   PRINT "FRE(a$(1)) after deallocation: ", FRE(a$(1))

   PRINT
   PRINT "Case #3. String of 12000 bytes assigned."
   big% = 12000
   a$(1) = SPACE$(big%)
   PRINT "FRE(a$(1)) after allocation: ", FRE(a$(1))
   small% = 0
   a$(1) = SPACE$(small%)
   PRINT "FRE(a$(1)) after deallocation: ", FRE(a$(1))

   PRINT "Case #4: Another string of 12000 bytes assigned."
   a$(1) = SPACE$(12000)
   PRINT "FRE(a$(1)) after allocation: ", FRE(a$(1))
   a$(1) = SPACE$(0)
   PRINT "FRE(a$(1)) after deallocation: ", FRE(a$(1))
 END

 Code Example 2
 --------------

 The program below shows that the problem also occurs in $DYNAMIC
 arrays in SUBprograms.

 Compile and link as follows:

    BC STRING2.BAS ;
    LINK STRING2 ;

 DECLARE SUB sub1 ()
 CALL sub1
 END
 SUB sub1
   DIM s(2) AS STRING   'This array is dynamic, since SUB is non-STATIC
   PRINT "FRE before string allocation: "; FRE(s(0))
   s(1) = STRING$(1000, 255)
   PRINT "FRE after string allocation: "; FRE(s(1))
   s(1) = ""
   PRINT "FRE after string deallocation: "; FRE(s(2))
 END SUB


 346. BASIC PDS 7.00 and 7.10 Cannot Use IOCTL and Far Strings

 Product Version(s): m7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900904-34
 Last Modified:  6-SEP-1990    ArticleIdent: Q65480

 Some customers have reported that the IOCTL$ function and IOCTL
 statement do not work with far strings (BC /Fs) in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10.
 Microsoft has not confirmed this to be a problem.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The IOCTL$ function and IOCTL statement allow BASIC programs to
 interact with MS-DOS character device drivers that can give and
 receive control data strings. Not all character device drivers support
 IOCTL control data strings. For instance, ANSI.SYS, which replaces the
 standard CON device driver in DOS, is a character device driver, but
 it cannot receive or send control data strings.

 For more information on MS-DOS device drivers, device driver classes,
 character device drivers, and how IOCTL works, see "Advanced MS-DOS
 Programming" by Ray Duncan (published by Microsoft Press).

 Note that the IOCTL$ function and IOCTL statement cannot be used under
 MS OS/2. You can, however, make equivalent OS/2 API function calls to
 interact with OS/2 character device drivers.


 347. "Invalid Column" If CREATEINDEX on Field of Nested User TYPE

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900822-21 docerr
 Last Modified: 21-SEP-1990    ArticleIdent: Q65506

 In Microsoft BASIC ISAM, you cannot create an index on a user-defined
 TYPE, nor can you create an index on a field of a nested user-defined
 TYPE.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 under MS-DOS and version 7.10
 under OS/2.

 Page 333 of the "Microsoft BASIC 7.0: Programmer's Guide" and Page 72
 of the "Microsoft BASIC 7.0: Language Reference" manual for versions
 7.00 and 7.10 correctly state that an index cannot be created on an
 aggregate data type such as a user-defined TYPE. However, they fail to
 state that you cannot create an index on a field of that nested
 user-defined TYPE.

 For example, in the following TYPE...END TYPE declaration, you can
 create an index on the field "CustomerName" but not on the
 user-defined TYPE "CompanyInfo" or on the field of the nested
 user-defined TYPE "CompanyID". If you try to create an index on these
 fields, an "Invalid Column" error is generated on the CREATEINDEX
 statement.

    TYPE CompanyRec
              CompanyID AS INTEGER
    END TYPE

    TYPE CustomerRec
              CustomerName AS STRING * 20
              CompanyInfo AS CompanyRec
    END TYPE


 348. BASIC OS/2 Routines to Replace UIASM.ASM for UI ToolBox

 Product Version(s): 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900821-212
 Last Modified: 21-SEP-1990    ArticleIdent: Q65515

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 provide sample User Interface (UI) Toolbox code written
 mostly in BASIC, with a few sections written in assembler. The code is
 written specifically for MS-DOS and does not support OS/2 unless the
 code is modified.

 The UI Toolbox uses three assembler routines to provide direct video
 access to get a window (GetCopyBox), put a window (PutCopyBox), and
 change the attributes of a window (AttrBox). These routines are
 located in the UIASM.ASM source file. These three routines do not work
 under OS/2 unless you modify them for OS/2 IOPL (Input Output
 Privileges) support, or rewrite them in BASIC using OS/2 Video I/O
 (VIO) API calls.

 The following code example provides one way to replace these three
 assembler routines with BASIC code utilizing the OS/2 VIO API Calls.

 Since this code is written in BASIC, you will need to compile these
 routines with the same options you use on the modules that call them.
 These compiler options include near/far strings, protected mode, and
 alternate/emulation math.

 GetCopyBox, PutCopyBox, AttrBox are currently written in assembly
 language (in UIASM.ASM on the 7.00 and 7.10 release disk) for greater
 speed. The UIASM.BAS program below contains the equivalent BASIC
 routines using OS/2 VIO API calls. Since the code is written in BASIC,
 the speed may be notably slower compared to straight assembler code.
 Also, the multitasking nature of OS/2 adds overhead compared to
 running the same program under MS-DOS.

 GetCopyBOX and PutCopyBox uses the MID$() statement and function to
 modify the Screen Buffer variable to store and restore the screen
 contents. An "Illegal Function Call" error may occur at run time if
 the size of the window is zero (0) bytes.

 UIASM.BAS
 ---------

 '| The module below contains the following three BASIC procedures:
 '|
 '|  DECLARE SUB GetCopyBox (ULRow%, ULCow%, LRRow%, LRCol%, buffer$)
 '|  GetCopyBox -- Gets screen box info and places the info into a
 '|                string variable.
 '|
 '|  DECLARE SUB PutCopyBox (ULRow%, ULCow%, buffer$)
 '|  PutCopyBox -- Puts screen box info back on the screen from a
 '|                string variable.
 '|
 '|  DECLARE SUB AttrBox (ULRow%, ULCow%, LRRow%, LRCol%, NewAttr%)
 '|  AttrBox -- Changes the color attributes of all characters within
 '|             a box.
 '|
 '| In the above parameter lists, the beginning two characters specify the
 '| portion of the rectangle of the box being referred to, as follows:
 '|      UL = Upper-left corner of the rectangle/box
 '|      LR = Lower-right corner of the rectangle/box
 '
 ' Below are DECLARE Statements for the OS/2 VIO (Video I/O) routines:
 DECLARE FUNCTION VioReadCellStr% ( BYVAL    CellAdd&,      _
                                    SEG      NumCells%,     _
                                    BYVAL    SRow%,         _
                                    BYVAL    SCol%,         _
                                    BYVAL    VidHandle%  )
 DECLARE FUNCTION VioWrtCellStr%  ( BYVAL    CellAdd&,      _
                                    BYVAL    NumCells%,     _
                                    BYVAL    SRow%,         _
                                    BYVAL    SCol%,         _
                                    BYVAL    VidHandle%  )
 SUB GetCopyBox (ULRow%, ULCol%, LRRow%, LRCol%, ScreenBuffer$)
     '| Subtract 1 from all screen coordinates to reflect the difference
     '| between BASIC's screen BASE 1 and the VIO API BASE 0.
     '| We also make a copy of the variables, since we do not force the
     '| caller to use BYVAL or by reference calling convention.
     '|    UL = Upper-left corner of the rectangle/box
     '|    LR = Lower-right corner of the rectangle/box
     URow% = ULRow% - 1
     UCol% = ULCol% - 1
     LRow% = LRRow% - 1
     LCol% = LRCol% - 1
     '| Find width and height of the Box
     BoxHeigth% = LRow% - URow% + 1
     BoxWidth% = LCol% - UCol% + 1
     '| Calculate the actual width of the line before the FOR-loop
     '| thus performing the operation once. We need a copy of the
     '| results, since the function call changes the value of
     '| parameter passed to it.
     ActualWidth% = BoxWidth% * 2
     OldBoxWidth% = ActualWidth%
     FOR i% = URow% to LRow%
         Work$ = Space$ (ActualWidth%)
         '| Read one line from the Box of BoxWidth% long into
         '| a Work String. The format of the string is
         '| character + attribute (every two bytes make a cell)
         VIORt% = VioReadCellStr ( SSEGADD (Work$), _
                                   ActualWidth%,    _
                                   i%,              _
                                   UCol%,           _
                                   VideoHandle%  )
         '| VioReadCellStr changes the value "ActualWidth%" to reflect
         '| how many characters were actually placed into the buffer.
         '| We reset the value after every call, so we don't lose one
         '| character and attribute each time through the FOR-Loop.
         ActualWidth% = OldBoxWidth%
         '| We calculate the offset into the string where we
         '| will place the line of text.
         ScrnOff% = ActualWidth% * (i% - URow%) + 3
         '| By using the MID$ statement, we can place the information
         '| over the existing information with little work on our part.
         Mid$ (ScreenBuffer$, ScrnOff%, Len (Work$) ) = Work$
     Next i%
     '| Store the Width and Height of the BOX in the first
     '| two characters of the buffer. The Height will be on the
     '| BASE of ONE, and PutCopyBox will convert it to a BASE zero.
     Mid$(ScreenBuffer$, 1, 1) = chr$(BoxWidth%)
     Mid$(ScreenBuffer$, 2, 1) = chr$(BoxHeigth%)
 END SUB

 SUB PutCopyBox (ULRow%, ULCol%, ScreenBuffer$)
     '| Subtract 1 from all screen coordinates to reflect the difference
     '| between BASIC's screen BASE 1 and the VIO API BASE 0.
     '| We also make a copy of the variables, since we do not force the
     '| caller to use the BYVAL or by reference calling convention.
     '|    UL = Upper-left corner of the rectangle/box
     '|    LR = Lower-right corner of the rectangle/box
     URow% = ULRow% - 1
     UCol% = ULCol% - 1
     '| The first two bytes are the Width and Height used by GetCopyBox.
     '| Where the Height is from BASE 1 rather then ZERO
     BoxWidth%  = ASC(Mid$ (ScreenBuffer$, 1, 1))
     BoxHeigth% = ASC(Mid$ (ScreenBuffer$, 2, 1)) - 1
     '| We calculate the actual width of the line before the loop,
     '| rather than inside the loop.
     ActualWidth% = BoxWidth% * 2
     FOR i% = 0 to BoxHeigth%
         '| Calculate the offset into the string for each line of the box.
         ScrnOff% = ActualWidth% * i% + 3
         '| The actual row on the screen that we are printing to:
         NewRow% = URow% + i%
         '| We extract a line of text with the attributes in a
         '| similar manner to how we placed them in the string:
         Work$ = Mid$ (ScreenBuffer$, ScrnOff%, ActualWidth%)
         '| Write the line of text and attributes to the screen:
         VIORt% = VioWrtCellStr ( SSEGADD (Work$),  _
                                  ActualWidth%      _
                                  NewRow%,          _
                                  UCol%,            _
                                  VideoHandle%   )
     Next i%
 END SUB

 SUB AttrBox (ULRow%, ULCol%, LRRow%, LRCol%, NewAttr%)
     '| Subtract 1 from all screen coordinates to reflect the difference
     '| between BASIC's screen BASE 1 and the VIO API BASE 0.
     '| We also make a copy of the variables, since we do not force the
     '| caller to use the BYVAL or by reference calling convention.
     '|    UL = Upper-left corner of the rectangle/box
     '|    LR = Lower-right corner of the rectangle/box
     URow% = ULRow% - 1
     UCol% = ULCol% - 1
     LRow% = LRRow% - 1
     LCol% = LRCol% - 1
     '| Find width and height of the Box:
     BoxHeigth% = LRow% - URow% + 1
     BoxWidth% = LCol% - UCol% + 1
     '| Calculate the actual width of the line before the FOR-loop,
     '| thus performing the operation once. We need a copy of the
     '| results, since the function call changes the value of
     '| parameter passed to it.
     ActualWidth% = BoxWidth% * 2
     OldBoxWidth% = ActualWidth%
     FOR i% = URow% to LRow%
         Work$ = Space$ (ActualWidth%)
         '| Read one line from the Box of BoxWidth% long into
         '| a Work String. The format of the string is
         '| character + attribute (every two bytes make a cell)
         VIORt% = VioReadCellStr ( SSEGADD (Work$), _
                                   ActualWidth%,    _
                                   i%,              _
                                   UCol%,           _
                                   VideoHandle%   )
         '| VioReadCellStr changes the value "ActualWidth%" to reflect
         '| how many characters were actually placed into the buffer.
         '| We reset the value after every call, so we don't lose one
         '| character and attribute each time through the FOR-Loop.
         ActualWidth% = OldBoxWidth%
         For j% = 2 to ActualWidth% STEP 2
             Mid$(Work$, j%, 1) = chr$ (NewAttr%)
         Next j%
         VIORt% = VioWrtCellStr ( SSEGADD (Work$), _
                                  ActualWidth%,    _
                                  i%,              _
                                  UCol%,           _
                                  VideoHandle%   )
     Next i%
 END SUB



 349. PDS 7.10 Can Now Buffer COM1 or COM2 Input Data During a SHELL

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900904-18 B_QuickBas
 Last Modified: 21-SEP-1990    ArticleIdent: Q65548

 In most versions of Microsoft BASIC Compiler and QuickBASIC, during a
 SHELL, data coming in through the communications port is not buffered
 and is lost. A new feature of Microsoft BASIC Professional Development
 System (PDS) version 7.10 allows programs compiled with the BC /O
 (stand-alone) option to continue to buffer communications input during
 a SHELL. However, programs that use the run-time module with BASIC PDS
 7.10 still cannot handle COM1 or COM2 input during a SHELL.

 This information applies to Microsoft BASIC PDS 7.10 for MS-DOS and MS
 OS/2. The above feature is not available in the following products:
 Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50 for MS-DOS; Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and MS OS/2; and Microsoft BASIC PDS version
 7.00 for MS-DOS and MS OS/2.

 This feature is available only when you compile with BC /O. The /O
 compiler switch causes the program to be completely stand alone, which
 means it will run without the run-time module. This feature is not
 available with the run-time module because the run-time module is
 taken out of memory during a SHELL and reloaded when the SHELL is
 exited. Since the code for communications support is contained in the
 run-time module, it is not available during the SHELL. Therefore, the
 program cannot continue to buffer the communications data because the
 code that supports communications has been removed from memory. With a
 stand-alone program, the code for communications support is directly
 linked to the program and stays in memory, thus allowing the program
 to continue to buffer communications data during a SHELL.


 350. Disappearing SUB Statement When Editing in QB.EXE/QBX.EXE

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900830-44 buglist7.00 buglist7.10 B_QuickBAS
 Last Modified: 21-SEP-1990    ArticleIdent: Q65549

 While programming inside the QB.EXE or QBX.EXE environment, a SUB
 statement may temporarily disappear when specific steps are performed.
 These steps involve a combination of deleting the comment line above a
 SUB...END SUB, moving the cursor with the DOWN ARROW key, and using
 the TAB key. The steps below demonstrate the problem.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC version 4.50 (buglist4.50) for MS-DOS and in
 the QBX.EXE environment of Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS. We are researching
 this problem and will post new information here as it becomes
 available. This particular problem (using the exact steps below) does
 not occur in earlier versions.

 To reproduce this problem, create a SUB containing the following code:

    '
    SUB DeleteMe
        PRINT "dummy line"
    END SUB

 Do the following on the code above:

 1. Move the cursor to the first line and delete the comment.

 2. Press the DOWN ARROW key to attempt to move the cursor to the next
    line.

 3. The following error message box will pop up:

       Blank lines not allowed before SUB/FUNCTION line. Is remark OK?

    Press the ENTER key, which will accept the message and delete the
    blank line.

 4. Press the DOWN ARROW key again to move the cursor to the next line.
    If you are using the QB.EXE program that comes with Microsoft
    QuickBASIC version 4.50, the line that says "SUB DeleteMe" will be
    deleted. If you are using the QBX.EXE program that comes with BASIC
    PDS version 7.00 or 7.10, continue to Step 5 to reproduce the
    problem.

 5. After using the DOWN ARROW key to move the cursor to any line of
    code in the SUB, press the TAB key and that line will be replaced
    with the line "SUB DeleteMe".

 6. If you press the DOWN ARROW key again, the original line will
    reappear.

 Note: If the text is not returned, you may be able to recover the text
 in BASIC PDS versions 7.00 and 7.10 by choosing the Undo command from
 the Edit menu to reverse the previous edit. The Undo command reverses
 up to 20 previous edits.


 351. SHELL "CHDIR", "Input Path for Run-Time Module" if No BC /O

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900823-137 buglist7.00 buglist7.10 B_QuickBas
 Last Modified: 14-DEC-1990    ArticleIdent: Q65550

 A SHELL statement that changes the current directory or drive (using
 DOS's CHDIR command) will display the following message when returning
 control to the BASIC program if the program is compiled to require the
 BASIC run-time module (compiled without BC /O):

    Input path for run-time module brt7nxxx.EXE [or brun4n.EXE,
                                                 or brun6nxx.EXE]

 This problem occurs only when you run the .EXE from its own directory,
 and BASIC's run-time module is also in that current directory. The
 problem does not occur if the .EXE or the run-time module is in a
 non-current directory (that is along the DOS PATH).

 Microsoft has confirmed this to be a problem in the Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS; in Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50
 (buglist4.00, buglist4.00b, buglist4.50) for MS-DOS; and in Microsoft
 BASIC Compiler versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for
 MS-DOS. We are researching this problem and will post new information
 here as it becomes available.

 This problem does not occur in an OS/2 protected-mode program (in
 BASIC 6.00, 6.00b, 7.00, or 7.10).

 Any one of the following works around the problem:

 1. Create a stand-alone (BC /O) .EXE file.

 2. Run your compiled .EXE while a different directory is the current
    directory. For example, if your PROG.EXE program is in the
    directory C:\DIR1, then log on to any other directory and run
    C:\DIR1\PROG or take advantage of the DOS PATH to find PROG.EXE.
    (This problem occurs only when the current directory is the same
    directory as where both the PROG.EXE program and the BASIC run-time
    module sit.)

 Code Example
 ------------

 The code example below duplicates the problem. Compile as follows:

    BC TEST.BAS;
    LINK TEST;

 To duplicate the problem, put both the TEST.EXE program and the BASIC
 run-time module (BRT7nxxx.EXE or BRUN4n.EXE or BRUN6nxx.EXE) into a
 subdirectory, make that subdirectory the current directory, then run
 TEST.EXE.

    ' TEST.BAS
    SHELL "CHDIR \"
    PRINT "TEST"


 352. Correction to DIR$ Example In "BASIC 7.0: Language Reference"

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900909-1 docerr
 Last Modified: 21-SEP-1990    ArticleIdent: Q65597

 The DIR$ function example on Page 107 of the "Microsoft BASIC 7.0:
 Language Reference" manual contains an error. To correct the problem,
 the variable "FileCount" in the last line in the following code
 fragment should be changed to "FileCount&" to match the other
 references to it in the example:

    IF LEN(DIR$(filespec$)) = 0 THEN
       FileCount& = 0
    ELSE
       FileCount = 1

 The corrected code is as follows:

    IF LEN(DIR$(filespec$)) = 0 THEN
       FileCount& = 0
    ELSE
       FileCount& = 1

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 353. Differences/Enhancements from BASIC PDS 7.00 to 7.10

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900730-152
 Last Modified: 21-SEP-1990    ArticleIdent: Q65598

 In August 1990, Microsoft released the Microsoft BASIC Professional
 Development System (PDS) version 7.10 for MS-DOS and MS OS/2 systems.
 This article documents those features that were added to BASIC PDS
 7.10 that are not supported in BASIC PDS 7.00. The lists below are
 titled "Language Enhancements," "New Utilities and Utility
 Improvements," and "Software Corrections."

 This information applies to Microsoft BASIC Professional Development
 System version 7.10 for MS-DOS and MS OS/2.

 Language Enhancements
 ---------------------

 1. REDIM PRESERVE changes the upper bounds (top-right dimension) of an
    $DYNAMIC array and preserves the data in the array. Previous
    versions of BASIC initialized the array to zeroes or null strings
    on a REDIM.

 2. It is now possible to pass fixed-length-string arrays as parameters
    to SUB and FUNCTION procedures.

 3. A CALL by value using BYVAL for BASIC SUB and FUNCTION subprograms
    is now possible. Previously, BASIC only supported CALL by value
    using BYVAL when calling a non-BASIC language such as C. The BYVAL
    attribute for passed parameters is now allowed when calling a BASIC
    SUB or FUNCTION.

 4. ISAM is now supported under OS/2. ISAM in PDS 7.10 can be used in
    OS/2 protected mode. (Note that ISAM in PDS 7.10 is still
    single-user ISAM as in 7.00.)

 5. ISAM support in 7.10 operates up to 50% faster than in 7.00,
    depending on the program.

 6. Communications input is buffered during a SHELL if the program was
    compiled with BC /O (stand alone) option. All previous versions of
    BASIC disabled communications support and buffering of communications
    data during a SHELL. BASIC PDS 7.10 does not, however, buffer
    communications data during a SHELL if you are using the run-time
    module (BRT71xxx.EXE).

 7. Compatibility with Microsoft C version 6.00 for interlanguage
    calling. BASIC PDS 7.10 now allows interlanguage calling to
    functions created with Microsoft C Compiler version 6.00. (BASIC
    PDS 7.00 only allowed calling to Microsoft C Compiler version 5.10
    functions.)

 New Utilities and Utility Improvements
 --------------------------------------

 1. QBX.EXE improvement: The 7.10 QuickBASIC extended (QBX.EXE)
    environment uses expanded memory more efficiently than 7.00. In
    BASIC PDS 7.00, each subprogram from 1K to 16K in size uses a full
    16K of expanded memory. In BASIC PDS 7.10, subprograms smaller than
    16K will use expanded memory in 1K chunks. In 7.10, if a subprogram
    is 2K in size, it will use only 2K of expanded memory. (Subprograms
    larger than 16K are stored in conventional memory in both 7.00 and
    7.10.)

 2. Programmer's WorkBench (PWB), a new utility: The Programmer's
    WorkBench is the integrated development environment that is
    provided with Microsoft's newest "high-end" language products. It
    integrates the following features:

    - Keyboard-driven or mouse-driven control of the WorkBench through
      use of menus and scroll bars.

    - Other utilities can be launched from PWB such as NMAKE or
      CodeView.

    - Context sensitive online Help.

    - Multiple windows allow managing multiple files for large
      projects.

    - Multiple-language development within PWB.

    - Supports development under both DOS and OS/2.

    - Customizable program editor.

    - PWB is a combination of Microsoft's Quick environments (such as
      QuickBASIC and QuickC) and the Microsoft Editor, providing easier
      learning for anyone familiar with those environments. However,
      PWB offers many features over and above the Quick environments
      and the earlier Microsoft Editor.

 3. Source Browser: Source Browser is a powerful cross-referencing tool
    that can be launched from within PWB.

 4. CodeView 3.10 debugger is included.

 5. NMAKE facility: A superset of the earlier Microsoft MAKE facility.
    PWB saves you the inconvenience of remembering makefile syntax by
    building and maintaining makefiles for you.

 6. QuickHelp: QuickHelp allows you to access online documentation
    without running QBX.EXE or PWB.EXE. QuickHelp can be run from the
    DOS or OS/2 command line and can also be installed as a keyboard
    monitor under OS/2. Any Help files with the correct format can be
    used with QuickHelp.

 7. QBX.EXE improvement: In the QBX environment under the Run menu, the
    Make .EXE File command now lets you set any BC.EXE compiler option
    in the "Additional Options:" field.

 Software Corrections
 --------------------

 For a list of known problems with BASIC PDS 7.00 (or QuickBASIC 4.50)
 that are corrected in BASIC PDS 7.10, query in this Knowledge Base on
 the word "fixlist7.10".


 354. ERROR ERR May Cause "Illegal Function Call" in QBX.EXE 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900827-59 buglist7.00 fixlist7.10
 Last Modified: 20-SEP-1990    ArticleIdent: Q65640

 In a multiple-module program in which each of the modules contains an
 active error handler, executing the statement ERROR ERR within an
 error handler of any support module will normally pass control back to
 the next active error handler in the CALL tree. If an active error
 handler is not found, the program will terminate.

 Within the QBX.EXE environment of Microsoft BASIC Professional
 Development System (PDS) version 7.00, using ERROR ERR in a
 module-level error handler will incorrectly generate either "Illegal
 function call" or "Device I/O error". This problem does not occur when
 the same program is compiled using BC.EXE.

 Microsoft has confirmed this to be a problem in only the QBX.EXE
 environment of BASIC PDS 7.00 for MS-DOS. This problem was corrected
 in BASIC PDS version 7.10.

 When the following program is run in QBX.EXE version 7.00, an "Illegal
 Function Call" or "Device I/O error" results. When the program is
 compiled using BC.EXE, it will compile and run without error.

 MOD1.BAS
 --------

    '=================This is Module 1==========================
    DECLARE SUB mod2sub1 ()        'this sub is in Mod2
    ON ERROR GOTO MainErr          'Main error Handler
    CLS
    CALL mod2sub1                  'Calls the sub in Mod2
    END
    MainErr:
       PRINT "main error "; ERR    'prints the Error number
       END

 MOD2.BAS
 --------

    '===================This is Module 2========================
    Mod2ErrorHandler:            'This error handler is at the
       PRINT "Mod2 Error "       'Module level in Mod2.
       ERROR ERR                 'This causes the error again.
       RESUME NEXT
    SUB mod2sub1
       ON ERROR GOTO Mod2ErrorHandler  'Goto err handler in Mod2
       ERROR 5                         'Cause an Error 5
    END SUB

 Workaround for MOD2.BAS
 -----------------------

 To work around the problem, convert the module-level error handler (in
 the MOD2.BAS support module) into a local error handler, as follows:

    SUB Mod2Sub1
         ON LOCAL ERROR GOTO Mod2ErrorHandler
         ERROR 5
         EXIT SUB
         Mod2ErrorHandler:
             PRINT "Mod2 Error "
             ERROR ERR           'Forces the error again.
             RESUME NEXT
    END SUB


 355. BASIC 7.00 QBX.EXE: PAINT Statement Uses Far Heap

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900920-17 buglist7.00 fixlist7.10
 Last Modified: 18-OCT-1990    ArticleIdent: Q65831

 In the QBX.EXE environment of Microsoft BASIC Professional Development
 System (PDS) version 7.00, the PAINT statement allocates an area of
 memory in the far heap that cannot be deallocated.

 Microsoft has confirmed this to be a problem in the QBX.EXE
 environment of Microsoft BASIC PDS version 7.00 for MS-DOS. This
 problem was corrected in the QBX.EXE environment of Microsoft BASIC
 PDS version 7.10 for MS-DOS.

 The following code example demonstrates the problem. When run inside
 the QBX.EXE environment of version 7.00, the values returned by the
 FRE(-1) function are different. The problem does not appear in a
 compiled .EXE program.

 Code Example
 ------------

    CLS
    SCREEN 1
    CIRCLE (190, 100), 100, 1, , , .3  'Draw an ellipse
    PRINT FRE(-1)                      'Print far heap memory available
    PAINT (190, 100), 2, 1             'Fill in the ellipse
    PRINT FRE(-1)   'This FRE(-1) value is different than previous FRE(-1)


 356. How to Pass a BASIC COMMON Block to a FORTRAN 5.00 Subroutine

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S900810-80 H_Fortran B_QuickBas
 Last Modified: 22-OCT-1990    ArticleIdent: Q65884

 This article explains how to pass a BASIC COMMON block to a FORTRAN
 version 5.00 subroutine.

 This information applies to Microsoft QuickBASIC version 4.50, to
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS and MS OS/2, and to Microsoft FORTRAN Compiler version 5.00.
 This information does not apply to earlier versions of these products
 (due to incompatibilities).

 To program interlanguage calling between FORTRAN 5.00 and BASIC PDS
 version 7.10, you must obtain the following application note from
 Microsoft Product Support:

    "How to Link BASIC PDS 7.10 with C 5.10, FORTRAN 5.00, or Pascal
     4.00." (application note number BB0345)

 (The FORTRAN 5.00 run-time libraries must be rebuilt as shown in this
 application note to be compatible with the BASIC PDS 7.10 run-time
 libraries.)

 The technique illustrated below shows how to pass a named BASIC COMMON
 block to a FORTRAN subroutine. This technique will not work with
 unnamed BASIC COMMON blocks. This technique will work only with
 FORTRAN version 5.00 because you must use a FORTRAN STRUCTURE...END
 STRUCTURE data type, which is not supported in earlier versions of
 FORTRAN.

 The strategy is to pass the segment and offset of the first variable
 in the named BASIC COMMON block as a parameter in the call to the
 FORTRAN subroutine. The FORTRAN subroutine should set up a
 STRUCTURE...END STRUCTURE type variable with the same format as the
 BASIC COMMON block. The FORTRAN subroutine must receive this STRUCTURE
 type variable as a formal parameter.

 Code Example
 ------------

 Below is the BASIC program BASCOMMN.BAS that sets up the named COMMON
 block, initializes the values, and calls the FORTRAN subroutine:

    'BASCOMMN.BAS **********************************************
    DECLARE SUB FORSUB (BYVAL segment%, BYVAL offset%)
    COMMON SHARED /Example/ a%, b&, c!, d#
    CLS
    a% = 10
    b& = 2000
    c! = 30.3
    d# = 40.125
    PRINT
    PRINT "Hit any key to call the FORTRAN subroutine"
    SLEEP
    CALL FORSUB(VARSEG(a%), VARPTR(a%))
    LOCATE 8, 1: PRINT "back in basic"
    END

 Below is the FORTRAN program FORCOMMN.FOR, which contains the
 subroutine Forub(). It sets up a STRUCTURE type variable similar to
 the corresponding named BASIC COMMON block, and prints out the values:

 C FORCOMMN.FOR   **********************************************
       SUBROUTINE FORSUB( VAR )
       STRUCTURE /BASCOMMON/
           INTEGER*2 A
           INTEGER*4 B
           REAL*4    C
           DOUBLE PRECISION D
       END STRUCTURE
       RECORD /BASCOMMON/ VAR
       PRINT *, VAR.A
       PRINT *, VAR.B
       PRINT *, VAR.C
       PRINT *, VAR.D
       END

 Below is the BASIC code for NEARHEAP.BAS, which allocates near heap
 space for the FORTRAN subroutine. If you are working inside the
 QuickBASIC QB.EXE or QBX.EXE environment, compile this routine and put
 it into a Quick library along with the FORTRAN program. If you are
 compiling and linking into an .EXE program, put these lines in the
 source code of the BASIC program or in a separate BASIC .OBJ module in
 a .LIB library.

    ' NEARHEAP.BAS **********************************************
    DIM Heap%(2048)
    COMMON SHARED /NMALLOC/ Heap%()

 Compile the FORTRAN program as follows:

    FL /c /AM FORCOMMN.FOR

 To work inside the QuickBASIC 4.50 QB.EXE environment, build the
 libraries as follows:

    BC NEARHEAP.BAS;
    LIB FORCOMMN.LIB+NEARHEAP+FORCOMMN;
    LINK /Q FORCOMMN.LIB, FORCOMMN.QLB,,BQLB45.LIB MLIBFER.LIB;

 To compile and link from DOS, build the libraries the same way and
 compile and link BASCOMMN.BAS as follows:

    BC BASCOMMN;
    LINK /NOE BASCOMMN+FORCOMMN.LIB,,,BRUN45.LIB+MLIBFER.LIB ;

 To work inside the BASIC PDS 7.00 QBX.EXE environment, build the
 libraries as follows

    BC /Fs/FPi NEARHEAP;
    LIB FORCOMMN.LIB+NEARHEAP+FORCOMMN;
    LINK /Q FORCOMMN.LIB, FORCOMMN.QLB,,QBXQLB.LIB MLIBFER.LIB ;

 and compile and link from DOS as follows:

    BC /Fs/FPi BASCOMMN;
    LINK /NOE BASCOMMN+FORCOMMN.LIB,,,BRT70EFR+MLIBFER.LIB ;

 The output from the program is as follows:

    Hit any key to call the Fortran subroutine
                 10
               2000
              30.300000
              40.125000000000000

    Back in BASIC


 357. Interrupt to Get QB/QBX Invocation Command Line; vs. COMMAND$

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900925-39 B_QuickBas
 Last Modified: 19-OCT-1990    ArticleIdent: Q65923

 Below is an example of how to do a DOS interrupt to obtain the
 command-line arguments used to invoked a QuickBASIC program. The
 sample program works in the QB.EXE/QBX.EXE environment and in an .EXE
 program. This program can be used to obtain the name of the Quick
 library that QB or QBX was invoked with.

 The program returns the complete command line entered (if any) after
 your .EXE or QB/QBX program name. The BASIC language offers the
 COMMAND$ function to do the same thing, but COMMAND$ returns nothing
 in the QB.EXE/QBX.EXE environment.

 This sample code applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS; and to Microsoft BASIC PDS versions 7.00 and 7.10 for MS-DOS.
 (The code will also run under the DOS 3.x box in MS OS/2's real mode,
 but will not run under MS OS/2's protected mode.)

 The following program uses DOS interrupt 21 hex, with function 62 hex,
 to find the segment address of the program segment prefix (PSP). Based
 on this information, the program then uses the PEEK function to read
 the command line from memory. The Arguments$ function in the example
 returns a string containing all command-line arguments.

 The program arguments are located at an offset of &H80 (80 hex) from
 the PSP. The first byte at this offset is the number of characters in
 the command tail, followed by a string of ASCII characters terminated
 by a carriage return; the carriage return is not included in the
 count.

 For more information about MS-DOS interrupts, please refer to the
 following excellent book:

    "Advanced MS-DOS Programming, Second Edition", by Ray Duncan,
     published by Microsoft Press (1988).

 Sample Code
 -----------

 To use this sample code, QuickBASIC must be started with the /L option
 to load the default Quick library, QB.QLB or QBX.QLB, which contains
 the necessary INTERRUPT routine. (In QuickBASIC 4.x or BASIC compiler
 6.00x, the default Quick library is QB.QLB; in BASIC PDS 7.00 and
 7.10, it is QBX.QLB). Name the following program TEST.BAS:

 ' $INCLUDE: 'qb.bi'
 ' In QuickBASIC 4.x or BASIC compiler 6.00x, use the above include;
 ' but in BASIC PDS 7.00 and 7.10, change the above to use 'QBX.BI'
 DECLARE FUNCTION Arguments$ ()
 args$ = Arguments$
 PRINT args$
 END

 FUNCTION Arguments$
 DIM regs AS RegType
 regs.ax = &H6200
 CALL INTERRUPT(&H21, regs, regs)   ' Get the address of the PSP
 DEF SEG = regs.bx                  ' Set the current segment
 count = PEEK(&H80)                 ' Get the number of characters
 a$ = ""
 FOR a = 2 TO count                 ' Read the arguments from memory
      a$ = a$ + CHR$(PEEK(&H80 + a))
 NEXT
 Arguments$ = a$                    ' Return the arguments to program
 END FUNCTION

 If you invoked this program with

    QB TEST/L QB.QLB
       or
    QBX TEST/L QBX.QLB

 the program will print the following:

    TEST/L QB.QLB
       or
    TEST/L QBX.QLB

 If you invoked this program from an .EXE program (such as TEST.EXE) as
 follows

    TEST ARG1 ARG2

 then the program will print the following:

    ARG1 ARG2


 358. Using OS/2 API Calls for Keyboard Input from BASIC PDS

 Product Version(s): 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S900831-121
 Last Modified: 19-OCT-1990    ArticleIdent: Q65925

 This article contains a sample BASIC module, which calls the OS/2 API
 functions to perform a simple keyboard input routine in protected
 mode.

 This information applies to Microsoft BASIC compiler versions 6.00 and
 6.00b for MS OS/2 (for protected mode only) and Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for MS
 OS/2 (for protected mode only).

 For more information on the OS/2 keyboard input functions, please
 refer to the "Microsoft OS/2 Programmer's Reference" Volume 3, Pages
 164-180, published by Microsoft Press (1989).

 OS/2 protected mode allows for multiple logical keyboard buffers to be
 set up and used by a process. When a logical keyboard buffer is
 opened, it does not receive any characters until that buffer is given
 the focus by the KbdGetFocus function. When a keyboard buffer has the
 focus, it receives all characters that are typed in through the
 keyboard.

 The largest string that can be typed in is determined by the buffer
 that the program sets up; in this example, the buffer is set to 40.
 Any extra characters are ignored until the BACKSPACE, DEL, or arrow
 keys are pressed.

 This sample program uses the KbdOpen and KbdGetFocus function to open
 a logical keyboard. It then uses the KbdGetStatus and KbdSetStatus
 functions to preserve the status of the keyboard and then to modify
 the status, forcing the CAPSLOCK key on. It also uses the
 VioSetCurType function to set the display of the cursor (by default
 there is no cursor).

 To run the program in OS/2 protected mode, the program should be
 compiled and linked as follows:

      BC /Lp OS2KEY;
      LINK OS2KEY,,,BRT71ENP.LIB+OS2.LIB;

 OS2KEY.BAS
 ----------

 'This sample program OS2KEY.BAS uses OS/2 keyboard input routines.
 'Wait flags for keyboard input and status check:
 CONST IOWAIT     = 0
 CONST IONOWAIT   = 1
 'Constant declarations for KdbInfo.fsMask:
 CONST KEYBOARDECHOON            = &H0001
 CONST KEYBOARDECHOOFF           = &H0002
 CONST KEYBOARDBINARYMODE        = &H0004
 CONST KEYBOARDASCIIMODE         = &H0008
 CONST KEYBOARDMODIFYSTATE       = &H0010
 CONST KEYBOARDMODIFYINTERIM     = &H0020
 CONST KEYBOARDMODIFYTURNAROUND  = &H0040
 CONST KEYBOARD2BTURNAROUND      = &H0080
 CONST KEYBOARDSHIFTREPORT       = &H0100
 'Constant declarations for Keyboard flags:
 CONST RIGHTSHIFT    = &H0001
 CONST LEFTSHIFT     = &H0002
 CONST CONTROL       = &H0004
 CONST ALT           = &H0008
 CONST SCROLLLOCKON  = &H0010
 CONST NUMLOCKON     = &H0020
 CONST CAPSLOCKON    = &H0040
 CONST INSERTON      = &H0080
 CONST LEFTCONTROL   = &H0100
 CONST LEFTALT       = &H0200
 CONST RIGHTCONTROL  = &H0400
 CONST RIGHTALT      = &H0800
 CONST SCROLLLOCK    = &H1000
 CONST NUMLOCK       = &H2000
 CONST CAPSLOCK      = &H4000
 CONST SYSREQ        = &H8000
 TYPE KbdInfoType    'KbdInfo structure
     cb           AS INTEGER
     fsMask       AS INTEGER
     chTurnAround AS INTEGER
     fsInterim    AS INTEGER
     fsState      AS INTEGER
 END TYPE
 TYPE StringInBufType    'StringInBuf structure
     cb    AS INTEGER
     cchIn AS INTEGER
 END TYPE
 TYPE StringBufType    'Fixed length string to receive input characters
     Chars AS STRING * 40   'BASIC doesn't allow passing fixed length
 END TYPE                   'strings, so use a user-defined type of
                            'a fixed length string.
 TYPE VioCursorInfoType   'Type that holds the cursor attributes
     yStart AS INTEGER
     cEnd   AS INTEGER
     cx     AS INTEGER
     attr   AS INTEGER
 END TYPE
 'The fundamental OS/2 Keyboard functions
 DECLARE FUNCTION KbdOpen% (SEG hkbd%)
 DECLARE FUNCTION KbdClose% (BYVAL hkbd%)
 DECLARE FUNCTION KbdGetStatus% (SEG KbdInfo AS KbdInfoType, BYVAL hkbd%)
 DECLARE FUNCTION KbdSetStatus% (SEG KbdInfo AS KbdInfoType, BYVAL hkbd%)
 DECLARE FUNCTION KbdGetFocus% (BYVAL fWait%, BYVAL hkbd%)
 DECLARE FUNCTION KbdFreeFocus% (BYVAL hkbd%)
 DECLARE FUNCTION KbdStringIn% (SEG chBuffer AS StringBufType, _
         SEG StringInBuf AS StringInBufType, BYVAL fWait%, BYVAL hkbd%)
 DECLARE FUNCTION VioSetCurType% (SEG VioCursorInfo AS _
                                  VioCursorInfoType, BYVAL hvio%)
 'Dimension the structured variables
 DIM KbdInfo AS KbdInfoType
 DIM PrevkbdInfo AS KbdInfoType
 DIM StringInBuf AS StringInBufType
 DIM chBuffer AS StringBufType
 DIM VioCursorInfo AS VioCursorInfoType
 CLS
 ReturnVal% = KbdOpen%(hkbd%)             'Open a logical Keyboard
 IF ReturnVal% = 0 THEN
  PRINT "Opened logical keyboard"
  PRINT "Getting the focus: ";
  ReturnVal% = KbdGetFocus%(IONOWAIT, hkbd%)   'Make it the one to
                                               'receive keyboard
  IF ReturnVal% = 0 THEN                       'input
     PRINT "we have the focus"
     'Save the previous state of the keyboard, so it can be reset:
     PRINT "Saving the previous state of the input mode"
     PRINT "Getting the status and checking for echo mode, input mode"
     PrevkbdInfo.cb = LEN(KbdInfo)
     ReturnVal% = KbdGetStatus%(PrevkbdInfo, hkbd%)
     IF RetrunVal% = 0 THEN
       'Check echo mode:
       IF (PrevkbdInfo.fsMask AND KEYBOARDECHOON) THEN
        PRINT "Echo on, ";
       ELSE
        PRINT "Echo off, ";
       END IF
       'Check input mode:
       IF (PrevkbdInfo.fsMask AND KEYBOARDASCIIMODE) THEN  '
        PRINT "Ascii mode"
       ELSE
        PRINT "Binary Mode"
       END IF
       'Set the cursor type: size, and attribute:
       VioCursorInfo.yStart = 12    'beginning scan line for cursor
                                    'starting from top position
       VioCursorInfo.cEnd = 13      'ending scan line, zero-based
       VioCursorInfo.cx = 0         'default width, one character
       VioCursorInfo.attr = 0       'normal attribute, &hffff is hidden
       hvio% = 0                    'video handle
       ReturnVal% = VioSetCurType%(VioCursorInfo, hvio%)
       IF ReturnVal% = 0 THEN
        PRINT "Cursor is the normal TWO scan lines tall"
       END IF

       'Initialize KbdInfo to the new status:
       PRINT "Setting the CAPSLOCK on"
       KbdInfo.cb = LEN(KbdInfo)
       KbdInfo.chTurnAround = PrevkbdInfo.chTurnAround
       KbdInfo.fsInterim = PrevkbdInfo.fsInterim
       KbdInfo.fsMask = (PrevkbdInfo.fsMask OR _    'Turn on the modify
                         KEYBOARDMODIFYSTATE)       'state
       KbdInfo.fsState = (PrevkbdInfo.fsState OR _  'force caps lock on
                          CAPSLOCKON)
       ReturnVal% = KbdSetStatus%(KbdInfo, hkbd%)   'Set the status
       IF ReturnVal% = 0 THEN
        PRINT "Caps lock should be on"
        PRINT "Input some characters: ";
        StringInBuf.cb = LEN(chBuffer)
        'Input the string:
        RetrunVal% = KbdStringIn%(chBuffer, StringInBuf, IOWAIT, hkbd%)

      'During input, OS/2 does not advance the cursor, to prevent
      'writing over what was typed, use a LOCATE statement, or a double
      'PRINT to advance the cursor position
        PRINT : PRINT "This is what you typed: "; chBuffer.Chars
        SLEEP (3)                       'Sleep for three seconds
       ELSE
        PRINT "Caps on failed"
       END IF
       'Start cleaning up, restore the status, free focus, and close
       'keyboard:
       PRINT "Restoring the status"
       RetrunVal% = KbdSetStatus%(PrevKbdInfo, hkbd%)
       IF RetrunVal% = 0 THEN
        PRINT "Status Returned"
       ELSE
        PRINT "Status Could Not Be Restored
       END IF

       'Free the focus and close the logical keyboard
       PRINT "Freeing the focus and closing keyboard"
       ReturnVal% = KbdFreeFocus%(hkbd%)
       IF ReturnVal% = 0 THEN
        ReturnVal% = KbdClose%(hkbd%)
        IF ReturnVal% = 0 THEN
          PRINT "Keyboard closed"
        ELSE
          PRINT "Keyboard could not be closed, Error= "; ReturnVal%
        END IF
       ELSE
        PRINT "Focus could not be freed: "; ReturnVal%
       END IF
     ELSE
      PRINT "Get status failed: "; RetrunVal%
     END IF
  ELSE
     PRINT "ERROR on Focus, ReturnVal% = "; ReturnVal%
  END IF
 ELSE
     PRINT "Logical keyboard could not be opened"
 END IF
 END


 359. How PutCopyBox Determines Window Size in 7.00/7.10 UI ToolBox

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900924-84
 Last Modified:  8-NOV-1990    ArticleIdent: Q65926

 The User-Interface (UI) ToolBox uses three assembler routines to "Get
 a window from the screen" (GetCopyBox), "Put a window to the screen"
 (PutCopyBox), and "Change the attributes of a window" (AttrBox). The
 source code for these three assembler routines are located in the
 UIASM.ASM file.

 GetCopyBox and PutCopyBox are complimentary routines, except for the
 parameters that they use. GetCopyBox needs five parameters; four to
 define the rectangle of the window and one for the string to store the
 information. PutCopyBox uses only three parameters; two for the
 upper-left corner and one for the string where the information will
 come from.

 PutCopyBox determines the size of the rectangle by the window width
 and window height stored in the first four bytes of the string.
 GetCopyBox stores this information in the string as the first four
 bytes, then places the contents of the window following the height and
 width of the window.

 The window width is the first two bytes and the window height is the
 next two bytes.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The following is an extraction of code from UIASM.ASM used by the UI
 ToolBox routines to preserve and restore a window on the screen.

 The sections of code listed below that refer to "si,offset" are moving
 the data from memory to the string. The references to "di,offset" are
 moving the data from the string to memory.

 Sample Code
 -----------

 get_setstr:
         mov     al,x1
         sub     al,x0                   ;find width of box
         mov     bwidth,al               ;and save
         add     al,1                    ;add one to width
         mov     ah,0                    ;to find # words to move
         mov     movword,ax              ;MovWord = (width+1)
         mov     al,y1
         sub     al,y0                   ;find height of box
         mov     height,al               ;and save
         mov     es,strdseg
         mov     di,strdoff              ;string is the destination

         ; Place the Windows Width in the first word of the string
         ; The first and second bytes of the string

         mov     si,offset bwidth        ;point to width
         movsb                           ;put width in string

         ; Place the Windows Height in the second word of the string
         ; The third and fourth bytes of the string

         mov     si,offset height
         movsb                           ;and the height, too

 put_setstr:
         push    ds
         pop     es                      ;equate ES to DS

         mov     si,strdoff              ;point DS:SI to string mem
         push    ds
         mov     ds,strdseg

         ; Get the Windows Width from the string

         mov     di,offset bwidth
         movsb                           ;get width

         ; Get the Windows Height from the string

         mov     di,offset height
         movsb                           ;and height out of string

         pop     ds


 360. ISAMIO /E Cannot Extract Aggregate Types from ISAM Database

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901001-69
 Last Modified: 18-OCT-1990    ArticleIdent: Q66139

 The ISAMIO.EXE utility can extract the data from an ISAM table into an
 ASCII text file by using the /E switch. However, the ISAMIO.EXE
 utility cannot completely extract aggregate items in a table.
 Aggregate items are items in the TYPE record that are not simple
 types. Simple types are INTEGER, LONG, CURRENCY, DOUBLE, and STRING.
 Aggregate types are items such as nested TYPEs or an array in the
 TYPE. This is not a problem with the ISAMIO.EXE utility, but is a
 result of the way in which the ISAM engine stores aggregate types in
 the table and in the data dictionary. This article also describes two
 ways to view a database's data dictionary.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and version 7.10 for MS-DOS and
 MS OS/2.

 This behavior of ISAMIO results from the way in which the ISAM engine
 stores an aggregate item in the database. For an aggregate type, it
 calculates the size of the whole aggregate item, and then inserts an
 entry in the data dictionary describing it as a binary object of that
 many bytes. For example, consider the following TYPE:

 TYPE nested ' This gets nested in the TYPE below.
     junk1 AS DOUBLE
     junk2 AS STRING * 7
 END TYPE

 TYPE record
    key1 AS STRING * 20
    key2 AS nested
    key3 AS INTEGER
    key4(5) AS INTEGER
    key5 AS LONG
    key6(4)  AS DOUBLE
    key7 AS DOUBLE
    key8 AS CURRENCY
 END TYPE

 If you create a table in a database with this TYPE, the ISAM engine
 will put entries in the data dictionary saying that key2, key4, and
 key6 are "binary" objects of a certain size. Thus, when ISAMIO later
 tries to extract these items, it cannot determine what their original
 data types were; it only knows how big they were. Therefore, ISAMIO
 extracts these binary objects as a string (usually full of graphics
 characters).

 You can show what is in a database's data dictionary in two ways, as
 described in the following:

 1. ISAMIO can access the data dictionary. When you run ISAMIO to
    extract a database as a text file, you can specify a <specfile>
    parameter. For example, to extract the table called "test" in a
    database called "test.mdb" made with the above TYPEs, you use the
    following line:

       ISAMIO /E data.txt test.mdb test specfile.txt /C

    After this, DATA.TXT contains the output data. While it's
    extracting, ISAMIO takes the information in the data dictionary and
    builds "SPECFILE.TXT". Note that SPECFILE.TXT doesn't have to exist
    before you run ISAMIO. After running ISAMIO, this specfile will
    describe the data items in the ASCII text file just created. For
    instance, for the TYPE example above, the specfile created is as
    follows:

       variabletext,20,key1
       binary,,key2
       integer,,key3
       binary,,key4
       long,,key5
       binary,,key6
       double,,key7
       currency,,key8

    This clearly shows key2, key4, and key4 are seen as binary objects
    by ISAMIO.EXE.

 2. The second way to examine the data dictionary is to run the
    ISAMPACK.EXE utility. If you redirect the output from ISAMPACK into
    a file, you will have a record of the database's contents. For
    instance, use the following:

       ISAMPACK test.mdb > report.dat

    This creates a file called REPORT.DAT, which (among other things)
    has a description of the structure of each table in the database.
    The structure of the tables is determined by what is in the data
    dictionary. For the table discussed above, a part of REPORT.DAT
    will contain the following:

       Column Name               Column Type         Maximum Size
       -----------               -----------         ------------

       key1                      VarText             20
       key2                      Binary              64K
       key3                      Integer             2
       key4                      Binary              64K
       key5                      Long                4
       key6                      Binary              64K
       key7                      Double              8
       key8                      Currency            8

    Again, this shows that the data dictionary describes aggregate
    objects as being "binary".

 Code Example
 ------------

 To build the code example described above, you can use the following
 program. To run this program in QBX.EXE, you must first load the
 PROISAMD.EXE TSR. To compile and run the program, use the following:

    BC test.bas ;
    LINK test ;

 DEFINT A-Z
 TYPE nested
     junk1 AS DOUBLE
     junk2 AS STRING * 7
 END TYPE

 TYPE record
    key1 AS STRING * 20
    key2 AS nested
    key3 AS INTEGER
    key4(5) AS INTEGER
    key5 AS LONG
    key6(4)  AS DOUBLE
    key7 AS DOUBLE
    key8 AS CURRENCY
 END TYPE

 DIM Record1 AS record, Record2 AS record, Record3 AS record
 ' Code part.

 OPEN "test.mdb" FOR ISAM record "test" AS #1
 'SETINDEX #1, "testindex"

 FOR i = 1 TO 20
    PRINT "***********************************"
    PRINT "*       Get a new record          *"
    PRINT "***********************************"

    INPUT "Input a STRING * 20: ", Record1.key1
    INPUT "Input a DOUBLE: ", Record1.key2.junk1
    INPUT "Input a STRING * 7: ", Record1.key2.junk2
    INPUT "Input an INTEGER: ", Record1.key3
    FOR j = 1 TO 5
      INPUT "Input an INTEGER: ", Record1.key4(j)
    NEXT
    INPUT "Input a LONG: ", Record1.key5
    FOR j = 1 TO 4
      INPUT "Input an INTEGER: ", Record1.key6(j)
    NEXT
    INPUT "Input a DOUBLE: ", Record1.key7
    INPUT "Input a CURRENCY: ", curr1
    INSERT #1, Record1
 NEXT
 CLOSE
 END


 361. How to Change User Interface Global CONSTants in GENERAL.BI

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900313-103
 Last Modified: 18-OCT-1990    ArticleIdent: Q66140

 The GENERAL.BI $INCLUDE file in the User Interface (UI) Toolbox, which
 comes with Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10, contains several global constants (defined
 with CONST) that dictate how the Toolbox FUNCTIONs and SUBs will
 behave. When one of these CONSTants is changed, the entire Toolbox
 usually must be recompiled and linked, all libraries must be rebuilt,
 and the quick libraries must be rebuilt. This article gives
 instructions for this process.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS.

 To change the constants in the UI $INCLUDE files, follow these steps:

 1. Load the file GENERAL.BI into any editor (such as QBX.EXE).

 2. Move the cursor down to the Global Constants section.

 3. Change the CONSTant.

 4. Save the GENERAL.BI file.

 5. If you are loading the entire source code for the Toolbox into the
    QBX.EXE editor, then you can just load and run the current program
    and the changes will take effect.

 Most people use the Toolbox in the form of a compiled library or Quick
 library. To enable these changes to take effect in your Quick library
 or library, you must recompile and create both UITBEFR.QLB and
 UITBxxx.LIB. The "xxx" depends on what compiler options you use to
 create your final .EXE application and what compiler options you use
 to create the Toolbox.

 Within the QBX.EXE environment, you must use UITBEFR.QLB (which
 supports the emulator library, far strings, and real-mode). Therefore,
 a full example is provided here of altering UITBEFR.LIB and
 UITBEFR.QLB. To re-create these files, use the following commands (as
 shown in the form of an MS-DOS batch file to make rebuilding the
 libraries easier):

    REM  Recompile the four BASIC modules which make the Toolboxes
    REM  Note that the .OBJ names below MUST be used:
    BC /x /Fs /Lr /FPi GENERAL.BAS, GENEREFR.OBJ;
    BC /x /Fs /Lr /FPi MOUSE.BAS,   MOUSEEFR.OBJ;
    BC /x /Fs /Lr /FPi MENU.BAS,    MENUEFR.OBJ ;
    BC /x /Fs /Lr /FPi WINDOW.BAS,  WINDOEFR.OBJ;

    REM  Replace the existing modules in the UITBEFR.LIB. Note that
    REM  the following command should be on just one DOS command line:
  LIB UITBEFR.LIB -+GENEREFR.OBJ -+ MOUSEEFR.OBJ -+MENUEFR.OBJ -+WINDOEFR.OBJ;

    REM  Don't forget to save the old version of your library in case
    REM  an error occurs:
    RENAME UITBEFR.QLB UITBEFR.BAK

    REM  Link the new Quick library:
    LINK /q UITBEFR.LIB, UITBEFR.QLB,,QBXQLB.LIB;

 If you want to modify any of the other UITBxxx.LIB libraries, then the
 BC compile and LIB commands given above can easily be modified to work
 properly with all of these other libraries.

 The global constants that can be changed in GENERAL.BI are: FALSE,
 TRUE, MINROW, MAXROW, MINCOL, MAXCOL, MAXMENU, MAXITEM, MAXWINDOW,
 MAXBUTTON, MAXEDITFIELD, and MAXHOTSPOT. For a description of these
 constants, see page 533 of the "Microsoft BASIC 7.0: BASIC Language
 Reference."


 362. Problems May Occur When Passing the Same Array Element Twice

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | SR# S901018-67 B_QuickBAS
 Last Modified: 12-NOV-1990    ArticleIdent: Q66455

 The following program may give unexpected results when the same array
 element is passed twice to the subprogram. The problem results from a
 form of variable aliasing, where the same memory location is
 referenced by two different variables.

 To avoid aliasing problems, never pass the same variable twice in a
 given parameter list.

 Passing the same array element twice in the same parameter list can
 give incorrect or unexpected results regardless of array type or
 dynamic or static array allocation. The results may also vary between
 compiler versions. A customer reported that the program below gave the
 results that he wanted in QuickBASIC 4.00, but not in Microsoft BASIC
 Professional Development System (PDS) version 7.10; Microsoft has not
 confirmed this report.

 This behavior results from the fact the BASIC often requires a far
 pointer to access arrays, but parameters need to be passed as near
 pointers. On a CALL, BASIC sets aside a temporary location holding the
 array element and then passes a pointer to the temporary area.

 There are two options in this sort of situation: Recode the subprogram
 so that it is not necessary to pass the array element twice, or assign
 one of the parameters to a temporary variable and then pass the
 temporary variable.

 References:

 For a similar article on variable aliasing when a parameter is both
 SHARED and passed as a parameter to a subprogram, query in this
 Knowledge Base on the following words:

    DYNAMIC and ARRAY and ALIASES

 A variable should not be passed twice in the list of arguments passed
 to a procedure; otherwise, variable-aliasing problems will occur. This
 restriction is documented under "The Problem of Variable Aliasing" on
 Page 64 in the "Microsoft BASIC 7.0: Programmer's Guide" for BASIC PDS
 versions 7.00 and 7.10, on Page 68 of the "Microsoft QuickBASIC 4.5:
 Programming in BASIC" manual, and on Page 78 of the "Microsoft
 QuickBASIC 4.0: Programming in BASIC: Selected Topics" manual for
 QuickBASIC versions 4.00 and 4.00b.

 Code Example
 ------------

    DECLARE SUB MakeUpper(instring AS STRING, outstring AS STRING)
    DIM a$(15)
    a$(4)="abcdefg"
    CALL MakeUpper(a$(4), a$(4))
    PRINT a$(4)
    END

    SUB MakeUpper(instring AS STRING, outstring AS STRING)
      outstring = UCASE$(instring)
    END SUB


 363. BASIC PDS Reply Letters: Appnotes BB0354, BB0355, BB0356

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | policy appnote BB0354 BB0355 BB0356
 Last Modified: 14-NOV-1990    ArticleIdent: Q66490

 Below are the three form letters that Microsoft sends in response to
 unsolicited letters from customers who have Microsoft BASIC
 Professional Development System (PDS) version 7.00 or 7.10 for MS-DOS
 and MS OS/2:

    Appnote Number        Description
    --------------        -----------

    BB0354                BASIC PDS Question Reply Letter
    BB0355                BASIC PDS Suggestion Reply Letter
    BB0356                BASIC PDS Problem/Docerr Reply Letter

 These form letters are sent out from Microsoft Product Support
 Services (PSS) as application notes.

 Note: Page 1 of 2 is shown below for each reply letter. Page 2 of 2,
 the "Product Assistance Checklist," is the same for each reply letter
 and is shown in a separate article that can be found by querying for
 the following words:

    product and assistance and checklist

 BB0354: BASIC PDS Question Reply Letter
 ---------------------------------------

 Dear BASIC Professional Development System Customer:

 Thank you for your letter concerning the BASIC Professional
 Development System (PDS). Although we are unable to respond to your
 technical questions by letter, we do forward your letters to our BASIC
 PDS development team. This procedure provides developers with customer
 feedback, which will in turn make Microsoft's products even better.
 Now that we can no longer respond to letters (unless solicited by
 Microsoft), we are providing the following new service:

 Our toll-line number, (206) 637-7096, is available Monday through
 Friday (except holidays), 8 AM to 5 PM Pacific Standard Time, and is
 designed to answer questions about set up and installation procedures,
 problem reports, and documentation errors. We also address most
 programming, code debugging, and problem solving issues.

 We are also offering a 900-number service to provide a higher quality
 of service, extended hours, and a shorter waiting time. To access
 "OnCall(TM) for BASIC," call (900) 896-9999. The cost is $2 per
 minute, and the service is available Monday through Friday from 6 AM
 to 6 PM Pacific Standard Time. To obtain the best possible service, we
 recommend you be at your computer and have your BASIC Professional
 Development System reference manuals and disks handy when you call.

 There are many supplemental sources of information relating to the
 BASIC languages, including reference guides and books published by
 Microsoft Press, or you can contact our "OnCall for BASIC" service at
 (900) 896-9999. Support is also available electronically through
 Microsoft OnLine and CompuServe. One of the features of these services
 is to provide access to the Microsoft Knowledge Base. The Microsoft
 Knowledge Base contains the latest technical information about
 Microsoft language products. For more information about Microsoft
 OnLine, which is designed for software developers, call (800)
 443-4672. For more information about CompuServe, which is the largest
 general online information service for personal computer users, call
 (800) 848-8199.

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BB0354

 BB0355: BASIC PDS Suggestion Reply Letter
 -----------------------------------------

 Dear BASIC Professional Development System Customer:

 Thank you for your letter and suggestion concerning our BASIC
 Professional Development System (PDS). Although we are unable to
 respond to your technical questions by letter, we do forward your
 letters to our BASIC PDS development team. This procedure provides
 developers with customer feedback, which will in turn make Microsoft's
 products even better. Now that we can no longer respond to letters
 (unless solicited by Microsoft), we are providing the following new
 service:

 Our toll-line number, (206) 637-7096, is available Monday through
 Friday (except holidays), 8 AM to 5 PM Pacific Standard Time, and is
 designed to answer questions about set up and installation procedures,
 problem reports, and documentation errors. We also address most
 programming, code debugging, and problem solving issues.

 We are also offering a 900-number service to provide a higher quality
 of service, extended hours, and a shorter waiting time. To access
 "OnCall(TM) for BASIC," call (900) 896-9999. The cost is $2 per
 minute, and the service is available Monday through Friday from 6 AM
 to 6 PM Pacific Standard Time. To obtain the best possible service, we
 recommend you be at your computer and have your BASIC Professional
 Development System reference manuals and disks handy when you call.

 There are many supplemental sources of information relating to the
 BASIC languages, including reference guides and books published by
 Microsoft Press, or you can contact our "OnCall for BASIC" service at
 (900) 896-9999. Support is also available electronically through
 Microsoft OnLine and CompuServe. One of the features of these services
 is to provide access to the Microsoft Knowledge Base. The Microsoft
 Knowledge Base contains the latest technical information about
 Microsoft language products. For more information about Microsoft
 OnLine, which is designed for software developers, call (800)
 443-4672. For more information about CompuServe, which is the largest
 general online information service for personal computer users, call
 (800) 848-8199.

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BB0355

 BB0356: BASIC PDS Problem/Docerr Reply Letter
 ---------------------------------------------

 Dear BASIC Professional Development System Customer:

 Thank you for your letter concerning your BASIC Professional
 Development System (PDS) problem and/or documentation error. Although
 we are unable to respond to your technical questions by letter, we do
 forward your letters to our BASIC PDS development team. This procedure
 provides developers with customer feedback, which will in turn make
 Microsoft's products even better. Now that we can no longer respond to
 letters (unless solicited by Microsoft), we are providing the
 following new service:

 Our toll-line number, (206) 637-7096, is available Monday through
 Friday (except holidays), 8 AM to 5 PM Pacific Standard Time, and is
 designed to answer questions about set up and installation procedures,
 problem reports, and documentation errors. We also address most
 programming, code debugging, and problem solving issues.

 We are also offering a 900-number service to provide a higher quality
 of service, extended hours, and a shorter waiting time. To access
 "OnCall(TM) for BASIC," call (900) 896-9999. The cost is $2 per
 minute, and the service is available Monday through Friday from 6 AM
 to 6 PM Pacific Standard Time. To obtain the best possible service, we
 recommend you be at your computer and have your BASIC Professional
 Development System reference manuals and disks handy when you call.

 There are many supplemental sources of information relating to the
 BASIC languages, including reference guides and books published by
 Microsoft Press, or you can contact our "OnCall for BASIC" service at
 (900) 896-9999. Support is also available electronically through
 Microsoft OnLine and CompuServe. One of the features of these services
 is to provide access to the Microsoft Knowledge Base. The Microsoft
 Knowledge Base contains the latest technical information about
 Microsoft language products. For more information about Microsoft
 OnLine, which is designed for software developers, call (800)
 443-4672. For more information about CompuServe, which is the largest
 general online information service for personal computer users, call
 (800) 848-8199.

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BB0356


 364. "Illegal Function Call" Using Coprocessor in BASIC 7.10

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901018-77 buglist7.00 buglist7.10
 Last Modified: 12-NOV-1990    ArticleIdent: Q66560

 The following program gives an "Illegal Function Call" error when run
 as a .EXE program using a math coprocessor; however, it works
 correctly in the QBX.EXE environment or with the coprocessor disabled.

 Microsoft has confirmed this to be a problem in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 Workaround
 ----------

 To work around this problem, do one of the following:

 1. Break the complex equation into smaller parts that are evaluated
    separately.

 -or-

 2. Turn off use of the coprocessor with SET NO87="message" at the DOS
    prompt.

 -or-

 3. Compile using the alternate math (/FPa) option.

 Code Example
 ------------

 a = .475
 b = 75
 c = 62
 d = .007
 e = 22
 f = (b * e ^ 2 / d) * SQR(1 / ((2 * b * c * a) ^ 2 + (b ^ 2 - c ^ 2))

 Simplifying the equation eliminates the problem. For example, removing
 the (b * e ^ 2 / d) factor eliminates the error.


 365. ALT+240 Hangs QBX.EXE or QB.EXE with Phoenix BIOS

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901025-47 B_QuickBas
 Last Modified: 12-NOV-1990    ArticleIdent: Q66591

 The extended ASCII characters can be typed into a BASIC program using
 the combination of the ALT key plus the three digits that correspond
 to the character. However, in Microsoft QuickBASIC version 4.50 and
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10, typing ALT+240 can hang the QB.EXE and QBX.EXE environments
 temporarily. This problem has been reproduced on a Wyse 386 with a
 Phoenix BIOS version 3.53. Pressing CTRL+BREAK will get you out of the
 hang.

 To work around the problem, use the PRINT CHR$(240) statement instead.

 This problem also occurs in a WYSE 286, running Phoenix 286 ROM BIOS
 version 2.72, and has been reported with a clone computer running
 Phoenix ROM BIOS version 3.07.

 For a related article concerning how to enter extended ASCII and
 control characters into QB.EXE and QBX.EXE, search in this Knowledge
 Base for the following words:

    extended and ASCII and ALT and 240 and 255


 366. ALERT Function in BASIC 7.10 UI Toolbox Destroys TEXT$

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901030-181 buglist7.00 buglist7.10
 Last Modified: 14-NOV-1990    ArticleIdent: Q66690

 The ALERT function in the User Interface (UI) Toolbox destroys the
 string sent to it in the TEXT$ field of the function call.

 Microsoft has confirmed this problem in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS. Suggested
 workarounds for this problem are shown below.

 Workarounds
 -----------

 Any one of the following workarounds will correct the problem but
 choices 1 and 2 may be easiest because they don't require recompiling
 WINDOW.BAS or building new UI Toolbox support libraries:

 1. Enclose the TEXT$ parameter in parentheses. For example, the
    following statement

       Alert(4, a$, 6, 20, 15, 60, "OK", "CANCEL", "")

    should be changed to the following:

       Alert(4, (a$), 6, 20, 15, 60, "OK", "CANCEL", "")

 2. Make a copy of the string before calling the ALERT function, as
    follows:

       temp$ = a$
       ALERT(4, a$, 6, 20, 15, 60, "OK", "CANCEL", "")
       a$ = temp$

 3. Modify the ALERT function in WINDOW.BAS as follows:

       a. Right after the line that says

             FUNCTION Alert (style, text$...

          put the following statement:

             TempText$ = test$

        b. Right before the END FUNCTION at the bottom of the function,
           put the following statement:

              test$ = TempText$

    You should then make a new Quick library (.QLB) and a new LINK
    library (.LIB) that use the new version of ALERT, as shown in the
    following:

       BC /X/FS GENERAL.BAS;
       BC /X/FS WINDOW.BAS;
       BC /X/FS MOUSE.BAS;
       BC /X/FS MENU.BAS
       LIB UITB+GENERAL+WINDOW+MOUSE+MENU+UIASM+QBX.LIB;
       LINK /Q UITB.LIB, UITB.QLB, , QBXQLB.LIB;

    Invoke QBX.EXE using the new UITB.QLB Quick library, as follows:

       QBX /L UITB


 367. No "Block IF Without END IF" Using IF...THEN REM in QB/QBX.EXE

 Product Version(s): 6.00 6.00b 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | B_QUICKBAS buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified: 14-NOV-1990    ArticleIdent: Q66691

 In compiled BASICs that support block IF statements, the following
 statement correctly implies a block IF ... END IF statement, instead
 of a single-line IF statement syntax (whereas GW-BASIC correctly
 treats this as a single-line IF because GW-BASIC has no block IF
 syntax):

    IF expression THEN ' Comment

 However, using a THEN REM statement, as follows, poses a problem:

    IF expression THEN REM Comment

 The problem is that the QBX.EXE (or QB.EXE) environment interprets
 THEN REM as indicating a single-line IF statement, whereas BC.EXE
 compiler interprets THEN REM as indicating a block IF.

 This inconsistency applies to Microsoft QuickBASIC versions 4.00,
 4.00b, 4.50 (buglist4.00, buglist4.00b, buglist4.50) for MS-DOS; to
 Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2; and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 When compiling the code example below, BC.EXE gives a "Block IF
 without END IF" error but the QBX.EXE or QB.EXE environment doesn't
 give an error, and interprets the IF ... THEN REM statement as a
 single-line IF statement. If an END IF statement is put at the end of
 the code, the code example will compile with no error in BC.EXE but
 the QBX.EXE or QB.EXE environment will give an "END IF without block
 IF" error.

 The problem is caused by the REM statement on the IF line. In the
 QBX.EXE or QB.EXE environment, this case is interpreted as a
 single-line (non-block) IF. The BC.EXE compiler, however, strips off
 the REMark and interprets the line as the start of a block IF
 statement.

 Microsoft is researching which consistent syntax requirement should be
 adopted for IF ... THEN REM and will post new information here as it
 becomes available.

 Code Example
 ------------

 IF a = 3 THEN REM  Gives "Block IF without END IF" in BC.EXE
 a = 5

 To a avoid this problem, a remark should never be placed after a THEN
 statement. For example, the following code example avoids this problem
 by putting the remark on a separate line:

 REM   This remark doesn't cause a problem.
 IF a = 3 THEN
 a = 5
 END IF


 368. How to Re-create BASIC Help Files Using HELPMAKE.EXE

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901105-139
 Last Modified:  8-NOV-1990    ArticleIdent: Q66771

 HELPMAKE.EXE is designed to allow you to decode/encode the Help files
 included with BASIC PDS, and to create your own Help files for use
 with BASIC, QuickHelp, and other products that use these files.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 To decode a BASIC Help file, use the following command:

    HELPMAKE /D <HelpFileName> /O<OutputFile>

 You may now modify (customize) the decoded Help file.

 To re-encode the Help file after you have edited it, use the following
 command:

    HELPMAKE /E <SourceFile> /A: /T /W78 /O<HelpFileName>

 The options on the above encode line are explained below:

   /E   Encode the file. /E with no value gives the maximum
        compression. /E may optionally be followed by a value
        specifying the amount of compression to use:

            0 - No Compression
            1 - Run-length compression
            2 - Keyword compression
            4 - Extended keyword compression
            8 - Huffman compression

        These values may be added together to combine compression
        types. For example, /E5 will generate Run-length and Extended
        keyword compression.

   /A:  Specifies a colon as the control character. This is the default
        value so it may be omitted.

   /T   Translates dot commands. This is required to re-encode the
        BASIC Help files.

   /W78 Specifies the width of the resulting Help file. BASIC uses a
        width of 78 characters. The default is 76 so this option must
        be included.

 For a more detailed discussion of HELPMAKE, refer to Chapter 11 of
 "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10.


 369. Far FIELD Variable Assigned to Itself Doesn't UnFIELD in PDS

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901114-86
 Last Modified:  5-DEC-1990    ArticleIdent: Q67107

 When using far strings in the example below, BASIC Professional
 Development System (PDS) doesn't unFIELD a FIELDed variable when that
 variable is assigned to itself. The variable does get unFIELDed if the
 program is compiled with near strings or compiled in earlier versions
 of BASIC, or if the variable is assigned to a new value.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS and MS OS/2.

 This behavioral inconsistency emphasizes the point that you should
 never make your program depend on a variable being unFIELDed. You
 should set the contents of a FIELDed variable only with the LSET or
 RSET statement; never assign values to FIELDed variables with LET or
 direct assignment.

 If you want to use and reassign a variable without affecting the
 FIELDed buffer, copy the FIELDed variable to a permanent variable that
 is not used in a FIELD statement. Better yet, for easier programming,
 Microsoft recommends using user-defined TYPE variables instead of
 FIELD statements for defining random-access file records.

 Reference:

 The following is taken from the FIELD statement description on page
 131 of the "Microsoft BASIC 7.0: Language Reference" manual for
 versions 7.00 and 7.10:

    Do not use a variable name defined as a field in an INPUT or
    assignment statement if you want the variable to remain in a field.
    Once a variable name is a field, it points to the correct place in
    the random-access file buffer. If a subsequent INPUT or assignment
    statement with that variable name is executed, the variable's
    pointer no longer refers to the random-access record buffer, but to
    string space.

 The example below describes a specific exception to the last sentence,
 where the variable still points to the random-access record buffer and
 not to a new location in string space.

 Code Example
 ------------

 First, create a text file "data.dat" that contains the following
 data on one line:

    abcd defg hijk lmno pqrs tuvw xyz1 2345 6789

 Then run the following program in QBX.EXE, or as an .EXE compiled with
 BC /Fs (the far variable-length strings option):

 DEFSTR A-Z
 OPEN "data.dat" FOR RANDOM AS #1 LEN = 15
 FIELD #1, 5 AS a, 5 AS b, 5 AS c
 GET #1   ' Get first 15 bytes.
  PRINT a; b; c
 GET #1   ' Get next 15 bytes.
 a = a
  PRINT a; b; c
 GET #1   ' Get next 15 bytes.
  PRINT a; b; c
 CLOSE #1

 With far strings, the above example will give an output of the
 following:

    abcd defg hijk
    lmno pqrs tuvw
    xyz1 2345 6789

 The above output shows that the variable "a" was retained as a FIELDed
 variable. Adding a null string, for example < a = a + "" >, also does
 not cause the variable to be unFIELDed.

 However, if the line < a = a > is changed to < a = "test" >, then the
 variable "a" becomes unFIELDed, and the output will be as follows:

    abcd defg hijk
    test pqrs tuvw
    test 2345 6789

 The variable is only unFIELDed when it is changed.


 370. OS/2 "Path/File Access Error" Instead of "Permission Denied"

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S901024-38 buglist6.00 buglist6.00b buglist7.00 buglist7
 Last Modified:  5-DEC-1990    ArticleIdent: Q67206

 When attempting to open a file under multiple OS/2 processes or in an
 OS/2 networking environment, a BASIC program will incorrectly generate
 the error message "Path/File access error" (error code 75) when
 attempting to open a locked file. The error message it should generate
 is "Permission denied" (error code 70). This problem does not occur in
 a DOS networking environment, such as when accessing files on a server
 from a DOS LANMAN workstation. Under these conditions, the BASIC
 program generates the correct error message, "Permission denied."

 This problem occurs in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2, and in Microsoft BASIC PDS (Professional
 Development System) versions 7.00 and 7.10 for MS OS/2. Microsoft is
 researching this problem and will post new information here as it
 becomes available.

 The following test program demonstrates the problem. To reproduce the
 problem, compile and run the program in an OS/2 session. Then switch
 to a new session and run the same program again. The file should be
 locked for writes; the second program is supposed to terminate with a
 "Permission denied" error, but instead, displays "Path/file access
 error."

 Code Example
 ------------

 OPEN "TESTFILE" FOR APPEND LOCK WRITE AS #1
 PRINT #1, "Hello"
 WHILE INKEY <> "q": WEND


 371. "Bad Record Number" Using Network Printer in OS/2, LANMAN 2.00

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified:  5-DEC-1990    ArticleIdent: Q67313

 When the DOS device "LPT1" or "LPT2" is OPENed to print over a
 Microsoft LANMAN version 2.00 network printer under OS/2, the error
 "Bad record number in line <nn> in module <module name> at address
 xxxx:xxxx" will occur when the device is closed. This error does not
 occur when printing to a local printer or to a LANMAN 2.00 network
 printer under DOS.

 Microsoft has confirmed this problem in programs compiled in Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS OS/2 and in Microsoft
 BASIC PDS (Professional Development System) versions 7.00 and 7.10 for
 MS OS/2. Microsoft is researching this problem and will post new
 information here as it becomes available.

 The following code segment demonstrates the "Bad record number" error
 when compiled and run under OS/2 with logical device "LPT1:" connected
 to a Microsoft LANMAN 2.00 network.

 Note: The code example will compile and run without error when run
 under DOS or if the logical device LPT1: refers to a local printer.

    OPEN "LPT1" FOR OUTPUT AS #1
    PRINT "Hello world"
    CLOSE #1

 To work around the problem, open the BASIC logical device "LPTn:"
 instead of the DOS "LPTn" device. The following code example will
 compile and run without error when run under DOS or OS/2, and printing
 to a local or network printer device:

    OPEN "LPT1:" FOR OUTPUT AS #1
    PRINT "Hello world"
    CLOSE #1

 Note: There is a problem when the BASIC device "LPTn:" is opened
 across two CHAINed programs. For more information, please query on the
 following words:

    CHAIN and device and I/O and LPT1 and LPRINT


 372. BC.EXE "Out of Memory" with Numeric Array Elements and SWAP

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist7.00 buglist7.10
 Last Modified:  5-DEC-1990    ArticleIdent: Q67314

 Compiling the following code segment with the BC.EXE compiler gives a
 "BC : Out of memory" error. The problem will occur for any simple
 mathematical operation (addition, subtraction, multiplication, or
 division) performed on the two static-array elements appearing in the
 assignment statement below. The problem does not occur in the QBX.EXE
 environment.

    DIM d#(1), e#(1), b!(1), c&(1)
    n = 1
    a% = b!(n) + c&(n)
    SWAP d#(n), e#(n)

 Microsoft has confirmed this to be a problem in BC.EXE in Microsoft
 BASIC Profession Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 You can work around the problem in any one of the following ways:

 1. Compile the program with the BC /D option to produce debug code.

 2. Use the CINT or CLNG function to convert the first array element in
    the mathematical expression to an integer type. The example above
    will compile without error if the assignment statement is changed
    as follows:

       a%= CINT(b!(n)) + c&(n)

 3. Save one of the variables being swapped to a temporary variable and
    use the temporary variable as an argument to the SWAP statement.
    The example above will compile without error if the SWAP statement
    is changed as follows:

       f# = d#(n)
       SWAP f#,e#(n)

 4. Use dynamic arrays (instead of static arrays) by adding
    REM $DYNAMIC to the top of the program.

 The problem occurs when all of the following conditions occur
 simultaneously (as shown in the first code example):

 1. An integer variable (INTEGER or LONG type) is assigned to the
    addition, multiplication, division, or subtraction of two numeric
    static-array elements.

 2. The first array element in the mathematical expression is of type
    SINGLE.

 3. The second array element in the mathematical expression is of type
    LONG.

 4. A SWAP of two array elements of any numeric type occurs after the
    assignment statement.

 5. The code is compiled using BC.EXE


 373. In QBX 7.10, F8 Step then Editing Active Statement Can Fail

 Product Version(s): 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.10
 Last Modified:  5-DEC-1990    ArticleIdent: Q67363

 When you single step (F8) through a program in the QBX.EXE version
 7.10 environment, editing the active (highlighted) statement can give
 unexpected results under certain circumstances. For example, if you
 attempt to split the active line in two by pressing the ENTER key, the
 next line may duplicate the current line. Sometimes the first line
 splits correctly but the next line becomes an altered version of the
 first line. Note that pressing "ALT+BACKSPACE" will usually undo the
 editing problem.

 Microsoft has confirmed this to be a problem with the QuickBASIC
 extended environment (QBX.EXE) that comes with Microsoft BASIC
 Professional Development System (PDS) version 7.10 for MS-DOS. We are
 researching this problem and will post new information here as it
 becomes available.

 This problem can occur on any statement where a variable is first
 declared, including the following statements: COMMON SHARED, DIM
 SHARED, REDIM, FOR, WHILE, DO...LOOP, or IF. When creating the problem
 with FOR, WHILE, DO...LOOP, or IF statements, you must actually try
 and divide the BASIC reserved word (for example, put the cursor in the
 middle of WHILE and press ENTER).

 To reproduce the problem, perform the following steps:

 1. Add the line below to the beginning of an empty program window:

       COMMON SHARED A, B

 2. Make the line the current executing line by single stepping with
    the F8 key until that line is highlighted.

 3. Now put the cursor anywhere before the "B" (for example, put the
    cursor on the "A") and press ENTER.

 4. A dialog box will appear saying "You will have to restart your
    program after this edit. Proceed anyway?" Press ENTER.

 5. Your source code will now resemble the following:

       COMMON SHARED A
       COMMON SHARED A, B

 To reproduce the problem with an assignment statement, enter the
 single BASIC line of code "x = a + b + c" and follow the steps above.
 When the line is highlighted, place the cursor on the variable "a" and
 press ENTER. This will not duplicate the current line but will cause
 the "+" to be deleted between a and b.


 374. QBX.EXE "EMS Corrupt" Using Expanded Memory in Windows 3.00

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-JAN-1991    ArticleIdent: Q67364

 When trying to utilize expanded memory, QBX.EXE (from Microsoft BASIC
 PDS versions 7.00 and 7.10) will have problems running under Microsoft
 Windows version 3.00 enhanced mode if Windows 3.00 has not set the
 starting page-frame address for expanded memory. QBX.EXE will try to
 use expanded memory if it is available, unless the QBX /E:0 switch is
 used.

 For QBX.EXE to successfully use expanded memory, Windows needs to
 create a consecutive 64K page-frame area in the High Memory Area
 (HMA), C000 hex to EFFF hex. If this memory area is not available for
 use by QBX.EXE 7.00, QBX.EXE will give an "EMS corrupt" error message
 and return to the DOS window, or if run from an application icon, will
 return back to the Program Manager. QBX.EXE version 7.10 will fail to
 make use of expanded memory and will not give an error message.

 If QBX.EXE fails when trying to use expanded memory, the EMMExclude
 setting in the [386enh] section of your Windows SYSTEM.INI file may
 need to be changed. EMMExclude is needed to keep Windows from using
 the same memory as another device that Windows cannot detect, such as
 a network card, video card, or parts of BIOS for certain machines. To
 enable QBX.EXE to work correctly, use the EMMExclude setting for the
 minimum amount of memory, and try to move the address space used by
 network and video cards to consecutive addresses starting at C000 hex.
 Also, if there is an area of memory that you know is NOT in use, then
 the EMMInclude or EMMPageFrame setting can be used to tell Windows
 that this area is available for use.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 (For more information, see the application note "Memory Management
 Under Windows 3.00," which is available from the Windows Applications
 Support Group at Microsoft Product Support Services.)

 Windows 3.00 attempts to determine what other devices are using the
 address space C000 to EFFF hex before creating the page frame area.
 Sometimes Windows will not detect that another process is using a
 section of memory and will try to use that section of memory for
 itself. The following are symptoms that this may be happening:
 hanging; Windows immediately returning to the MS-DOS prompt after
 displaying the Windows logo; or video problems such as garbage on the
 screen or flashing colors. In this situation, the command EMMExclude
 is used to prevent Windows from conflicting with other devices.

 Also, in some situations Windows will sometimes mistakenly think that
 a section of memory is in use and will avoid creating the page frame
 area there. To make sure that Windows uses an area of memory, you can
 use the EMMInclude command. Also, the EMMPageFrame command can be used
 to specify the specific area for the expanded memory page frame.
 EMMPageFrame will only work if Windows thinks that area is available.

 The following memory map shows the common usage of each area of memory
 from A000 to EFFF hex:

 Address    Used By                  Common Usage
 -------    -------                  ------------

 A000-BFFF  Display adapter reserve  EGA and VGA use all, CGA and MDA
                                     use a portion.

 C000-DFFF  ROM expansion            Used for I/O channel BIOS.

                                     C000-C3FF: EGA BIOS.
                                     C000-DFFF: many VGA cards use the
                                     whole range.
                                     C600-C63F: PGA communications area.
                                     C800-CBFF: hard disk BIOS.
                                     D000-DFFF: unused.
                                     C800-DFFF: commonly used by
                                     network cards.

 E000-EFFF  Expansion of system      Used by many ATs and PS/2s but
            ROM                      not used by other computers.

 For example, if you have video card A, which requires address space
 C000 to C7FF hex, and network card B, which requires C800 to D7FF hex,
 use the following EMMExclude command:

    EMMExclude=C000-D7FF

 This should provide enough space for QBX.EXE to use expanded memory.

 If it is not possible to move the required HMA for the given
 applications to consecutive addresses, then you can give multiple
 EMMExclude commands. For example, if you have an IBM PS/2 that uses
 E000-EFFF hex for parts of its BIOS area that cannot be moved, and a
 network card that can use addresses C000 to CFFF or C7FF to D7FF, then
 you need to use the following EMMExclude commands:

    [386enh]
    EMMExclude= C000-CFFF
    EMMExclude= E000-EFFF

 The lower memory area for the network card should be chosen to limit
 memory fragmentation in the High Memory Area. If you know you are not
 using the area C800-DFFF and Windows still does not create a page
 swapping area, then use the EMMInclude command to force Windows to try
 and use that area of memory. The EMMInclude command overrides the
 EMMExclude command for the parts of memory that the two statements may
 have in common:

    [386enh]
    EMMInclude= C800-DFFF
    EMMExclude= C000-CFFF
    EMMExclude= E000-EFFF

 Instead of using the EMMInclude command, the EMMPageFrame command can
 be used to tell Windows exactly where to start the page frame area if
 Windows believes that the specified area is available for use:

    [386enh]
    EMMPageFrame=C800
    EMMExclude= C000-CFFF
    EMMExclude= E000-EFFF

 Making Windows create a page swapping area may not be possible with
 some machine configurations. If the above clues do not help create a
 page frame area, then the Windows Applications Unit of Microsoft
 Product Support Services may have more information about your
 particular machine configuration and may be able to help you further.

 Code Example
 ------------

 The following BASIC PDS program will tell you at what address, if any,
 a page frame has been set. By compiling as shown and running the
 program in the Windows DOS box, you can determine if and where Windows
 is creating the expanded memory page frame.

 To make a stand-alone executable program out of the following code
 sample, perform the following steps from the DOS prompt:

    BC emspage.bas /o;
    LINK emspage.obj,,,QBX.LIB;

 'This is the sample program emspage.bas
 REM $INCLUDE: 'QBX.BI'
 DIM inregs AS regtype
 DIM outregs AS regtype
 inregs.ax = &H4100
 CALL interrupt(&H67, inregs, outregs)
 IF (outregs.ax AND &HFF00) = 0 THEN
    PRINT "PAGE FRAME ADDRESS: "; HEX$(outregs.bx)
 ELSE
    PRINT "PAGE FRAME ADDRESS: NONE "
 END IF


 375. Recursive CALL in 7.0 .EXE Forgets Parent's Passed Near String

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S901116-127 buglist7.00 fixlist7.10
 Last Modified:  5-DEC-1990    ArticleIdent: Q67372

 When the first layer (first call) of a recursive procedure passes a
 near string to the next layer of recursion, the value of the initial
 string passed by the parent recursive layer is forgotten within the
 parent SUB after returning from subsequent recursive layers of the
 routine. This problem does not occur if you compile with far strings
 (BC /Fs).

 This problem applies to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and MS OS/2. This problem has
 been corrected in BASIC PDS version 7.10.

 The code below demonstrates the problem when passing a near string in
 a recursive subprogram CALL. You can work around the problem by
 compiling with far strings.

 CLS
 CALL RecCall("A")
 END

 SUB RecCall (Text AS STRING)
    PRINT Text; "<"
    IF Text <> "B" THEN
       CALL RecCall (CHR$(ASC(Text) + 1))
       'Could use CALL ReCall("B") with same problem
    END IF
    PRINT Text; "<"
 END SUB

    Compiled with   Interpreted in QBX.EXE
    Near String     or Compiled with Far
    (Problem)       String Option (No Problem)
    -------------   --------------------------
       >A               >A
       >B               >B
       >B               >B
       >                >A


 376. CIRCLE(x,y),rad,,-0.1,0 Draws Only the Radius in BASIC

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | B_MQuickB B_QuickBas
 Last Modified: 17-JAN-1991    ArticleIdent: Q67374

 This article describes a problem with the CIRCLE statement. The CIRCLE
 command takes the following parameters:

    CIRCLE[STEP](x,y),radius!,,start!,stop!

 If you specify start! and stop!, with start! slightly larger than
 stop!, then the CIRCLE command should draw an almost complete circle.
 However, if the difference between start! and stop! is very small,
 CIRCLE may draw only a point or radius, instead of an almost complete
 circle. This problem happens in both the interpreter environment and
 in compiled programs.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 version 1.00 (buglist1.00) for Apple Macintosh systems; in Microsoft
 QuickBASIC versions 4.00, 4.00b, and 4.50 (buglist4.00, buglist4.00b,
 buglist4.50) for MS-DOS; in Microsoft BASIC Compiler versions 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2; and in
 Microsoft BASIC Professional System (PDS) versions 7.00 and 7.10
 (buglist7.00, buglist7.10) for MS-DOS and OS/2. We are researching
 this problem and will post new information here as it becomes
 available.

 Changing the size of radius changes the requirement for the distance
 between start! and stop! necessary to reproduce the problem. When
 start! is near zero, leaving off the stop! will produce different
 results than if stop! is specified. Use the following code examples
 to reproduce the problems described above.

 Code Examples
 -------------

 ' When start! or stop! is negative, CIRCLE draws a radius and
 ' treats the angle as positive. Without the negative sign, no
 ' radius is drawn.
 '
 SCREEN 12  'Problem occurs in any graphics screen mode.
 10 CIRCLE (50, 50), 50, , -.01         'Works correctly.
 20 CIRCLE (50, 150), 50, , -.01, 0     'Should be same as line
                                        '10 but draws only the radius.
 30 CIRCLE (50, 250), 50, , -.011, 0    'Slightly larger difference
                                        'from start & stop works.
 40 CIRCLE (420, 240), 200, , -.01, 0   'This works with same end/start
                                        'as line 20 but has larger
                                        'radius

 On the Apple Macintosh, use the following code:

 CIRCLE (50, 50) 10, ,-0.001, 0


 377. OPEN "SCRN:" or "CONS:" Wrong Output in QBX.EXE When Step (F8)

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901109-37 buglist7.00 buglist7.10
 Last Modified:  5-DEC-1990    ArticleIdent: Q67378

 When you single step (F8) through a program that redirects screen
 output to either of the DOS standard devices "SCRN:" or "CONS:", the
 output will incorrectly flash momentarily on the QBX.EXE programming
 environment, instead of going to the output window.

 This problem occurs in the editing environment (QBX.EXE) of Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10.
 This problem does not occur in the Microsoft QuickBASIC environment
 (QB.EXE) shipped with QuickBASIC version 4.00, 4.00b, and 4.50.
 Microsoft is researching this problem and will post new information
 here as it becomes available.

 The following short program demonstrates the problem:

 OPEN "SCRN:" FOR OUTPUT AS #1   ' "CONS:" also shows problem.
 FOR i = 1 TO 10
         PRINT #1, i
 NEXT i

 Single step through this program in the QBX.EXE 7.00 or 7.10
 environment by repeatedly pressing the F8 key. The output will
 momentarily flash on the environment screen; no text will be displayed
 on the output screen. Note that just running the program (F5) will
 correctly print to the output screen.


 378. "BASIC 7.0: Programmer's Guide" Correction for ISAMCVT.EXE

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S900918-59
 Last Modified:  5-DEC-1990    ArticleIdent: Q67449

 The ISAMCVT utility shipped with Microsoft BASIC PDS (Professional
 Development System) versions 7.00 and 7.10 requires a "specfile" when
 converting MS/ISAM files (created by IBM BASIC Compiler version 2.00)
 that have been rebuilt without a data dictionary. Page 391 of the
 "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10
 omits the "specfile" field in its example of the ISAMCVT.EXE
 command-line syntax, when in fact, the "specfile" may be necessary if
 no data dictionary is present in the MS/ISAM file.

 Page 392 of the same manual incorrectly states that the "specfile" is
 required for converting MS/ISAM files; it should say that the
 "specfile" is required only when no data dictionary is present in the
 file. MS/ISAM database files usually contain a data dictionary, and
 only if a database is rebuilt without a data dictionary is "specfile"
 required. Therefore, the command-line syntaxes on page 391 should be
 changed as follows:

 For db/LIB
 ----------

    ISAMCVT /D filename tablename databasename

 For MS/ISAM
 -----------

    ISAMCVT /M filename tablename databasename [specfile]

 For Btrieve
 -----------

    ISAMCVT /B filename tablename databasename specfile


 379. Use hmamin Not tsrmin on Page 86 "BASIC 7.1: Getting Started"

 Product Version(s): 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901031-88 docerr
 Last Modified: 12-DEC-1990    ArticleIdent: Q67589

 On page 86 of the "Microsoft BASIC 7.1: Getting Started" manual, the
 first sentence of the second paragraph under the "Extended Memory"
 section has a typographical error. The word "tsrmin" should be changed
 to read "hmamin".

 The corrected sentence should read as follows:

    When using the HIMEM.SYS device driver, you should set hmamin to 63
    (64512 bytes) to ensure that QBX has access to the high-memory
    area.

 This information applies to Microsoft Professional Development System
 (PDS) version 7.10 for MS-DOS.


 380. UI Toolbox: "Subscript Out of Range" or Hang on WindowDo Call

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist7.00 buglist7.10
 Last Modified: 14-DEC-1990    ArticleIdent: Q67697

 If more than 20 buttons and edit fields are opened simultaneously
 within a single window, a "Subscript out of range" error will occur on
 a call to the SUB procedure WindowDo at run time. In some instances, a
 call to WindowDo may lead to a "String space corrupt" error message or
 cause the computer to hang.

 Microsoft has confirmed this to be a problem with the User Interface
 (UI) Toolbox provided with Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10. The correction for this problem
 is provided further below.

 This information applies to BASIC PDS versions 7.00 and 7.10 for
 MS-DOS.

 To avoid the problem, change the default value of the constant
 MAXHOTSPOT, which appears in the file, GENERAL.BI. Two other constants
 MAXBUTTON and MAXEDITFIELD, which appear in GENERAL.BI, set the
 maximum number of buttons and edit fields allowed. The value of
 MAXHOTSPOT should be changed from its current setting of 20 to the sum
 of these two constants. The default setting for MAXBUTTON is 50, and
 the default setting for MAXEDITFIELD is 20. MAXHOTSPOT should be
 changed to 70.

 If a call to the SUB program WindowDo leads to a computer hang or a
 "String space corrupt" error message, Microsoft suggests changing the
 constants as described in the above paragraph and rebuilding the UI
 Toolbox default libraries, UITBEFR.LIB and UITBEFR.QLB. A computer
 hang or "String space corrupt" error message usually occurs when the
 default libraries have been modified and the modules that make up the
 UI Toolbox have not been compiled with the /D option. The /D option
 enforces array bounds checking on arrays. Using the /D compile option
 will help to avoid a computer hang or a "String space corrupt" error
 message at run time.

 The following assumes that you are using the default LINK library
 UITBEFR.LIB and the Quick library UITBEFR.QLB built during set up of
 BASIC PDS.

 Once the modifications to GENERAL.BI have been made, update the
 library UITBEFR.LIB and re-create the default Quick library
 UITBEFR.QLB. Below are the steps necessary to update the .LIB file and
 re-create the .QLB file.

 Because the files GENERAL.BAS, MENU.BAS, MOUSE.BAS, and WINDOW.BAS all
 require GENERAL.BI, they must be recompiled from DOS as follows:

         BC GENERAL.BAS /FS/X/D;
         BC MENU.BAS /FS/X/D;
         BC MOUSE.BAS /FS/X/D;
         BC WINDOW.BAS /FS/X/D;

 Enter the following command line from DOS to modify the library,
 UITBEFR.LIB:

         LIB UITBEFR.LIB-+GENERAL.OBJ-+MENU.OBJ-+MOUSE.OBJ-+WINDOW.OBJ

 Enter the following from DOS to re-create the Quick library,
 UITBEFR.QLB:

         LINK /Q UITBEFR.LIB,,,QBXQLB.LIB;


 381. VAL() Fails When BASIC 7.10 NOFLTIN.OBJ Stub File Is Linked

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist7.10
 Last Modified:  2-JAN-1991    ArticleIdent: Q67886

 Any argument passed to the VAL() function makes VAL() return zero or
 incorrect results in a program linked with the NOFLTIN.OBJ file from
 BASIC PDS version 7.10.

 Microsoft has confirmed this to be a problem with Microsoft BASIC
 Professional System (PDS) version 7.10 for MS-DOS and MS OS/2. We are
 researching this problem and will post new information here as it
 becomes available. (This problem does not occur in BASIC PDS 7.00.)

 The code example below prints an incorrect result for VAL() at run
 time when linked with the BASIC 7.10 stub file NOFLTIN.OBJ.

 ' File name: STUB.BAS
 d$ = "5"
 PRINT VAL(D$)   ' Is supposed to print "5".

 Compile and link with the following command lines:

    BC STUB.BAS /O;
    LINK /NOE STUB.OBJ+NOFLTIN.OBJ;


 382. "Illegal Function Call," Negative Number to Fractional Power

 Product Version(s): 1.00a 1.00b | 6.00 6.00b 7.00 7.10
 Operating System:   MACINTOSH   | MS-DOS
 Flags: ENDUSER | B_QuickBas B_GWBasicI
 Last Modified:  2-JAN-1991    ArticleIdent: Q67887

 Raising a negative number to a fractional power gives an "Illegal
 function call" in BASIC because the result will be a complex number,
 which is not supported in BASIC. (A complex number is of the form
 x+y*i where x is the real component and y is the imaginary component;
 i is the square root of -1.)

 Note: -5^(-Y) is not the same as X^(-Y) when X = -5 because -5^(-Y) is
 actually parsed as -(5^(-Y)). In other words, the exponentiation
 operator (^) has greater precedence than the subtraction (-) operator.

 This information applies to most versions of Microsoft BASIC,
 including the following:

 1. Microsoft QuickBASIC version 1.00 for the Apple Macintosh.
 2. Microsoft BASIC Compiler version 1.00 for the Apple Macintosh.
 3. Microsoft BASIC Interpreter versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh.
 4. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, 4.50 for MS-DOS.
 5. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS.
 6. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS.
 7. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2.
 8. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, 3.23 for
    MS-DOS.

 The first PRINT statement below gives "Illegal function call." Many
 programmers will try debugging this code by substituting an actual
 constant for X, and the PRINT will seem to give the correct result.
 However, upon close examination of the precedence of operators, it
 will be apparent that the exponential symbol takes precedence over the
 minus sign. The expression 5^(-1/6) is parsed first and then the
 negation of this expression is performed. The third PRINT demonstrates
 what is actually happening in the first PRINT statement:

 X = -5
 PRINT X ^ (-1 / 6)       ' generates "Illegal function call"
 PRINT -5 ^ (-1 / 6)      ' same as PRINT -(5 ^ (-1 / 6)); no error
 PRINT (-5) ^ (-1 / 6)    ' generates "Illegal function call"

 To avoid the "Illegal function call" message, raise the absolute value
 (ABS) of X to the fractional power. If you do this when X is a
 negative number, please remember that you must multiply by i (the
 square root of -1) to get the true mathematical result. Because the
 square root of -1 cannot be represented in BASIC, you must keep track
 of imaginary number results yourself using a flag variable or warning
 message, for example:

    X=-5
    PRINT ABS(X) ^ (-1 / 6)
    IF SGN(X) < 0 THEN
       PRINT "Warning: the resulting root is an imaginary number. This"
       PRINT "root should be multiplied by i, the square root of -1."
    END IF


 383. LOCK May Fail to Properly Return Error After CHAIN Under OS/2

 Product Version(s): 7.00 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S901205-16 buglist7.00 buglist7.10
 Last Modified:  9-JAN-1991    ArticleIdent: Q68021

 Under MS OS/2, the following program demonstrates how a LOCK statement
 can fail to properly give a "Permission Denied" error for a locked
 record in a file kept open across a CHAIN. This problem does not occur
 under MS-DOS.

 Microsoft has confirmed this to be a problem with Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for MS
 OS/2. We are researching this problem and will post new information
 here as it becomes available.

 Code Samples
 ------------

 TEST01.BAS
 ----------

 10 ON ERROR GOTO 70
 20 OPEN "pippo" FOR RANDOM ACCESS READ WRITE SHARED AS #1 LEN=128
 30 LOCK 1, 1
 40 CHAIN "TEST02"
 70 PRINT ERR; ERL
 80 END

 TEST02.BAS
 ----------

 10 ON ERROR GOTO 70
 20 LOCK 1, 1
 30 END
 70 PRINT ERR; ERL
 80 END

 Compile and link the above programs as follows:

   BC /X/LP test01;
   LINK test01;
   BC /X/LP test02;
   LINK test02;

 Under MS-DOS, the second (CHAINed) program correctly returns a
 "Permission Denied" error (error code 70) for the LOCK statement;
 however, under OS/2, this program fails to give an error.


 384. BC "Internal Error" with Array of TYPE Using Array of STRING*1

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901222-1 buglist7.00 buglist7.10
 Last Modified:  9-JAN-1991    ArticleIdent: Q68023

 The following code example demonstrates a problem using an array of
 user-defined TYPE variables that contain an array of fixed-length
 strings of length one. The BC.EXE compiler incorrectly gives the
 message "BC : Internal Error near XXXX" when compiling this example.
 The QBX.EXE environment compiles the same example without error.

 This problem applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2. We are
 researching this problem and will post new information here as it
 becomes available.

 Code Sample
 -----------

 '$DYNAMIC
 TYPE rectype
   a(10) AS STRING * 1
 END TYPE
 DIM b(10) AS rectype
 byte% = 0
 10 b(1).a(byte%) = "a"

 Save the file as TEST.BAS and then attempt to compile with BC.EXE
 using the following command line:

    BC TEST;

 The compiler will issue the "Internal Error" message.

 The error occurs only if ALL the following conditions are met:

 1. The array b() is dynamic.

 2. The second array element in line 10 is referenced with a
    variable.

 3. The fixed-length string in the TYPE is of length one (STRING * 1).

 4. The program is compiled without run-time error checking (without
    the BC /D option).

 To work around this problem, just counteract any one of the above
 conditions, using one of the following four suggested workarounds:

 1. Make the array b() static. For example, if you add the '$STATIC
    metacommand before the DIM as follows, the program will compile
    correctly:

       '$STATIC
       DIM b(10) AS rectype
       '$DYNAMIC

 2. Reference the second element in line 10 with a constant instead of
    a variable.

 3. Use STRING * 2 or a longer length.

 4. Compile with the BC /D option.


 385. BC.EXE "AS Missing" in TYPE Using Space Between Array and ()

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901121-21 buglist7.00 buglist7.10
 Last Modified:  9-JAN-1991    ArticleIdent: Q68024

 The BC.EXE compiler gives the error "AS Missing" on an array in a TYPE
 statement if you mistakenly leave a space between the last letter in
 the array name and the left parenthesis. (This misleading error
 message will occur only if you create the program in an editor other
 than QBX.EXE. The problem doesn't occur when you save the program in
 QBX.EXE because QBX.EXE automatically removes the offending space
 character.)

 Microsoft has confirmed this to be a problem with the Microsoft BASIC
 Professional Development System versions 7.00 and 7.10 for MS-DOS and
 MS OS/2. We are researching this problem and will new information here
 as it becomes available.

 Workaround
 ----------

 To work around the problem in any editor other than QBX.EXE, remove
 the offending space character.

 To reproduce this problem, enter the following code example into any
 text editor other than QBX.EXE. (Note that if you load this program
 into the QBX.EXE environment, the space between the array name and the
 "(" character will automatically be removed.)

 TYPE t1
   s (1 TO 45) AS SINGLE
 END TYPE

 The BC.EXE compiler produces the following output when compiling this
 code:

 Microsoft (R) BASIC Compiler Version 7.10
 Copyright (C) Microsoft Corporation 1982-1990. All rights reserved.
  0030   0006       s (1 TO 45)  AS SINGLE
                      ^ AS missing
                      ^ Skipping forward to END TYPE statement

 45962 Bytes Available
 45853 Bytes Free

     0 Warning Error(s)
     2 Severe  Error(s)


 386. "Feature Removed" Using WIDTH "LPT1:",wdth% and BC /Fs in 7.00

 Product Version(s): 7.00   | 7.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S901220-9 buglist7.00 fixlist7.10
 Last Modified:  9-JAN-1991    ArticleIdent: Q68025

 Compiled with the far strings (BC /Fs) option, the following statement
 incorrectly gives the error message "Feature removed":

    WIDTH "LPT1:",137

 This statement works correctly within the QBX.EXE environment.

 Microsoft has confirmed this to be a problem in BASIC Professional
 System (PDS) versions 7.00 for MS-DOS. This problem was corrected in
 BASIC PDS version 7.10.

 Enter the following program and name it SAMPLE.BAS:

    wdth% = 137
    WIDTH "LPT1:",wdth%

 Compile the program with the following options:

    BC SAMPLE.BAS /D/O/Fs/Lr/FPi/T/C:512;
    LINK SAMPLE.OBJ;

 Now, run SAMPLE.EXE to demonstrate the error message "Feature removed
 in line No line number in module <name>".

 To work around the problem, compile without the far strings option
 (without /Fs), or upgrade to version 7.10, or change the program to
 read as follows:

    WIDTH LPRINT wdth%


 387. QBX.EXE, PWB.EXE Help Files "Not Found," Conflict Under OS/2

 Product Version(s): 7.10
 Operating System:   OS/2
 Flags: ENDUSER | SR# S901116-141 S_PWB
 Last Modified:  9-JAN-1991    ArticleIdent: Q68027

 If you are running under OS/2 and you have QuickBASIC Extended
 (QBX.EXE from Microsoft BASIC Professional Development System) version
 7.10 running in the DOS box, as well as Programmer's WorkBench
 (PWB.EXE) in an OS/2 window, you may be unable to access BASIC help
 files from QBX.EXE.

 The error message

    File <HelpFile>.HLP not found -
    Correct your help path in options + set paths

 will appear in QBX.EXE when you attempt to use the online help if
 PWB.EXE is already using the same help files. Ending the PWB session
 will allow QBX.EXE to use the BASIC help files.

 Note: PWB does not need to have open the same help screen as QBX.EXE
 for this error to occur.

 Microsoft has confirmed this to be a problem in BASIC Professional
 Development System (PDS) version 7.10 for MS OS/2. A workaround is
 given below.

 If you have PWB configured to use the BASIC help files, then while
 running it in protected mode, the BASIC help files cannot be accessed
 from QBX.EXE. It does not matter in what order you start the programs;
 PWB.EXE can access the help files, and QBX.EXE cannot.

 The following error message is misleading:

    File <HelpFile>.HLP not found - ...

 In the test performed, the help file existed, the HELPFILES
 environment variable was set correctly, and the help files path under
 the Options menu within QBX.EXE was set correctly.

 Workaround
 ----------

 Make two copies of the help files on your hard drive and set the help
 files path in PWB.EXE and QBX.EXE, each to a different set of help
 files. Make sure that the help files are not in the same directory as
 either PWB.EXE or QBX.EXE. In this situation, the two programs will
 not conflict with one another.


 388. 7.10 "Subscript Out of Range," WindowDo with No Open Windows

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901228-57
 Last Modified: 17-JAN-1991    ArticleIdent: Q68123

 If a WindowDo statement is executed before any windows are opened, a
 "Subscript out of range" error will occur. This article explains why
 the error happens and gives two ways of correcting the error.

 This information applies to the User Interface (UI) ToolBox provided
 with Microsoft BASIC Professional Development System (PDS) versions
 7.00 and 7.10 for MS-DOS.

 The problem is caused by WindowInit incorrectly initializing the
 variable GloStorage.currMenu to -1 instead of 0 (zero). WindowDo
 checks to see if currMenu is 0 (zero) to determine if there are no
 open windows, and WindowDo generates the error when it tries to access
 window number -1.

 To work around this problem, do one of the following:

 1. Open a window and then immediately close it. This will set currMenu
    back to 0 (zero). For example:

       WindowInit
       WindowOpen 1,6,5,12,25,0,7,0,7,15,FALSE,FALSE,FALSE,FALSE,0,""
       WindowClose 1
       WindowDo 0,0

 2. To correct the problem permanently, modify WINDOW.BAS:

    a. Load the WINDOW.BAS module into QBX.EXE.

    b. Push F2 to view the subprograms and then move to WindowInit.

    c. Locate the line that reads "GloStorage.currMenu = -1", and change
       it to "GloStorage.currMenu = 0".

    d. Save the new copy of WINDOW.BAS. Then follow the instructions at
       the beginning of GENERAL.BAS to create a new LINK library (.LIB)
       and Quick library (.QLB).

 Code Sample
 -----------

 When the following program is run in the QBX.EXE environment, it will
 generate a "Subscript out of range in Quick library module: WINDOW"
 error.

 ' QBX must be started with "QBX /L UITBEFR" to load the UI ToolBox
 ' Quick library

 '$INCLUDE: 'general.bi'
 '$INCLUDE: 'mouse.bi'
 '$INCLUDE: 'menu.bi'
 '$INCLUDE: 'window.bi'
 COMMON SHARED /uitools/ GloMenu           AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle()        AS MenuTitleType
 COMMON SHARED /uitools/ GloItem()         AS MenuItemType
 COMMON SHARED /uitools/ GloWindow()       AS windowType
 COMMON SHARED /uitools/ GloButton()       AS buttonType
 COMMON SHARED /uitools/ GloEdit()         AS EditFieldType
 COMMON SHARED /uitools/ GloStorage        AS WindowStorageType
 COMMON SHARED /uitools/ GloWindowStack()  AS INTEGER
 COMMON SHARED /uitools/ GloBuffer$()
 DIM GloTitle(MAXMENU)           AS MenuTitleType
 DIM GloItem(MAXMENU, MAXITEM)   AS MenuItemType
 DIM GloWindow(MAXWINDOW)        AS windowType
 DIM GloButton(MAXBUTTON)        AS buttonType
 DIM GloEdit(MAXEDITFIELD)       AS EditFieldType
 DIM GloWindowStack(MAXWINDOW)   AS INTEGER
 DIM GloBuffer$(MAXWINDOW + 1, 2)
 WindowInit
 WindowDo 0,0
 END


 389. BASIC 7.10 LINK "L4051 Cannot Find Library" If Using 7.00 .LIB

 Product Version(s): 7.10   | 7.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# S901113-69 LINK.EXE 4051
 Last Modified: 15-JAN-1991    ArticleIdent: Q68158

 If you get the linker warning message "L4051 : BCL70xxx.LIB : cannot
 find library" while linking a program in BASIC PDS version 7.10, the
 problem may be that you are linking to a .LIB library you created with
 BASIC PDS 7.00. This will happen even if BASIC PDS version 7.00 has
 been deleted from your hard disk. If you created your own .LIB library
 in 7.00 and then link it to your BASIC 7.10 module, then you will need
 to recompile the BASIC routines in the .LIB using BASIC version 7.10
 and rebuild the .LIB library (using the LIB.EXE Library Manager).

 The L4051 error can also occur because of an incorrectly set LIB path.
 Type "SET" at the DOS command line to be sure that the LIB environment
 variable points to the BASIC 7.10 libraries. You can set the LIB path
 (automatically at boot time) in your AUTOEXEC.BAT batch file as
 follows:

    SET LIB=C:\BC71\LIB

 This information applies to Microsoft BASIC Professional Development
 System (PDS) version 7.10 for MS-DOS and MS OS/2.

 To duplicate the "L4051 : cannot find library" warning, build a
 library from the following code using BASIC version 7.00:

 'test.bas
 'demo file built with BASIC PDS 7.00
 SUB Pds70sub
 print "this is from the library built with PDS 7.00"
 END SUB

 Compile and build the library as follows in BASIC version 7.00:

    BC /O /Fs test ;
    LIB mylib + test ;        [builds MYLIB.LIB]
    LINK /Q mylib.lib,mylib.qlb,,qbxqlb.lib ;    [links MYLIB.QLB]

 Then create a module to CALL the above SUBprogram Pds70sub from the
 library MYLIB:

 'main.bas
 'This module calls the SUBprogram in a library created with PDS 7.00
 print "this is the calling module"
 call pds70sub

 Compile and link as follows in BASIC version 7.10:

    BC /O /Fs main ;
    LINK main,,,BCL71EFR.LIB + MYLIB.LIB ;

 Now you should receive the warning message:

    LINK : warning L4051 : BCL70EFR.lib : cannot find library
    Enter new file spec:

 To correct the problem, recompile, relink, and rebuild the library
 MYLIB using BASIC PDS version 7.10.


 390. StringAssign of Zero-Length (Null) String Fails; BASIC 7.10

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901016-16 S_C S_QuickC
 Last Modified: 15-JAN-1991    ArticleIdent: Q68225

 There is no way to use the StringAssign routine to create a
 zero-length string. For example, the following gives unpredictable
 (bad) results, and should not be done:

    StringAssign(NULL,0,basicstring,0)
    // (The NULL pointer is defined in STDIO.H in Microsoft C.)

 This statement is NOT the same as the BASIC statement A$ = "". This
 article explains this limitation of the StringAssign routine, and
 gives the correct method to create a null BASIC string by using
 StringRelease.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The StringAssign routine lets you transfer far or near string data
 from one language's memory space to another, using the following C
 syntax:

    StringAssign(sourceaddress&,sourcelength%,destaddress&,destlength%)

 StringAssign expects to receive a far pointer (sourceaddress&) either
 to a valid BASIC string descriptor or to the beginning of some string
 text. If the length of the source string (sourcelength%) is 0 (zero),
 StringAssign assumes that sourceaddress& is a pointer to a valid BASIC
 string descriptor. StringAssign then dereferences the descriptor and
 assigns the value to the destaddress& supplied.

 Each programmer is responsible for making sure that the pointer passed
 to StringAssign is valid. StringAssign doesn't validate the pointers.
 Thus, to pass the NULL pointer is an error. If the address passed does
 not point to a string descriptor, then the results will be
 unpredictable.

 Note: Someone might want to do this to set a BASIC variable-length
 string to the empty or null string from some other language. The
 intention is to simulate the following line of BASIC code:

     A$ = ""

 To assign a null string, you can use the StringRelease routine.
 StringRelease isn't exactly the same as A$="", but it does result in a
 string descriptor that will be treated as a null string. It deletes
 the string data associated with the string descriptor and zeros the
 string descriptor. A string descriptor that contains 0 (zero) as the
 length and 0 (zero) as the offset is the same as an uninitialized
 string, which is treated as null. This method should work around the
 limitation of StringAssign described above.

 Code Example
 ------------

 The following is an example of this workaround in Microsoft C and
 BASIC. To compile and link the program, you can use the following
 compile and link lines:

    bc test1.bas /Fs /o /Zi ;
    cl /c /AL /Zi test2.c ;
    link /NOE /NOD /CO test1 test2,,,bcl71efr.LIB llibcer.lib;

 Note that the following program prompts you for input. If you input a
 string, then the C function will StringAssign the string. However, if
 you literally type "null" (with no quotation marks), then the function
 will use StringRelease to null the string.

 Test1.BAS -- BASIC Routine
 --------------------------

 DECLARE SUB cfunc CDECL (a$)
 CLS
 locate 10, 1
 print "Before call to cfunc"
 a$ = "This is a test"
 print "A$ = ", a$
 PRINT "Len A$: "; LEN(a$)
 print
 CALL cfunc(a$)    ' CALL the C function
 print "After call to cfunc"
 print "A$ = ", a$
 PRINT "Len A$: "; LEN(a$)
 print

 Test2.C -- C Routine
 --------------------

 #include <stdio.h>
 #include <stdlib.h>
 extern void far pascal StringAssign(char far *,int,char far *, int);
 extern void far pascal StringRelease(char far *);
 void cfunc(BasicString)
      char far * BasicString;
 {
     char name[80] ;
     char NullStr[] = "";
     printf("Input name[]: ");
     scanf("%s",name);
     if(stricmp(name,"null") == 0) {
       name[0] = '\x00'; // Set it to null
     }
     if ((name == NULL) | (name[0] == '\x00')) {
        StringRelease(BasicString);
     } else {
         StringAssign(name, strlen(name), BasicString,0);
     }
 }


 391. Can't Use LINK Overlays in a BASIC OS/2 Dual-Mode Application

 Product Version(s): 7.00 7.10 | 7.00 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S900920-70
 Last Modified: 29-JAN-1991    ArticleIdent: Q68236

 Dual-mode applications are programs that can run under both OS/2 and
 DOS. You can use the Microsoft BASIC PDS 7.00 or 7.10 to create a
 dual-mode application; however, you cannot use BASIC to create a
 dual-mode application that also uses LINKed overlays for the DOS part
 of the program.

 This information applies to Microsoft BASIC Professional Development
 System 7.00 and 7.10 for MS-DOS and MS OS/2.

 A dual-mode application is not the same as a bound application under
 OS/2. A dual-mode application is actually two programs, one DOS and
 one OS/2, that are "glued" together to form one executable file.

 Every OS/2 program, when linked, has the option to link-in a "stub"
 DOS program. Originally, the stub DOS program was meant to print an
 appropriate message when you attempt to run an OS/2 program under DOS.
 Usually the message is "This program cannot be run in DOS mode," or a
 similar message. You include this stub DOS program by putting the
 following line in the linker .DEF file when you link the OS/2 program
 (where DOSPROG.EXE is the name of your own DOS program):

    STUB 'DOSPROG.EXE'

 Originally, the only purpose of this stub file was to print this
 user-friendly message, and then exit back to DOS. Eventually,
 programmers began to let this "stub" program get larger and larger
 until it became a full-blown application that ran under DOS when you
 attempted to run the OS/2 program in DOS. (The user can't tell the
 difference.) Commercial applications, such as Microsoft Word version
 5.00, were created this way. Because dual-mode applications are
 literally two full applications glued together, they tend to be huge.

 This technique can be used with programs created with the Microsoft
 BASIC PDS product. However, one limitation of dual-mode applications
 is that the DOS portion cannot contain overlays. Attempting to run a
 dual-mode application, where the DOS portion was linked with overlays,
 will hang the machine.

 Illustration
 ------------

 The following compile and link lines create two dual-mode program
 examples, OS2OVL.EXE and OS2NOOVL.EXE. (Source code is not provided
 but you can write it easily). OS2OVL.EXE is an OS/2 program and
 includes a DOS stub program that uses overlays.

 WARNING: Running OS2OVL.EXE will hang your machine, requiring you to
 reboot.

 OS2NOOVL.EXE is an OS/2 program, with an identical DOS version of the
 program enclosed as its stub file. OS2NOOVL.EXE does not use overlays,
 and will run without problem under DOS or OS/2.

 To compile and link the hypothetical programs, use the following
 commands:

 bc dosprog.bas /Lr /o ;
 bc mod1.bas    /Lr /o ;
 bc mod2.bas    /Lr /o ;
 link dosprog mod1 mod2, dosnoovl.exe ;
 link dosprog (mod1) (mod2), dosovl.exe ;
 bc dosprog.bas /Lp /o ;
 bc mod1.bas    /Lp /o ;
 bc mod2.bas    /Lp /o ;
 link os2prog mod1 mod2, os2noovl.exe,,, os2noovl.def ;
 link os2prog mod1 mod2, os2ovl.exe ,,, os2ovl.def ;

 DOSPROG.BAS is a main program that calls subprograms contained in
 separate support modules, MOD1.BAS and MOD2.BAS.

 OS2NOOVL.DEF contains the following line:

    STUB 'DOSNOOVL.EXE'

 OS2OVL.DEF contains the following line:

    STUB 'DOSOVL.EXE'

 (A LINK.EXE .DEF file is a module definition file that BASIC can use
 when linking OS/2 protected-mode programs.)


 392. ISAM Files Cannot Be Opened by Multiple Networked Workstations

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S910107-151 docerr
 Last Modified: 16-JAN-1991    ArticleIdent: Q68339

 The note on page 336 of the "Microsoft BASIC 7.0: Programmer's Guide"
 for Microsoft BASIC PDS 7.00 and 7.10 incorrectly states that you can
 open an ISAM database for read-only by one BASIC process and then have
 another BASIC process open it for reading as well.

 If a database is already open, even if it is opened for read-only
 access, the ISAM engine will generate a "Permission denied" error when
 another process attempts to open the database. If the first process
 closes the file, then the second process can access it.

 This information apples to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS and 7.10 for MS OS/2.

 Note that "processes" refer to two separate programs or users
 attempting to access a file on a network server. However, this can
 also apply to two separate programs under multitasking, systems such
 as OS/2 or Microsoft Windows.

 For an in-depth explanation for why BASIC PDS 7.10 does not yet
 support multiuser ISAM, query on the following:

    why and BASIC and multiuser and ISAM


 393. WIDTH "CONS:" or "SCRN:" Uses Only 40 or 80 in BASIC 7.00/7.10

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901023-92 buglist7.00 buglist7.10 docerr
 Last Modified: 29-JAN-1991    ArticleIdent: Q68446

 In BASIC PDS 7.00 and 7.10, the WIDTH for the screen device is
 restricted to 40 or 80 characters across all the different WIDTH
 syntaxes.

 The WIDTH statement fails to set widths other than 40 or 80 for the
 "CONS:" device name in QuickBASIC 4.50 (buglist4.50) and BASIC PDS
 7.00 and 7.10. The WIDTH statement also fails to set widths other than
 40 or 80 for the "SCRN:" device name for BASIC PDS 7.00 and 7.10, but
 succeeds in QuickBASIC 4.50. (The problem occurs both in the
 environment and in a compiled .EXE program.) The documentation does
 not explicitly say what is expected for the WIDTH dev$,wid% syntax.

 This may be a design restriction. Microsoft is researching this
 problem and will post new information here as it becomes available.

 This information applies to QuickBASIC version 4.50 and to Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS.

 BASIC PDS 7.00 and 7.10 only lets you use WIDTH of 40 or 80 for the
 WIDTH dev$,wid% syntax when dev$ is the screen device name "CONS:" or
 "SCRN:". (This behavior actually matches the documented restriction
 for the separate WIDTH wid%,height% syntax for screen output.)

 The following code example demonstrates this behavior:

 Code Example
 ------------

 CLS
 WIDTH "scrn:", 11   ' Sets screen width to 11 characters.
 OPEN "scrn:" FOR OUTPUT AS #1                ' OK in 4.50, but
 PRINT #1, "123456789012345678901234567890"   ' WIDTH ignored in BASIC
 CLOSE                                        ' 7.x in .EXE and QBX.EXE
 OPEN "scrn:" FOR OUTPUT AS #2
 WIDTH #2, 11                                 ' OK in 4.50, but WIDTH
 PRINT #2, "123456789012345678901234567890"   ' ignored in BASIC 7.x
 CLOSE
 WIDTH "cons:", 11
 OPEN "cons:" FOR OUTPUT AS #3
 PRINT #3, "123456789012345678901234567890"  ' WIDTH ignored, 7.x, 4.50
 CLOSE
 OPEN "cons:" FOR OUTPUT AS #4
 WIDTH #4, 10
 PRINT #4, "123456789012345678901234567890"  ' WIDTH ignored, 7.x, 4.50
 CLOSE

 ' Note that the problem doesn't occur with the "LPT1:" device:
 WIDTH "lpt1:", 11   ' Sets printer width to 11 characters.
 OPEN "lpt1:" FOR OUTPUT AS #1
 PRINT #1, "123456789012345678901234567890"  ' Works find in all versions.
 CLOSE

 Reference:

 The following partial description of the WIDTH statement is taken from
 the QBX.EXE online help:

    WIDTH {#filenumber% | device$}, width%

 WIDTH {#filenumber% | device$}, width%
   The WIDTH #filenumber%, width% form:
     - Sets the line width of an output device already opened as a file
       (for example, LPT1: or CONS:).
     - The argument filenumber% is the number associated with the
       file in the OPEN statement.
     - The "#" character in front of filenumber% is not optional.
     - The width assignment takes place immediately.
   The WIDTH device$, width% form:
     - Sets to width% the line with of device$ (a device filename).
       The device should be a string expression (for example, "LPT1:").
     - The width assignment is deferred until the next OPEN statement
       affecting the device.
     - The assignment does not affect output for an already open file.


 394. ISAM Files Open at Once, "Too Many Files" Error 67, Correction

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 29-JAN-1991    ArticleIdent: Q68462

 Page 673 of the "Microsoft BASIC 7.0: Language Reference" (under the
 "Too many files" error in Appendix D) incorrectly states that ISAM is
 limited to opening 12 databases at once.

 This should be corrected to read as follows:

    At run time, the "Too many files" error may occur because:

    ISAM has a limit to the number of databases and tables that can be
    open at one time and your program has exceeded this limit.
    The maximum number of database files that you can have open at once
    is four. Also, the maximum number of tables that you can have
    open at once is 13 tables in one database file, or 10 tables in 2
    database files, or 7 tables in 3 database files, or 4 tables in 4
    database files.

 This information applies to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and 7.10 for MS OS/2.

 Reference:

 An ISAM database file in Microsoft BASIC Professional Development
 System (PDS) version 7.00 or 7.10 is created with the default
 extension .MDB and contains the physical data for each table plus the
 indexes used to define and point to the data.

 (This correct ISAM information is taken from page 388 of the
 "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10
 [Chapter 10, "Database Programming with ISAM"].)


 395. OutGText% Works Only on First Call If WINDOW Invoked; UI Font

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910114-77
 Last Modified: 29-JAN-1991    ArticleIdent: Q68588

 Using the OutGText% function more than once does not display the text
 in the same location if you have invoked the SCREEN command prior to
 invoking OutGText%. GTextWindow must be called before any OutGText%
 commands.

 This information applies to the User Interface (UI) Toolbox Font
 procedures in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS. (See GTextWindow in the README.DOC
 file.)

 The procedure OutGText% initializes the screen to its full-screen
 parameters before displaying the user's text. To reinitialize the
 screen back to its original user-specified parameters, GTextWindow
 must have been called. GTextWindow stores the screen coordinates for
 later use (for example, in the OutGText% function).

 Because the WINDOW statement uses the same parameters as GTextWindow,
 you may want to include the command WINDOW(X1,Y1,X2,Y2) in the
 GTextWindow procedure, and substitute the GTextWindow call whenever
 referencing the WINDOW statement.

 Code Example
 ------------

 The code below demonstrates the correct method to display the text
 "Hello world" in the location (0,100). If GTextWindow is not called,
 "Hello world" will be displayed twice in two different locations.

 SCREEN 9
 FontNum% = RegisterFonts("TMSRB.FON")
 var1% = LoadFont%("N4,N5,N6")
 a$ = "Hello world"
 CALL GTextWindow(-200, -200, 200, 200, FALSE)   'store coordinates
 WINDOW (-200, -200)-(200, 200)
 PSET (0, 100)
 var1% = OutGText%(0, 100, a$)
 var1% = OutGText%(0, 100, a$)
 PSET (0, 100)
 END

 Reference
 ---------

 According to the README.DOC file for BASIC PDS 7.00 and 7.10, after
 the first call to OutGText to output text, you must precede each
 subsequent call to OutGText with a call to GTextWindow in order to
 preserve logical coordinates of the window.


 396. How to Display Mouse Pointer on Multiple Pages, in UI Toolbox

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910111-277 B_QuickBas H_Mouse
 Last Modified: 29-JAN-1991    ArticleIdent: Q68589

 The User Interface (UI) Toolbox demonstration programs supplied with
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 are not written to accomodate mouse support on video pages
 other than page 0 (zero). If you change the SCREEN statement to use
 any video page other than page 0, the mouse cursor (pointer) will not
 be visible. To make the mouse cursor visible, you must call DOS
 interrupt 33 hex.

 Note that you may also use interrupt 33 hex with QuickBASIC version
 4.00, 4.00b, and 4.50 to show the mouse cursor on desired video pages.

 DOS function 33 hex, with function 1D hex, selects the display page
 for the mouse pointer. Before calling this DOS service, you must load
 the AX register with 1D hexadecimal, and the BX register with the
 desired page number. This page number coincides with the second
 argument to BASIC's SCREEN statement.

 Code Example
 ------------

 Combine (load into QBX.EXE) the following main-module code and
 subprogram along with the MOUSE.BAS source file provided with BASIC
 PDS 7.00 and 7.10.

 '$INCLUDE: 'qbx.bi'
 DIM SHARED Regs as Regtype
 MouseShow
 SelectPage(9,0,0)
 SLEEP
 SelectPage(9,1,0)
 END
 SUB SelectPage(Mode%, Page%, Visible%)
    Regs.AX = &H1D
    Regs.BX = 0
    Interrupt &H33, Regs, Regs
 END SUB


 397. "Symbol Defined More Than Once" LINKing BASIC 7.10/FORTRAN 5.0

 Product Version(s): 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910111-256 H_FORTRAN
 Last Modified: 29-JAN-1991    ArticleIdent: Q68590

 Below is an example where linking BASIC PDS 7.10 with FORTRAN 5.00
 gives several "Symbol defined more than once" errors. In this specific
 case, the problem can be worked around by compiling with BC /O (the
 stand-alone .EXE option, using BCL71ENR.LIB).

 =======================================================================

 IMPORTANT NOTE: Linking Microsoft BASIC Professional Development
 System (PDS) 7.10 with Microsoft FORTRAN 5.00 requires first changing
 the FORTRAN library and including a Microsoft C 6.00 library, as
 explained in a separate application note, "How to Link BASIC PDS 7.10
 with C 5.10, FORTRAN 5.00, or Pascal 4.00." To find this application
 note in a separate article in this knowledge base, search for the
 words shown in the title of the application note, or BB0345. Despite
 using the steps in the application note, linking certain BASIC 7.10
 and FORTRAN 5.00 programs may generate the "Symbol defined more than
 once" errors described in the example below.

 Although the methods in the application note have been designed to
 produce compatible results, we have not put the methods through a
 standard Microsoft mixed-language testing cycle, and it is possible
 that you may still encounter compatibility problems under certain
 conditions. We cannot guarantee the complete success of mixed-
 language programming of BASIC PDS 7.10 with C 5.10, FORTRAN 5.00, or
 Pascal 4.00. Further problems or questions can be directed to
 Microsoft Language Support Services.

 =======================================================================

 To duplicate the problem, create the following code:

 BASIC.BAS
 ---------

 REM *********************BASIC CODE*****************************
 DIM x%(2048)
 COMMON SHARED /nmalloc/ x%()
 DECLARE SUB Test()
 CALL Test
 END

 FORTRAN.FOR
 -----------

 C  *********************FORTRAN CODE***************************
       SUBROUTINE Test
       REAL frq(1)
       WRITE(6,*)wreal
       i=INT(frq(i))
       RETURN
       END

 Compile and link with the following commands:

    (Note: To create MIXED.LIB, you must obtain the application note
    "How to Link BASIC PDS 7.10 with C 5.10, FORTRAN 5.00, or Pascal
    4.00.")

  BC /E /FPi /Zi basic.bas;
  fl /c /4Yb /FPi /Zi fortran.for
  link /NOD/NOE/CO basic.obj + fortran.obj,s.exe,,brt71enr.lib+
                    llibcer.lib+mixed.lib;

 LINK.EXE generates the following errors:

 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __flds : symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fsts : symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fadds: symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fdivs: symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fsubs: symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fmuls: symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fstsp: symbol defined
 more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fdivsr: symbol
 defined more than once.
 mixed.lib(\mrt\c\87ccallf.asm) : error L2025: __fsubsr: symbol
 defined more than once.

 To work around this problem, add /O to the BASIC compiler command line
 and then relink, as follows:

    BC /O /E /FPi /Zi basic.bas;
    link /NOD/NOE/CO basic.obj + fortran.obj,s.exe,,BCL71ENR.LIB+
                    llibcer.lib+mixed.lib;


 398. "Illegal Function Call" Selecting Menu Item Using UI Toolbox

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901120-94
 Last Modified: 14-FEB-1991    ArticleIdent: Q69109

 An "Illegal function call" error can occur when you select an item
 from a user-defined menu with the ALT+Key1+Key2 combination, even
 though selecting the same item with the mouse does not give an error.
 This error can be caused by using an incorrect parameter in the
 MenuSet procedure. The fifth argument of the MenuSet SUB is
 accesskey%. If zero is passed as the fifth parameter, then that menu
 item and any after it will generate an error when selected with key
 combinations. This error does not occur if you use the mouse. This
 article shows why this error occurs, and gives a workaround for this
 problem.

 This information applies to the User Interface (UI) Toolbox in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 The MenuSet SUB is described on pages 545 and 546 of the "Microsoft
 BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10.

 The accesskey% argument specifies the position of the character within
 the menu item text that is used in conjunction with the ALT key to
 select that item. You may want accesskey% to be zero if you don't want
 the item to be selected. If you don't want the item to be selected,
 pass a zero as the third parameter (the State% argument).

 Code Example
 ------------

 The following code example demonstrates the "Illegal function call"
 error. In this case, a zero is passed as the fifth parameter of
 MenuSet because the text is just a horizontal line across the menu.

 To run this example, save the code as <filename>.BAS, then invoke
 QBX.EXE with the following command:

 QBX <filename> /L UITBEFR

 ' UIERROR.BAS
 DEFINT A-Z
 '$DYNAMIC
 '$INCLUDE: 'GENERAL.BI'
 '$INCLUDE: 'MENU.BI'
 '$INCLUDE: 'MOUSE.BI'
 '$INCLUDE: 'WINDOW.BI'

 'These global variables are required by the UI Toolbox routines:
 COMMON SHARED /uitools/ GloMenu         AS MenuMiscType
 COMMON SHARED /uitools/ GloTitle()      AS MenuTitleType
 COMMON SHARED /uitools/ GloItem()       AS MenuItemType

 '******************************************************************
 'MAXMENU and MAXITEM are constants defined in *.BI above.
 'The TYPEs MenuTitleType and MenuItemType are also defined
 'in the *.BI files above.
 '******************************************************************
 DIM GloTitle(MaxMenu)         AS MenuTitleType
 DIM GloItem(MaxMenu, MaxItem) AS MenuItemType
 COLOR 2, 1
 CLS
 MenuInit
 COLOR 15, 1                       'Sets the background to blue
 MenuSet 1, 0, 1, "Salutation", 1  'Menu title
 MenuSet 1, 1, 1, "Hello", 1       'First item under Salutation
 MenuSet 1, 2, 1, "-", 0           'Line across the menu
 MenuSet 1, 3, 1, "Goodbye", 1     'Last item under Salutation
 MenuPreProcess
 MenuShow
 MouseShow
 ProgramFinished = False
 WHILE NOT ProgramFinished
   kbd$ = MenuInkey$
   WHILE MenuCheck(2)
     GOSUB MenuTrap
   WEND
 WEND
 MouseHide
 END

 MenuTrap:
   Menu = MenuCheck(0)
   item = MenuCheck(1)
   COLOR 2, 1
   SELECT CASE Menu
     CASE 1
       SELECT CASE item
         CASE 1                        'If hello was selected then
           LOCATE 12, 37               'print hello.
           PRINT "Hello"
         CASE 3                        'If goodbye was selected then
           LOCATE 13, 36               'print goodbye and end.
           PRINT "GoodBye"
           ProgramFinished = True
         CASE ELSE
           ProgramFinished = False
       END SELECT
     CASE ELSE
       ProgramFinished = False
   END SELECT
   RETURN

 Workaround
 ----------

 This problem can be solved by either not passing a zero as the fifth
 parameter in MenuSet or by changing a few lines of code in the
 MENU.BAS program. The problem lies in the MENU.BAS program in the
 MenuDo SUB. There is a DO LOOP shortly after the following comment:

 '==================================================================
 'If menu is selected, search items for matching access key, and
 'select that (menu,item) and exit MenuDo if item is enabled
 '==================================================================

 The LOOP statement reads:

 LOOP UNTIL UCASE$(MID$(GloItem(currMenu, newItem).text,_
 GloItem(currMenu, newItem.accesskey,1)) = kbd$ AND GloItem(currMenu,_
 newItem).state > 0 AND RTRIM$(GloItem(currMenu, newItem).text) <>_
 "-") OR newItem = loopEnd

 Note: The above is one line of code in MENU.BAS. The underscore (_)
 characters indicate line continuation.

 If zero was passed as the fifth parameter in MenuSet, then
 GloItem(currMenu, newItem).accesskey = 0 when the loop reaches that
 menu item. This condition causes an "illegal function call" in the
 MID$ function. Adding the following IF statement to the loop will
 solve the problem:

 DO
   newItem = (newItem) MOD MAXITEM + 1
   IF GloItem(currMenu, newItem).accesskey = 0 THEN
     LoopDone% = (newItem = loopEnd)
   ELSE
     LoopDone% = UCASE$(MID$(GloItem(currMenu, newItem).text,_
     GloItem(currMenu, newItem.accesskey,1)) = kbd$ AND_
     GloItem(currMenu, newItem).state > 0 AND RTRIM$(GloItem(currMenu,_
     newItem).text) <> "-") OR newItem = loopEnd
   END IF
 LOOP UNTIL LoopDone%

 To include these changes in the files UITBEFR.LIB and UITBEFR.QLB, do
 the following:

 1. At the DOS prompt, type:

       QBX MENU

 2. Make the changes in the DO LOOP as stated above.

 3. Save the new MENU.BAS.

 4. Exit QBX.EXE.

 5. At the DOS prompt, type:

       BC MENU /X/Fs;

 6. Type:

       LIB UITBEFR - MENU.OBJ + MENU.OBJ

 7. Type:

       LINK /Q UITBEFR.LIB, UITBEFR.QLB,, QBXQLB.LIB;


 399. Correction for Scroll SUB in GENERAL.BAS, UI Toolbox

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910115-118 buglist7.00 buglist7.10
 Last Modified: 14-FEB-1991    ArticleIdent: Q69111

 The subprogram Scroll within GENERAL.BAS will not display the correct
 attributes if you select a negative number for "lines" when you want
 to scroll the window down. A correction for this problem is shown
 below. (Scrolling in the up direction displays the correct attributes,
 and needs no correction.)

 This correction applies to the User Interface (UI) Toolbox in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 The DOS Interrupt call 16 hex with function 7 or 6 requires that the
 BX register be set with the color attribute. The bits 6 through 4 are
 set to the desired background attribute. The following formula shifts
 this attribute into the correct location in the word register BX:

    regs.bx = 256 * (attr MOD 8) * 16

 The original code for subprogram Scroll has the following attributes
 set for the BX register:

    regs.bx = 256 * attr

 The following excerpt is from Scroll with the correct modifications:

 SUB Scroll (row1, col1, row2, col2, lines, attr)
           .
           .
           .
      MAXCOL THEN
         DIM regs AS RegType
         IF lines < 0 THEN
             regs.ax = 256 * 7 + (-lines)
            'regs.bx = 256 * attr                 <=== old code
             regs.bx = 256 * (attr MOD 8) * 16   '<=== change to this
             regs.cx = 256 * (row1 - 1) + (col1 - 1)
             regs.dx = 256 * (row2 - 1) + (col2 - 1)
         ELSE
             regs.ax = 256 * 6 + lines                  'AH = 06
             regs.bx = 256 * (attr MOD 8) * 16
             regs.cx = 256 * (row1 - 1) + (col1 - 1)
             regs.dx = 256 * (row2 - 1) + (col2 - 1)
         END IF
         INTERRUPT 16, regs, regs
     END IF
 END SUB


 400. How to Estimate Size of BASIC PDS ISAM Database Components

 Product Version(s): 7.00 7.10 | 7.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S910114-194
 Last Modified: 14-FEB-1991    ArticleIdent: Q69112

 Using the output of ISAMPACK.EXE can give you a rough estimate of the
 size of an ISAM database.

 This information applies to Microsoft BASIC Professional System (PDS)
 versions 7.00 and 7.10 for MS-DOS and 7.10 for OS/2.

 Because an ISAM file contains descriptive information, it has some
 size overhead. This overhead is required for the speed and efficiency
 that ISAM files possess compared to random access files. With this
 overhead, data manipulation, such as searches, seeks, and sorts,
 becomes extremely easy. The ISAM engine is responsible for all this
 data manipulation, which allows you to spend your time developing the
 code, and frees you from worrying about the fine details of the
 database management.

 You can use the output of the ISAMPACK.EXE utility to roughly guess
 the size of the components of an ISAM database.

 The ISAM database is divided into several components, which have the
 following size requirements:

 1. A database requires a header of 3K for its own use.
 2. The system data dictionary requires 39K.
 3. Each table requires 4K of overhead beyond the data space.
 4. Each index is allocated in 2K chunks.
 5. Actual data is allocated in 2K increments.

 Additionally, to optimize speed and flexibility, the file will grow in
 large increments of 32K, rather than in record-size increments as
 single records are added. For this same reason, the indexes and data
 are allocated in 2K chunks. Although the files are quite large
 compared to random access files, the ISAM file has room for growth and
 can be extremely fast. This can be a hurdle for some programmers, and
 is an important consideration when designing a program. Please read
 "ISAM Components/When to Use ISAM" on page 329 of the "Microsoft BASIC
 7.0: Programmer's Guide" (for 7.00 and 7.10) to determine which is
 more appropriate for your needs, ISAM files or random access files.

 The following tables were constructed using the sample database
 AMAZRAYS.MDB and the output from ISAMPACK.EXE.

 To run ISAMPACK.EXE, first invoke the PROISAMD.EXE TSR (terminate and
 stay resident) program, then use the following arguments for
 ISAMPACK.EXE:

    ISAMPACK AMAZRAYS.MDB AMAZRAYS.RPT

 More information on ISAMPACK.EXE can be found on page 394 of the
 "Microsoft BASIC 7.0: Programmer's Guide."

 Header
 ------

  * Each database requires a 3K header.                           3K

 Data Dictionary
 ---------------

  * Five system tables and eight system indexes.                  39K

 Tables Overhead
 ---------------

  * Each table has 4K of overhead beyond its actual data records.

       CustTable
       InventTable
       InvoiceTable
       TransTable          4 * 4K =                               16K

 Indexes
 -------

  * Each index is allocated in 2K chunks:

    IndexName      Columns        Size   NumRecords  Size   Actual
    ---------      -------        ----   ----------  ----   ------

    AcctIndex      AcctNo(5)        5      7           35    2K

    CompanyIndex   Company(70)
                   AcctNo(5)       75      7          525    2K

    ItemIndex      ItemNo(5)        5      8           40    2K

    InvoiceIndex   InvoiceNo(6)     6     24          144    2K

    DateIndex      Date(6)
                   InvoiceNo(6)    12     24          288    2K

    InvAcctIndex   AcctNo(6)
                   Date(6)
                   InvoiceNo(6)    36     24          864    2K

    TransInvIndex  InvoiceNo(6)
                   TransNo(2)      12     46          552    2K

                                        Total Index Space...    14K

 Database
 --------

  * Each database is allocated in 2K chunks.

    Table        b/rec    #rec     Calc(K)  Act(K)
    -----        -----    ----     -------  ------

    CustTable     326        7     2.282       4
    InventTable   163        8     1.304       2
    InvoiceTable   33       24     0.792       2
    TransTable     23       46     1.058       2
                                                    Total...    10K

 Database Size
 =============

  * Growth is in 32K chunks.

                                   Grand total(82K)....   83,968 bytes
    Adjusted for 32K chunk (3 * 32K * 1024 bytes/K)....   98,304 bytes
            Actual file reported after packing file....   98,304 bytes


 401. ISAMCVT Doesn't Properly Convert db/LIB Date Fields

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910116-88 buglist7.00 buglist7.10
 Last Modified: 11-FEB-1991    ArticleIdent: Q69158

 Page 393 of the "Microsoft BASIC 7.0: Programmer's Guide" (for
 versions 7.00 and 7.10) states that the ISAMCVT utility will convert
 db/LIB date fields to BASIC double-precision numbers for use with the
 Date/Time add-on libraries.

 ISAMCVT does convert a date field to a double-precision number, but
 the resulting number is not a serial number that can be used with the
 date libraries included with BASIC.

 Microsoft has confirmed this to be a problem with the ISAMCVT.EXE
 utility for Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS. We are researching this problem and
 will post new information here as it becomes available.

 When ISAMCVT converts a date field, it converts it to a 8-byte string,
 but tags it internally as a double. To see the string, you must use
 the MKD$ function to convert the double to a string.

 However, ISAMCVT also converts the year portion of the date
 incorrectly by dropping the last two digits (for example, 1990 becomes
 19, and 1890 becomes 18.)

 For example, if you have a db/LIB file ("test.dbf") containing
 three fields and one record

    NUMERIC (length=4, # decimals=1)   = 1.2
    CHARACTER (length = 50)            = My Name
    DATE                               = 19901214

 and then you converted it using

    ISAMCVT /D test.dbf table test.mdb

 the program below will then show that the ISAM file contains the
 following:

     CustNum = 1.2
     Name    = My Name
     Date    = 12/14/19

 Code Sample
 -----------

 Note: PROISAM.EXE must be loaded before running this program inside of
 QBX.EXE.

 TYPE rectype
     CustNum AS DOUBLE
     Name AS STRING * 50
     Date AS DOUBLE
 END TYPE
 DIM a AS rectype
 OPEN "test.mdb" FOR ISAM rectype "table" AS #1
 SETINDEX #1, ""
 MOVEFIRST #1
 RETRIEVE #1, a
 PRINT a.CustNum
 PRINT a.Name
 PRINT MKD$(a.Date)
 CLOSE #1


 402. Example of How to Call BASIC SetUEvent from C; ON UEVENT GOSUB

 Product Version(s): 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910107-180 B_QUICKBAS S_C
 Last Modified: 14-FEB-1991    ArticleIdent: Q69159

 Page 310 of the "Microsoft BASIC 7.0: Programmer's Guide" states:

    Trapping a user-defined event involves writing a non-BASIC
    routine, such as in Microsoft Macro Assembler (MASM) or C, ....

 On the same page, this statement is followed by an example of how to
 set up the ON UEVENT GOSUB routine in assembly language.

 This article shows how the same example can be written in the
 Microsoft C language.

 The code example below applies to Microsoft QuickBASIC versions 4.00b
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 Compile the C program below with:

    CL -Od -AM -c uevent.c

 Compile the BASIC program below with:

    BC /O/V BASIC.BAS;

 Link the programs together with:

    LINK /NOE BASIC+UEVENT, UEVENT.EXE;

 When the program is executed, the line "Arrived here after 4.5
 seconds" will print every 4.5 seconds.

 Note: The C program must be compiled with the medium memory model
 because the DS register must point to BASIC's DGROUP space when
 SetUevent is called.

 BASIC Code Example, BASIC.BAS
 -----------------------------

 DECLARE SUB SetInt
 DECLARE SUB RestInt
 ' Install new interrupt service routine:
 CALL SetInt
 ' Set up the BASIC event handler:
 ON UEVENT GOSUB SpecialTask
 UEVENT ON

 DO
 ' Normal program operation occurs here.
 ' Program ends when any key is pressed.
 LOOP UNTIL INKEY$ <> ""

 ' Restore old interrupt service routine before quitting:
 CALL RestInt
 END

 ' Program branches here every 4.5 seconds:
 SpecialTask:
 ' Code for special task goes here, for example:
 PRINT "Arrived here after 4.5 seconds"
 RETURN

 C Code Example, UEVENT.C
 ------------------------

 #include <dos.h>
 void (_interrupt _far *OldInt) (void);    // The old interrupt vector.
 void _interrupt _far EventHandler (void);       // The UEVENT handler.
 char TimerTicks = 0;                      // Number of ticks elapsed.

 void pascal SetInt()                      // Set up the interrupts
 {                                         //   to point to the UEVENT
     OldInt = _dos_getvect(0x1C);          //    handler.
     _dos_setvect(0x1C, EventHandler);
 }

 void interrupt EventHandler()            // This is the UEVENT handler.
 {
     extern pascal SetUevent();
     if (++TimerTicks > 82)               // Check to see if 4.5 secs
       {                                  //    has elapsed (18.2
         TimerTicks = 0;                  //    ticks = 1 sec).
         SetUevent();
       }
     _chain_intr(OldInt);                // Continue through old
 }                                       //    interrupt routine.

 void pascal RestInt()                   // Restore old interrupt
 {                                       //    when done to avoid
     _dos_setvect(0x1C, OldInt);         //    conflicts after exit.
 }


 403. "Subscript Out of Range," Graphics GET with LONG Integer

 Product Version(s): 6.00 6.00b 7.00 7.10 | 6.00 6.00b 7.00 7.10
 Operating System:   MS-DOS               | OS/2
 Flags: ENDUSER | b_quickbas buglist6.00 buglist6.00b buglist7.00 buglist7.10
 Last Modified: 14-FEB-1991    ArticleIdent: Q69160

 If the graphics GET statement is used in a subprogram with a LONG
 integer array and if the starting index of the array is not the first
 element, a "Subscript out of Range" error will be generated if the
 program is compiled with BC /D. If the program is compiled without the
 /D option, BC.EXE will give an "Illegal function call" error.

 This problem does not occur in the QBX.EXE or QB.EXE environment.

 Microsoft has confirmed this to be a problem with Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS; Microsoft BASIC compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2; and Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. We are researching this problem and will post new
 information here as it becomes available.

 The program below demonstrates the problem. Compile and link as
 follows:

    BC /D SAMPLE;
    LINK SAMPLE;

 When the program is run, it will draw a circle and then print
 "Subscript out of Range in line 7 of module SAMPLE."

 To work around this problem, either place the array in COMMON SHARED
 or use a local array instead of one that is passed as a parameter. It
 is also possible to uses SINGLE precision numbers instead of LONG
 integers.

 Code Sample: SAMPLE.BAS
 -----------------------

 DECLARE SUB test (array() AS LONG)
 1 DIM array(1000) AS LONG
 2 SCREEN 1
 3 CIRCLE (50, 50), 50
 4 CALL test(array())
 5 CLS
 6 PUT (100, 100), array(4)

 SUB test (array() AS LONG)
 7  GET (50, 50)-(100, 100), array(4)
 END SUB


 404. ISAMCVT Btrieve Specfiles Cannot Have Spaces; Must Use Commas

 Product Version(s): 7.00 7.10
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S910205-152
 Last Modified: 14-FEB-1991    ArticleIdent: Q69343

 Page 392 of the "Microsoft BASIC 7.0: Programmer's Guide" (for BASIC
 PDS 7.00 and 7.10) gives an incorrect example of a Btrieve specfile.
 The fields of each entry are incorrectly shown separated by spaces;
 instead, the fields should be separated by commas.

 ISAMCVT specfiles must not contain spaces.

 This information applies to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS.

 The specfile on page 392 should be changed to the following:

    string,4,StringCol
    integer,2,IntColumn
    Long,10,LongColumn
    Double,5,DoubleCol

 If ISAMCVT is run with this specfile and an appropriate Btrieve file,
 the Btrieve file will be successfully converted. Note that the
 specfile must specify the format for every column in the Btrieve file
 (for both indexes and non-indexes).

 Page 392 gives the following incorrect example of a Btrieve specfile:

    string 4 StringCol
    integer 2 IntColumn
    Long 10 LongColumn
    Double 5 DoubleCol

 ISAMCVT gives the following error message when using the above
 specfile:

    ISAMCVT: Invalid data type 'string 4 StringCol
    ' in line 1 of <specfilename>.

 ISAMCVT does not allow spaces as field separators. It is also illegal
 to mix commas and spaces as in the next example:

    string, 4, StringCol
    integer, 2, IntColumn
    Long, 10, LongColumn
    Double, 5, DoubleCol

 ISAMCVT gives the following error message when using the above
 specfile:

    ISAMCVT: Missing or invalid column name in line 1 of <specfilename>

 The fields of an ISAMCVT specfile must be separated by commas and no
 spaces should be in the file.






 Microsoft QuickBASIC
 =============================================================================


 1. Getting the DTA Address Using INT86

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q11785

 Problem:

 I would like to search for files with a given extension, save them in
 an array, and display them on the screen for user selection using
 QuickBASIC Version 2.00 and the DOS interrupt routine INT86. I have
 written a sample program that calls function 4E and 4F to find the
 desired files. They appear to be working correctly, as the flag
 returned in the low byte of register AX is showing 0 for each
 successful find and 18 when no files exist or when the last file has
 been found. However, I do not know how to read the DTA (Disk Transfer
 Address) after I successfully find a file, thus I cannot store the
 filename for later display.

 Response:

 In QuickBASIC Versions 2.00, 2.01, and 3.00, you can perform DOS
 Interrupts by calling the external routine INT86. In QuickBASIC
 Versions 4.00, 4.00b, and 4.50, you can call the external routines
 INT86OLD INT86XOLD INTERRUPT and INTERRUPTX.

 It is difficult to find the current DTA of a program (and its offset
 is subject to change without notice); therefore, it is better to ask
 DOS (via INT 21, function Hex 1A "Set DTA") to reassign the DTA to a
 location over which you have control. For the application indicated,
 you should try the following:

 1. Issue the DOS function call to change the DTA address (INT 21,
    function Hex 1A) to an address of a structure in your code space
    (this way you will know where to find it).

 2. Perform your "Find first" (INT 21, function Hex 4E).

 3. Perform your loop of "Continue file search" (INT 21, function Hex
    4F).

 Within your loop you may check your variables in the structure as
 desired. The "Microsoft MS-DOS Programmer's Reference" manual includes
 an example of how to set up the structure for the DTA in assembler.

 The book "Advanced MS-DOS," by Ray Duncan (Microsoft Press, 1986) also
 is a very helpful reference for using DOS function calls.


 2. "Illegal Number" Using -2147483648& in Long Integer Notation

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890824-44 B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q48725

 BC.EXE, QB.EXE, and QBX.EXE do not allow the "&" character on the end
 of the smallest (negative) constant allowed for a long integer,
 -2147483648. To enter the smallest long integer constant in your
 source code, you must use either (-2147483647& - 1&) or -2147483648#.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 The BC.EXE compiler reports an "Illegal type character in numeric
 constant" error, and the QB.EXE and QBX.EXE editors report an "Illegal
 number" error for the following statement:

    A& = -2147483648&

 The error may have surprised you since -2147483648& is within the
 allowed range for long integers (-2147483648& to +2147483647&).

 However, this is not a software problem. Both the BASIC compiler and
 the QB and QBX interpreters parse -2147483648& as follows:

    - (2147483648&)

 In other words, "take a large long integer and negate it." This means
 that the number is first parsed as a positive long integer and then it
 is negated before it is assigned to the number. However, the largest
 positive long integer is 2147483647 (one fewer than the largest
 negative number), making 2147483648& an illegal number, and therefore,
 causing an error.

 You must use one of the following instead:

    A& = (-2147483647& - 1&)
 or
    A& = -2147483648#


 3. Printing Delayed when DOS PRINT Command Invoked from SHELL

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  7-FEB-1989    ArticleIdent: Q28208

 If you invoke the DOS Print utility during a SHELL, the printer output
 does not print until you exit QuickBASIC. This problem occurs because
 DOS Print is a terminate-and-stay-resident (TSR) program.

 Note: You should never install a TSR program, such as DOS Print, with
 the SHELL statement because it fragments memory. This can result in
 the following error messages: "Out of Memory" and "Program Too Large
 to Fit in Memory". You must reboot to eliminate the memory
 fragmentation.

 If you must SHELL to a TSR program, it must have been installed in
 memory before running the QuickBASIC program. Note: Many TSR programs
 may conflict with QuickBASIC with other symptoms, and may not be
 compatible.

 We do not recommended you use DOS Print, or any TSR program, with
 QuickBASIC. Due to a memory conflict, the printing will be delayed
 when the DOS Print is invoked during the execution of a SHELL command.

 In the first example below, printing occurs immediately because the
 Print is invoked (i.e., loaded into memory) prior to the running of
 QuickBASIC. In this case, Print takes a portion of memory for its
 buffer, QuickBASIC loads, the SHELL executes, and the previously
 allocated buffer is used.

 If DOS Print is initially invoked by the SHELL statement itself, then
 printing does not occur until after exiting QuickBASIC. In this case
 QuickBASIC loads, the SHELL executes, Print tries to set up the buffer
 but does not have enough room so it spools. Once memory is freed up,
 either after exiting QuickBASIC or after the SHELL is executed, a
 print buffer can be allocated and the DOS Print is executed. Similar
 limitations occur in earlier versions of the QuickBASIC compiler.

 Below is the first example. DOS Print is loaded prior to running
 QuickBASIC, and no delayed printing occurs in the following example:

 1. Invoke DOS Print utility. Resident portion of Print gets loaded
    into memory.

 2. Invoke the QuickBASIC editor (QB.EXE).

 3. Run the following program:

              CLS
              Shell "print filename"
              End

 Below is the second example. DOS Print is loaded by the SHELL
 statement itself, and printing is delayed until after leaving
 QuickBASIC, and memory is fragmented in the following example:

 1. Reboot.

 2. Invoke the QuickBASIC editor (QB.EXE).

 3. Run the program above. Print loads resident portion.


 4. Negative Array Subscripts Checked with Debug, /D

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q11880

 Question:

 I have two questions on subscripts in QuickBASIC, as follows:

 1. What is supposed to happen when I use negative array subscripts in
    QuickBASIC?

 2. Does QuickBASIC check the validity of subscripts?

 Response:

 The following are responses to your questions:

 1. Negative subscripts are not supported in Versions 3.00 and earlier,
    so when you use negative subscripts, the results are unpredictable.
    Versions 4.00 and later support the "TO" optional syntax, which allows
    for subscripts in the range of -32768 to 32767. However, invalid
    subscripts, such as negative values in Versions 3.00 and later, and
    subscripts out of range in all versions, are not checked for unless
    you have compiled with /D.

    For example, compile the following program with BC.EXE without /D:

       DIM A(10), B(10)
       A(9) = 1
       A(10) = 2
       PRINT B(-1)  'the value printed is 2, which is value of A(10)
       PRINT B(-2)  'the value printed is 1, which is the value of A(9)
       END

       Since BASIC may move items around in memory, the above results
       might not occur if there were other operations between the
       assignment statements and the PRINT statements.

 2. QuickBASIC checks subscript range validity when the /D switch is
    on, or when the Debug option is selected in the editors in Versions
    2.x and 3.00.


 5. List of BASICs Using MBF versus IEEE Floating-Point Format

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-FEB-1991    ArticleIdent: Q11936

 This article lists which BASIC versions (for MS-DOS) use Microsoft
 Binary Format (MBF) and which versions use IEEE format for storing
 single- and double-precision floating-point numbers.

 Single- and double-precision real numbers are stored in the Microsoft
 Binary Format (MBF) in the following languages:

 1. QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, and the
    non-coprocessor QB.EXE version 3.00, for MS-DOS

 2. IBM and Compaq BASICA Interpreters (BASICA.COM) for MS-DOS

 3. GW-BASIC Interpreter versions 3.20, 3.22, and 3.23 (GWBASIC.EXE)
    for MS-DOS

 4. Microsoft BASIC Interpreter version 5.28 for MS-DOS

 5. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS

 QuickBASIC versions 4.00, 4.00b, and 4.50 (QB.EXE, BC.EXE) and the
 coprocessor version of QuickBASIC version 3.00 (QB87.EXE) use IEEE
 floating-point format for single- and double-precision real numbers.

 Note that Microsoft Business BASIC Compiler versions 1.00 and 1.10 use
 a different floating-point format called Decimal Math. Decimal Math is
 very slow but has no rounding or representation errors because numbers
 are stored in their exact decimal form, instead of in an approximate
 binary form. (Sales of Business BASIC were discontinued.)

 In QuickBASIC version 3.00, the coprocessor version of QuickBASIC uses
 IEEE format numbers. Conversion routines are provided in version 3.00
 to convert between the MBF used in the non-coprocessor version
 (QB.EXE) and the IEEE floating-point format used in the coprocessor
 version (QB87.EXE).

 QuickBASIC versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler
 versions 6.00 and 6.00b, and Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 only use IEEE format numbers, but
 conversion routines and a compiler switch are provided to convert
 between MBF and IEEE format. This conversion is necessary if you want
 to retrieve floating-point numbers from random access files that were
 created using MBF.

 References:

 For additional articles that discuss MBF and IEEE, search for the
 following words:

    floating and point and format and QuickBASIC


 6. "Bad File Name"; OPEN "COM1:"; 8 Data Bits Must Have No Parity

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  4-SEP-1990    ArticleIdent: Q12027

 When you use the OPEN "COM" statement with the data bits set to 8 and
 parity set to Even or Odd, you will get a "Bad File Name" error. For
 example, "Bad File Name" occurs at run time when you open the serial
 communications port as follows:

    OPEN "COM1:9600,E,8,1" AS 2

 This error disappears using 7 data bits, or No (N) parity.

 When you specify 8 data bits, you must specify a parity of N. This is
 a limitation in the design of QuickBASIC versions 1.00, 1.01, 1.02,
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50; Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2; and Microsoft BASIC
 PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 As a workaround in QuickBASIC versions 4.00 and later, Microsoft BASIC
 Compiler versions 6.00 or 6.00b, or BASIC PDS, you can call a
 Microsoft C version 5.10 routine from BASIC to do the communications
 with 8 bits and odd or even parity. The following book will help in
 doing this:

    "Microsoft C Programming for the IBM" by Robert Lafore (published by
    the Waite Group)

 The QuickBASIC Compiler, BASIC compiler 6.00, and BASIC PDS 7.00 are
 designed with a 10-bit data frame for communications. The frame is as
 follows:

             1 2  -  8 9 A
             S DDDDDDD P S

 Bit  1     = Start Bit    (Always 1)
 Bits 2 - 8 = Data Bits    (7 or 8)
 Bit  9     = Parity       (Odd, Even, or None)
 Bit  A     = Stop Bit(s)  (1 or 2)

 The combination of the bits should add up to 10 bits. When you try to
 set 1 start + 8 data + 1 parity + 1 stop, that adds up to an 11-bit
 data frame, which BASIC is not designed for.


 7. CLEAR Should Not Be Used in Event Trap

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  4-JAN-1990    ArticleIdent: Q12074

 The presence of a CLEAR statement in the following event handling
 routine generates an "Illegal function call" error at compile time:

       CLEAR ,,800
       KEY(2) ON
       ON KEY(2) GOSUB 200
       WHILE INKEY$="" : WEND
       PRINT "this is a test"
       END
   200 CLEAR ,,800
       PRINT "this worked"
       RETURN

 The error occurs because the CLEAR statement changes the stack. The
 CLEAR statement is not allowed in an event handler because it would
 destroy the return address.


 8. How to Obtain Upper and Lower Bytes of an Integer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q27097

 The following program demonstrates how to obtain the upper and lower
 bytes of an integer. The following is sample code:

 CLS
 a% = &HA0B0
 ah% = (a% AND &HFF00) \ 256 AND &HFF   'Note: "\" means integer division
 al% = a% AND &HFF
 PRINT HEX$(ah%)                 'Prints upper bytes: A0
 PRINT HEX$(al%)                 'Prints lower bytes: B0

 This information applies to Microsoft QuickBASIC 4.00 4.00B and 4.50
 for MS-DOS, to Microsoft BASIC Compiler 6.00 and 6.00B for MS-DOS and
 MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS
 OS/2.


 9. No Error Listing File in QB 2.00; Error-Only File in 2.01/3.00

 Product Version(s): 2.00 2.01 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-OCT-1989    ArticleIdent: Q12243

 QuickBASIC Version 2.00 cannot list compiler errors to a file when
 compiling from the DOS command line (outside the QB.EXE editor) (see
 "Separate Compilation Method" in Appendix D of the "Microsoft
 QuickBASIC Compiler" Version 2.0 and 3.0 manual). This means that all
 debugging must be done in the QB.EXE Version 2.00 editor.

 In contrast, earlier versions of QuickBASIC (1.00, 1.01, and 1.02)
 give a listing (.LST) file that includes all source lines and flags
 those lines that have errors.

 Versions 2.01 and 3.00 have enhanced the Separate Compilation Method
 so that you can redirect compiler error messages to a file or device.
 If you compile from a DOS batch (.BAT) file, this feature allows you
 to automatically report the errors to an output file. For example:

    Command Line               Action
    ------------               ------

    QB TEST.BAS;               Compile TEST.BAS and display any errors
                               encountered on the screen.

    QB TEST.BAS; > TEST.LST    Compile TEST.BAS and redirect any error
                               messages generated to the file TEST.LST.

    QB TEST.BAS; > PRN         Redirects output to the DOS printer device.

 Only the lines in error and their associated error messages are sent
 to the screen or output file in 2.01 and 3.00. Source lines that don't
 have errors aren't listed.

 As there is no full-source-listing (.LST) output feature in QuickBASIC
 Versions 2.00, 2.01, and 3.00, there is also no compiler /A option to
 output the assembler translation of the BASIC code. The compiler /A
 option is supported only in QuickBASIC Versions 1.00, 1.02, 1.02,
 4.00, 4.00b, and 4.50.


 10. Explanation of String Space Garbage Collection; FRE Function

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q12337

 This article discusses three topics regarding string space
 compression:

 1. When QuickBASIC compresses string space during execution of a
    program

 2. Whether disabling string space compression is possible

 3. Whether string descriptors are fixed in memory or if they move

 This information applies to Microsoft QuickBASIC 4.00 4.00B and 4.50,
 to Microsoft BASIC Compiler 6.00 and 6.00B, and to Microsoft BASIC PDS
 Version 7.00 for MS-DOS and MS OS/2.

 1. When a string variable is assigned a new value, the new string
    takes the next available memory in string space. The old string
    value is deallocated but takes up space until string space "garbage
    collection" occurs.

    A program compresses string space as part of "garbage collection"
    when deallocated strings fill up the 60,000 bytes of available data
    space and the program needs to reallocate a string variable or a
    temporary string variable. You can force string compression with
    the FRE function [PRINT FRE("")], but there is no other way to
    predict when it will occur. An OPEN or CLOSE of a file can also
    trigger garbage collection.

 2. There is no way to disable the automatic garbage collection. At
    the time garbage collection occurs, your program is out of memory,
    so that if you were to disable it, your program could not continue
    to execute.

    You can schedule garbage collection to some extent by using the FRE
    function before executing code where you do not want garbage
    collection to occur, but if memory is tight, garbage collection may
    occur again anyway.

 3. String descriptors are the first bytes of each string, and they
    move as the strings move.


 11. Sperry PC BASIC's SCREEN B Is Not Supported

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q21792

 QuickBASIC does not support the SCREEN B statement found in the BASIC
 sold by Sperry with its PC/IT. This information also applies to
 Microsoft BASIC Compiler Versions 6.00 and 6.00b and to Microsoft
 BASIC PDS Version 7.00.


 12. No Support for More Than Two Communications Ports in BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-MAR-1990    ArticleIdent: Q21789

 QuickBASIC does not support more than two communications ports.
 QuickBASIC supports only the devices COM1 and COM2. Some computers
 supply COM3 and COM4 devices, but these are not supported in compiled
 BASIC. This information applies to Microsoft QuickBASIC Versions 1.00,
 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50; to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b; and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00.

 To access COM3 and COM4, it may be possible for compiled BASIC to call
 third-party library routines, which are listed in catalogs such as the
 "Programmer's Connection Buyer's Guide," which can be obtained by
 calling (800) 336-1166 in the United States; (800) 225-1166 in Canada;
 or (216) 494-8899 for the Customer Service department. Using this
 catalog, you may wish to contact the company Software Interphase at
 401) 274-5465, for example, to determine if its product QuickComm
 supports COM3 and COM4 called from Microsoft compiled BASIC.

 When purchasing add-on products, make sure the vendor has tested its
 product under your version of BASIC. For a list of other catalogs,
 query on the following words:

    programmer and tool and catalog


 13. "/" Switches on the Wang PC

 Product Version(s): 1.00 1.01 1.02 2.00 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-FEB-1989    ArticleIdent: Q21795

 Problem:

 I cannot use compiler switches when I run BASCOM on a Wang PC. For
 example, BASCOM test.bas/E/D does not work correctly.

 Response:

 On some Wang PC models, you must use "-" instead of "/" for the
 QuickBASIC Version 1.x compiler switches.


 14. Compatibility with AT&T PC 6300: No SCREEN 100 or SCREEN B

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q21790

    In general, QuickBASIC works very well on the AT&T PC 6300
 computer. However, please note that in QuickBASIC Versions 2.x, 3.00,
 4.00, 4.00b, and 4.50 you must run QB with the /B option to see the
 QuickBASIC editor menus and help screens properly on the AT&T's
 monochrome monitor.
    The BASIC that comes with the AT&T PC 6300 has SCREEN B and SCREEN
 100 statements that are not supported in any version of QuickBASIC or
 IBM BASICA. However, QuickBASIC Version 4.00b has added a new screen
 mode, SCREEN 4, which is supported on the following machines:

    Olivetti Personal Computers, models M24, M28, M240, M280, M380
    AT&T 6300 Personal Computer series

    SCREEN 4 is a 640x400 graphics mode that allows you to specify one
 of 16 colors (0-15) as the foreground color. Use the SCREEN statement
 to select the mode and the COLOR statement to select the foreground
 color. The example below shows how to specify this mode with a blue
 foreground color:

    SCREEN 4
    COLOR 1

    You must invoke QB with the /B option on the AT&T PC 6300 because
 the AT&T has a graphics card and a monochrome monitor installed.
 QuickBASIC can detect what graphics card is installed, but you have to
 tell it with the /B option that a monochrome monitor is installed.
 (Please read about the QB /B option on Page 72 of the "Microsoft
 QuickBASIC Compiler" manual for Versions 2.x and 3.00, or Page 49 of
 the "QuickBASIC Version 4.00: Learning and Using" manual.)
    The BASIC interpreter provided with the AT&T 6300 gives a cursor on
 graphics screens; however, there is no cursor in IBM BASICA or
 Microsoft QuickBASIC when working with graphics screens.
    On the AT&T machines, the communications ports ("COM1:" and
 "COM2:") produce errors such as "Device not available" in QuickBASIC
 Versions 1.00, 1.01, and 1.02. QuickBASIC Versions 2.x and later have
 had few reports of problems with communications on the AT&T PC 6300.


 15. Communications Device Buffer Size Can Be Set with /C: Switch

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21787

 The communications device receiving buffer size can be set with the
 /C: compiler switch. For example, in Versions 1.x, you can set the COM
 receiving buffer to 1000 bytes by compiling BASCOM/C:1000. This
 information needs to be added to Pages 46 and 176 in the "Microsoft
 QuickBASIC Compiler" documentation for Versions 1.x. Note that for
 Version 1.x, if you specify a buffer between 1 and 255 in QuickBASIC,
 you always get 255 bytes; in IBM BASICA Interpreter you get whatever
 buffer size you specify.

 In Versions 2.x and 3.00, the communications buffer must be set before
 invoking the editor. This action is done in a similar manner, for
 example, QB/C:xxxx, where xxxx represents the desired number of bytes.
 The command line method of compilation is also similar, but the
 command line ends with a semicolon (;), for example, QB program/C:xxxx;.

 In Versions 4.00, 4.00b, and 4.50, you may set the transmission buffer
 size as well as the receiving buffer size.


 16. Cannot Access FIELDed Variables After CLOSE in Compiled BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 15-MAR-1989    ArticleIdent: Q21815

 Problem:

 I cannot access FIELDed variables after I close the random access
 file. I am able to access the variables in IBM BASICA, but not in the
 QuickBASIC compiler.

 Response:

 This is a difference between the IBM BASICA Interpreter and the
 QuickBASIC Compiler.

 You must assign the FIELDed variables to unFIELDed string variables to
 access the data in the FIELD buffer after the file is closed.

 Note: If the file is closed, and a FIELD variable is used as an
 argument to a function, you may receive an "Illegal Function Call"
 message.

 This information needs to be added to Appendix A "Converting BASICA
 Programs to QuickBASIC" in the following manuals:

 1. "Microsoft BASIC Compiler Version 6.00 for MS OS/2 and MS-DOS:
    Learning and Using Microsoft QuickBASIC"

 2. "Microsoft QuickBASIC: Programming in BASIC Version 4.50"

 This information can also be added to Chapter 10,
 "Compiler-Interpreter Language Differences," of the "Microsoft
 QuickBASIC Compiler" Versions 2.0x and 3.00 manual.


 17. QB 4.50 SETUP.EXE Hanging Problem on Leading Edge Model D

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900510-44
 Last Modified: 27-JUL-1990    ArticleIdent: Q64099

 Two separate customers reportedly hung their Leading Edge Model D
 computers after executing the QuickBASIC version 4.50 installation
 program (SETUP.EXE on the Setup/Microsoft QB Express Disk) under DOS
 version 3.20. Microsoft could not duplicate this problem using either
 MS-DOS or PC-DOS version 3.20. The reported problem did not occur when
 the customers attempted installation with the next version of the
 operating system, DOS version 3.21, on their Leading Edge Model D
 computers.

 Please note that the SETUP.EXE program for QuickBASIC 4.50 is mostly a
 file-transferring program. To work around the problem above without
 upgrading DOS, you can set up QuickBASIC by simply copying the files
 directly from the original distribution disks.

 The QB Express program can also be copied and run from a hard disk. To
 run QB Express, copy all files on the root directory of the
 Setup/Microsoft QB Express disk. Then type LEARN to start QB Express.


 18. Support for IBM EGA and Hercules Graphics Cards

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21839

 This article describes which versions of QuickBASIC support the IBM
 EGA (Enhanced Graphics Adapter) Card and which versions support
 Hercules Monochrome Graphics Cards.

 EGA Support
 -----------

 QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 support
 EGA through the use of SCREEN modes 7, 8, 9, and 10. QuickBASIC
 Versions 1.00, 1.01, and 1.02 do not support the EGA. The 43-line EGA
 mode is supported in the Editor and in the WIDTH statement in
 QuickBASIC Versions 3.00, 4.00, 4.00b, and 4.50. The EGA is also
 supported in OS/2 real mode and MS-DOS for programs compiled with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and Microsoft BASIC PDS Version 7.00. The EGA is not currently
 supported for BASIC programs that run in OS/2 protected mode.

 Hercules Support
 ----------------

 Microsoft QuickBASIC Versions 4.00 and later, the Microsoft BASIC
 Compiler 6.00 and 6.00B, and Microsoft BASIC PDS 7.00 all support the
 Hercules Monochrome Graphics Card, Hercules Graphics Card Plus,
 Hercules InColor Card, and cards that are 100 percent compatible with
 these cards. The following describes how Hercules cards are supported
 in QuickBASIC:

 1. Hercules graphics mode is SCREEN 3.

 2. Hercules text mode is SCREEN 0.

 3. With Hercules, you must use a monochrome monitor.

 4. You must load the Hercules driver (QBHERC.COM) before running your
    program. If the driver is not loaded, the SCREEN 3 statement gives
    an "Illegal function call" error message. Type "QBHERC" to load the
    driver.

 5. The text dimensions are 80x25 (9x14 character box); the bottom two
    scan lines of the 25th row are not visible.

 6. The resolution is 720x348 pixels, monochrome.

 7. SCREEN 3 supports two pages (0 and 1); SCREEN 0 used with Hercules
    supports only one page.

 8. The PALETTE statement is not supported.

 9. To make function calls to the Microsoft Mouse, you must follow
    special instructions for Hercules cards in the "Microsoft Mouse
    Programmer's Reference Guide." (This manual must be ordered
    separately; it is not supplied with either the QuickBASIC or the
    Microsoft Mouse packages.)

 The use of Hercules cards is also documented in the README.DOC file on
 the QuickBASIC Version 4.00, 4.00b, and 4.50 release disk, which
 supplements the Microsoft QuickBASIC Compiler documentation.


 19. Integer Overflow Handling in Compiler Differs from Interpreter

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 27-DEC-1989    ArticleIdent: Q21844

 Question:
    Why does the compiler give negative numbers or "Overflow" errors in
 intermediate calculations involving two integers, when the same program
 works correctly in the IBM BASICA and GW-BASIC Interpreters?
    The following program is an example of the problem:

    10 FOR I%=240 TO 300
    20 Z! = INT( 130 * I% )
    30 PRINT I%,Z!
    40 NEXT

    The above program will give incorrect negative results in
 QuickBASIC Version 1.x when I% exceeds 252 and Z! exceeds 32K
 (32,767).
    In QuickBASIC Versions 2.x and greater, you will get an "Overflow"
 error.
    The same program will run in GW-BASIC and IBM BASICA completely
 through to I%=300 and print the correct values for Z!.

 Response:
    The above program will work properly if you make the integer
 constant "130" into a single-precision constant ("130!" or "130.") or
 double-precision constant "130#" as shown in the following example:

    20 Z! = INT( 130! * I% )

    QuickBASIC Version 1.x should not give negative results when an
 integer overflow occurs. This problem was corrected in Version 2.x and
 later, in which you properly get an "Overflow" message.
    The QuickBASIC compiler handles integer overflow differently than
 the GW-BASIC and IBM BASICA Interpreters handle it.
    When the compiler compiles a mathematical expression, it has to
 decide at compile time how to most efficiently optimize the expression
 into machine language. When the compiler sees the intermediate
 calculation 130*I% in the above program, it decides to restrict it to
 integer limits at compile time because 130*I% is the product of two
 integers. Changing the intermediate expression to the product of an
 integer and a higher-precision constant or variable will prevent the
 overflow problem.
    The interpreters are able to dynamically make the decision at
 run time to convert 130*I% to a single-precision constant to avoid
 integer overflow. The disadvantage of dynamic handling is the slower
 speed of the interpreters when compared with the compiler.


 20. Duplicate Labels Can Only Be Separately Compiled             s

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 27-DEC-1989    ArticleIdent: Q21862

 Question:

 Can I use the same line numbers or line labels in different
 subprograms that are compiled in the same source file?

 Response:

 No, but you can use the same line numbers or line labels if the
 subprograms are separately compiled.

 Line numbers and labels are local to the compiled module in which they
 occur. Line numbers and labels must be unique within a given compiled
 module. You do not need to worry about duplicate labels in separately
 compiled modules.

 Note that using the REM $INCLUDE metacommand to include source code
 from a separate file is similar to putting the two sources into one
 file. Any files included at compile time with the REM $INCLUDE
 metacommand are considered as part of that module, and are included in
 the .OBJ file.

 This information needs to be added to Section 9.2.1, "Using Line
 Labels", on Page 160 of the "Microsoft QuickBASIC Compiler" manual for
 Versions 2.00, 2.01, and 3.00.


 21. CALL ABSOLUTE "Unresolved Subprogram Reference," "Not Defined"

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q21899

 Problem:

 When I attempt to use the CALL ABSOLUTE statement in the QB.EXE
 editor, I get an "Unresolved Subprogram Reference" error message at
 compile time in QuickBASIC Versions 2.00, 2.01, and 3.00. I get a
 "Subprogram not defined" error message in QB.EXE in QuickBASIC
 Versions 4.00, 4.00b, 4.50.

 Response:

 For QuickBASIC Versions 4.00, 4.00b, 4.50
 -----------------------------------------

 The routine named ABSOLUTE is an external assembly language routine
 located in the QB.QLB Quick library (and in the QB.LIB linker
 library). To invoke CALL ABSOLUTE from within the QB.EXE 4.00, 4.00b,
 or 4.50 editor, you must invoke QB /L to load the QB.QLB Quick
 library. If you choose Make EXE File... from the Run menu, QuickBASIC
 then automatically links your program with QB.LIB.

 For QuickBASIC Versions 2.00, 2.01, 3.00
 ----------------------------------------

 The routine called ABSOLUTE is an external assembly language routine
 located in a file called USERLIB.OBJ in QuickBASIC Versions 2.00 and
 2.01, and in a file called ABSOLUTE.OBJ in Version 3.00. To CALL
 ABSOLUTE, you will need to build a user library containing ABSOLUTE's
 .OBJ file, or link your program directly to it, as in the following
 examples:

 1. To CALL ABSOLUTE from a user library in Versions 2.00 and 2.01, do
    the following:

       BUILDLIB USERLIB.OBJ,USELIB1.EXE;
       QB test.bas/L USELIB1.EXE;

    To LINK TEST.BAS to ABSOLUTE in Versions 2.00 and 2.01, do the
    following:

       QB test.bas;
       LINK test.OBJ+USERLIB.OBJ;

 2. To CALL ABSOLUTE from a user library in Version 3.00, do the
    following:

       BUILDLIB ABSOLUTE.OBJ,USELIB1.EXE;
       QB test.bas/L USELIB1.EXE;

    To LINK TEST.BAS to ABSOLUTE in Version 3.00, do the following:

       QB test.bas;
       LINK test.OBJ+ABSOLUTE.OBJ;


 22. QuickBASIC and BASIC Compiler 6.00 Support Only MS-NET, PC-NET

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21850

 The only network supported by QuickBASIC versions earlier than and
 including Version 4.50 is the MS-NET family, including IBM PC-NET.

 Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft BASIC
 PDS Version 7.00 also only support networks in the MS-NET family,
 including IBM PC-NET.


 23. FILES Statement Always Displays Name of Current Directory

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 27-DEC-1989    ArticleIdent: Q21809

 Problem:
    When I request a directory listing of a subdirectory other than the
 current directory using FILES "\subdir", I get the file list for the
 different subdirectory, but I get the name of the current directory
 displayed at the top. I expected the requested subdirectory name to be
 at the top.

 Response:
    The FILES statement in QuickBASIC is behaving in a manner
 consistent with BASICA and GW-BASIC Version 3.20. It is not likely that
 this behavior will change.


 24. 8087 Coprocessor Support for QuickBASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 27-DEC-1989    ArticleIdent: Q21819

 Question:

 Does QuickBASIC support the 8087 or 80287 coprocessor?

 Response:

 QuickBASIC Versions 3.00 and later support the 8087 and 80287 coprocessor.

 The QuickBASIC Versions 1.x and 2.x do not support the 8087 chip.
 However, Hauppage Computer Works, New York (516-360-3827), may offer a
 library to which you can link to provide this support.


 25. Compatibility of Compiled BASIC with Microsoft Windows

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified: 21-SEP-1990    ArticleIdent: Q21831

 This article discusses compatibility between Microsoft Windows and the
 following BASIC products and their compiled programs: QuickBASIC for
 the IBM PC, Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Windows 3.00 Compatibility
 --------------------------

 If you use Microsoft Windows version 3.00 with the special 386
 enhanced mode, you can run a BASIC program in a text window, which you
 could not do in earlier versions of Windows. In 386 enhanced mode,
 BASIC programs can run as background processes in the text window. In
 earlier Windows releases, you could only run BASIC programs as
 full-screen processes. However, in both Windows 3.00 and in earlier
 versions, you cannot run the QB.EXE or QBX.EXE editor in a window; you
 must instead run QB.EXE or QBX.EXE as a full-screen process.

 In Windows 3.00 standard mode (WIN /r) and real mode (WIN /s), you can
 run a compiled program, QB.EXE, or QBX.EXE only as full-screen
 processes, which means that they won't run in the background. You
 cannot press the Windows key combinations CTRL+ESC or ALT+ESC to get
 out of the full-screen BASIC program. Furthermore, other Windows
 processes will be stopped while you run the full-screen process. You
 must terminate the BASIC program to return to Windows.

 Windows 1.x, 2.x Compatibility
 ------------------------------

 Compiled BASIC programs, QB.EXE, and QBX.EXE run only as "bad
 applications" in Microsoft Windows versions 1.x and 2.x. "Bad
 applications" require you to create a PIF (Program Information File)
 using the Windows PIFEDIT.EXE program. When you make a PIF for QB.EXE,
 QBX.EXE, or BASIC compiled programs, you need to specify that the
 program directly modifies the screen, the keyboard, COM1, COM2, and
 memory. QuickBASIC version 4.00, 4.00b, and 4.50 programs have been
 successfully tested under Microsoft Windows 1.x and 2.x.

 The QB.PIF or QBX.PIF file provided on the QuickBASIC 4.00, 4.00b, and
 4.50, BASIC compiler 6.00 and 6.00b, or BASIC PDS 7.00 and 7.10
 release disks can be studied in PIFEDIT.EXE as a guideline for making
 your own PIF files for your compiled .EXE programs.

 Neither QuickBASIC version 3.00 and its earlier versions nor Microsoft
 BASIC Compiler 5.36 or earlier versions have been tested under
 Microsoft Windows. Therefore, they may or may not run successfully as
 bad applications.


 26. Reserved Words Not Necessarily Implemented as Features

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q21832

 This article discusses why some of the reserved words listed in the
 manual are not implemented in QuickBASIC. For example, LCOPY is not
 supported in QuickBASIC Version 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
 4.00, 4.00b, or 4.50 for MS-DOS, Microsoft BASIC Compiler Version
 6.00, 6.00b for MS-DOS and MS OS/2, or Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2. Another case is where PALETTE and PALETTE
 USING were not supported in QuickBASIC Versions 1.x, but were added in
 Versions 2.00 and later.

 Keywords are reserved for reasons of compatibility with past, present,
 and future versions of Microsoft BASIC. A list of reserved words is
 provided to warn programmers not to use keywords used in past and
 present versions of Microsoft BASIC. Some words are on the list but
 not currently implemented or supported because these reserved words
 represent possible additions for future versions of BASIC.


 27. .EXE File Size Larger than Other BASIC Compilers

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 27-DEC-1989    ArticleIdent: Q21833

 Question:

 Why is an .EXE file compiled in QuickBASIC larger than an .EXE file
 compiled in the IBM Version 1.0 BASIC Compiler or the generic
 Microsoft MS-DOS BASIC Compiler Version 5.36?

 Response:

 QuickBASIC .EXE programs are larger because of added features and
 functionality. A program compiled with QuickBASIC will usually be
 larger than one compiled with older compilers.


 28. Last SOUND Truncated at End of Program

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-DEC-1989    ArticleIdent: Q21835

 Question:

 When I put SOUND statements at the end of the program and run the .EXE
 file, why is the sound truncated at the end?

 Response:

 When a program ends, the BASIC run-time system is exited, which
 immediately stops any SOUND whose duration exceeds the time taken to
 execute any remaining statements in the program. If you have
 QuickBASIC Version 2.00 or later, the problem will not occur in the
 editor environment, because the run-time system is still available.

 To give the program time to complete its SOUND statements, give the
 program something to do after the SOUND (a dummy loop for example) so
 that the SOUND has time to finish before the program terminates.


 29. Length of Strings, String Descriptors in Compiler, Interpreter

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified:  1-AUG-1990    ArticleIdent: Q21836

 String variables in QuickBASIC versions 1.00 through 4.50 and in
 Microsoft BASIC Compiler versions 6.00 and 6.00b and in Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 can
 contain up to 32,767 characters (32K). Each variable-length string
 variable has a 4-byte string descriptor, which is composed of a 2-byte
 length followed by a 2-byte address.

 Fixed-length strings (which were introduced in QuickBASIC versions
 4.00 and later and in BASIC compiler 6.00 and later) do not have a
 string descriptor.

 For comparison, variable-length string variables in Microsoft GW-BASIC
 (versions 3.20, 3.22, 3.23) and IBM BASICA Interpreters have 3-byte
 string descriptors, with 1 byte of length followed by 2 bytes of
 address. String variables may contain up to 255 characters in GW-BASIC
 and IBM BASICA.


 30. Maximum Number of Records in a Random Access File

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 22-JAN-1990    ArticleIdent: Q21811

 Question:

 What is the largest number of records that I can use in a random
 access file?

 Response:

 The maximum relative record number for QuickBASIC Versions 3.00 and
 earlier is 16,777,215 (16 megabytes).

 QuickBASIC Version 4.00 is capable of handling up to 2 to the 31st
 power minus 1 (or 2,147,483,647), but DOS limits you to 32 megabytes
 of one-byte records.

 For all versions of QuickBASIC, a record length cannot exceed 32,767
 bytes.

 DOS versions up to Version 3.30 and OS/2 Version 1.00 limit you to a
 total file size of 32 megabytes, or 32,768,000 bytes. The following
 are two examples of the maximum number of records allowed:

 1. 8.192 million records with 4 bytes each

 2. 2.048 million records with 16 bytes each


 31. WIDTH 40, WIDTH 80; "Illegal Function Call"

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-DEC-1988    ArticleIdent: Q21859

 Question:

 Why do I get an "Illegal Function Call" using a WIDTH statement with a
 width other than 40 or 80?

 Response:

 The WIDTH statement operates the same way in QuickBASIC as it does in
 the GW-BASIC Version 3.20 and IBM BASICA interpreters.

 To change the allowed width of screen output, you need to open the
 "SCRN:" device and output as follows:

   width "scrn:",11    ' Sets screen width to 11 characters.
   open "scrn:" for output as #1
   print#1, "123456789012345678901234567890"
   close


 32. < RESUME Linenumber > Is Not Allowed for Subprograms

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 16-NOV-1988    ArticleIdent: Q21805

 Question:

 How can I use ON ERROR GOTO to trap errors that occur inside of
 subprograms separately compiled from the main program in QuickBASIC
 Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, and 4.00 for MS-DOS?

 Response:

 The following information should be added to the "Microsoft QuickBASIC
 Compiler" documentation for Versions 1.x, 2.x, and 3.00:

 Error handling in separately compiled subprograms should be coded in
 the following fashion:

    SUB test STATIC
    ON ERROR GOTO errortrap
       ' body of subprogram
    END SUB
    errortrap:
       ' The error is handled here:
       PRINT "Error Number Trapped="ERR
       RESUME NEXT

 In QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, and 4.00,
 the ON ERROR GOTO Label statement must be established for each module;
 otherwise, an error occurring in that module will not be trapped, and
 the program will stop. In QuickBASIC Versions 4.00 and earlier, error
 handling routines are local to each separately compiled module. A
 given error handling routine serves all subprograms that are compiled
 in the same module. To trap errors, the ON ERROR GOTO statement should
 appear in each subprogram that is compiled separately from the main
 module.

 In contrast to earlier versions, QuickBASIC Versions 4.00b and 4.50,
 and the Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and MS OS/2 offer global handling of ON ERROR (as explained in the
 UPDATE.DOC disk file). With global error-handling, an ON ERROR handler
 in the main program handles errors occurring in separate modules when
 those modules do not have their own ON ERROR handlers.

 All versions of QuickBASIC do not allow you to use < RESUME
 linenumber > or < RESUME linelabel > to handle errors that occur in
 subprograms. QuickBASIC only allows the use of RESUME or RESUME NEXT
 with subprograms. This fact needs to be added to Pages 128 and 129 of
 the "Microsoft QuickBASIC Compiler" documentation for Versions 2.x and
 3.00.

 In Version 1.02, if a < RESUME linenumber > or < RESUME linelabel >
 statement is used in a separately compiled subprogram, an "SB"
 (subprogram) error displays, but an OBJ file still will be created.
 You should not LINK the OBJ file if it receives an "SB" error, or if
 it uses < RESUME linenumber > or < RESUME linelabel > with
 subprograms. If you did use the file, you could receive unpredictable
 errors at run time due to eventual stack overflow.

 QuickBASIC Versions 2.00 and later will properly give you a
 "Subprogram Error" message and will not produce an OBJ file if you use
 < RESUME linenumber > or < RESUME linelabel >.

 Note also that < RETURN linenumber > or < RETURN linelabel > is not
 allowed with "ON event GOSUB" trapping used with subprograms; only
 RETURN is allowed. This fact applies to ON TIMER GOSUB, ON KEY GOSUB,
 ON PLAY GOSUB, ON STRIG GOSUB, and ON PEN GOSUB. Event trapping should
 be structured similar to error trapping in the sample program above.

 For a related article, you may query on "subprogram module error
 resume QuickBASIC" in this database.


 33. Passing Variables to ON ERROR and ON Event Handlers

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21863

 This article discusses how a QuickBASIC program can I pass variables
 to ON ERROR and ON "event" handler routines compiled with subprograms
 that are separate from the main program.

 (The different ON "event" statements are ON TIMER GOSUB, ON KEY GOSUB,
 ON PLAY GOSUB, ON STRIG GOSUB, and ON PEN GOSUB.)

 This information applies to Microsoft QuickBASIC 1.00 1.01 1.02 2.00
 2.01 3.00 4.00 4.00B and 4.50, to Microsoft BASIC Compiler 6.00 and
 6.00B, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Variables can be passed through the COMMON SHARED statement to ON
 ERROR and ON "event" handler routines compiled separately from the
 main program. Variables that are not in COMMON SHARED are not
 accessible to the handler routines (unless the handler is in the same
 source file as the main program).

 The following is an example of a separately compiled subprogram that
 shares a flag variable with its error handler routine:

    ' TEST.BAS
    COMMON SHARED FLAG
    errortrap:
       ' The error is handled here:
       PRINT "Error Number Trapped="ERR
       FLAG=5
       RESUME NEXT  ' Resumes to line after where error occurred.
    SUB test STATIC
    ON ERROR GOTO errortrap
    FLAG=0
    ERROR 5  ' Forces a test error number 5 to occur.
    PRINT "FLAG=",FLAG  ' Execution resumes here after the error.
    END SUB

 This program is called by the following separate main program module:

    ' MAIN.BAS
    CALL TEST

 First, compile as follows:

    BC MAIN/X;
    BC TEST/X;

 You then can LINK MAIN+TEST; run the resulting program as an example.

 You cannot use the linenumber or linelabel option of RETURN or RESUME
 in conjunction with subprograms.

 In QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, and 4.00,
 error and event handling routines are local to each separately
 compiled module. A given error or event handling routine serves all
 subprograms compiled in the same module. The ON ERROR GOTO or ON event
 GOSUB statement should appear in each subprogram that is compiled
 separately from the main program.

 QuickBASIC Versions 4.00b and 4.50, Microsoft BASIC Compiler Versions
 6.00 and 6.00b, and Microsoft BASIC PDS Version 7.00 offer global
 error handling, which is described in a separate article. For more
 information, query on the following words:

    global and error and handling and QuickBASIC


 34. COMSPEC; SHELL "Illegal Function Call", Can't Find COMMAND.COM

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21901

 Customers who have floppy disk drive systems frequently find that the
 SHELL command fails in the QuickBASIC editor or in a program running
 on the system because QuickBASIC cannot find COMMAND.COM.

 Note that the SHELL command will work reliably only under DOS Version
 3.00 or later.

 Failure to locate COMMAND.COM during a SHELL can generate one of the
 following errors:

 1. The error message "File not found"

 2. The error message "Could not load COMMAND.COM"

 3. The error message "Illegal Function Call"

 4. A refusal to SHELL

 A program needs to find COMMAND.COM before it can execute a SHELL
 statement. The SHELL command in the File menu in the editor in
 QuickBASIC Version 2.00, 2.01, 3.00, 4.00, 4.00b, or 4.50 also needs
 to find COMMAND.COM before executing.

 QuickBASIC looks first for COMMAND.COM in the directory specified by
 the system COMSPEC environment variable and then in the current
 directory.

 The COMSPEC environment variable can be set by the MS-DOS SET command
 in your AUTOEXEC.BAT file or in the MS-DOS command line, as follows:

    SET COMSPEC=drive:\directory

 To tell MS-DOS where to find COMMAND.COM, you can also specify the
 following command in your MS-DOS Version 3.20 CONFIG.SYS file (which
 is executed at boot time):

    SHELL=A:\COMMAND.COM /E:1000 /P

 In the above command, /E:size sets the size (in bytes) for MS-DOS
 environment space, and /P tells the command processor that it is the
 first program in the system so that it can process the MS-DOS EXIT
 command. This SHELL= statement may not work under MS-DOS Version 3.30,
 but works properly under MS-DOS Version 3.20. Under MS-DOS Version
 3.30, you need to use SET COMSPEC.

 This article applies to QuickBASIC Versions 2.00, 2.01, 3.00, 4.00,
 4.00b, and 4.50 for the IBM PC and compatibles, Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS, and Microsoft BASIC PDS
 Version 7.00 for MS-DOS.


 35. EGA 43-Line Mode Supported in QuickBASIC Version 3.00 Editor

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 24-JAN-1990    ArticleIdent: Q21911

 This article discusses which versions of QuickBASIC will display EGA
 43-line mode in the editor or "environment."

 QuickBASIC Versions 2.00, 2.01, and earlier do not support EGA 43-line
 mode.

 QuickBASIC Versions 3.00 and later do support EGA 43-line mode. The
 MODE43.EXE program can be run in DOS to toggle 43-line mode on or off
 before running QuickBASIC.

 In Versions 4.00 and later, an /h option for QB has been added to
 automatically display the highest resolution possible on your
 hardware. For example, if you have an EGA card, QuickBASIC displays 43
 lines and 80 columns of text when you type the following at the DOS
 prompt:

    QB DEMO1.BAS /H

 As with QuickBASIC Version 3.00, a compiled program itself can also
 put the screen into 43-line mode on an EGA-equipped computer by using
 the WIDTH statement. The 43-line mode syntax for WIDTH is documented
 in the README.DOC file for QuickBASIC Version 3.00, in the BASIC
 language reference for QuickBASIC Versions 4.00, 4.00b, and 4.50, and
 also in the QB Advisor in Version 4.50.


 36. Beep When Editing INPUT or LINE INPUT Statement Responses

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21915

 This article explains why the UP, DOWN, PGUP, and PGDN cursor keys
 produce a beep when editing what is typed in response to the INPUT or
 LINE INPUT statement at run time.

 The input editor used by INPUT and LINE INPUT is a line editor only.
 This means you can move and edit only horizontally, such as with the
 LEFT and RIGHT ARROW cursor-control keys and the BACKSPACE key.
 Attempts to use the UP, DOWN, PGUP, and PGDN cursor keys produce a
 beep.

 This information applies to Microsoft QuickBASIC 2.00 2.01 3.00 4.00
 4.00B and 4.50, to Microsoft BASIC Compiler 6.00 and 6.00B, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.


 37. CIRCLE Starting Angle of -0 Does Not Draw Line from Center

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q21947

 In SCREEN 1 or 2 (or a higher graphics mode such as SCREEN 8), a
 CIRCLE statement with a start or end angle value of negative zero (-0)
 does not generate a line from the circle edge to the center in
 QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50, Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and Microsoft BASIC
 PDS Version 7.00. It does generate the line in BASICA or GW-BASIC
 Version 3.20.

 The following is an example:

    10 SCREEN 1
    20 X=0
    25 REM  Radius=100, -x=start angle, 1=end angle:
    30 CIRCLE (160,100),100,,-X,1

 A workaround is to use x=.00001 instead of x=0 in the above program,
 as follows:

    10 SCREEN 1
    20 X=.00001
    30 CIRCLE (160,100),100,,-X,1

 Microsoft considers this to be an acceptable difference between the
 QuickBASIC Compiler and the BASIC interpreters.


 38. ENVIRON Statement Produces "Out of Memory" Error Message

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | b_basiccom
 Last Modified: 29-APR-1990    ArticleIdent: Q21963

 Most forms of the ENVIRON statement produce the run-time error message
 "Out of memory" (on DOS Versions 2.x through 3.30). The following
 example produces the "Out of memory" error message:

    ENVIRON "PATH=C:\COBOL"

 The following example usually works correctly, however, the ENVIRON
 statement is not very practical in QuickBASIC:

    ENVIRON "PATH=;"

 Expanding the environment table cannot be done in a QuickBASIC program
 because the size of the environment table is limited to its size
 rounded up to the nearest multiple of 16 bytes, when QuickBASIC or a
 QuickBASIC program is initiated.

 QuickBASIC does not modify the actual DOS environment table; it only
 modifies a local copy.

 You can work around this problem by doing the following:

 1. SET a large string in the MS-DOS environment table before running
    QB.EXE or a compiled program, as in the following example:

    SET JUNK=123456789012345678901234567890

 2. Use the following ENVIRON statements in your program to set the
    large string equal to a null string, then you can allocate strings
    whose length totals up to the size that was deallocated:

    PRINT ENVIRON$("JUNK")  ' DOS environment variables MUST be
                            ' uppercase.

 ENVIRON "JUNK=;"           ' This deallocates environment table
                            ' space.

 PRINT ENVIRON$("JUNK")     ' This confirms deallocation; prints
                            ' nothing.

 ENVIRON "TEST=C:\COBOL"    ' This sets up new environment string.

 PRINT ENVIRON$("TEST")     ' This displays the new environment
                            ' string.

    Note that the MS-DOS environment variable names must be uppercase.


 39. "Subscript Out of Range" Dimensioning a Dynamic Numeric Array

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 11-JAN-1990    ArticleIdent: Q21964

 Problem:
    I can dimension a single-dimensional dynamic integer array with
 32,000 elements; however, I get the message "Subscript Out of Range"
 dimensioning a two-dimensional integer array with only 30,000
 elements. The following is an example:

    Rem $dynamic
    dim b%(32000) 'this is okay
    dim c%(10,2850) 'this is also okay
    dim a%(10,3000) ' this will give a "subscript out of range" error

 Response:
    The statement DIM A%(10,3000) exceeds the 64K size limit that
 exists for each dynamic numeric array. In QuickBASIC Version 4.00 and
 greater, you can compile with QB /AH or BC /AH to allow dynamic
 numeric (or fixed-length string) arrays to exceed 64K. The /AH switch
 is not implemented in QuickBASIC 3.00 and previous versions.
    An array dimensioned DIM B%(32000) actually has 32,001 elements
 because the counting begins at element 0 by default, and the array
 will take up 64,002 bytes, since there are two bytes per integer
 element.
    You may change the default starting element to 1 with the OPTION
 BASE 1 statement. An array dimensioned DIM C%(10,2850) actually has
 31,361 elements (11 multiplied by 2,851) which would take up 62,722
 bytes. An integer array dimensioned (10,3000) gives a "subscript out
 of range" error because it has 33,011 elements, or 66,022 bytes, which
 exceeds the dynamic numeric array size limit of 65,536 bytes (64K).
    Note that there are 1,024 bytes per Kilobyte (K), therefore 64K
 multiplied by 1024 bytes per Kilobyte equals 65,536 bytes.


 40. ON KEY Trap Fails If CAPS/NUM LOCK Active; Need Separate KEY

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr
 Last Modified: 15-JAN-1990    ArticleIdent: Q21987

 This article describes a necessary addition to the "Microsoft
 QuickBASIC Compiler" manual for Versions 2.00, 2.01, and 3.00. This
 information is already covered in the documentation for QuickBASIC
 Versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler Versions
 6.00, 6.00b, and Microsoft BASIC Professional Development System (PDS)
 Version 7.00. The information below also applies to these versions.

 Key trapping does not function while the CAPS LOCK key or NUM LOCK key
 is activated, unless you specifically set up special user-defined keys
 for that key combination. The program below (and the similar program
 on Page 317 of the "Microsoft QuickBASIC Compiler" manual for Versions
 2.00, 2.01, and 3.00) demonstrates the ignored key trapping when CAPS
 LOCK or NUM LOCK is active.

 The following program correctly traps CTRL+C when CAPS LOCK and NUM
 LOCK are NOT active, but does NOT trap CTRL+C if either CAPS LOCK or
 NUM LOCK (or both) is activated:

    key 15,chr$(&H04)+chr$(&H2E)
    key(15) on
    on key(15) gosub test
    while x$<>chr$(27)
    x$=inkey$
    if x$<>"" the print x$,asc(x$)
    wend
    end
    test:
    print "Control-C has been trapped"
    return

 This behavior is not a problem in the compiler. The following notes
 should be added to Page 317 of the "Microsoft QuickBASIC Compiler"
 manual for Versions 2.0x and 3.00; these notes also apply to
 QuickBASIC Versions 4.00, 4.00b, and 4.50, BASIC Compiler Versions
 6.00, 6.00b, and BASIC PDS Version 7.00.

 To trap the desired key in combination with the CAPS LOCK or NUM LOCK
 key active, a different keyboard flag must be used for each
 combination. A value of &H20 hex must be added to the keyboard flag if
 you want to trap a key while the NUM LOCK key is down. An &H40 must be
 added to the keyboard flag if you want to trap a key while the CAPS
 LOCK key is down. For example, a KEY 16 can be added to the above
 program to trap CTRL+C while the CAPS LOCK key is down, as in the
 following:

    KEY 16, CHR$(&H44)+CHR$(&H2E)
    ON KEY (16) GOSUB TEST

 The &H44 above reflects the sum of &H40 (for CAPS LOCK active) and
 &H04 (the keyboard flag for CTRL).

 A KEY 17 can be added to the above program to trap CTRL+C when both
 CAPS LOCK and NUM LOCK are pressed down, as in the following:

    KEY 17, CHR$(&H64)+CHR$(&H2E)
    ON KEY (17) GOSUB TEST

 The keyboard flag &H64 above reflects the sum of &H40 (for CAPS LOCK
 active), &H20 (for NUM LOCK active), and &H04 (the keyboard flag for
 CTRL).


 41. Using Page 2 in SCREEN 9 Gives "Illegal Function Call" on EGA

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 11-JAN-1990    ArticleIdent: Q21956

 Question:

 Why do I get an "Illegal Function Call" error message when I reference
 Page 2 in SCREEN mode 9 on a computer with an EGA card? The following
 is an example:

    SCREEN 9,1,2,2  'EGA mode=9, 1=colorswitch on, apage=2, vpage=2
    COLOR 2,0
    LINE (1,1)-(100,100)

 Response:

 Screen 9 does have two pages available, but the pages are referenced
 as "0" and "1". Note that "2" is not a valid page number in screen 9.
 The program will work correctly if coded as follows:

    SCREEN 9,1,1,1  'EGA mode=9, 1=colorswitch on, apage=1, vpage=1
    COLOR 2,0
    LINE (1,1)-(100,100)


 42. CTRL+BREAK Doesn't Break Program on Tandy 1000; Use CTRL+HOLD

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 11-JAN-1990    ArticleIdent: Q21973

 On a Tandy 1000, running a program from the QuickBASIC editor, the
 CTRL+BREAK key sequence does not break execution of the program.

 This is not a problem with QuickBASIC but is rather a nonstandard
 keyboard sequence on the Tandy 1000. CTRL+HOLD should be used instead
 of CTRL+BREAK on a Tandy 1000. This also applies to the Tandy 1000 SX.

 This information applies to the QB.EXE environment in Microsoft
 QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for
 MS-DOS, to QB.EXE in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS, and to QBX.EXE in Microsoft BASIC PDS Version 7.00 for
 MS-DOS.


 43. SCREEN 1 COLOR Yellow Is Brown (Muddy) on EGA Versus CGA Card

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 11-JAN-1990    ArticleIdent: Q21969

 The following program, which uses the COLOR statement on SCREEN 1, may
 give different colors on a machine with an EGA card compared to the
 colors on a machine equipped with a CGA card:

    10 SCREEN 1
    20 COLOR 8,0
    30 LINE (30,100)-(40,150),3,bf
    40 LINE (10,40)-(60,100),2,bf
    50 LINE (100,100)-(130,130),1,bf

 The background color selected is dark gray (8). Palette 0 is selected,
 and includes red, green, and yellow on a CGA. Under QuickBASIC on an
 EGA card, the colors may appear "muddy" compared to running on a CGA
 card: the red and green are less intense than shown on a CGA card and
 the yellow is brown.

 This is not a problem with QuickBASIC, but is a difference between CGA
 and EGA cards. The EGA allows only nonintensified colors. The same
 colors occur on an EGA card in the Microsoft GW-BASIC Version 3.20,
 3.22, or 3.23 Interpreter on an EGA card.

 Note that in SCREEN 1 on an EGA or VGA, the PALETTE statement can
 change the color used by output from the PRINT statement, for example

    PALETTE 3,n

 where n can be a color from 0 to 15. On an EGA card, PALETTE 3,6
 (where 6 is brown) is the default. PALETTE 3,14 will make PRINT output
 appear in yellow.

 The PALETTE statement is not supported on CGA cards. On a CGA card,
 the color of text output with the PRINT statement can only be changed to
 one of two possible colors by changing the palette argument of the
 COLOR statement. For example

    COLOR b,p

 where b is the background color, and p (the palette) can be 0 or 1. If
 the p argument is 0, PRINT output displays in color number 6 (brown on
 an EGA, yellow on some CGA cards). If the p argument is 1, PRINT
 output displays in color number 7 (white). See the COLOR statement in
 the BASIC language reference documentation for more information.

 Graphics statements such as LINE and CIRCLE can use color (attribute)
 arguments 0, 1, 2, or 3 to allow simultaneous display of four colors
 at once (including the background) in SCREEN 1 on CGA, EGA, or VGA.


 44. SHELL Can Give "Out of Memory" Error or Fragment Memory

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q21902

 Question:

 Why do I get an "Out of Memory" error when I use the SHELL statement
 or the Shell command?

 Response:

 The SHELL statement does not clean up or compress memory. If not
 enough contiguous memory is available (for example, if many CHAIN
 statements have been executed, or several dynamic arrays were
 allocated then erased), a SHELL statement may fail with an "Out of
 memory" error. This includes both the Shell command from the File menu
 and also the SHELL statement in a running program.

 Also, if you mistakenly install any TSR (terminate and stay resident)
 program during a SHELL command, you will fragment memory, which often
 results in an "Out of Memory" error. For example, if you run the
 QuickBASIC environment, choose the Shell command from the File menu,
 install a TSR, EXIT the Shell, Exit the QuickBASIC environment, and
 reinvoke the QuickBASIC environment from DOS, then you get an "Out of
 Memory" error immediately before you can do anything in the
 environment. You must reboot to unfragment DOS memory.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS.

 TSR programs should NEVER be installed during a SHELL statement or a
 Shell from the File menu. Examples of TSR programs are MSHERC.COM
 (from QuickBASIC 4.50) and QBHERC.COM (from QuickBASIC 4.00/4.00b and
 the BASIC compiler 6.00/6.00b).


 45. "Type Mismatch" Using TAB() Between PRINT USING Variables

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 22-JAN-1990    ArticleIdent: Q32968

 When using the TAB function between variables in the following PRINT
 USING and LPRINT USING statements, a "Type Mismatch" error displays in
 the QB.EXE Version 4.00 or 4.00b environment:

    PRINT USING "$$##.##";x;TAB(10);z
    LPRINT USING "$$##.##";x;TAB(10);z

 However, when run as an .EXE program, the above statements print
 successfully. They also run correctly in QuickBASIC Version 3.00,
 either in the editor or as an .EXE program.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in the QuickBASIC editor provided with Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS (buglist6.00,
 buglist6.00b). This problem was corrected in QB.EXE in QuickBASIC
 Version 4.50 and does not occur in the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 (fixlist7.00).

 Note: The documentation for PRINT USING and LPRINT USING does not say
 whether TAB is legal in the PRINT USING expressionlist. TAB should be
 avoided in PRINT USING statements because compatibility with future
 Microsoft BASIC versions cannot be guaranteed.

 The best workaround for the above problem is to avoid using the TAB
 function in the PRINT USING or LPRINT USING statement, as shown in the
 following examples:

 1. To output at a desired column, use spaces between the desired
    format strings, instead of using the TAB function, as follows:

       x = 12.34 : z = 56.78
       PRINT USING"$$##.##         $$##.##";x;z

 2. To position the cursor at a desired column, use the LOCATE
    statement before executing the PRINT USING statement, as in the
    following example:

       x = 12.34: z = 56.78
       LOCATE 2, 1
       PRINT USING "$$##.##"; x
       LOCATE 2, 10
       PRINT USING "$$##.##"; z

 Note: When you type the following statement in QB.EXE Versions 4.00 or
 4.00b, the editor automatically inserts the missing semicolon in front
 of z:

    PRINT USING "$$##.##";x;tab(10) z

 The program then usually runs correctly (without getting a "Type
 Mismatch" error) in QB.EXE.


 46. PLAY "N0" First Note of Rest Clicks Speaker in QuickBASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist3.00 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q22018

 In QuickBASIC, the PLAY statement can produce a click on the speaker
 for the first note of rest (but not for subsequent notes of rest). For
 example, the following program will produce no sound when run under
 the BASICA or GW-BASIC Interpreter, but produces a single click when
 run as a compiled QuickBASIC program:

    10 while inkey$ = ""
    20 play "N0"    ' N followed by zero (0) means play a note of rest.
    30 wend

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 2.00, 2.01 (buglist2.00, buglist2.01), 3.00, 4.00, 4.00b, and 4.50; in
 Microsoft BASIC Compiler versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b); and in Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.


 47. XON/XOFF Communications Protocol Not Supported in QuickBASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 17-JAN-1991    ArticleIdent: Q22019

 The XON/XOFF handshaking protocol of the ASC option of the OPEN COM
 statement is not implemented in any version of QuickBASIC (including
 versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50), in Microsoft BASIC
 Compiler version 6.00 or 6.00b for MS-DOS, or in Microsoft BASIC
 Professional Development System (PDS) version 7.00 or 7.10 for MS-DOS.

 Except for XON/XOFF protocol, the other features of the ASC option of
 the OPEN COM statement work properly. During communications, the ASC
 option expands tabs to spaces, forces carriage returns at the
 end-of-line, treats CTRL+Z (ASCII value 26) as the end-of-file flag,
 and transmits CTRL+Z when you CLOSE the communications channel.

 When you OPEN the COM1 or COM2 communications port and specify the ASC
 option, XON and XOFF bytes have no effect. A program will continue to
 transmit and pass all received XON and XOFF characters to the program
 without halting or resuming transmission. This behavior occurs because
 the XON/XOFF handshaking protocol of the ASC option of the OPEN COM
 statement is not implemented.

 The sentence saying "XON/XOFF protocol is enabled" should be deleted
 in the documentation for the ASC option of the OPEN COM statement in
 the following manuals:

 1. Page 375 of the "Microsoft QuickBASIC Compiler" manual for
    QuickBASIC versions 2.x and 3.00

 2. Page 297 of the "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" manual for QuickBASIC versions 4.00 and 4.00b

 3. Page 297 of the "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" manual for versions 6.00 and 6.00b

 This documentation error has been corrected in the documentation for
 Microsoft QuickBASIC 4.50 and the BASIC Professional Development
 System (PDS) for MS-DOS and MS OS/2.

 Additional Background Information
 ---------------------------------

 XOFF is also known as CTRL+S, which is a character with an ASCII
 value of 19. CTRL+S tells a device or program that knows XON/XOFF
 protocol to stop transmission.

 XON is also known as CTRL+Q, which is a character with an ASCII value
 of 17. CTRL+Q tells a device or program that knows XON/XOFF protocol
 to continue transmission.

 The CTRL+S (XOFF) and CTRL+Q (XON) bytes pass without special handling
 through devices or programs that do not support the XON/XOFF
 communications protocol. While it is possible to write a BASIC program
 that checks every character for XON or XOFF and then programmatically
 starts or stops communications, such a program is unlikely to be as
 reliable as the XON/XOFF handshaking that is built into dedicated
 commercial communications software or hardware packages.


 48. SHELL "PATH=\..." Affects Only a Local Copy of DOS

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-JAN-1990    ArticleIdent: Q22015

 SHELLing to the DOS PATH command fails to change the default directory
 search path when you exit QuickBASIC. BASICA Version 3.10 behaves
 similarly.

 The following is an example:

    SHELL "PATH=\BASIC"

 According to Page 458 of the "Microsoft QuickBASIC Compiler" manual
 for Version 3.00 and Page 396 of the "Microsoft QuickBASIC Version
 4.0: BASIC Language Reference" manual, the SHELL statement allows
 execution of DOS commands such as DIR, PATH, and SORT.

 When you invoke a SHELL command from a QuickBASIC program, a local
 copy of COMMAND.COM and the DOS environment is spawned. When paths are
 changed, only the local environment copy is changed, not the original
 DOS environment.


 49. OPEN LEN=reclen Effect on Sequential File Buffering and Speed

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 19-JAN-1990    ArticleIdent: Q22021

 QuickBASIC Versions 2.00, 2.01, and 3.00 don't behave according to the
 following statement on Page 370 of the "Microsoft QuickBASIC Compiler"
 manual for Versions 2.00, 2.01, and 3.00, which discusses the
 recordlength option of the OPEN statement for sequential files:

    When used to open a sequential file, recordlength specifies the
    number of characters to be loaded to the buffer before it is
    written to, or read from, the disk. A larger buffer means more room
    taken from BASIC, but faster file I/O.

 Changing the LEN=reclen statement will not change the sequential
 file-access speed or buffering for QuickBASIC Versions 2.00, 2.01, or
 3.00, but WILL change speed and buffering for QuickBASIC 4.00 and
 later versions.

 For greater file-access speed, boot with a BUFFERS=20 statement in
 your CONFIG.SYS file (DOS configuration file) on the root directory of
 your start-up disk.

 Please note that in QuickBASIC Versions 4.00, 4.00b, and 4.50 for
 MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and OS/2, and Microsoft BASIC Professional Development System (PDS)
 Version 7.00, the LEN=reclen statement changes both the buffer size
 and sequential file-access speed. The default sequential-access buffer
 size is 512 bytes in these versions.

 The 512-byte size gives fast disk input/output speed because it
 matches the sector size or a multiple of the sector size for most disk
 drives. This is correctly documented in the "Microsoft QuickBASIC 4.0:
 BASIC Language Reference" manual for Versions 4.00 and 4.00b.

 By changing LEN=256 to LEN=10 or LEN=1000 in the following program, no
 file-output buffering or speed changes are apparent in QuickBASIC 2.x
 and 3.00 when you watch the disk-access light on the drive. However,
 you will notice buffering and speed changes in later QuickBASIC
 versions:

    PRINT "Start of program"
    OPEN "buf.dat" FOR OUTPUT AS #1 LEN=256
    PRINT "File was just opened"
    WHILE INKEY$="":WEND
    FOR Index% = 1 to 30
    PRINT "Record number --> ";Index%
    WRITE #1, STRING$(79,CHR$(48+Index%))
    WHILE INKEY$="":WEND
    NEXT Index%
    CLOSE #1
    END


 50. PRINT Forces Contiguous String to Next Row & Doesn't Wrap It

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_GWBasicI B_BasicCom
 Last Modified: 19-JAN-1990    ArticleIdent: Q22022

 The PRINT statement displays a contiguous string constant on the next
 row below the current print position (without breaking or wrapping the
 string) if printing it from the current screen column exceeds the 80th
 column.

 This behavior is by design. You will need to break the string into a
 piece small enough to fit within the space before the 80th column to
 avoid forcing the whole string to the next line (see example below).

 This standard behavior occurs in most retail Microsoft BASIC versions
 for MS-DOS, including the following products:

 1. QuickBASIC Compiler (Versions 2.00, 2.01, 3.00, 4.00, 4.00b,
    and 4.50) for MS-DOS

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    OS/2

 3. Microsoft BASIC Professional Development System (PDS) Version 7.00
    for MS-DOS and OS/2

 4. GW-BASIC Versions 3.20, 3.22, and 3.23

 The following is a code example:

    5  CLS
    10 LOCATE 1,1    ' LOCATEs in column 1.
    20 PRINT "LOCATED ON ROW 1, THIS STRING STAYS ON ROW 1."
    30 LOCATE 2,70    ' LOCATEs in column 70, leaving no room.
    40 PRINT "DESPITE BEING LOCATED ON ROW 2, THIS PRINTS ON ROW 3"
    50 LOCATE 4,71   ' To make it wrap, break up the string as follows:
    60 PRINT "1234567890";"THIS STARS IN COLUMN 1"


 51. SCREEN 7,8,9 "Illegal Function Call" Using Foreground COLOR 0

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q22036

 Executing the COLOR statement with a zero (0) as the foreground color
 gives "Illegal Function Call" on the EGA SCREEN modes 7, 8, and 9. For
 example:

    10 SCREEN 9
    20 COLOR 0,0   ' Gives "Illegal function call"

 This is because zero (0) is not within the allowed range of attributes
 with the EGA. The range of attributes is 1 to 3 for an EGA with 64K,
 and 1 to 15 for an EGA with more than 64K of memory.

 You can work around this behavior by using the PALETTE statement to
 reassign the color of zero to another attribute number. This can be
 accomplished by doing the following:

    DIM Pal%(16)
    SCREEN 7
    Pal%(0) = 15
    Pal%(15) = 0
    PALETTE USING Pal%(0)
    COLOR 15,1
    CLS

 This information applies to QuickBASIC versions 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Another way to simulate a foreground color of zero (0) in screen mode
 9 or 12 is shown in a separate article in this Knowledge Base. To find
 this article, query on the following words:

    foreground and background and GET and PUT and 16 and simultaneously

 (The graphics GET and PUT technique and sample program shown in this
 separate article could be modified for QuickBASIC 2.0x and 3.00.)


 52. CTRL+UP and CTRL+DOWN ARROW Keys No Longer Scroll the Screen

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 22-JAN-1990    ArticleIdent: Q23388

 CTRL+UP ARROW and CTRL+DOWN ARROW do not scroll the screen in QB.EXE
 in QuickBASIC Version 3.00, but they do in QuickBASIC Versions 2.00,
 2.01, 4.00, 4.00b, 4.50, in the QB.EXE editor that is included with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and in
 the QBX.EXE editor of Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for MS-DOS.

 Changes were made in the QuickBASIC Version 3.00 editor to allow
 Superkey support; support for CTRL+UP ARROW and CTRL+DOWN ARROW was
 removed during this change. In the non-3.00 product versions above,
 these keys successfully scroll the screen down or up one line at a
 time.


 53. Unexpected Result from CINT(.5) in QB87; IEEE Rounds to Even

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-FEB-1991    ArticleIdent: Q23389

 The coprocessor version of QuickBASIC version 3.00 (QB87.EXE) returns
 0 (zero) in the following example (as do QuickBASIC versions 4.00,
 4.00b, and 4.50; Microsoft BASIC Compiler versions 6.00 and 6.00b; and
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10, which all use the IEEE floating-point format):

    PRINT CINT(1/2)
    PRINT CINT(.5)
    PRINT CINT(1.0/2.0)

 Three zeros (0) are printed. This differs from the non-coprocessor
 version of QuickBASIC version 3.00 (QB.EXE) and earlier versions,
 which instead prints three ones (1).

 Compare this with the fact that PRINT CINT(1.5) returns 2 in both the
 coprocessor and non-coprocessor versions of QuickBASIC version 3.00
 (and in the other more recent products listed above).

 The observed rounding difference in the first case above is not caused
 by any bug. The IEEE standard dictates that rounding of x.5 occurs to
 the even integer nearest to x, for example, CINT(.5)=0, CINT(1.5)=2,
 CINT(2.5)=2, CINT(3.5)=4, CINT(4.5)=4, etc.

 The non-coprocessor version of QuickBASIC 3.00 (QB.EXE) supports a
 different floating-point format, the Microsoft Binary format (MBF),
 which rounds differently than the IEEE standard.


 54. Workarounds for CLOSE of COM(n) Disconnecting Phone Connection

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 16-APR-1990    ArticleIdent: Q26471

 QuickBASIC disconnects the phone connection when a program CLOSEs the
 communications port or when the program ENDs. This happens because the
 DTR line is dropped on a CLOSE or END statement. Below are several
 possible workarounds that might help you to overcome this design
 limitation of Microsoft QuickBASIC.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 The first workaround is to attempt to reset the DTR line immediately
 after the CLOSE statement. To do this, the correct OUT instruction is
 sent to the modem control register to set DTR (pin 20) high. Consider
 the following example:

      OPEN "COM(n): <parameters>" FOR <mode> AS #n
      ' The rest of your program code goes here.
      CLOSE #n
      OUT &H3FC,3
      END

 However, this example may not work because there is a small period of
 time between the CLOSE and the OUT statements. The modem may
 disconnect the phone connection even in this small time period.

 Some "smart" modems allow you to adjust the time-out period for the
 DTR line. If you set this time-out period higher, the modem will wait
 longer before disconnecting the phone connection. This gives you just
 enough time to execute the OUT instruction to set the DTR line higher.
 The following is an example:

      OPEN "COM(n): <parameters>" FOR <mode> AS #n
      PRINT #n, <control string>
      ' The rest of your program code goes here.
      CLOSE #n
      OUT &H3FC,3
      END

 In the above example, <control string> is a series of control codes
 sent to the modem to set the DTR time-out period higher. Consult the
 manual for your modem to determine the correct control code string.
 The following is an example of the above code modified to work with a
 Hayes Smartmodem:

      OPEN "COM(n): <parameters>" FOR OUTPUT AS #1
      PRINT #n, "AT S25=100" 'Sets the DTR time out to 100/100 seconds
      ' or 1 second. Note that a carriage return is sent after this
      ' PRINT statement. If you OPEN for BINARY, you have to send a
      ' CHR$(13) also, which tells the modem you are at the end of the
      ' initial control string.
      CLOSE #1
      OUT &H3FC,3
      END

 In some cases, a complaint about losing DTR may really be about losing
 RTS. If this is the case, some modems allow you to ignore RTS, as
 follows:

      OPEN "COM(n): <parameters>" FOR <mode> AS #n
      PRINT #n, <control string>
      ' The rest of your program code goes here.
      CLOSE #n
      END

 In this case, you would send a control string to the smart modem to
 tell it to ignore the RTS line.

 Note: If you do not have a smart modem and the first workaround does
 not correct the problem for you, it will be very difficult to work
 around this limitation of QuickBASIC. The best method is obtain a
 smart modem and attempt the second or third workarounds.

 The above examples use software instructions to set the DTR time-out
 period or to ignore the RTS line. However, some modems also allow
 these adjustments to be made with DIP switches.

 Notes on CHAINing and RUNning
 -----------------------------

 Whenever you compile standalone programs (/O), the CLOSE is performed
 implicitly when you do a RUN or a CHAIN. If your programs use
 BRUNxxx.EXE and the COM port is not CLOSEd, DTR and RTS should stay
 high. Compiling with BCOMxxx.LIB or closing the COM port always drops
 DTR.


 55. BC.EXE /T (Terse) Suppresses Warning Messages

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q27799

 The /T switch is not documented in QuickBASIC Versions 4.00b or 4.50.
 This option needs to be added to the following manuals:

 1. Page 211, "Microsoft QuickBASIC 4.0: Learning and Using" for
    Versions 4.00 and 4.00b

 2. Page 211, "Microsoft BASIC Compiler 6.0: Learning and Using
    Microsoft QuickBASIC" for Versions 6.00 and 6.00b

 3. Page 354 "Microsoft QuickBASIC 4.5: Programming in BASIC" for
    Version 4.50

 The /T (terse) option for the BC.EXE compiler Versions 4.00b and 4.50
 (not found in QuickBASIC Version 4.00 or earlier) suppresses warning
 messages during compilation. However, severe error messages are still
 displayed. The /T switch is also supported in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and OS/2 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2. The /T switch is correctly documented in BASIC PDS 7.00.

 When compiling with the Make EXE File command on the Run menu in the
 QB.EXE Version 4.00b or 4.50 editor, the BC /T option is automatically
 invoked. When you upgrade from QuickBASIC Version 4.00 to Version
 4.00b, you will notice /T automatically added to the BC command line
 in Version 4.00b whenever you choose the Make EXE File command in
 QB.EXE.

 The function of the /T switch is to suppress all warning-level
 messages (for example, "array not dimensioned"). However, all
 severe-level messages, which prevent the creation of OBJ files, will
 still be displayed.

 Note that the default communications buffer-size switch /C:512 is also
 automatically invoked for BC when you choose Make EXE File in QB.EXE
 in QuickBASIC Version 4.00b. This is not done automatically in QB.EXE
 in QuickBASIC Version 4.00 (even if QB.EXE Version 4.00 is invoked
 with the /C: option).

 The BC /T and /C: options are also automatically invoked when you
 choose Make EXE File in the QuickBASIC QB.EXE editor provided with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and in the QBX.EXE
 editor provided with Microsoft BASIC PDS Version 7.00.


 56. WIDTH Over 255 Not Trapped as Error in Version 4.00 Editor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 22-JAN-1990    ArticleIdent: Q27139

 If a width greater than 255 is used in the WIDTH statement, no error
 is generated within the QuickBASIC editor. No error is given by either
 the editor or BC.EXE if the width is specified using a variable.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 The maximum allowable width that can be specified using the WIDTH
 statement is 255. If a number greater than that is given, the error
 "Math overflow" should be generated. However, this message is not
 given when running in the editor or when the WIDTH argument is
 assigned to a variable.

 Results of testing with previous versions indicate that an error
 message is correctly given in the Version 3.00 editor.

 The following is a code example:

 open "cons:" for output as #1
 a = 400
 width #1, a   ' If 400 is used instead of "a", the error is correctly
               ' flagged when compiled with BC.EXE.


 57. ON X GOTO Line-List Allows Only <= 59 Line Labels or Numbers

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q27142

 An ON <expression> GOTO <line-list> statement allows only 59
 line-numbers or line-labels in the line-list.

 Using more than 59 labels gives you the error message "Too Many
 Labels" when run from a QuickBASIC Version 4.00, 4.00b, or 4.50
 executable .EXE file. The limitation does not occur when run in the
 QB.EXE Version 4.00, 4.00b, or 4.50 editor.

 The following manuals incorrectly imply that you can have up to 255
 line-numbers/line-labels in the ON <expression> GOTO statement: "Too
 Many Labels" error on Page 502 in "Microsoft QuickBASIC 4.0: BASIC
 Language Reference" for Versions 4.00 and 4.00b for MS-DOS, and Page
 502 of "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 The program below works without errors in Microsoft GW-BASIC Version
 3.22.

 The program below gives the error "Too Many Statement Numbers" in the
 QuickBASIC Version 3.00 editor. In QuickBASIC Version 3.00, the
 limitation occurs both in the editor and from an .EXE file.

 The following code demonstrates the 59-label limitation:

 t% = 62
 ON t% GOTO 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
  20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,_
  39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,_
  58, 59, 60, 61, 62, 63
 END
 1  '
 2  '
 3  '
 4  '
 5  '
 6  '
 7  '
 8  '
 9  '
 10 '
 11 '
 12 PRINT "here we are"
 13 '
 14 '
 15 '
 16 '
 17 '
 18 '
 19 '
 20 '
 21 '
 22 '
 23 '
 24 '
 25 '
 26 '
 27 '
 28 '
 29 '
 30 '
 31 '
 32 '
 33 '
 34 '
 35 '
 36 '
 37 '
 38 '
 39 '
 40 '
 41 '
 42 '
 43 '
 44 '
 45 '
 46 '
 47 '
 48 '
 49 '
 50 '
 51 '
 52 '
 53 '
 54 '
 55 '
 56 '
 57 '
 58 '
 59 '
 60 '
 61 '
 62 PRINT "line 62"
 63 '


 58. Passed Double-Precision Array Assigned Long Integer Hangs

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 22-JAN-1990    ArticleIdent: Q27201

 In the following program, a double-precision array is passed to a
 subprogram where a long integer is inserted into that array. If
 compiled with BC.EXE (without /D debug switch), your machine will stop
 when the program is run. The same program runs correctly inside the
 editor.

 The workaround is to use the debug (/D) option when compiling with
 BC.EXE.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and Microsoft BASIC Compiler Versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2. This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 The following code is an example of this problem:

 DECLARE SUB BFPPAC (A#(), i%)
                         'If put in $DYNAMIC OR $STATIC, it will work.
      DIM A#(4, 4)       'If it is a one-dimensional array, it will work.
      A#(1, 1) = 12345
      CALL BFPPAC(A#(), 3)   'If you pass only the array, it will work.
                           'CodeView says there is an illegal instruction
                           'here, and points to a POP statement in the
                           'assembly language version of the program.
      PRINT "THREE "
      FOR Z% = 1 TO 4        'If you do not print the array here, it
                             'will not hang, but when you print A#(1, 1)
            PRINT A#(Z%, 1)  'in the subprogram, it equals
      NEXT                   '2.316524914777163D-272 instead of 12345.
      END
 SUB BFPPAC (A#(), i%) STATIC
      'w% = i%               'If you insert this line, it will work.
      M1& = A#(1, 1)
      PRINT "ONE", M1&, A#(1, 1)  'Always prints out correctly.
      A#(i%, 1) = M1&
      PRINT "TWO", M1&, A#(1, 1), A#(3, 1)
                                 'M1& and A#(3,1) always print correctly,
                         'but if you have the program so it will
                     'hang, A#(1,1) will be
                                 '9.058940453046392D-233 when it is printed
                                 'out here.
 END SUB


 59. Can't Use Border Parameter of COLOR Statement on EGA, VGA Card

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified:  8-MAR-1989    ArticleIdent: Q25581

 The border argument, which is the third parameter of the COLOR
 statement (in SCREEN 0 only), is NOT supported on EGA, VGA, or MCGA
 cards.

 If you have an EGA card installed on your system, using the border
 parameter of the COLOR statement causes unpredictable results in
 QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50.

 The border argument is supported in SCREEN 0 on CGA cards.

 The following correction should be made on Page 222 of the "Microsoft
 QuickBASIC Compiler" documentation for Versions 2.00, 2.01, and 3.00:

    The EGA card does not support the COLOR statement border parameter.

 The documentation for the COLOR statement in QuickBASIC Versions 4.00,
 4.00b, and 4.50 correctly states that the following cards do NOT
 support the border argument of the COLOR statement:

    EGA (IBM Enhanced Graphics adapter)
    VGA (IBM Video Graphics Array adapter)
    MCGA (IBM Multicolor Graphics Array adapter)

 (The same applies to BASIC compiler Versions 6.00 and 6.00b for
 MS-DOS.) The border parameter of the COLOR statement is allowed only
 in SCREEN 0 on the CGA card, as shown:

    COLOR foreground,background,border

 The border color is used to draw the screen border.


 60. Integer "Overflow" Is Not Trapped without /D Debug Switch

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | b_basiccom
 Last Modified: 20-JUL-1989    ArticleIdent: Q11697

 The following program returns the error "Overflow in line 20 of module
 at address xxxx:xxxx" when compiled with the /D switch:

    10  x% = 129
    20  print 256 * x%
    30  end

 If the sample program is compiled without the /D switch, no error is
 reported, but an incorrect (negative) value is returned.

 Forcing "256" to single precision by using 256! or 256.0 will
 eliminate the overflow error. "256" is an integer, and the result of
 129 times 256 is greater than 32,767, which is the highest integer
 allowed.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS and to
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2.

 These compilers don't handle type coercion, nor do they check for
 overflow unless the program was compiled with the /D switch.


 61. DATE$, TIME$ in Loop Can Push System Time Backwards in DOS 3.x

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR67824 B_BasicCom
 Last Modified: 31-AUG-1989    ArticleIdent: Q25989

 The following BASIC program makes the system time go backwards when
 run under MS-DOS Versions 3.x.

 FOR i = 1 TO 40
    DATE$ = "11/17/87"
    PRINT TIME$
 NEXT

 This behavior is caused by a DOS Versions 3.x problem, not a BASIC
 problem. The problem does not occur in MS OS/2 real mode.

 As a workaround, do not reset the date multiple times within a loop.

 This information applies to Microsoft QuickBASIC Versions 3.00, 4.00,
 4.00b, and 4.50 and to Microsoft BASIC Compiler Versions 6.00 and
 6.00b when run under MS-DOS Versions 3.x.

 For related information concerning Microsoft C, query on the following
 words:

    _DOS_SETDATE and CLOCK and TIME and C


 62. "Type Mismatch" Using PRINT VAL("100.1 %") or VAL("E%")

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 26-MAR-1990    ArticleIdent: Q25993

 A "Type Mismatch" error occurs for the PRINT VAL("100.0 %") statement,
 because the percent (%) symbol can be appended only to integer
 constants, and 100.0 is a floating-point constant. BASIC notices the
 "%" symbol despite its separation with a space from the floating-point
 constant 100.0.

 "Type Mismatch" also properly occurs for PRINT VAL("E%") and PRINT
 VAL("D%"), where "E" represents single-precision exponential notation,
 and "D" represents double-precision exponential notation.

 The following statements print 100.0 without error:

    PRINT VAL("100.0 *")
    PRINT VAL("100.0 !")
    PRINT VAL("100.0 #")

 This behavior occurs in Microsoft QuickBASIC Versions 4.00, 4.00b,
 4.50 for MS-DOS, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2.

 Please note that QuickBASIC Version 3.00 and Microsoft GW-BASIC
 Versions 3.20, 3.22, and 3.23 fail to give an error for the statement
 PRINT VAL("100.0 %").


 63. No EOF (CTRL+Z) Marker Written at End of Sequential File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR68492 B_BasicCom
 Last Modified:  7-JUN-1989    ArticleIdent: Q25996

 Programs compiled in QuickBASIC Version 4.00, 4.00b, or 4.50, or in
 BASIC Compiler Version 6.00 or 6.00b, don't add an end-of-file (EOF)
 marker [chr$(26), or CTRL+Z] at the end of output or appended
 sequential files.

 Sequential files created with QuickBASIC Version 4.00 (and later) and
 BC 6.00 (and later) programs will correctly read into programs
 compiled in QuickBASIC Version 3.00 even though there is no EOF
 marker, but other applications (those that follow the DOS Versions 1.x
 standard for EOF) may generate an "input past end" error looking for
 the CTRL+Z.

 This is not an error in the QuickBASIC or compiled BASIC software.

 The lack of writing CTRL+Z to mark the end of the file was a
 deliberate change to allow QuickBASIC programs to read files that
 contain embedded CTRL+Z's. CTRL+Z's can often occur with binary files
 and screen files saved with the BSAVE command.

 The use of CTRL+Z to mark the end of file is a DOS Versions 1.x
 application standard (which was carried over from the CP/M-80
 operating system). Applications written for DOS Versions 2.x and 3.x
 standards use the exact number of bytes in the file to determine the
 end of file, which is a more practical design. This file size is
 stored for each file in the File Allocation Table (FAT) on each disk.

 You can write your own CTRL+Z to the end of a file by writing a
 program that opens the file for append and sends a chr$(26) to the
 file.


 64. "Duplicate Definition" with Same Name of SUBprogram, Variable

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  7-FEB-1989    ArticleIdent: Q25998

 When you run the program below, a "Duplicate definition" occurs
 because a variable and SUBprogram have the same name, not counting the
 type of declaration suffix (i.e., !, #, $, &, or %).

 You can work around this design limitation by changing the variable
 name or the subprogram name.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 and the BASIC compiler Versions 6.00 and 6.00b.

 The following program demonstrates the "Duplicate Definition"
 error:

 ' THIS IS THE MAIN PROGRAM:
 DECLARE SUB abc ()
 DEFINT A-Z
 abc! = 2
 CALL abc

 SUB abc STATIC
 PRINT "hello"
 END SUB


 65. ASCII Codes That Do Not Output Using SCRN:, CONS:, or PRINT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-MAR-1990    ArticleIdent: Q35651

 Most ASCII values display graphics or alphanumeric symbols when sent
 to the screen. However, there are some ASCII character codes for which
 BASIC displays nothing on the screen of a PC. The list of excluded
 characters for the PRINT statement is the same as for the PRINT#
 statement sending output to a file opened with the "SCRN:" device
 name. The list of excluded characters is different for the "CONS:" and
 "SCRN:" device names, as shown below.

 Note that you can display all the excluded character codes by directly
 poking them into video memory (under MS-DOS only, not in OS/2), as
 shown farther below.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
 for MS-DOS and to the Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS.

 For a table of the graphics and alphanumeric symbols associated with
 ASCII bytes, please refer to Appendix A of the BASIC language
 reference manuals for QuickBASIC Versions 4.00, 4.00b, and 4.50 for
 MS-DOS or the language reference manual for Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2. See also the QB
 Advisor online Help system for QuickBASIC 4.50.

 The following ASCII values cannot be output with PRINT, or with PRINT#
 to either "SCRN:" or "CONS:"

    Decimal  Hex    ASCII  Description
    -------  ---    -----  -----------

    007      7H     BEL    Bell
    009      9H     HT     Horizontal Tab
    010      AH     LF     Linefeed
    013      DH     CR     Carriage Return

 PRINT# to "SCRN:" and PRINT output the following characters, but
 PRINT# to "CONS:" does not:

    Decimal  Hex    ASCII  Description
    -------  ---    -----  -----------

    027      1BH    ESC    Escape
    127      7FH    (The DOS device CONS: recognizes code 127 as DEL.)

 PRINT# to "CONS:" outputs the following control characters, but PRINT#
 to "SCRN:" and PRINT do not:

    Decimal  Hex    ASCII  Description
    -------  ---    -----  -----------

    011      BH     VT     Vertical Tab
    012      CH     FF     Formfeed
    028      1CH    FS
    029      1DH    GS
    030      1EH    RS
    031      1FH    US

 There is a method in QuickBASIC of displaying every character,
 including those on the above lists. This involves using the POKE
 statement to send the appropriate ASCII code into the even-numbered
 byte in video memory that corresponds to a particular screen position.
 (The color attribute (default=7) is POKEd into the odd byte that
 follows the even byte.) This requires knowing the starting address for
 the correct page of screen memory (as shown on Page 85 of the "Peter
 Norton Programmer's Guide to the IBM PC"), as well as the desired row
 and column position.

 Code Examples
 -------------

 The following code POKEs a given ASCII character at a specific row and
 column position on a Hercules-compatible monochrome monitor:

    DEF SEG = &HB000 'start of Hercules memory page 0.
    'DEF SEG = &hB800 'start for EGA or CGA Cards page 0
    DEFINT A-Z
    row = 10
    column = 30
    attribute = 7 'normal white-on-black
    Character = 7 'The bell, normally
    CharPos = 2 * (row * 80 + column)
    POKE CharPos, Character
    POKE CharPos + 1, attribute
    ' Additional characters can be POKEd here as desired.
    END

 The following code verifies which characters can be displayed in
 QuickBASIC. You can change "SCRN:" to "CONS:" and rerun for
 comparison. You can also change the < PRINT#1, > statement to the
 < PRINT > statement for comparison.

    CLS
    OPEN "scrn:" FOR OUTPUT AS #1
    FOR k = 0 TO 255
       WHILE INKEY$ = "": WEND
       PRINT #1, k; CHR$(k)
    NEXT


 66. "Illegal Function Call" from EXE Using Coprocessor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR68499
 Last Modified: 31-OCT-1988    ArticleIdent: Q26006

 When compiled with BC (/o and /d options make no difference) and run
 on a machine equipped with a math coprocessor, the following program
 generates an "Illegal function call" message at run time.

    SCREEN 1            'fails in any graphics mode
    OPEN "file4" FOR RANDOM AS #4
    CLOSE #4
    WINDOW (-320, -100)-(320, 100)
    FOR x = -202 TO 202 STEP 4
       aspect = ABS(202 / x) * 5 / 12
       IF aspect < 1 THEN
          radius = 20 / aspect
       ELSE radius = 20
       END IF
       y = 40 * SQR(1 - x ^ 2 / 40804)
       CIRCLE (x, y), radius, , , , aspect
       CIRCLE (x, -y), radius, , , , aspect
    NEXT x

 In QuickBASIC Version 4.00, if you use the DOS command SET NO87="none"
 to turn off the coprocessor, or if you run inside the QuickBASIC
 editor, the program executes successfully. The program also runs
 properly in QB and QB87 in QuickBASIC Version 3.00.

 This is not an error in the QuickBASIC Version 4.00 software.

 The behavior of the above program in Version 4.00 is due to a
 difference in the way optimization is handled between the editor and
 BC. The error occurs in the following line:

    y = 40 * SQR(1 - x ^ 2 / 40804)

 When the program is run inside the editor this line is ultimately
 evaluated as follows:

    y = 40 * SQR( 0 )

 However, as an EXE, the same line results in an attempt to find the
 SQR of a negative number; the same number rounded to zero in the
 editor.

 To work around the problem, assign (1 - x^2 / 40804) to an
 intermediate variable, set the intermediate variable to zero if it is
 less than zero, and use the intermediate value in the SQR function.


 67. IEEE Math Rounding Differs in Compiled .EXE and QB.EXE Editor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR68500 B_BasicCom
 Last Modified: 17-NOV-1989    ArticleIdent: Q26007

 The results of floating-point calculations may differ between the
 QuickBASIC Version 4.00, 4.00b, or 4.50 QB.EXE editor and an .EXE
 program compiled with BC.EXE. The BC.EXE compiler produces .EXE
 programs that return more accurate answers than the QB.EXE editor.

 The different answers are caused by rounding differences and the
 different way in which the intermediate single-precision arithmetic
 results are stored in the editor versus a compiled .EXE program.
 Inside the QB.EXE Version 4.00, 4.00b, or 4.50 editor, an 8-byte
 temporary single-precision floating-point variable is used by default,
 whereas BC.EXE uses a 10-byte temporary single-precision variable.
 This information also applies to BC.EXE and QB.EXE in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 You can force the QB.EXE editor to use a more accurate, 10-byte
 temporary variable by changing your variables to double precision
 (DEFDBL A-Z). Note that minor rounding differences may still occur in
 QB.EXE compared to a compiled .EXE program even when using double
 precision.

 Example 1
 ---------

 The program in Code Example 1 shown further below should display a
 value of 2500. Running this program gives the following results using
 QuickBASIC Versions 3.00 and 4.00, 4.00b, or 4.50, comparing single
 and double precision with and without a coprocessor, and with and
 without using double precision variables:

 QB.EXE 3.00    -- no coprocessor -- (single)  -- 2403.3181     (MBF)
 QB.EXE 3.00    -- no coprocessor -- DEFDBL A  -- 2499.xxxx     (MBF)
 QB.EXE 4.00    -- no coprocessor -- (single)  -- 2477.24414063 (IEEE) *!
 QB.EXE 4.00    -- no coprocessor -- DEFDBL A  -- 2500.0000     (IEEE)

 QB87.EXE 3.00  -- with coprocessor -- (single) -- 2500.0000  (IEEE)
 QB87.EXE 3.00  -- with coprocessor -- DEFDBL A -- 2500.0000  (IEEE)
 QB.EXE 4.00    -- with coprocessor -- (single) -- 2477.24414063 * Note!
 QB.EXE 4.00    -- with coprocessor -- DEFDBL A -- 2500.0000  (IEEE)
 BC.EXE 4.00    -- with coprocessor -- (single) -- 2500.0000  (IEEE)
 BC.EXE 4.00    -- with coprocessor -- DEFDBL A -- 2500.0000  (IEEE)

 In the Microsoft Binary Format (MBF) in QB.EXE 3.00, miscalculations
 are due to expected binary format rounding errors. The IEEE format
 used in QB87.EXE Version 3.00 and QuickBASIC Version 4.00 produces a
 more accurate answer. However, not using DEFDBL in the QB.EXE Version
 4.00 (or 4.00b or 4.50) editor produces a less-accurate answer due to
 a smaller buffer for intermediate calculations.

 The following is Code Example 1:

 DEFDBL A   ' Try using with and without DEFDBL A for comparison.
 n$ = "####.########"
 CLS
 PRINT "Calculating, please wait...."
 a = 1
 starttime = TIMER
 FOR i = 1 TO 2499
    a = TAN(ATN(EXP(LOG(SQR(a * a))))) + 1
 NEXT i
 t = TIMER - starttime
 CLS
 PRINT "calculation complete:"
 PRINT USING n$; a, t
 END

 Example 2
 ---------

 The rounding results performed in IEEE mathematics performed inside
 the QB.EXE 4.00, 4.00b, or 4.50 editor may differ from a compiled .EXE
 program, even for double precision. The numbers are similar, but the
 IEEE rounding is performed differently.

 The following program demonstrates this issue by returning 1.19209E-07
 inside the editor and 1.084E-19 when compiled to an .EXE program.
 These results from Code Example 2 occur in QuickBASIC Versions 4.00,
 4.00b, 4.50 and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2.

 The following is Code Example 2:

 ' For greater accuracy, add DEFDBL A-Z to program, or use e#.
 ' However, the .EXE program compiled in BC.EXE will still return more
 ' accurate results than when the program is run in the QB.EXE editor.
 e = 1!
 DO WHILE e + 1 > 1
    e = e / 2
 LOOP
 e = 2 * e
 PRINT e
 END


 68. CONST "Syntax Error" with BC.EXE 4.00, but Works in Editor

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 25-APR-1989    ArticleIdent: Q26009

 The following line of code compiles properly inside the QB.EXE Version
 4.00, 4.00b, or 4.50 editor, but BC.EXE issues a "Syntax error" at the
 last parenthesis at compile time, as follows:

    CONST True% = (0=0)

 QB.EXE Version 3.00 issues an "illegal constant" error message when
 this code is either run from memory or compiled.

 To work around this problem, use -1 or any other nonzero value to
 represent a logical TRUE, as follows:

    CONST True% = -1
    CONST False% = 0

 Microsoft is researching this problem and will post new information
 as it becomes available.


 69. "Type Mismatch" in Editor Changing Size of Array in COMMON

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER |  buglist4.00 fixlist4.00b fixlist4.50
 Last Modified: 21-NOV-1988    ArticleIdent: Q26015

 The program below demonstrates a problem when changing the size of an
 array that is included in a COMMON statement. After running the
 program in the editor once, if the size of the array is changed, a
 type-mismatch error occurs on the COMMON statement. The program must
 be reloaded to change the size of the array. The same error occurs
 regardless of whether the program is run with a SHIFT+F5 or an F5. If
 the variable is explicitly typed, for example, DIM a%(1000), the same
 error occurs. The array may be set back to its original size for the
 error to disappear. The program is as follows:

 DIM a(1000)
 COMMON SHARED a()     ' COMMON without SHARED also shows problem.

 Microsoft has confirmed this to be a problem in Version 4.00. This
 problem is corrected in QuickBASIC Versions 4.00b and 4.50.


 70. QB87 Hang or Bad Numbers When "Divide By Zero" on PC-DOS 3.20

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR63164
 Last Modified: 10-APR-1989    ArticleIdent: Q26082

 When floating-point exception error occurs on a machine with a
 coprocessor (8087 or 80287), some programs display improper numeric
 values or hang in QB87.EXE (the coprocessor version of QuickBASIC
 Version 3.00), instead of stopping and displaying a "divide by zero."
 There is a problem in IBM PC-DOS Version 3.20 which can cause this
 problem in QuickBASIC 3.00 (but not in later versions of QuickBASIC
 running on IBM PC-DOS 3.20).

 The following is an excerpt from Page Update-7 of the "Microsoft
 QuickBASIC Version 3.00 Update" manual:

    IBM PC-DOS Version 3.20 contains a bug that may cause errors when
    QB87 programs are run. You can see which version DOS your computer
    is running by using the DOS VER command.

    If your computer is using IBM PC-DOS Version 3.20, you must install
    the patch from Disk 2 of the set labeled "For Systems with a Math
    Coprocessor." The necessary files are in the subdirectory PATCH.

    To install the patch, follow the directions in the file README.DOC
    in the PATCH subdirectory.

 Please note that this patch is not necessary when using QuickBASIC
 3.00 programs under MS-DOS 3.20 -- the patch is only for PC-DOS 3.20.

 This patch is specific to QuickBASIC 3.00 and PC-DOS 3.20, and does
 not apply to later versions of QuickBASIC (which are designed to work
 around the problem) or other versions of PC-DOS or MS-DOS.

 For QuickBASIC 4.00, 4.00b, or 4.50, a separate article describes a
 different patch necessary (in these versions only) to work around a
 different MS-DOS 3.20 (not PC-DOS) problem handling coprocessor
 floating point exceptions. Query in this KnowledgeBase on the
 following: COPROCESSOR AND 4.00B AND EXCEPTIONS AND PATCH.


 71. No Cursor Displayed in Graphics SCREENs 1, 2, 3, 7 through 13

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 26-OCT-1989    ArticleIdent: Q26088

 When you poll the INKEY$ function, a blinking cursor is displayed only
 in SCREEN 0 (text mode), and not in any graphics screen mode. A
 blinking cursor is not displayed in SCREEN 1, 2, 3, 7, 8, 9, 10, 11,
 12, or 13 (please see the SCREEN statement in your BASIC language
 reference manual to find out which SCREEN modes your version of BASIC
 supports). This is a hardware video-graphics limitation, not a
 limitation of BASIC. This information applies to Microsoft QuickBASIC
 Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for
 MS-DOS, to the Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and OS/2, and to Microsoft GW-BASIC Versions 3.20, 3.22, and
 3.23.

 In graphics modes, to get a cursor (which will be non-flashing and
 block-shaped), you can use the INPUT or LINE INPUT statement. You may
 also design a program that draws a cursor.

 The following program does not display a blinking cursor in SCREEN
 modes other than 0:

    SCREEN 9 ' using SCREEN 0 lets you see cursor.
    LOCATE 1, 1, 1 ' Try to turn on the cursor
    PRINT "t": CLS
    10 a$ = INKEY$
    IF a$ = "" THEN GOTO 10

 Using SCREEN 0, you get a blinking, underscore-shaped cursor while the
 INKEY$ function is being polled.

 There is a more detailed explanation of this text-mode cursor in the
 "Video Basics" chapter of Peter Norton's "Programmer's Guide to the
 IBM PC," published by Microsoft Press (see Page 92 of the 1985 edition
 and Page 94 of the 1988 edition).

 The blinking, underscore-shaped cursor is a feature of the text modes
 (i.e., SCREEN 0 only) and is created by hardware. To have a cursor in
 graphics mode, you must draw it within your program.

 Below is an example of drawing a graphics mode cursor in SCREEN 9. It
 uses the underscore character, clears the screen, and starts over
 after you reach line 25, column 80.

 SCREEN 9
 CLS
 PRINT "_"
 y% = 1 ' Start at row 1
 WHILE 1
 a$ = INKEY$
 IF a$ <> "" THEN
   x% = POS(0)
   LOCATE y%, x%
   PRINT a$;
   IF x% < 80 THEN
      PRINT "_";
      LOCATE y%, x% + 1
   ELSEIF y% = 25 THEN
       y% = 1
       x% = 0
       CLS
   ELSE
     y% = y% + 1
     x% = 0 ' Set the column to zero.
   END IF
 END IF
 WEND


 72. CALL INTERRUPTX to Read Disk Sector Can Fail in QB; OK in .EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q26483

 The program below uses the CALL INTERRUPTX statement to invoke a
 software interrupt to read a disk sector (interrupt 13 hex, function
 2). The program correctly reads the specified sector when an .EXE file
 is created. However, the program does not read the correct sector from
 within the QuickBASIC editor environment.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS (buglist6.00, buglist6.00b); and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are researching
 this problem and will post new information here as it becomes
 available.

 This problem is specific to interrupt 13 hex, function 2 -- other
 interrupts invoked with CALL INTERRUPTX should work properly.

 The following is a code example:

 ' Define the type needed for INTERRUPTX
 TYPE RegTypeX
      ax    AS INTEGER
      bx    AS INTEGER
      cx    AS INTEGER
      dx    AS INTEGER
      bp    AS INTEGER
      si    AS INTEGER
      di    AS INTEGER
      flags AS INTEGER
      ds    AS INTEGER
      es    AS INTEGER
 END TYPE

 ' Generate a software interrupt 13 hex, function 2, loading all
 ' registers.
 ' Note: The underscore line-continuation mark is no longer supported in
 '       QuickBASIC version 4.00. For illustrative purposes it appears
 '       in the DECLARE statement below. If this program were to be
 '       loaded into the QuickBASIC version 4.00 editor, the underscore
 '       would be stripped out and the DECLARE statement would be
 '       contained on one line.
 DECLARE SUB INTERRUPTX (intnum AS INTEGER, inregs AS RegTypeX,_
                         outregs AS RegTypeX)
 DEFINT A-Z
 DIM buf(1792)
 DIM inregs AS RegTypeX, outregs AS RegTypeX
 CLS
 inregs.ax = &H201
 inregs.cx = &H101
 inregs.dx = &H0
 inregs.bx = VARPTR(buf(0))
 inregs.es = VARSEG(buf(0))
 CALL INTERRUPTX(&H13, inregs, outregs)
 DEF SEG
 FOR I = 0 TO (512)
   p = PEEK(VARPTR(buf(0)) + I)
   IF p > 31 AND p < 127 THEN PRINT CHR$(p);  ELSE PRINT ".";
 NEXT I
 PRINT HEX$(inregs.ax)


 73. Trapping ALT+, SHIFT+, or CTRL+PRINT SCREEN, &H80 Key Flag

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_GWBasicI
 Last Modified: 23-MAY-1989    ArticleIdent: Q26485

 Problem:

 I am unable to trap the PRINT SCREEN key (on an IBM extended
 keyboard, such as on an IBM AT) when pressed simultaneously with the
 ALT, SHIFT, or CTRL key. However, these can be trapped, with the
 exception of CTRL+PRINT SCREEN, within the QuickBASIC editing
 environment.

 These keys can be trapped using GW-BASIC Interpreter Version 3.20. The
 following is a code example:

 KEY 15, CHR$(&H04) + CHR$(&H37)
 KEY(15) ON
 ON KEY(15) GOSUB keytrap
 idle: GOTO idle
 keytrap:
    PRINT "CONTROL+PRINT SCREEN key sequence trapped"
    RETURN

 Response:

 This problem results because the value &H80 is missing from the
 keyboardflag argument of the KEY statement. You must add this value
 whenever you trap the PRINT SCREEN key on an extended keyboard.
 Therefore, the correct method for trapping the key is as follows:

 KEY 15, CHR$(&H80 + &H04) + CHR$(&H37)
 KEY(15) ON
 ON KEY(15) GOSUB keytrapidle: GOTO idle
 keytrap:
    PRINT "CONTROL+PRINT SCREEN key sequence trapped"
    RETURN


 74. Hardware Errors During CALL INTERRUPT Hang the System

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q26543

 DOS interrupt calls that result in a hardware error, such as an open
 disk-drive door or a bad sector, cause the system to hang.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2. This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 When you are inside the editor and using the DOS interrupt procedures
 (INT86OLD, INTERRUPT) to open a data file that is on a floppy disk, if
 the disk-drive door is left open, the error is caught and handled by
 the editor. However, if the program is made into an executable, when
 the door is left open, the error is not trapped and control is never
 returned to the BASIC program. This effectively hangs the system.

 To work around the problem, OPEN a file for input on the floppy disk
 and trap potential disk errors with ON ERROR GOTO before attempting to
 CALL INTERRUPT.

 Results of testing with earlier versions show that the errors are
 trapped correctly with QuickBASIC Version 3.00; therefore, the problem
 does not occur in Version 3.00.

 The following is example code:

 TYPE RegType
      ax    AS INTEGER
      bx    AS INTEGER
      cx    AS INTEGER
      dx    AS INTEGER
      bp    AS INTEGER
      si    AS INTEGER
      di    AS INTEGER
      flags AS INTEGER
 END TYPE

 DECLARE SUB INTERRUPT (intnum AS INTEGER, inreg AS RegType, outreg AS RegType

 DIM inarray AS RegType, outarray AS RegType

 file$ = "a:dummy.dat" + CHR$(0)

 inarray.ax = &H3D02
 inarray.dx = SADD(file$)

 CALL INTERRUPT(&H21, inarray, outarray)
 PRINT outarray.flags
 PRINT outarray.ax
 END


 75. DOS APPEND Path Can Affect Make EXE File Command in QB/QBX.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q26478

 Using the Make EXE File command on the Run menu in the QuickBASIC
 version 4.00, 4.00b, or 4.50 environment fails to make an EXE file
 when the MS-DOS APPEND command points to the directory where QB.EXE
 and BC.EXE are located and you are running QB.EXE from a different
 directory.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of QuickBASIC versions 4.00, 4.00b, and 4.50; in the QB.EXE
 environment of Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS (buglist6.00, buglist6.00b); and in the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10).

 The following steps demonstrate the problem:

 1. Put BC.EXE and QB.EXE in a directory called C:\QB.

 2. Type the following DOS PATH command:

       PATH=C:\QB

 3. Type the following DOS command:

       APPEND C:\QB

 4. Log onto the following:

       C:\QB\BUGS

 5. Run QB.EXE and load in any simple program to compile.

 6. When you attempt to use the Make EXE File command on the Run menu,
    you shell out to DOS but immediately get a prompt to "Press any key
    to continue," and no EXE file is created. Control is immediately
    returned to the editor even if you use the Make .EXE and EXIT
    command.

 To work around this problem, put BC.EXE in a subdirectory other than
 the one specified by the DOS APPEND command.


 76. "Subscript Out of Range" for Array > 128K; Gaps in Far Heap

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-OCT-1989    ArticleIdent: Q26494

 The program below, which is compiled with the /ah option (in QB.EXE or
 BC.EXE) to support a huge (larger than 64K) array, produces a
 "Subscript out of range" message for an array larger than 128K, even
 though the FRE(-1) function indicates that there should be enough
 available memory.

 To make an array larger than 128K and avoid the "Subscript out of
 range" message, the number of bytes in a single element of the huge
 array must be a power of 2 (i.e., evenly divisible into 64K), as
 explained below.

 This information applies to the Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2.

 Space is allocated for a huge array contiguously in far heap, with the
 restriction that no single array element (or record) is allowed to be
 split across a 64K boundary. If a record size is not a power of 2, the
 array is allocated at an offset high enough, relative to the array's
 base segment address (returned by the VARSEG function), such that no
 array element is split across the boundary at exactly 64K above the
 base segment. The value returned by the VARPTR function for the first
 element of the array then indicates both the offset of the array, and
 also the size of a gap created in far heap. The size of the gap is
 also equal to (65,536) MOD (array record size). This gap fragments far
 heap, and is wasted, unused memory. In the worst case, the gap can be
 up to (array record size) minus 1 in size.

 A "Subscript out of range" error occurs when allocating a huge array
 larger than 128K if the array elements have a size that is not an even
 power of 2. Arrays larger than 128K must have an element (or record)
 size that is a power of 2 (2, 4, 8, 16, 32, 64, etc.), since arrays
 must be stored contiguously and no single array element is allowed to
 span across a 64K boundary.

 You can compensate for this limitation by padding each array element
 to a size that can be evenly divided into 64K (i.e., a power of 2,
 such as 4, 8, 16, 32, 64, 128, or 512 bytes), as shown in the example
 below.

 A huge array must be DIMensioned as a dynamic array, either with a
 variable in the array subscript or with the preceding metacommand
 REM $DYNAMIC. The /AH option allows dynamic arrays of user-defined
 types, fixed-length strings, and numeric data to occupy all of
 available memory.

 The following example shows how to work around the "Subscript out of
 range" error message:

 DEFINT A-Z
 TYPE test
    a   AS DOUBLE         ' 8 bytes.
    b   AS STRING * 288   ' 288 bytes.
    PAD AS STRING * 216   ' Must pad to make 512-byte total record size
 END TYPE
 max = 453
 REM $DYNAMIC
 DIM x(1 TO max)  AS test
 END

 Note that huge (larger than 64K) arrays are not available in versions
 of QuickBASIC earlier than Version 4.00.

 The following code example demonstrates the "Subscript out of range"
 error message:

 DEFINT A-Z
 TYPE test
    a  AS DOUBLE         ' uses 8 bytes
    b  AS STRING * 288   ' uses 288 bytes
 END TYPE
 max = 453
 REM $DYNAMIC
 PRINT FRE(-1)                ' prints free heap space
 DIM x(1 TO max)  AS test     ' 453 * (288 + 8) = 134088 bytes used
 PRINT FRE(-1),"AFTER DIM"
 END


 77. BC.EXE "Line Too Long" for Source Lines of 256+ Characters

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-JUL-1990    ArticleIdent: Q26605

 The program below, which has a 263-character-long CONST statement in
 one line, runs without error when loaded in QB.EXE or QBX.EXE, but
 gives a "Line too long" error when compiled with BC.EXE.

 A blank line filled with 256 or more space characters (ASCII byte
 value 32) also gives a "Line too long" error at compile time with
 BC.EXE. This is difficult to see, unless you put the cursor on the
 blank line and press the END key to move the cursor to the actual end
 of the line. The column status indicator in the lower-right corner of
 the QB.EXE or QBX.EXE environment then shows the number of characters
 in that line.

 The "Line too long" error occurs by design in both cases above because
 the BC.EXE compiler restricts line length to 255 characters, which
 includes the CR (carriage return), LF (linefeed), and the underscore
 (_) line-continuation character.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS and to Microsoft BASIC Professional Development
 System (PDS) version 7.00 for MS-DOS and MS OS/2.

 The QB.EXE and QBX.EXE editors initially prevent you from typing a
 line past column 255, but if you move the cursor to a different line,
 then back, the editors let you add characters past column 255. Despite
 this capability, you should not type lines that exceed 255 characters.
 You can easily check the number of characters in any line by placing
 the cursor on the line in question, pressing the END key, and looking
 at the column counter on the lower-right corner of the screen in the
 QB.EXE or QBX.EXE environment.

 Code Example
 ------------

 BC.EXE compiles this program correctly if you remove one character to
 make the CONST line 262 characters long. Normally, the line limit is
 255 characters, but CONST statements are parsed differently than other
 lines of code, giving you 7 additional characters of leeway in this
 case.

 ' The following CONST line (where you should type all 263 characters
 ' on one line to demonstrate the "Line too long" error in BC.EXE)
 ' can be typed past column 255 in QB.EXE or QBX.EXE if you press the
 ' DOWN ARROW then the UP ARROW back onto the long line, and
 ' continue typing:
 CONST A$ = "12345678901234567890123456789012345678901234567890
 12345678901234567890123456789012345678901234567890
 12345678901234567890123456789012345678901234567890
 12345678901234567890123456789012345678901234567890
 12345678901234567890123456789012345678901234567890"

 PRINT A$


 78. QuickBASIC Updates Screen Faster than CGA Can Update

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890309-13 b_basiccom
 Last Modified: 22-MAR-1989    ArticleIdent: Q42660

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
 for MS-DOS and to the Microsoft BASIC Compiler Version 6.00 and 6.00b
 for MS-DOS and OS/2.

 Below is an example of a basic program that attempts to print data on
 a screen. Most video systems are fast enough that all of the
 information can be printed to the screen. The Color Graphics Adapter
 (CGA) system, however, does not update the screen frequently enough
 for all lines to be scrolled up. This results in less than 25 lines of
 text being displayed on the screen while the program is printing. The
 entire 25 lines will appear on the screen at the end of the loop.
 Because this is caused by printing to the screen too fast, if this
 presents a problem for some specific application, put a delay loop
 inside of the print loop to slow down the print process.

 This problem did not occur with earlier versions of QuickBASIC.

 Code Example

 COLOR 11, 1, 1
 d$ = STRING$(80, 65)
 FOR d% = 1 TO 1000
   PRINT d$
 NEXT


 79. Make .EXE Option Cannot Find .LIB If Not in Current Directory

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q26633

 When QB is invoked with the /L switch to load a Quick library and you
 choose the Make EXE File or Make Library commands from the Run menu,
 LINK.EXE is unable to find the .LIB file that corresponds to the Quick
 library when the Quick library and .LIB are not in the current
 directory.

 This LINK problem occurs even when the directory where the Quick
 library and the .LIB are located is correctly pointed to with the DOS
 command "SET LIB=path."

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in the version of QuickBASIC that comes with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 QBX.EXE in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 One workaround is to give a full pathname to the .QLB when invoking
 QuickBASIC, as in the following example:

    QB test.bas /L c:\direct1\qb.qlb

 Another workaround is to manually perform the link from the DOS
 command line, correctly putting the .LIB file as the fourth argument,
 as follows:

    LINK test.obj,,,qb.lib;

 The following steps demonstrate the problem:

 1. Assume that QB.EXE and LINK.EXE are in the root directory on Drive
    C. Assume that QB.QLB and QB.LIB are located in subdirectory
    c:\direct1.

 2. Type the following:

       SET LIB=C:\DIRECT1

 3. When logged on in the root directory, type the following:

       QB test.bas /L qb.qlb

 4. Choose Make EXE File from the Run menu. QuickBASIC will put the
    QB.LIB file in the incorrect spot in the link step. (Press F4 as a
    toggle to see the DOS output window.)


 80. ASCII 0, 1, and 2 Control Character Problems in DATA Statement

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 17-JAN-1991    ArticleIdent: Q26637

 BASIC is not designed to support ASCII 0, 1, or 2 byte values (control
 characters) embedded in a DATA statement or in a quoted string, such
 as the following statements using ASCII 1 (CTRL+P+A) and 2 (CTRL+P+B)
 typed into the QB.EXE or QBX.EXE editor:

    DATA CTRL+P+A, CTRL+P+B
 or
    DATA "CTRL+P+A", "CTRL+P+B"

 (Note that the QB.EXE or QBX.EXE editor does not allow you to enter a
 byte value of 0 into the source code, but you can enter a byte value
 of 1 with CTRL+P+A and 2 with CTRL+P+B. The CTRL+P feature for
 entering control characters is a feature specific to the QB.EXE or
 QBX.EXE editor. ASCII 1 looks like a smiling face; ASCII 2 looks like
 an inverse video smiling face; when displayed in DOS using the TYPE
 command, ASCII 0 looks like ASCII 32, a blank space.)

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00, and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10.

 The BC.EXE compiler correctly strips out all control-character byte
 values equal to 0, 1, or 2 from DATA statements in the source file.
 (The BC.EXE compiler uses ASCII 1 and 2 byte values internally to mean
 end-of-statement and end-of-line). Currently, the above DATA
 statements behave like the following DATA statements when run as an
 .EXE program:

    DATA ,
 or
    DATA "",""

 To work around this limitation in .EXE programs compiled with BC.EXE,
 you should not READ into string variables the ASCII byte values
 (control characters) of 0, 1, and 2 in DATA statements; instead, use
 numeric constants and READ into a numeric variable, as shown in the
 workaround example at the bottom of this article.

 The QB.EXE or QBX.EXE editor is more lenient than BC.EXE in supporting
 0, 1, and 2 bytes in DATA statements. The QB.EXE editor in QuickBASIC
 versions 4.00 and 4.00b correctly loads DATA statements containing
 ASCII 1 or 2 control codes, but you get "Out of data" at run time for
 ASCII 1 unless you READ into a string variable and put
 double-quotation  marks around the ASCII 1 byte value. QB.EXE in
 QuickBASIC 4.50 and QBX.EXE in BASIC PDS 7.00 and 7.10 allow ASCII 1
 to be read into a string variable with or without quotation marks in
 the DATA statement; but attempting to read ASCII 1 into a numeric
 variable correctly gives "Syntax error."

 Example 1
 ---------

 This example shows BC.EXE limitations using ASCII values 1 and 2 in
 quoted strings:

 FOR j = 1 TO 2
 READ Y$
 PRINT Y$    'Prints OK in QB.EXE/QBX.EXE; but "null string" in BC.EXE
 IF Y$="" THEN PRINT "This DATA item is a null string"
 NEXT
 ' The following DATA statement will give errors in BC.EXE at compile
 ' time if the source file was saved in Fast Load format, no BC.EXE error
 ' at compile time if saved as Text format. For a separate article
 ' that discusses this problem, query on the following words:
 '    FAST and LOAD and "UNRECOGNIZABLE STATEMENT"
 ' You can type ASCII byte values of 1 and 2 into the QB.EXE or
 ' QBX.EXE editor by pressing the CTRL (control) characters shown
 ' in quoted strings:
 DATA "CTRL+P+A", "CTRL+P+B"

 Example 2
 ---------

 This example shows that you should not READ control code bytes into a
 numeric variable, since you get "syntax error" in QB.EXE 4.50 and
 QBX.EXE 7.00/7.10, and "Out of Data" in QB.EXE 4.00 and 4.00b (and in
 QB.EXE shipped with BASIC compiler 6.00 and 6.00b).

 This example uses ASCII 1, 2, and 3 byte values typed directly into
 the DATA statement without surrounding quotation marks (""):

 PRINT
 FOR j = 1 TO 3
 READ X  ' Error occurs here for READing any control bytes in QB.EXE or
         ' QBX.EXE at run time.
 ' From .EXE at run time, this program prints 0 for both
 ' ASCII 1 and 2 since ASCII 1 and 2 are stripped out at compile time.
 ' The .EXE program gives an error for ASCII 3, since it is
 ' incorrectly being read into a numeric variable. You must read
 ' control characters like ASCII 3 through 31 into a string variable,
 ' as shown in Example 2b.
 PRINT X; CHR$(X)
 NEXT
 ' The following DATA statement will give errors in BC.EXE at compile
 ' time if the source file was saved in Fast Load format, no BC.EXE error
 ' at compile time if saved as Text format. For a separate article
 ' that discusses this problem, query on the following words:
 '    FAST and LOAD and "UNRECOGNIZABLE STATEMENT"
 ' You can type ASCII byte values of 1 and 2 into the QB.EXE or
 ' QBX.EXE editor by pressing the CTRL (control) characters shown
 ' (don't use quotation marks in this example).
 DATA CTRL+P+A, CTRL+P+B, CTRL+P+C

 Example 2b
 ----------

 This example works in all versions of BASIC mentioned in this article
 (however, in QuickBASIC 4.00 and 4.00b and in BASIC compiler 6.00 and
 6.00b, you must type the control codes inside double-quotation marks
 or else you get "Out of Data".) This example successfully READs the
 ASCII control codes 3, 4, 5, and 6 into a string variable:

 FOR J=1 TO 4
 READ Y$
 PRINT Y$
 NEXT
 ' Type the following control codes with or without quotation marks in
 ' QB.EXE 4.50 or in QBX.EXE 7.00/7.10. In QB.EXE 4.00 and 4.00b, you
 ' must type the control codes inside double-quotation marks or else
 ' you get "Out of Data".
 DATA CTRL+P+C, CTRL+P+D, CTRL+P+E, CTRL+P+F

 Example 3
 ---------

 The following program creates a BASIC source file called TEST.BAS,
 which has a null (0) byte in quotation marks in a DATA statement. This
 program is necessary to show the problem since you can't type a null
 byte directly into a source file with QB.EXE or QBX.EXE. Run the
 following program to create TEST.BAS:

    OPEN "test.bas" FOR OUTPUT AS #1
    PRINT #1, "FOR j = 1 TO 3"
    PRINT #1, "READ Y$   "
    PRINT #1, "PRINT Y$, LEN(Y$)"
    PRINT #1, "NEXT"
    a$ = CHR$(34)
    b $= "DATA " + a$ + CHR$(0) + a$ + "," + a$ + CHR$(1) + a$ + ","
    b$ = b$+ a$ + CHR$(2) + a$
    PRINT #1, b$
    CLOSE

 TEST.BAS is now created, and appears as follows if you display it at
 the DOS prompt using the TYPE command:

    FOR j = 1 TO 3
    READ Y$
    PRINT Y$, LEN(Y$)
    NEXT
    DATA "<null byte appears as space>","<ASCII 1>","<ASCII 2>"

 If you compile TEST.BAS with BC.EXE, the 0, 1, and 2 byte values are
 stripped out of the quoted strings in the DATA statement, and the
 length of each Y$ input by the READ statement will display as zero. If
 you load TEST.BAS into QB.EXE or QBX.EXE, the DATA statement will be
 truncated at the null (0) byte, thus ignoring the remaining data on
 that line, giving you an "Out of Data" error at run time.

 Workaround Code Example
 -----------------------

 The DATA statement in the following program works correctly in all
 versions of compiled BASIC mentioned in this article:

    CLS
    ' ASCII 0 is null byte (displays nothing), ASCII 1 is happy face,
    ' ASCII 2 is inverse video happy face, ASCII 3 is filled heart
    FOR j = 1 TO 4
    READ X
    PRINT X; CHR$(X) ' Displays correctly.
    NEXT
    DATA 0,1,2,3


 81. "Out of Memory," "Error R6005," with CHAIN/RUN in DOS 2.x

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  4-SEP-1990    ArticleIdent: Q26677

 Below are some DOS versions 2.x-specific problems with the CHAIN
 and/or RUN statements that can be avoided by running the program under
 DOS version 3.00 or later. The symptoms differ in three different
 cases, depending on whether you have the following:

 1. QuickBASIC version 4.00.

 2. QuickBASIC version 4.00b or 4.50, or Microsoft BASIC Compiler
    version 6.00 or 6.00b, which CHAIN correctly in DOS versions 2.x
    when compiled with the BRUN library (unlike version 4.00). However,
    as in version 4.00, CHAIN or RUN still fails in these versions when
    compiled with the BCOM library.

 3. QuickBASIC version 3.00.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 3.00, 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler version
 6.00 or 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 (fixlist7.00, fixlist7.10).

 Note that to avoid another cause of a DOS or BASIC error message when
 executing CHAIN or RUN, you must put the DOS 2.10 COMMAND.COM (command
 interpreter) on each disk (or floppy) where you use BASIC or
 QuickBASIC .EXE programs under DOS 2.10.

 Programs compiled in Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 let you work around CHAIN problems under
 DOS versions 2.x. According to the 7.00 and 7.10 README.DOC file, you
 must CHAIN as follows:

    Under DOS 2.1, CHAIN <filespec$> will not work unless <filespec$>
    provides a path. Also under DOS 2.1, if the run-time module is in
    the root directory, the root directory must be listed in the PATH
    environment variable.

 Also, you must put the DOS 2.10 COMMAND.COM (command interpreter) on
 each disk (or floppy) where you use .EXE programs under DOS 2.10, or
 else you will get a DOS or BASIC error message.

 Another workaround under MS-DOS version 2.10 for programs compiled in
 BASIC PDS 7.00 and 7.10 is, instead of CHAIN or RUN, to LINK with
 overlays and use OVLDOS21.OBJ for DOS 2.10 support. However,
 converting from using CHAIN or RUN to using link overlays requires
 redesigning your program.

 Note: QuickBASIC versions 4.00 and later require DOS version 2.10,
 2.11, or later.

 The CHAIN statement gives run-time errors such as "Out of Memory,"
 "Error R6005," or MS-DOS "EXEC failure" in QuickBASIC version 4.00
 programs (compiled with the BRUN40.LIB or BCOM40.LIB library) under
 DOS versions 2.x. These problems don't occur in DOS versions 3.00 or
 later.

 The following are workarounds for the QuickBASIC version 4.00 CHAIN
 problem under DOS versions 2.x when you compile with the BRUNxx.LIB
 library:

 1. Using the RUN statement instead of the CHAIN statement works around
    the problem in version 4.00 when you compile with the BRUN library
    (but not if you compile with the BCOM library).

 2. When compiled with the BRUN library option in QuickBASIC version
    4.00b or 4.50, or Microsoft BASIC Compiler version 6.00 or 6.00b for
    MS-DOS and MS OS/2, CHAIN works properly under DOS versions 2.x
    (but not if you compile with the BCOM library).

 For programs compiled with the BCOM library (BC /O option), the CHAIN
 and RUN statements fail on the SECOND CHAIN or RUN attempt on DOS
 versions 2.x, when compiled in QuickBASIC version 4.00, 4.00b, or
 4.50, or in Microsoft BASIC Compiler version 6.00 or 6.00b.

 The following error messages can occur: "Out of Memory," "Error
 R6005," or MS-DOS "Not enough memory to exec."

 When compiled with BRUN30.LIB from QuickBASIC version 3.00, the
 programs run properly. However, programs compiled with BCOM30.LIB from
 QuickBASIC version 3.00 incorrectly produce the message "Out of memory
 during CHAIN" when the first program CHAINs to the second.

 The following two sample programs demonstrate the above problems:

    ' Prog1
    PRINT "hello"
    a$ = INKEY$
    IF a$ <> "" THEN END
    CHAIN "prog2"

    ' Prog2
    PRINT "program 2"
    a$ = INKEY$
    IF a$ <> "" THEN END
    CHAIN "prog1"

 The above programs compiled in QuickBASIC version 4.00 with BRUN40.LIB
 produce the message "Out of memory during CHAIN" when the first
 program CHAINs to the second. This error does not occur in QuickBASIC
 version 4.00b or 4.50 or in Microsoft BASIC Compiler version 6.00 or
 6.00b compiled with BRUNxx.LIB.

 You can successfully RUN or CHAIN from the first program to the second
 if you compile with BCOMxx.LIB (BC /O). However, the message "Runtime
 Error R6005" or "EXEC Failure" displays when the second program tries
 to RUN or CHAIN back to the first. This problem occurs in programs
 compiled with BCOMxx.LIB in QuickBASIC 4.00, 4.00b, and 4.50 and BASIC
 compiler 6.00 and 6.00b.


 82. BC.EXE "Internal Error" Long-Integer Arrays; OK /D or QB.EXE

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist6.00b fixlist4.50
 Last Modified: 21-DEC-1988    ArticleIdent: Q26710

 The following program, which uses long-integer arrays, gives an
 "Internal Error" when compiled with BC.EXE.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Versions 6.00 for
 MS-DOS and MS OS/2. This problem was corrected in QuickBASIC Version
 4.50 and Basic Compiler Version 6.00b.

 No error message is generated when this program is run within the
 QB.EXE editor/interpreter.

 The workarounds are as follows:

 1. Use the debug option (BC /d) when compiling.

 2. Convert all long-integer arrays to any other numeric type.

 Note: Long integers are not supported in previous versions of
 QuickBASIC.

 The following code demonstrates the problem:

 DECLARE SUB connect (TransMap%())
 'THIS FILE RETURNS AN <INTERNAL ERROR NEAR 5F15> WHEN
 'COMPILED WITH BC.EXE without the /d (debug) option.

 CONST MaxBlob% = 60
 DIM SHARED BlobPrX&(MaxBlob%)
 DIM SHARED BlobUp%(MaxBlob%), BlobDn%(MaxBlob%)
 CALL connect(BlobUp%())

  SUB connect (TransMap%()) STATIC
      linewidth& = TransMap%(PrNo% + 1)
      BlobPrX&(BBno%) = BlobPrX&(BBno%) + ABS(TransMap%(PrNo%) -
           BlobUp%(BBno%)) + ABS(TransMap%(PrNo% + 1) - BlobDn%(BBno%))
 END SUB


 83. LIB.EXE Displays .LIB Contents, QLBDUMP.BAS Displays .QLB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q26767

 You can display the contents of a .LIB library file using the LIB.EXE
 library manager that comes with Microsoft QuickBASIC versions 4.00,
 4.00b, and 4.50; with Microsoft BASIC Compiler 6.00 and 6.00b; and
 with Microsoft BASIC Professional Development System (PDS) 7.00 and
 7.10. The "listfile" argument for the library manager allows you to
 specify the name of a cross-reference listing file. When you specify
 the name CON, the listing will be displayed on the screen. You also
 may output the list file to a disk file by specifying an output
 filename.

 To display the contents of a Quick library .QLB file, you may compile
 and run the program QLBDUMP.BAS, which is located in the \SOURCE
 subdirectory on release-disk 3 of QuickBASIC version 4.00 or 4.00b,
 and in the subdirectory \EXAMPLES on the "Setup/Microsoft QB Express"
 disk of QuickBASIC version 4.50. QLBDUMP.BAS is also included with
 BASIC Compiler 6.00 and 6.00b and BASIC PDS 7.00 and 7.10.

 The QLBDUMP program displays the contents of a .QLB Quick library.

 The purpose of .QLB Quick library files is to resolve external routine
 calls in the QB.EXE/QBX.EXE editor/interpreter environment at run
 time. If you use a .QLB file, you must have a matching .LIB file if
 you want to use the Make .EXE File option.

 .LIB files are used by the LINK.EXE program to resolve external
 routine calls at link time. LIB.EXE can display the contents of a .LIB
 file.

 The cross-reference listing file output from LIB.EXE contains the
 following lists:

 1. An alphabetical list of all public symbols in the library. Each
    symbol is followed by the name of the module in which it is
    referred to.

 2. A list of the modules in the library. Under each module name is an
    alphabetical listing of the public symbols defined in that module.

 For more information on the LIB.EXE library manager, please refer to
 pages 227 to 234 in the "Microsoft QuickBASIC 4.0: Learning and Using"
 manual for versions 4.00 and 4.00b.

 Note that a copy of QuickBASIC (QB.EXE) comes with Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS.

 LIB.EXE Example
 ---------------

 The following is a copy of a sample session in which LIB.EXE is used
 to display the contents of the file QB.LIB to the screen:

 c:> LIB

 Microsoft (R) Library Manager  Version 3.08
 Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.

 Library name: qb.lib
 Operations:
 List file: con

 ABSOLUTE..........absolute          INT86OLD..........int86old
 INT86XOLD.........int86old          INTERRUPT.........intrpt
 INTERRUPTX........intrpt

 absolute          Offset: 00000010H  Code and data size: cH
   ABSOLUTE

 intrpt            Offset: 000000e0H  Code and data size: 107H
   INTERRUPT         INTERRUPTX

 int86old          Offset: 000002a0H  Code and data size: 11eH
   INT86OLD          INT86XOLD


 84. Colored Text in SCREEN 1 in QB Versions 2.x and 3.00, Not 4.00

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q26768

 For QuickBASIC Versions 2.00, 2.01, and 3.00, it was reported that a
 particular POKE statement forces colored text from the PRINT statement
 when using SCREEN 1. This method does NOT work in QuickBASIC Versions
 4.00, 4.00b, 4.50 [or in Microsoft BASIC Compiler Versions 6.00,
 6.00b, or in Microsoft BASIC Professional Development System (PDS)
 Version 7.00] due to significant internal changes in how video
 graphics are created.

 The COLOR statement, not the POKE statement, should be used to change
 the color of text.

 You need to use SCREEN 0, 7, 8, 9, 10, 12, or 13 if you want more than
 one color of text displayed at once on the screen. On these screens,
 you can invoke the desired COLOR statement followed by a PRINT
 statement to get a desired text color. (QuickBASIC Version 4.00 or
 later is required to support SCREEN 11, 12, or 13.) Note: The COLOR
 statement cannot be invoked in monochrome SCREEN 2 or 11.

 Note: In SCREEN 1, the COLOR statement cannot change the foreground
 (text) color -- it can only change the background color and the
 palette. As a result, for a given background color, you may only have
 one color of text on the screen at once in SCREEN 1 in QuickBASIC
 4.00, 4.00b, 4.50, in BASIC Compiler 6.00, 6.00b, and in BASIC PDS
 7.00. To work around this limitation by using a BIOS interrupt, search
 for a separate article with the following words:

    INTERRUPT and HEX and 10 and FUNCTION and 9 and COLOR

 The following is a code example that shows multiple text colors on the
 screen at once in QuickBASIC Versions 2.00, 2.01, or 3.00, but not in
 later versions:

    'Numbering scheme for colors:
    '    0 - black                 2 - light magenta
    '    1 - light blue            3 - white
    SCREEN 1
    DEF SEG
    POKE &H53, 2                ' numbers 0-3 give colored text
    PRINT "HELLO in light magenta"
    POKE &H53, 1
    PRINT "HELLO in simultaneous light blue"


 85. VAL("&H") and VAL("%") Unexpectedly Returning Nonzero Value

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q26931

 When "&H", "&", and "%" are passed alone as arguments to the VAL
 function, VAL returns 0 (zero) as expected in QuickBASIC Version 3.00.
 In QuickBASIC Version 4.00, VAL returns a nonzero value for "&H" and
 "&", and returns a "type mismatch" (error 5) at run time for "%". VAL
 is expected to return 0 (zero) because "&H" is 0 in hexadecimal
 notation, "&" is 0 in long integer notation, and "%" is 0 in integer
 notation.

 Passing "&H0" or "0%" to VAL returns 0 as expected.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00, buglist6.00b). This problem was corrected in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 (fixlist7.00).

 If your program accepts input into a string variable and then uses
 VAL, you may want to filter out the character combinations that are
 not accepted. On the Microsoft QuickBASIC Versions 4.00 and 4.00b
 Utilities and Examples Disk in the \Source subdirectory there is a
 program called STRTONUM.BAS that filters out all characters from a
 string except numeric digits, the decimal point, and a minus sign.
 STRTONUM.BAS can be modified if you want to allow hexadecimal
 constants but exclude the special cases "&H" and "H" that return
 nonzero values from VAL. You can also write your own filtering
 routine.

 The presence of a coprocessor makes no difference. The following is
 a code example:

 ' The following two statements print 203 in the QuickBASIC Version
 ' 4.00 editor; they print 233 compiled to EXE with BRUN40.LIB, print
 ' 1889 with BCOM40.LIB, and print 0 (zero) in QuickBASIC Version 3.00:

 PRINT VAL("&h")
 PRINT VAL("&")

 ' The following statement gives "type mismatch" in QuickBASIC Version
 ' 4.00 editor or EXE; it prints 0 (zero) in QuickBASIC Version 3.00:

 PRINT VAL("%")


 86. Using Joystick, STRIG(1) Incorrectly Returns 1, Not -1

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 18-OCT-1989    ArticleIdent: Q26895

 The joystick buttons are not recognized in the program shown below.
 The program incorrectly returns a 1 instead of a -1 when the button is
 pressed in programs compiled with QuickBASIC Versions 4.00 and 4.00b
 and with Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 (buglist6.00, buglist6.00b).

 This problem was corrected in Microsoft QuickBASIC Version 4.50.

 The problem does not occur in QuickBASIC Version 3.00, which correctly
 returns -1.

 Under GW-BASIC Version 3.20, the program also works correctly and
 returns -1.

 The following is a code example of this problem:

    lp:
    button= 0
    button = strig(1)
    print button
    goto lp


 87. CASE Statement Never Executed When Tracing with F8 Key in QB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  8-FEB-1990    ArticleIdent: Q26898

 When a CASE statement is selected inside the QuickBASIC Version 4.00
 or 4.00b editor as a breakpoint, that CASE is never executed when
 tracing through the program using the F8 key.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and the QB.EXE editor provided with Microsoft BASIC
 Compiler Versions 6.00 or 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in QuickBASIC Version 4.50
 and in the QBX.EXE environment of Microsoft BASIC Professional
 Development System (PDS) Version 7.00 (fixlist7.00). QuickBASIC 4.50
 and BASIC PDS 7.00 do not allow CASE statements to become breakpoints,
 and will give an appropriate error message when an attempt is made to
 make a CASE statement a breakpoint.

 In the following example, the PRINT "a$= "; a$ statement is never
 executed when the line CASE "a" is set as a breakpoint.

 Results of testing with previous versions indicate that Version 3.00
 will allow the CASE statement to execute when it is set as a
 breakpoint.

 The following code example demonstrates the problem:

 CLS
 a$ = "a"
 SELECT CASE a$
         CASE "a"                  'Set as breakpoint and PRINT "a$..." is
              PRINT "a$= "; a$     'never executed when step through using
         CASE ELSE                 'F8.
 END SELECT
 PRINT "done"                      'always executed
 END


 88. QuickBASIC Versions 3.00, 4.00, 4.50 Patch for IBM PCjr

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-JUN-1989    ArticleIdent: Q27252

 QuickBASIC Versions 3.00, 4.00, 4.00b, and 4.50 do not run on the IBM
 PCjr. This incompatibility results from the ROM BIOS of the IBM PCjr,
 which differs from that in a standard IBM PC.

 Through individuals who are using QuickBASIC, Microsoft has become
 aware of several versions of a patch that claim to correct this
 incompatibility problem. The following is a list of sources for this
 patch:

 1. "The Junior Report" magazine, December 1987, Page 24.

 2. On CompuServe, the patch is called INT9JR.ARC, and is located in DL
    1 of the IBMJR SIG. There is another file called KBFIX.ARC in DL 0
    of the IBMJR SIG that may do the same thing or may be better.

 3. On the Twin City PC bulletin board at (612) 888-0468 or (612)
    888-7570, the filename for the patch is also INT9JR.ARC.

 4. Synetics Software and Systems sells a cartridge called
    "Quicksilver" that can be used to make QuickC run on the PCjr. A
    customer reported that this took care of a duplicate-keystroke
    problem in QuickBASIC. The cartridge costs $34.95, and can be
    obtained by contacting Synetics Software at the following address
    and phone number:

       P.O. Box 53501
       San Jose, CA 95153-0501
       (408) 281-7780

 These patches were developed by individuals who are using QuickBASIC
 on the PCjr, not by Microsoft. Microsoft gives the above references to
 individuals in need of the patch, but in no way supports or guarantees
 the patch.


 89. IF Statement Missing Colon Not Always Trapped at Compile Time

 Product Version(s): 3.00 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist3.00 buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 17-JAN-1990    ArticleIdent: Q27277

 The program below, which is missing a colon (:) before the GOTO
 statement in the IF statement, correctly gives the run-time error
 "Expected: end-of-statement" in the QuickBASIC Version 4.00 editor.

 However, when compiled from the DOS command line with BC.EXE and
 LINKed into an EXE program, the EXE program runs successfully without
 an error, printing "a=1" as if the missing colon were present.

 The same behavior occurs when compiling with QB.EXE Version 3.00 using
 the separate compilation method. (There is no BC.EXE in 3.00).

 To work around the problem, detect the missing colon by running and
 debugging the program in the editor before compiling to an EXE file.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 3.00, 4.00, and 4.00b, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS and OS/2. This
 problem was corrected in QuickBASIC Version 4.50 and in Microsoft
 BASIC Professional Development System Version 7.00 for MS-DOS
 (fixlist7.00).

 The following is the sample program:

 if a = 0 then a = 1 goto ending   ' A colon is missing before the GOTO.
 print "should not be seen"
 ending:
 print "a =";a
 system


 90. How to Assign High & Low Registers for CALL INTERRUPT, INT86

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 31-OCT-1988    ArticleIdent: Q27287

 The QuickBASIC interrupt routines (CALL INT86 and PTR86 in QuickBASIC
 2.x and 3.00; and INT86old and INTERRUPT in QuickBASIC 4.00/4.00b and
 the BASIC Compiler 6.00/6.00b) are passed full-word register variables
 such as AX instead of half registers AH (high byte of AX) and AL (low
 byte of AX). The CALL statement documentation in the reference manual
 for QuickBASIC Versions 2.x, 3.00, and 4.00 does not clearly state how
 to assign or read half registers before or after calling the interrupt
 routines.

 The following are two methods to assign values to high and low
 registers and to load them into the full word (two-byte) registers:

 1. The simplest method is to combine the hexadecimal values of the
    high and low registers into one hexadecimal constant:

    AX = &H0941             ' where AH=&H09, AL=&H41
    BX = &H0002             ' where BH=&H00, BL=&H02
    CX = &H07D0             ' where CH=&H07, CL=&HD0

 2. The following is a more flexible method, letting you assign
    variables to the high and low registers with a formula:

    AX, BX, CX, or DX = (high% * 256) + low%

    In this case, "high" and "low" contain the decimal values which you
    want to assign to the respective half registers. For example:

    high% = 9                   ' 9 = &H09
    low% = 65                   ' 65 = &H41
    AX = (high% * 256) + low%    ' AX = 2369 = &H0941

 Note that the following is a quick way to convert a decimal number to
 hexadecimal using the immediate mode window of the QuickBASIC Version
 4.00 editor:

 PRINT HEX$(number)

 (Pressing F6 in the QuickBASIC Version 4.00 editor lets you activate
 the immediate mode window. Pressing F4 toggles between viewing the
 editor and viewing the output window.)

 The following formulas return the contents of the half registers,
 which are stored in the two bytes of a full register such as AX
 returned from an interrupt routine:

 AL% = AX% MOD 256 ' MOD operator returns integer remainder of division
 PRINT "The AL register contains &H"; HEX$(AL%)

 AH% = AX% \ 256  ' Integer division by 256 removes the lower byte.
 PRINT "The AH register contains &H"; HEX$(AH%)


 91. Passing BASIC Variable-Length String to C by Near Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27289

 The following is an example of how to pass a BASIC variable-length
 string variable by near reference to a Microsoft C routine.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB StringNear CDECL (_
         BYVAL p1o AS INTEGER,_
         SEG p3 AS INTEGER)
 CLS
 a$ = "This is a test" + CHR$(0)
 CALL StringNear(SADD(a$), LEN(a$))
 END

 /* ===== C ROUTINE ===== /*

 #include <stdio.h>
 void StringNear(a,len)
    char near *a;
     int *len;
  {
     int i;
     printf("The string is : %s \n\n",a);
     printf(" Index       Value       Character\n");
     for (i=0;i < *len; i++)
        {
          printf("  %2d          %3d            %c\n",i,a[i],a[i]);
        };
  }

 ===== OUTPUT =====

 The string is : This is a test

  Index       Value       Character
    0           84            T
    1          104            h
    2          105            i
    3          115            s
    4           32
    5          105            i
    6          115            s
    7           32
    8           97            a
    9           32
   10          116            t
   11          101            e
   12          115            s
   13          116            t
   14            0


 92. Passing BASIC Double-Precision Array to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27290

 The example below demonstrates how to pass a double-precision array
 from compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB DoubleArray CDECL (_
             BYVAL p1 AS INTEGER,_
             BYVAL p2 AS INTEGER)
 DEFINT A-Z
 DIM i AS DOUBLE
 DIM array(10) AS DOUBLE
 CLS
 FOR i = 1 TO 10
    array(i) = i + 100
 NEXT i
 'Array must be a FAR pointer, so offset and segment must be passed:
 CALL DoubleArray(VARPTR(array(0)), VARSEG(array(0)))
 LOCATE 15, 1
 PRINT "Back in BASIC"
 FOR i = 1 TO 10
    PRINT i, array(i)
 NEXT i
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 void DoubleArray(array)
    double far *array;
  {
     int i;
     printf("Index         Value\n");
     for (i=0;i < 11; i++)
        {
          printf("  %d          %lf\n",i,array[i]);
          array[i]=array[i]+100;
        };
  }

 ===== OUTPUT =====

 Index         Value
   0          0.000000
   1          101.000000
   2          102.000000
   3          103.000000
   4          104.000000
   5          105.000000
   6          106.000000
   7          107.000000
   8          108.000000
   9          109.000000
  10          110.000000

 Back in BASIC
  1             201
  2             202
  3             203
  4             204
  5             205
  6             206
  7             207
  8             208
  9             209
  10            210


 93. Example Passing Numeric Variables from BASIC to C by Value

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27291

 The program below demonstrates how to pass numeric values from
 compiled BASIC to Microsoft C by VALUE.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 and to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB NumericValue CDECL (_
             BYVAL p1 AS INTEGER,_
             BYVAL p2 AS LONG,_
             BYVAL p3 AS SINGLE,_
             BYVAL p4 AS DOUBLE)
 a% = 32767
 b& = 32769
 c! = 123.312
 d# = 129381.333#
 CLS
 CALL NumericValue(a%, b&, c!, d#)
 END

 /* ===== C ROUTINE ===== */
 /* The variables are put into structs for memory alignment. */
 #include <stdio.h>
 struct struct_int{
    int x;
    };
 struct struct_long{
    long x;
    };
 struct struct_float{
    float x;
    };
 struct struct_double{
    double x;
    };
 void NumericValue(a, b, c, d)
    struct struct_int a;
    struct struct_long b;
    struct struct_float c;
    struct struct_double d;
    {
          printf("INTEGER  %d        \n",a.x);
          printf("LONG     %ld        \n",b.x);
          printf("FLOAT    %f        \n",c.x);
          printf("DOUBLE   %lf        \n",d.x);
    }

 ===== OUTPUT =====

 INTEGER  32767
 LONG     32769
 FLOAT    123.311996
 DOUBLE   129381.333000


 94. Passing BASIC Fixed-Length String to C by Near Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  3-NOV-1989    ArticleIdent: Q27292

 The following program demonstrates how to pass a fixed-length string
 from compiled BASIC to Microsoft C by near reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB StringNear CDECL (_
             BYVAL p1o AS INTEGER,_
             SEG p3 AS INTEGER)
 CLS
 DIM a AS STRING * 15
 a = "This is a test" + CHR$(0)
 CALL StringNear(VARPTR(a), LEN(a))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 void StringNear(a,len)
    char near *a;
     int *len;
  {
     int i;
     printf("The string is : %s \n\n",a);
     printf(" Index       Value       Character\n");
     for (i=0;i < *len; i++)
        {
          printf("  %2d          %3d            %c\n",i,a[i],a[i]);
        };
  }

 ===== OUTPUT =====

 The string is : This is a test

  Index       Value       Character
    0           84            T
    1          104            h
    2          105            i
    3          115            s
    4           32
    5          105            i
    6          115            s
    7           32
    8           97            a
    9           32
   10          116            t
   11          101            e
   12          115            s
   13          116            t
   14            0


 95. Passing BASIC Fixed-Length String to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27293

 The example below demonstrates how to pass a fixed-length string from
 compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM BASIC Program

 DECLARE SUB StringFar CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p1s AS INTEGER,_
             SEG p3 AS INTEGER)
 CLS
 DIM a AS STRING * 15
 a = "This is a test" + CHR$(0)
 CALL StringFar(VARPTR(a), VARSEG(a), LEN(a))
 END

 /* C Routine */

 #include <stdio.h>
 void StringFar(a,len)
    char far *a;
     int *len;
  {
     int i;
     printf("The string is : %s \n\n",array);
     printf(" Index       Value       Character\n");
     for (i=0;i < *len; i++)
        {
          printf("  %2d          %3d            %c\n",i,a[i],a[i]);
        };
  }

 Output
 ------

 The string is : This is a test

  Index       Value       Character
    0           84            T
    1          104            h
    2          105            i
    3          115            s
    4           32
    5          105            i
    6          115            s
    7           32
    8           97            a
    9           32
   10          116            t
   11          101            e
   12          115            s
   13          116            t
   14            0


 96. Passing BASIC INTEGER Array to Microsoft C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27294

 The example below demonstrates how to pass an array of integers from
 compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, search in the Software/Data Library for the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB IntArray CDECL (_
             BYVAL p1 AS INTEGER,_
             BYVAL p2 AS INTEGER)
 DEFINT A-Z
 DIM i AS INTEGER
 DIM array(10) AS INTEGER
 CLS
 FOR i = 1 TO 10
    array(i) = i
 NEXT i
 'Array must be a FAR pointer, so offset and segment must be passed:
 CALL IntArray(VARPTR(array(0)), VARSEG(array(0)))
 LOCATE 15, 1
 WHILE INKEY$ = "": WEND
 PRINT "Back in BASIC"
 FOR i = 1 TO 10
    PRINT i, array(i)
 NEXT i
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 void IntArray (array)
      int far *array;
  {
     int i;
     printf("Index         Value\n");
     for (i=0;i < 11; i++)
        {
          printf("  %d          %d\n",i,array[i]);
          array[i]=array[i]+100;
        };
  }

 ===== OUTPUT =====

 Index      Value
   0          0
   1          1
   2          2
   3          3
   4          4
   5          5
   6          6
   7          7
   8          8
   9          9
   10         10

 Back in BASIC
  1             101
  2             102
  3             103
  4             104
  5             105
  6             106
  7             107
  8             108
  9             109
  10            110


 97. Passing BASIC SINGLE-Precision Array to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27295

 The example below demonstrates how to pass a single-precision array
 from compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 ===== BASIC PROGRAM =====

 DECLARE SUB FloatArray CDECL (_
             BYVAL p1 AS INTEGER,_
             BYVAL p2 AS INTEGER)
 DEFINT A-Z
 DIM i AS SINGLE
 DIM array(10) AS SINGLE
 CLS
 FOR i = 1 TO 10
    array(i) = i + 100
 NEXT i
 'Array must be a FAR pointer, so offset and segment must be passed:
 CALL FloatArray(VARPTR(array(0)), VARSEG(array(0)))
 LOCATE 15, 1
 PRINT "Back in BASIC"
 FOR i = 1 TO 10
    PRINT i, array(i)
 NEXT i
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 void FloatArray(array)
    float far *array;
  {
     int i;
     printf("Index         Value\n");
     for (i=0;i < 11; i++)
        {
          printf("  %d          %f\n",i,array[i]);
          array[i]=array[i]+100;
        };
  }

 ===== OUTPUT =====

 Index         Value
   0          0.000000
   1          101.000000
   2          102.000000
   3          103.000000
   4          104.000000
   5          105.000000
   6          106.000000
   7          107.000000
   8          108.000000
   9          109.000000
   10          110.000000

 Back in BASIC
  1             201
  2             202
  3             203
  4             204
  5             205
  6             206
  7             207
  8             208
  9             209
  10            210


 98. Example Passing BASIC String Descriptor to Microsoft C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27296

 The example below demonstrates how to pass a string descriptor from
 compiled BASIC to Microsoft C.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB StringNear CDECL (a$)
 CLS
 array$ = "This is a test" + CHR$(0)
 CALL StringNear(array$)
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct struct_string{
      int length;
      char *address;
 };

 void StringNear(string)
    struct struct_string near *string;
  {
     int i;
     printf("The string is : %s \n\n",string->address);
     printf(" Index       Value       Character\n");
     for (i=0;i < string->length; i++)
        {
        printf("  %2d          %3d            %c\n",i,
               string->address[i], string->address[i]);
        };
  }

 ===== OUTPUT =====

 The string is : This is a test

  Index       Value       Character
    0           84            T
    1          104            h
    2          105            i
    3          115            s
    4           32
    5          105            i
    6          115            s
    7           32
    8           97            a
    9           32
   10          116            t
   11          101            e
   12          115            s
   13          116            t
   14            0


 99. Passing BASIC User-Defined Type to C by Near Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27297

 The example below demonstrates how to pass a user-defined type from
 compiled BASIC to Microsoft C by near reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 TYPE record
    a AS INTEGER
    b AS STRING * 20
    c AS SINGLE
 END TYPE

 DECLARE SUB TypeReference CDECL (SEG p1 AS record)

 CLS
 DIM element AS record
 element.a = 128
 element.b = DATE$ + CHR$(0)
 element.c = 39.6
 CALL TypeReference(element)
 END

 /* ===== C ROUTINE ===== /*

 #include <stdio.h>
 struct record{
        int a;
        char b[20];
        float c;
        };

 void TypeReference(element)
      struct record near *element;
  {
      printf("Record.A = %d\n",element->a);
      printf("Record.B = %s\n",element->b);
      printf("Record.C = %f\n",element->c);
  }

 ===== OUTPUT =====

 Record.A = 128
 Record.B = 02-02-1988
 Record.C = 39.599998


 100. Passing BASIC Array of Long Integers to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27298

 The following example demonstrates how to pass an array of long
 integers from compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB LongArray CDECL (_
             BYVAL p1 AS INTEGER,_
             BYVAL p2 AS INTEGER)
 DEFINT A-Z
 DIM i AS LONG
 DIM array(10) AS LONG
 CLS
 FOR i = 1 TO 10
    array(i) = i + 100
 NEXT i
 'Array must be a FAR pointer, so offset and segment must be passed:
 CALL LongArray(VARPTR(array(0)), VARSEG(array(0)))
 LOCATE 15, 1
 PRINT "Back in BASIC"
 FOR i = 1 TO 10
    PRINT i, array(i)
 NEXT i
 END

 /* ===== C ROUTINES ===== */

 #include <stdio.h>
 void LongArray(array)
    long far *array;
  {
     int i;
     printf("Index         Value\n");
     for (i=0;i < 11; i++)
        {
          printf("  %d          %ld\n",i,array[i]);
          array[i]=array[i]+100;
        };
  }

 ===== OUTPUT =====

 Index         Value
   0          0
   1          101
   2          102
   3          103
   4          104
   5          105
   6          106
   7          107
   8          108
   9          109
   10          110

 Back in BASIC
  1             201
  2             202
  3             203
  4             204
  5             205
  6             206
  7             207
  8             208
  9             209
  10            210


 101. Passing BASIC Array of Variable-Length Strings to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27299

 The following example demonstrates how to pass an array of
 variable-length strings from compiled BASIC to Microsoft C.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB StringArray CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p2s AS INTEGER)
 CLS
 DIM array$(10)
 FOR i = 0 TO 10
   array$(i) = STRING$(9, 65 + i) + CHR$(0)
 NEXT i
 CALL StringArray(VARPTR(array$(0)), VARSEG(array$(0)))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct struct_string{      /* structure that looks like a */
      int length;           /* string descriptor           */
      char *address;
      };
 void StringArray(string)
    struct struct_string far *string;
  {
     int i;
     printf(" Index  Length    String\n");
     for (i=0;i < 10; i++)
        {
          printf("  %2d     %3d     %s\n",i,string->length,
                 string->address);
          string++;
        };
  }

 ===== OUTPUT =====

  Index  Length    String
    0      10     AAAAAAAAA
    1      10     BBBBBBBBB
    2      10     CCCCCCCCC
    3      10     DDDDDDDDD
    4      10     EEEEEEEEE
    5      10     FFFFFFFFF
    6      10     GGGGGGGGG
    7      10     HHHHHHHHH
    8      10     IIIIIIIII
    9      10     JJJJJJJJJ


 102. Passing BASIC Array of Fixed-Length Strings to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27300

 The following example demonstrates how to pass an array of
 fixed-length strings from compiled BASIC to Microsoft C.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB StringFar CDECL (_
         length%,_
         num%,_
         BYVAL p3o AS INTEGER,_
         BYVAL p3s AS INTEGER)
 CLS
 DIM array(10) AS STRING * 10
 length% = 10
 num% = 3
 FOR i = 0 TO 10
    array(i) = STRING$(9, 65 + i) + CHR$(0)
 NEXT i
 CALL StringFar(length%, num%, VARPTR(array(0)), VARSEG(array(0)))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 void StringFar(len,num,array)
    int  *len;
    int  *num;
    char far *array;
  {
     int i;
     printf("The string length is : %d \n\n",*len);
     printf("The number of elements is : %d \n\n",*num);
     printf(" Index        String\n");
     for (i=0;i < *num; i++)
        {
          printf("  %2d         %s\n",i,array);
          array=array+*len;
        };
  }

 ===== OUTPUT =====

 The string length is : 10

 The number of elements is : 3

  Index        String
    0         AAAAAAAAA
    1         BBBBBBBBB
    2         CCCCCCCCC


 103. Passing BASIC User-Defined Type to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27301

 The following example demonstrates how to pass a user-defined type
 from compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 TYPE record
    a AS INTEGER
    b AS STRING * 20
    c AS SINGLE
 END TYPE
 DECLARE SUB TypeReference CDECL (BYVAL p1o AS INTEGER, _
                                  BYVAL p1s AS INTEGER)
 CLS
 DIM element AS record
 element.a = 128
 element.b = DATE$ + CHR$(0)
 element.c = 39.6
 CALL TypeReference(VARPTR(element), VARSEG(element))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct record{
        int a;
        char b[20];
        float c;
        };

 void TypeReference(element)
      struct record far *element;
  {
      printf("Record.A = %d\n",element->a);
      printf("Record.B = %s\n",element->b);
      printf("Record.C = %f\n",element->c);
  }

 ===== OUTPUT =====

 Record.A = 128
 Record.B = 02-02-1988
 Record.C = 39.599998


 104. Passing BASIC Array of User-Defined Type to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27302

 The following example demonstrates how to pass an array of
 user-defined-type records from compiled BASIC to Microsoft C.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 TYPE record
    a AS INTEGER
    b AS STRING * 20
    c AS SINGLE
 END TYPE
 DECLARE SUB TypeArray CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p1s AS INTEGER)
 CLS
 DIM element(10) AS record
 FOR I = 0 TO 10
     element(I).a = 128 + I
     element(I).b = STR$(I) + ". " + DATE$ + CHR$(0)
     element(I).c = 39.6 * I
 NEXT I
 CALL TypeArray(VARPTR(element(0)), VARSEG(element(0)))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct record{
        int a;
        char b[20];
        float c;
 };
 void TypeArray(element)
      struct record far *element;
  {
     int i;
     for (i=0;i<3;i++)
       {
         printf("Record[%d].A = %d\n",i,element->a);
         printf("Record[%d].B = %s\n",i,element->b);
         printf("Record[%d].C = %f\n",i,element->c);
         printf("\n");
         element++;
       };
  }

 ===== OUTPUT =====

 Record[0].A = 128
 Record[0].B =  0. 02-02-1988
 Record[0].C = 0.000000

 Record[1].A = 129
 Record[1].B =  1. 02-02-1988
 Record[1].C = 39.599998

 Record[2].A = 130
 Record[2].B =  2. 02-02-1988
 Record[2].C = 79.199997


 105. Passing BASIC 2-Dimension INTEGER Array to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27303

 The following example demonstrates how to pass a two-dimensional array
 of INTEGERs from compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

  DECLARE SUB TwoIntArray CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p1s AS INTEGER)
 CLS
 DIM x(4, 4) AS INTEGER
 FOR i = 0 TO 4
    FOR j = 0 TO 4
        x(i, j) = i * j
    NEXT j
 NEXT i
 CALL TwoIntArray(VARPTR(x(0, 0)), VARSEG(x(0, 0)))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct two_int_array{
        int a[5][5];
        };

 void TwoIntArray(x)
      struct two_int_array far *x;
      /* Note: The array does not have to be in a struct. */
  {
     int i,j;
     for (i=0;i<5;i++)
     {
        for (j=0;j<5;j++)
        {
           printf("  %3d   ",x->a[i][j]);
        };
        printf("\n");
     };
  }

 ===== OUTPUT =====

     0       0       0       0       0
     0       1       2       3       4
     0       2       4       6       8
     0       3       6       9      12
     0       4       8      12      16


 106. Passing BASIC 2-Dimensional Variable-Length String Array to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27323

 The following example demonstrates how to pass a two-dimensional array
 of variable-length strings from compiled BASIC to Microsoft C.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB TwoStringArray CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p1s AS INTEGER)
 CLS
 DIM array$(4, 4)
 FOR i = 0 TO 4
  FOR j = 0 TO 4
    array$(i, j) = STRING$(5, 65 + (i + j)) + CHR$(0)
  NEXT j
 NEXT i
 CALL TwoStringArray(VARPTR(array$(0, 0)), VARSEG(array$(0, 0)))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct struct_string{
      int length;
      char *address;
      };
 struct string_array{
      struct struct_string x[5][5];
 };

 void TwoStringArray(array)
    struct string_array far *array;
  {
     int i,j;
     for (i=0;i < 5; i++)
        {
          for(j=0;j<5;j++)
          {
              printf("  %s  ",array->x[i][j].address);
          };
          printf("\n");
        };
  }

 ===== OUTPUT =====

   AAAAA    BBBBB    CCCCC    DDDDD    EEEEE
   BBBBB    CCCCC    DDDDD    EEEEE    FFFFF
   CCCCC    DDDDD    EEEEE    FFFFF    GGGGG
   DDDDD    EEEEE    FFFFF    GGGGG    HHHHH
   EEEEE    FFFFF    GGGGG    HHHHH    IIIII


 107. Passing Numeric Variables between BASIC and C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27324

 The following example demonstrates how to pass numeric values from
 compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 ===== BASIC PROGRAM =====

 DECLARE SUB NumericFar CDECL (_
         BYVAL p1o AS INTEGER, BYVAL p1s AS INTEGER,_
         BYVAL p2o AS INTEGER, BYVAL p2s AS INTEGER,_
         BYVAL p3o AS INTEGER, BYVAL p3s AS INTEGER,_
         BYVAL p4o AS INTEGER, BYVAL p4s AS INTEGER)
 a% = 32767
 b& = 32769
 c! = 123.312
 d# = 129381.333#
 CLS
 CALL NumericFar(VARPTR(a%), VARSEG(a%),_
                 VARPTR(b&), VARSEG(b&),_
                 VARPTR(c!), VARSEG(c!),_
                 VARPTR(d#), VARSEG(d#))
 END

 ===== C ROUTINE =====

 #include <stdio.h>
 void NumericFar(a, b, c, d)
    int far *a;
    long far *b;
    float far *c;
    double far *d;
  {
          printf("INTEGER  %d        \n",*a);
          printf("LONG     %ld        \n",*b);
          printf("FLOAT    %f        \n",*c);
          printf("DOUBLE   %lf        \n",*d);
  }

 ===== OUTPUT =====

 INTEGER  32767
 LONG     32769
 FLOAT    123.311996
 DOUBLE   129381.333000


 108. Example Passing Near Numeric Variables between BASIC and C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27325

 The two programs shown below demonstrate how numeric variables can be
 passed from compiled BASIC to Microsoft C by near reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 The following BASIC program is BNUMNEAR.BAS, which passes each of the
 standard numeric types to a C subroutine:

 DECLARE SUB NumericNear CDECL (a%,b&,c!,d#)
 a% = 32767
 b& = 32769
 c! = 123.312
 d# = 129381.333#
 CLS
 CALL NumericNear(a%, b&, c!, d#)
 END

 The following program is CNUMNEAR.C, which prints out the standard
 numeric values passed from BASIC:

 #include <stdio.h>
 void NumericNear(a, b, c, d)
    int near *a;
    long near *b;
    float near *c;
    double near *d;
  {
     printf("INTEGER %d  \n", *a);
     printf("LONG    %ld \n", *b);
     printf("FLOAT   %f  \n", *c);
     printf("DOUBLE  %lf \n", *d);
  }

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

      BC BNUMNEAR.BAS;

      CL /c /AM CNUMNEAR.C;      < for Microsoft C Optimizing Compiler >

            or

      QCL /c /AM CNUMNEAR.C;     < for Microsoft QuickC Compiler >

      LINK /NOE BNUMNEAR CNUMNEAR;

 BNUMNEAR.EXE produces the following output:

      INTEGER  32767
      LONG     32769
      FLOAT    123.311996
      DOUBLE   129381.333000


 109. Passing BASIC Variable-Length String to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27326

 The following example demonstrates how to pass a variable-length
 string variable from compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB StringFar CDECL (_
         BYVAL p1o AS INTEGER,_
         BYVAL p1s AS INTEGER,_
         SEG p3 AS INTEGER)
 CLS
 a$ = "This is a test" + CHR$(0)
 CALL StringFar(SADD(a$), VARSEG(a$), LEN(a$))
 END

 /* ===== C ROUTINE ===== /*

 #include <stdio.h>
 void StringFar(a,len)
    char far *a;
     int *len;
  {
     int i;
     printf("The string is : %s \n\n",a);
     printf(" Index       Value       Character\n");
     for (i=0;i < *len; i++)
        {
          printf("  %2d          %3d            %c\n",i,a[i],a[i]);
        };
  }

 ===== OUTPUT =====

 The string is : This is a test

  Index       Value       Character
    0           84            T
    1          104            h
    2          105            i
    3          115            s
    4           32
    5          105            i
    6          115            s
    7           32
    8           97            a
    9           32
   10          116            t
   11          101            e
   12          115            s
   13          116            t
   14            0


 110. Passing COMMON Variables from BASIC to C by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  6-NOV-1989    ArticleIdent: Q27327

 The following example demonstrates how to pass COMMON variables from
 compiled BASIC to Microsoft C by far reference.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 REM ===== BASIC PROGRAM =====

 DECLARE SUB RCommon CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p1s AS INTEGER)
 COMMON SHARED element1 AS INTEGER, element2 AS STRING * 20, _
               element3 AS SINGLE
 element1 = 23
 element2 = "DATE : " + DATE$ + CHR$(0)
 element3 = 309.03
 CALL RCommon(VARPTR(element1), VARSEG(element1))
 END

 /* ===== C ROUTINE ===== */

 #include <stdio.h>
 struct common_block{   /* structure that looks like the BASIC */
        int a;          /* common block                        */
        char b[20];
        float c;
 };
 void RCommon(pointer)
      struct common_block far *pointer;
  {
      printf("Element1 = %d\n",pointer->a);
      printf("Element2 = %s\n",pointer->b);
      printf("Element3 = %f\n",pointer->c);
  }

 ===== OUTPUT =====

 Element1 = 23
 Element2 = DATE : 02-02-1988
 Element3 = 309.029999


 111. Explanation of Compiler "Bytes Available" and "Bytes Free"

 Product Version(s): 4.00 4.00 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q27347

 At the end of a successful compilation, the BC.EXE compiler displays
 the following message:

    nnnnn Bytes Available
    nnnnn Bytes Free

           0 Warning Error(s)
           0 Severe Error(s)

 This message gives the amount of compiler workspace available before
 (Bytes Available) and after (Bytes Free) a program is compiled.

 If the Bytes Free is approaching 1024 or less, then the compiler is
 reaching internal workspace limits in generating code for this module,
 and you should break your program into smaller, separately compiled
 SUBprogram procedures or FUNCTION procedures that can be linked
 together (with LINK.EXE). The CHAIN statement is another alternative.

 Note that BC.EXE can give you a "Program-memory overflow" or "Out of
 Memory" error at compile time when there are still plenty of Bytes
 Free. This happens when the compiler has enough workspace but the code
 segment that it generates exceeds 64K. To work around this limitation,
 you need to break the program into separately compiled procedure
 modules, or into separately compiled main programs, that can run each
 other with the CHAIN statement.

 This information applies to QuickBASIC Compiler versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft
 BASIC Compiler versions 5.35 and 5.36 for MS-DOS and versions 6.00,
 6.00b for MS OS/2 and MS-DOS; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The 64K memory segmentation architecture of the 8086 chip has
 influenced design limitations of the BASIC compiler so that it can use
 only 64K blocks for internal compiler workspace, and can generate only
 64K or less for a program's code segment.

 Bytes Available is the initial amount of compiler workspace available
 for storing the symbol table and the line number table, and for
 working storage for code generation and optimization.

 Bytes Free is the size of unused compiler workspace after the compiler
 has finished.

 For a separate article that discusses how code affects compiler
 workspace, search on the following words:

    BASIC and bytes available and free and symbol table and workspace

 Note: The number of bytes that BC.EXE generated for a module's code
 segment is NOT indicated by the size of the .OBJ file on disk.
 Instead, you must refer to the .MAP file that can be optionally output
 from the LINK.EXE linker. The program must have been successfully
 compiled and linked to get a valid link .MAP file. Your module will be
 listed by name in the .MAP file under a _Code Class, and its code
 segment size will be shown in hexadecimal (base 16) notation in the
 Length column.


 112. LINE INPUT to Fixed-Length String Crashes QB.EXE Interpreter

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER | ptm37 fixlistbc6.00 buglist4.00 fixlist4.00b fixlist4.50
 Last Modified:  7-NOV-1988    ArticleIdent: Q27385

 Using a fixed-length string to accept input in a LINE INPUT statement
 can hang the QB.EXE Interpreter.

 Microsoft has confirmed this to be a problem in Version 4.00. This
 problem was corrected in QuickBASIC Versions 4.00b and 4.50, and in
 the Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2.

 The following is an example program showing the problem:

    DIM C AS STRING * 10
    LINE INPUT C
    PRINT C

 Run the program and type 1 in response to the LINE INPUT. This will
 hang QB.EXE.

 The workaround for this problem is to LINE INPUT into a
 variable-length string and then assign to a fixed-length string.


 113. BC Hangs Compiling on f(1) GOTO with Constant in Function

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 ptm154 buglist4.00b fixlist4.50
 Last Modified: 29-NOV-1988    ArticleIdent: Q27402

 BC.EXE hangs at compile time when you compile a program that has an
 <ON x GOTO linelist> statement, where x is a FUNCTION statement that
 is passed as a constant in an argument.

 The program runs correctly in the editor/interpreter environment.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and the Microsoft BASIC Compiler Version 6.00
 (buglist6.00) for MS-DOS and OS/2. This problem is corrected in
 QuickBASIC Version 4.50 and in the BASIC Compiler Version
 6.00b(fixlist6.00b).

 The problem only occurs when the argument passed to the function is a
 literal value. The function size has no effect. BC will hang when
 invoked either from DOS or from "Make EXE" in the QB editor.

 Note that function procedures are not found in versions of QuickBASIC
 earlier than Version 4.00.

 The following is an example of the problem:

    DECLARE FUNCTION TEST (i)
    ON test((1)) GOTO ter
    ter:
      END

    FUNCTION test (i)
      test = i
    END FUNCTION

 The workaround is to not pass a literal value as the function
 argument. For example, change the ON x GOTO to the following:

     i = 1
     ON test(i) GOTO ter


 114. LINE (0,0)-(12231,12230) Causes Line Coordinates to Overflow

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 17-JAN-1990    ArticleIdent: Q27406

 A LINE graphics statement gives an Overflow Error with certain large
 (but valid) values for coordinates. The first two LINE statements of
 the example below work correctly; the third LINE statement gives the
 overflow error.

 This problem occurs both in the QB.EXE editor environment and as an
 .EXE file.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and OS/2 (fixlist7.00).

 The code example is as follows:

    screen 2
    line (0,0)-(12230, 12230)
    line (0,0)-(12231, 12231)
    line (0,0)-(12231, 12230)


 115. Can't Pass QuickBASIC COMMON Block to FORTRAN

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-JUN-1989    ArticleIdent: Q27475

 When passing a FORTRAN COMMON block to a compiled BASIC procedure, the
 first variable in the FORTRAN COMMON block is passed as a parameter in
 the CALL statement. The compiled BASIC procedure receives the variable
 as a user-defined type that corresponds to the COMMON block. This
 works when passing a FORTRAN COMMON block to a compiled BASIC
 procedure, but is not supported for passing a BASIC COMMON block to a
 FORTRAN routine, because FORTRAN does not support user-defined types.

 You cannot pass a COMMON block defined in a compiled BASIC procedure
 to a FORTRAN routine.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, and to the Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and OS/2.


 116. Guidelines for Interfacing FORTRAN with Compiled BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1988    ArticleIdent: Q27476

 Interfacing FORTRAN with compiled BASIC is fairly straightforward;
 however, there are several rules to observe.

 These rules are as follows:

 1. FORTRAN should not be linked with the small-memory model.

 2. When compiling the FORTRAN subroutine, no special switches need to
    be used. However, you need to LINK the BASIC and FORTRAN routines
    with the /NOE option.

 3. FORTRAN has the ability to call BASIC subprograms; however, the
    FORTRAN routine that calls the BASIC subprograms must have
    originally been called by a BASIC main program.

 4. All variables that are passed from a FORTRAN routine to a BASIC
    subprogram must be [NEAR] variables.

 5. FORTRAN routines can be used in a quick library if so desired.

 6. Microsoft FORTRAN Version 4.00 is needed to correctly interface
    with QuickBASIC Version 4.00. Microsoft FORTRAN Version 4.10 is
    needed to correctly interface with QuickBASIC Versions 4.00b and
    4.50 or BASIC Compiler Versions 6.00 and 6.00b programs.


 117. Passing FORTRAN COMMON Block to QuickBASIC SUBprogram

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 18-OCT-1989    ArticleIdent: Q27480

 The strategy for passing a FORTRAN COMMON block to QuickBASIC is to
 pass the first variable of the FORTRAN COMMON block as a parameter in
 the CALL to the BASIC routine. The BASIC program should set up a
 user-defined-TYPE variable with the same format as the COMMON in
 FORTRAN. The BASIC SUB statement must receive a variable of this type
 as a formal parameter.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and to the Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and OS/2.

 BASIC Program
 -------------

 The BASIC program is as follows:

 DECLARE SUB forsub ()

 TYPE CommonDescription
   a AS INTEGER             'Matches common block in FORTRAN
   b AS LONG
   c AS SINGLE
   d AS DOUBLE
 END TYPE

 CALL forsub

 SUB subbas (var AS CommonDescription)
   PRINT var.a
   PRINT var.b
   PRINT var.c
   PRINT var.d
 END SUB

 FORTRAN Subroutine
 ------------------

 The FORTRAN subroutine is as follows:

        INTERFACE TO SUBROUTINE SUBBAS (N1)
        INTEGER*2 N1 [NEAR]
        END

        SUBROUTINE FORSUB
        INTEGER*2 A
        INTEGER*4 B
        REAL*4 C
        REAL*8 D

       *The common block must be a named common block (any name will do).
       *The [NEAR] has to be there for it to work.

        COMMON /FORBLOCK [NEAR]/ A,B,C,D
        A = 9
        B = 999
        C = 99.99
        D = 999.999
        CALL SUBBAS(A)
        END

 OUTPUT
 ------

 The OUTPUT is as follows:

 9
 999
 99.99
 999.999


 118. "String Space Corrupt" Within Editor but Not in .EXE File

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 17-JAN-1990    ArticleIdent: Q27482

 The following program gives a "String Space Corrupt" error inside the
 QB.EXE editor when it is executed a second time. However, if the
 second to the last line is deleted, the program executes without
 causing the error.

 If various other lines are removed, the program will also run without
 giving the error message.

 The program executes correctly if compiled and run as an executable
 file.

 Microsoft has confirmed this to be a problem in QB.EXE in QuickBASIC
 Versions 4.00 and 4.00b, and in QB.EXE in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS (buglist6.00, buglist6.00b). This
 problem was corrected in QB.EXE in QuickBASIC Version 4.50 and in
 QBX.EXE in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 (fixlist7.00).

 As a workaround, compile and run the program as an executable file.

 The following is a code example:

 DEFINT A-Z
 INFI = 4: PARTIAL = 0
 P = 27
 OPEN "R", INFI, "LETHDR62", 220
 FIELD INFI, 220 AS FLD$
 BYTUSE = 4095
 FOR i = 1 TO 3
     J = 220 - P + 1
     IF J > BYTUSE THEN J = BYTUSE
     FIELD INFI, P - 1 AS D$, J AS D1$
     BYTUSE = BYTUSE - J: P = P + J
     IF P > 220 THEN P = 1
 NEXT
 PRINT "Hello, the next statement fails on the second pass through"
 D$ = CHR$(6)
 CLOSE INFI


 119. CALLing C I/O Routines Does Not Affect QB Cursor Position

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  7-FEB-1990    ArticleIdent: Q27486

 Problem:

 Microsoft C routines (medium model) linked with a compiled BASIC
 program that do screen output [such as printf ("hello, world.\n");] do
 not update the cursor position after returning to the calling BASIC
 program.

 For example, after 1) doing a PRINT from BASIC, 2) CALLing a C routine
 that does some printf's, and 3) returning to BASIC, the next PRINT
 statement goes directly after the last BASIC PRINT statement, ignoring
 the \n's (newline characters) from the called C routine.

 Response:

 This is expected behavior. C routines should not change the BASIC
 cursor position. This information applies to Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions
 6.00 and 6.00b, and to Microsoft BASIC Professional Development System
 (PDS) Version 7.00.

 To work around this limitation, OPEN "CONS:" as a device in BASIC and
 print to the console (screen) using PRINT# or PRINT# USING in BASIC.
 This forces BASIC to go through the operating system's console device
 instead of using direct writes to video memory.

 The following is a code example where a C function doesn't change the
 cursor position in BASIC:

    'The following QuickBASIC program prints:
    ' Hello.
    ' Goodbye.t part of this line gets erased.
    DECLARE SUB CRoutine CDECL ()
    CLS
    PRINT "Hello."
    CALL CRoutine
    PRINT "Goodbye."

    /* C program */
    #include <stdio.h>
    void croutine ()
    {
    printf ("The first part of this line gets erased.\n");
    }


 120. Installing Compilers on a Network Violates License Agreement

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_COBol B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q35270

 Installing any of the following products on a network is prohibited by
 the Microsoft License Agreement:

 1. Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 6.00, 6.00b and 7.00 for MS-DOS
    and MS OS/2

 3. Microsoft COBOL Compiler Versions 1.10, 1.12, 2.00, 2.10, 2.20, and
    3.00 for MS-DOS

 These applications are single-user products; network versions of them
 are unavailable at this time.

 Note that the applications created with the compilers are allowed to
 be used on networks.


 121. "Out of String Space," Dynamic Array of Fixed-Length Strings

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  7-FEB-1989    ArticleIdent: Q27489

 When running the program below inside the QuickBASIC Version 4.00,
 4.00b, or 4.50 environment, an "Out of String Space" error is
 generated after fewer than 70 iterations of concatenating a variable
 length string onto a fixed-length string array element. However, the
 FRE("") and FRE(-1) functions both return the same value all the way
 through the loop. Note that the fixed-length string array element is
 part of a dynamic array, which puts it in the far heap; therefore, it
 normally does not use up any of the normal string space in the default
 data segment.

 The program below demonstrates an internal limitation of the QB.EXE
 interpreter that is rarely encountered. Microsoft currently does not
 plan to change this limitation.

 Note that fixed-length strings are not supported by QuickBASIC
 versions earlier than Version 4.00.

 As a workaround, please note that the problem only occurs inside the
 QuickBASIC Version 4.00 editor. When compiled to an .EXE file, the
 sample program works properly.

 The problem is that QuickBASIC assumes that a far fixed-length string
 will always stay far. The BASIC run-time routines must have the string
 in DGROUP to manipulate it with string functions like LTRIM$ and
 RTRIM$.

 LTRIM$ and RTRIM$ require two copies of the string at one point, and
 the program eventually runs out of string space in the default data
 segment, DGROUP. This behavior also occurs in a version of the
 program compiled with BC /O if the strings are made longer. This
 limitation of BASIC is inherent in its construction, and Microsoft
 currently has no plans to change this construction.

 The following is a code example:

  REM $DYNAMIC
  DIM srv(0) AS STRING * 28000
  abc$ = STRING$(330,"0")
  srv(0) = abc$
  FOR t = 1 TO 79
    srv(0) = RTRIM$(srv(0)) + abc$
    PRINT t, LEN(RTRIM$(srv(0))), FRE(""), FRE(-1)
  NEXT T


 122. FUNCTION Fails to Return Zero by Default When Compiled as .EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q27490

 When a FUNCTION is called multiple times inside the QB.EXE editor, the
 FUNCTION automatically returns a value of (0) zero unless it is set to
 some other value within the FUNCTION, as expected.

 However, when run from an .EXE file, the value returned by a FUNCTION
 is no longer reset to zero by default; it retains its value from the
 previous invocation.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b); and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 (buglist7.00, buglist7.10) for MS-DOS and MS OS/2. We are
 researching this problem and will report new information here as it
 becomes available.

 When running the program below in the QB.EXE or QBX.EXE editor, the
 first five FUNCTION calls return a value of 99; the next five, from
 i%=6 to 10, return zeros, as expected. However, when run as an .EXE
 program, the last five FUNCTION calls incorrectly return a value of
 99 instead of zero.

 To work around the problem, add the line "fun%=0" as the first line of
 the function; the .EXE file will then work properly.

 The following a code example demonstrates the problem when compiled
 with BC.EXE, linked, and run as an .EXE program:

    DECLARE FUNCTION fun% (i%)
    FOR i% = 1 TO 10
      PRINT fun%(i%)
    NEXT i%
    FUNCTION fun% (i%) STATIC
      ' fun%=0   ' This line can be added as a workaround.
    IF i% <= 5 THEN fun% = 99
    END FUNCTION


 123. "Overflow" Error Using QLBDUMP.BAS with Large Quick Library

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 25-APR-1990    ArticleIdent: Q27496

 When running the program QLBDUMP.BAS, large Quick libraries can cause
 an "Overflow" error. The error occurs in the following line:

    QHdrPos = (EHdr.CParHdr + EHdr.CS) * 16 + EHdr.IP + 1

 This error can be corrected by making the 16 into a long-integer
 constant. To do this, change the line to read as follows:

    QHdrPos = (EHdr.CParHdr + EHdr.CS) * 16& + EHdr.IP + 1

 Alternatively, you can invoke the CLNG function as follows:

    QHdrPos = CLNG(EHdr.CParHdr + EHdr.CS) * 16 + EHdr.IP + 1

 Microsoft has confirmed this to be a problem in the QLBDUMP.BAS
 program example provided in QuickBASIC Versions 4.00, 4.00b, and 4.50,
 and in Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
 MS OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 (fixlist7.00).

 The problem occurs because the calculations on the right-hand side of
 the equation are being done in normal-integer math, even though the
 result is to be stored in a long-integer variable. Making the 16 a
 long integer forces the right-hand side of the equation to do its math
 in long-integer format.

 The QLBDUMP program lets you display the routines that are stored in a
 .QLB Quick library. The QB.EXE editor uses Quick libraries for calling
 external routines. Quick libraries (.QLB files) have no other purpose.


 124. Fixed String Initializing, Space & Null Bytes, LEN, and RTRIM$

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  9-FEB-1990    ArticleIdent: Q27631

 An uninitialized fixed-length string is filled with null bytes. When
 you initialize a fixed-length string to be equal to "" (the "null
 string"), the string will be filled with blank bytes. This behavior of
 fixed-length strings differs from variable-length strings, and may
 affect your program's use of functions like RTRIM$ in ways you don't
 expect (see code examples below).

 Note that a null byte has an ASCII value of zero, the same as is
 returned by the CHR$(0) function, whereas a blank byte has an ASCII
 value of 32, the same as is returned by the CHR$(32) function.

 The length shown by the LEN function for a fixed-length string x will
 always be the fixed size n determined in the DIM x AS STRING * n
 statement.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Note that fixed-length strings are not supported in QuickBASIC
 Versions 3.00 and earlier.

 Note that LEN(RTRIM$(x)) returns the actual length of just the
 non-null, nonblank contents of x if x is an INITIALIZED fixed-length
 string. (This is because RTRIM$ actually returns a variable-length
 string.) If x is an UNINITIALIZED fixed-length string, LEN(RTRIM$(x))
 always returns the fixed, dimensioned length, since RTRIM$ is ignored
 in this case.

 The following code example demonstrates the difference between
 assigned and unassigned fixed-length strings:

    DIM s AS STRING * 10                          'initially nulls
    PRINT LEN(s),LEN(RTRIM$(s)),ASC(RIGHT$(s,1))  '10,10 and 0 (null)
    s = ""                                        'pad with spaces
    PRINT LEN(s),LEN(RTRIM$(s)),ASC(RIGHT$(s,1))  '10,0 and 32 (space)

 In the following sample program, A is a fixed-length string with a
 length of 10 bytes, and B$ is a variable-length string. Both A and B$
 are assigned a string of ten blank characters (ASCII value 32).

    DIM a AS STRING * 10
    B$ = SPACE$(10)
    PRINT LEN(RTRIM$(a))  ' Prints 10 since fixed string is uninitialized.
    PRINT LEN(RTRIM$(b$))  ' Prints 0 for variable-length string.
    a = ""
    PRINT LEN(RTRIM$(a))  ' prints 0 as the length of the trimmed string
                          ' returned by RTRIM$ since fixed string is all
                          ' blanks.

 Note that the RTRIM$ function returns a variable-length string, even
 when a fixed-length string is its argument in parentheses. In the
 above program, the LEN function is operating on the variable-length
 string returned by the RTRIM$ function.

 The following code example illustrates one case where the incorrect
 assumption that fixed-length strings are automatically initialized to
 spaces will cause unexpected results. The INPUT statement will never
 get executed, unless the fixed length STRING "s" is initialized to all
 blanks:

 DIM s AS STRING * 10        'Desired result: wait until something entered.
 's = ""                     'Uncomment this line for expected results.
 WHILE RTRIM$(s) = ""        'Fails first time since RTRIM$(s)=10 nulls.
    INPUT "Input data: ",s   'Never executed
 WEND


 125. Old LINKer "Unrecognized Switch Error: 'EX'" when "Make EXE"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-JAN-1990    ArticleIdent: Q27857

 When making an EXE file from within the QB.EXE Version 4.00, 4.00b, or
 4.50 editor and QBX.EXE (from Microsoft BASIC PDS Version 7.00)
 editor, the following message is generated when the wrong version of
 LINK.EXE is used:

    Unrecognized switch error: "EX"

 When running an older linker from DOS with a newer switch (such as
 mistakenly using the /NOE option with the LINK.EXE Version 3.05
 provided with DOS Version 3.30), you can also get an "Unrecognized
 switch error" message.

 You must use the LINK.EXE that comes with QuickBASIC or the BASIC
 Compiler (or a later version of the linker). To find out the version
 number, invoke LINK from your working directory, and the linker
 displays a version number. This number can be compared with the number
 displayed by LINK.EXE on the product release disk.

 QuickBASIC Version 4.00 and QBX.EXE from BASIC PDS 7.00 each comes
 with its own copy of the LINK utility (LINK.EXE, Version 3.61 and
 Version 5.05 respectively). This version of the linker supports (and
 later versions support) the new /EX (/EXEPACK) switch. The function of
 this switch is to remove sequences of repeated bytes from object
 files. As a result, the switch provides a means for creating smaller
 EXE files. When the Make EXE option is chosen inside the editor from
 the Run menu, this switch is automatically used when the linker is
 invoked. Subsequently, if the wrong version of the linker is found
 (that is, one that does not support the new /EX switch), the error
 message "Unrecognized switch error" is generated.

 Because the message correctly indicates that the wrong version of
 LINK.EXE is being used, the workaround is to either remove all older
 versions of the linker from the machine or modify the DOS path
 statement so that the correct version of the linker is the first one
 found.


 126. Creating a Quick Library (.QLB) from a LINK Library (.LIB)

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_LINK
 Last Modified: 20-SEP-1990    ArticleIdent: Q27993

 The LINK.EXE utility can create a Quick library (.QLB) file from a
 LINKer library (.LIB) file. This can be done by using the LINK /Q
 option and the following syntax

    LINK xxxx.LIB /Q,,,BQLB40.LIB;

 where xxxx.LIB is your own .LIB library for which you want to make a
 Quick library. Also, you must link to the appropriate BQLBxx.LIB
 support library as follows: for QuickBASIC 4.00 and Microsoft BASIC
 Compiler 6.00, use BQLB40.LIB; for QuickBASIC 4.00b and BASIC compiler
 6.00b, use BQLB41.LIB; for QuickBASIC 4.50, use BQLB45.LIB.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, and to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS.

 Also, at the bottom of this article is a method to build a QuickBASIC
 version 2.00, 2.01, or 3.00 run-time user library from .LIB libraries.
 Run-time user libraries are created and used differently than the
 Quick libraries found in later versions.

 Note that Quick libraries (.QLB files) can only be used in the QB.EXE
 environment (and are loaded with the /L option).

 The QuickBASIC manual describes methods for creating Quick libraries
 using either .OBJ files or the Make Lib option on the Run menu from
 within the QB editor. The above LINK command lets you create a .QLB
 file when only a .LIB file is available.

 For example, when the following command is issued from the DOS command
 line, a Quick library (MOUSE.QLB) is created from the library file
 MOUSE.LIB:

    LINK MOUSE.LIB /Q,,,BQLB40.LIB;

 A similar method is used when you want to combine two or more existing
 libraries into one Quick library. For example, the following command
 will combine MY.LIB (a library created by you) with QB.LIB (a library
 provided with the compiler) to form MYNEW.QLB:

    LINK MY.LIB+QB.LIB /Q, MYNEW.QLB,, BQLB40.LIB;

 Please note that if the following command is used to create the Quick
 library, then only those files in QB.LIB that are called from MY.LIB
 will ultimately become a part of MYNEW.QLB:

    LINK MY.LIB /Q, MYNEW.QLB,, BQLB40.LIB+QB.LIB;

 Therefore, if the routines in QB.LIB are being called from the
 main-module level of the program, you must use the previous syntax
 (that is, all .LIB files must be specified in the first parameter).

 For more information on the creation of Quick libraries, see Pages
 189-201 and 221 of the "Microsoft QuickBASIC 4.0: Learning and Using
 Microsoft QuickBASIC" manual for versions 4.00 and 4.00b. See also
 Pages 377-389 (Appendix H: "Creating and Using Quick Libraries") in
 the "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for
 version 4.50.

 QuickBASIC 2.x, 3.00
 --------------------

 In QuickBASIC versions 2.00, 2.01, and 3.00, the BUILDLIB.EXE utility
 can convert subprogram .OBJ files into run-time user libraries, which
 can be called from within the QB editor or unlike in later versions,
 called from an EXE program compiled to require the run-time module.
 QuickBASIC versions released after 3.00 do not offer the BUILDLIB.EXE
 utility and don't support run-time user libraries for use with EXE
 programs. (However, BASIC compiler 6.00 and 6.00b, and Microsoft
 Professional Development System (PDS) 7.00 and 7.10 do offer a similar
 capability: a BUILDRTM.EXE utility to add .OBJ modules to the BASIC
 run-time module itself.)

 The BUILDLIB.EXE from QuickBASIC 2.x/3.00 can create user libraries
 from .LIB files when you invoke BUILDLIB with the /L option (BUILDLIB
 /L). Once invoked with /L, BUILDLIB then prompts you for the name of
 the .LIB library file to input and the name of the user library to
 output. Object .OBJ files cannot be input to BUILDLIB.EXE if you
 invoke with the /L switch, unless the .OBJ files first are put into
 .LIB files with the Microsoft LIB.EXE library manager utility.


 127. Extraneous Error Messages Compiling REMLINE.BAS with BC /E

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 15-JAN-1990    ArticleIdent: Q28022

 Using only an /e switch, compile the program REMLINE.BAS that is
 distributed as a sample program with Microsoft BASIC Compiler Version
 6.00. You will get the following three errors:

    bc remline /e;

      RESUME
           ^ Missing Resume Next (/X)
      RESUME NEXT
           ^ Missing Resume Next (/X)
    LOOP
       ^ Subprogram Error

 The LOOP referenced by the error is on line 248. It is not an error
 under any other combination of compilation switches, and the program
 compiles correctly with /X.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 (fixlist7.00).


 128. If "Disk Full" Message While Saving, Editor Can Delete File

 Product Version(s): 3.00 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 17-JAN-1990    ArticleIdent: Q27691

 If you receive the error "Disk full--Retry or Cancel" while saving a
 program in the QuickBASIC Version 3.00, 4.00, or 4.00b editor, you
 must save to another disk with more room or the program will be
 deleted from the disk even if you cancel the Save command.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 3.00, 4.00, and 4.00b, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS (buglist6.00, buglist6.00b). This problem was
 corrected in QB.EXE in QuickBASIC Version 4.50 and in QBX.EXE in
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 (fixlist7.00).

 To work around the problem, Save immediately onto a disk with more
 room before exiting the QuickBASIC environment.

 To duplicate the problem, fill a floppy disk with programs. Load one
 of these programs into the QuickBASIC editor and add some lines of
 code. Save the file. QuickBASIC will respond with a "Disk full--Retry
 or Cancel" message. Even if you cancel the Save command, the file will
 be gone when you leave QuickBASIC.



 129. PSET Color Argument Affect in Screen 2 Differs from BASICA

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 bc6PTM222 buglist4.00b buglist4.50
 Last Modified:  4-DEC-1988    ArticleIdent: Q28026

 There is a problem mapping color values used with the PSET statement
 in Screen 2. QuickBASIC Versions 4.00, 4.00b, and 4.50 map all
 non-zero values to one. IBM BASICA maps all values less than eight to
 MOD 2 of the value and all values eight and above to MOD 1.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in the Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). We are
 researching this problem and will post new information as it becomes
 available.


 130. If ANSI.SYS Sets Background Color, BASIC Clears Line 25

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 25-AUG-1989    ArticleIdent: Q28029

 If you have changed the background and foreground screen colors in
 MS-DOS using ANSI control codes, then when a BASIC program using
 screen input or output is run, the 25th line is incorrectly blackened
 (cleared) when the program exits.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Version 6.00 for
 MS-DOS (buglist6.00). The problem is corrected in QuickBASIC Version
 4.50 and in the Microsoft BASIC Compiler Version 6.00b for MS-DOS
 (fixlist6.00b).

 This problem does not occur in EXE programs compiled with QuickBASIC
 Version 3.00.

 The DOS ANSI.SYS driver can be used to change the background and
 foreground colors. For example, place the following in a file:

    An ESC byte (ASCII 27) followed by [44;37m

 Then use the DOS TYPE command to send the file to the screen. Typing
 the file will change the background color to blue and the foreground
 color to white. If a BASIC program using screen input or output is
 then run, the 25th line is incorrectly blackened (cleared) when the
 program exits.

 Please note that the 25th line is not used by BASIC unless the
 statement < VIEW PRINT 1 to 25 > is used or the KEY statement is used.
 When the BASIC program ends, the 25th line automatically is cleared in
 case the KEY statement has been used.

 To use ANSI control codes, the ANSI.SYS driver must be installed at
 boot time by placing the following statement in your DOS CONFIG.SYS
 file on your root directory:

    DEVICE=ANSI.SYS


 131. QB Fast-Load Format Source Code Cannot Be Used in MS CodeView

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | S_CodeView B_BasicCom
 Last Modified: 12-DEC-1988    ArticleIdent: Q28031

 Microsoft CodeView is not able to read the QuickBASIC source file if
 it is saved in Fast Load format. If you plan to use the Microsoft
 CodeView debugger, be sure the source file is saved in ASCII format.

 To save a file in ASCII format, use the SAVE AS... option in the FILE
 menu in the QB.EXE editor.

 To compile a BASIC program for use with CodeView, use the following:

 1. BC filename /Zi [other switches]

 2. LINK filename /Co [other switches]

 If your program invokes subprograms in separate modules, you will need
 to make sure that the subprogram source files are all saved in ASCII
 text format instead of Fast Load format, or CodeView will not be able
 to view or step through the subprogram.

 This information applies to QuickBASIC Versions 4.00, 4.00b, 4.50, and
 the QuickBASIC which comes with the BASIC Compiler Version 6.00 or
 6.00b for MS-DOS.


 132. QB.EXE Can Hang Using $INCLUDE on Single-Drive System

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 bc6PTM237 buglist4.00b fixlist4.50
 Last Modified:  4-DEC-1988    ArticleIdent: Q28033

 The QB.EXE editor can hang on a single-drive system when using
 $INCLUDE file loading, name parsing, and/or file opening, as shown in
 the example below.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Versions 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and OS/2. This problem
 was corrected in QuickBASIC Version 4.50.

 QuickBASIC will hang in the following single-drive configuration:

  1. Make the following two floppies (5.25 inch or 3.5 inch):

        Disk 1: QB.EXE
        Disk 2: HIDE.BAS, QB.BI, QB.QLB

     (Note that HIDE.BAS, QB.BI, and QB.QLB are provided on the
     QuickBASIC Version 4.00 release disks.)

  2. Set PATH, LIB, and INCLUDE to nothing (i.e., SET PATH=).

  3. Put Disk 1 in Drive A (single-floppy systems only, hard disk
     allowed).

  4. Set Drive A as the default drive.

  5. Type the following command:

        QB B:HIDE /L.

  6. Answer location for QB.QLB with Drive B.

  7. Swap disks as prompted.

  8. Modify the include line to be b:QB.BI instead of QB.BI (this can
     be done before starting QuickBASIC).

  9. Press SHIFT+F5.

 10. Insert Disk 1 in Drive A, press ENTER; at this point, QuickBASIC
     hangs.

 Please note that Disk 2 is the one to use when you are asked to insert
 a disk in Drive B. If you modify HIDE.BAS before running QuickBASIC,
 then QuickBASIC will hang when trying to load QB.BI.


 133. "String Space Corrupt" After CLEARing a Watch String

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28035

 In the QB.EXE debugger, set a WATCH on A$ and then execute the
 following program with SHIFT+F5. The program will produce a "String
 Space Corrupt" error:

    A$="TEST"
    CLEAR

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS (buglist6.00, buglist6.00b). This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).


 134. RESUME NEXT with Single-Line DEF FN RESUMEs Wrongly in QB.EXE

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28037

 In the QB.EXE editor, when an error occurs inside a single-line DEF
 FN function, RESUME NEXT returns control to an unexpected location.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).

 In QB.EXE, the code traps the error but resumes to the FOR before it
 exits the loop. (When compiled with BC.EXE, the EXE program handles
 the problem correctly.)

 As a workaround, use a multi-line function or FUNCTION procedure
 instead of a single-line DEF FN function.

 The problem only occurs with single-line DEF FN and RESUME NEXT. The
 interpreter treats line 20 as the current line (ERL) and resumes at
 line 30. The BASIC compiler says 40 is the current line (ERL) and
 resumes at 50.

 The following is a code sample:

    10 on error goto 900
    20 def FnTest(A) = 1-SQR(A)
    30 FOR I=4 to -2 STEP -1
    40    PRINT I, FNTEST(I)
    50 NEXT
    60 END

    900 PRINT "No negatives"
    910 RESUME NEXT


 135. Problems with VGA Modes on COMPAQ VGC Board & Video Seven VGA

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom Video-7 Video 7
 Last Modified:  8-NOV-1990    ArticleIdent: Q28040

 When using a COMPAQ VGC VGA or Video Seven VGA graphics card, you
 might receive only a blue foreground in QuickBASIC SCREEN mode 11.
 This behavior occurs because the COMPAQ VGC VGA and Video Seven VGA
 emulate SCREEN mode 11 by using SCREEN mode 12. This differs from the
 IBM VGA card's implementation of SCREEN 11 for which QuickBASIC is
 designed.

 The following versions of BASIC are not designed to work around this
 nonstandard case: Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS, Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS.

 BASIC PDS 7.10 compensates for this case and the colors will come up
 correctly.

 The following sample program is a work around for BASIC versions 7.00
 and earlier and QuickBASIC versions 4.x. By changing the Palette
 registers for SCREENs 12 and 13, this program changes the palette for
 SCREEN 11 for the video cards that perform this form of emulation.
 Interrupt 10 hex with function 10 hex and subfunction 12 hex changes a
 block of palette registers. The following program shows how to perform
 this interrupt call:

 Sample Code
 -----------

 ' In BASIC PDS 7.00, use the following $INCLUDE:
 REM $INCLUDE: 'QBX.BI'
 ' but if you are using QuickBASIC 4.x or BASIC compiler 6.00x, use:
 '         REM $INCLUDE: 'QB.BI' instead
 TYPE PaletteRegisterType
   Red AS STRING * 1
   Green AS STRING * 1
   Blue AS STRING * 1
 END TYPE

 DIM inregs AS regtypex
 DIM outregs AS regtypex
 DIM PaletteArray(0 TO 1) AS PaletteRegisterType

 SCREEN 11
 PALETTE 0, 63 * 256              'Try to change the colors to
 PALETTE 1, 63                    '  green on red.
 PRINT "THIS IS IN THE WRONG COLOR(blue on green)"
 PRINT "HIT ANY KEY TO CONTINUE"
 WHILE INKEY$ = "": WEND          'pause for keypress

 'Set up the palette for the right colors: Each palette entry ranges
 '  from 0 to 63

 'Set up the Background: Bright green

 PaletteArray(0).Red = CHR$(0)    'Set the amount of red  : 0
 PaletteArray(0).Green = CHR$(63) 'Set the amount of green: 63
 PaletteArray(0).Blue = CHR$(0)   'Set the amount of blue : 0

 'Set up the Foreground: bright red

 PaletteArray(1).Red = CHR$(63)   'Set the amount of red  : 63
 PaletteArray(1).Green = CHR$(0)  'Set the amount of green: 0
 PaletteArray(1).Blue = CHR$(0)   'Set the amount of blue : 0

 'Set up the registers for the interrupt call.

 inregs.ax = &H1012               ' Function &H10, Subfunction &H12
 inregs.bx = 0                    ' Starting Color register
 inregs.cx = 2                    ' Number of Color registers
 inregs.dx = VARPTR(PaletteArray(0))
 inregs.es = VARSEG(PaletteArray(0))

 CALL interruptx(&H10, inregs, outregs)
 PRINT "THE COLORS ARE NOW CORRECT (red on green)"


 136. BC.EXE Cannot Compile ASCII 1 or 2 in Fast Load Format Files

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q28044

 Files saved in the QuickBASIC Fast Load format that contain an ASCII 1
 or 2 byte value (control code) typed into a comment or quoted string
 constant (such as using CTRL+P+A for ASCII 1 or CTRL+P+B for ASCII 2
 in QB.EXE or QBX.EXE) cannot be compiled with BC.EXE. BC.EXE gives a
 "Statement Unrecognizable" error at compile time. (The ASCII 1 or 2
 control characters compile correctly with BC.EXE when saved in Text
 format. Other control character bytes compile successfully with BC.EXE
 when saved with Fast Load or Text format.)

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b); and
 in Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 In BC.EXE version 4.50 and in Microsoft BASIC PDS versions 7.00 and
 7.10 for MS-DOS and MS OS/2, you do not get a compile-time error (for
 the Fast Load format file), but the BC.EXE compiler strips the ASCII 1
 or 2 byte out of quoted strings, and the byte is not printed on the
 screen at run time. To work around this problem, you can use the CHR$
 function, as follows:

    CHR$(1)
 or
    CHR$(2)

 Press CTRL+P followed by a control character to type control
 characters into the QB.EXE or QBX.EXE editor.

 Related Note: The following limitation is by design, and distinct from
 the above software problem. ASCII byte values 1 (CTRL+P+A), 2
 (CTRL+P+B), and 3 (CTRL+P+C) can be placed in DATA statements, but
 your variable in the READ statement must be a string variable (such as
 X$) to receive the control character byte. Incorrectly using a numeric
 variable in the READ statement to receive these characters will give
 "Out of Data" in QB.EXE in QuickBASIC 4.00 and 4.00b, and "Syntax
 Error" in QB.EXE in QuickBASIC 4.50. Also in 4.00 and 4.00b, you get
 "Out of Data" unless you put double quotation marks around the byte
 values; in 4.50, the double quotation marks are optional around the
 byte values in the DATA statement.

 In contrast, when you use direct numeric constants such as 1, 2, and 3
 (DATA 1,2,3), you need to READ into a numeric variable.

 Example 1
 ---------

 Compiling the following statement in BC.EXE demonstrates the problem.
 Type CTRL+P followed by CTRL+A (that is, CTRL+P+A) to put an ASCII 1
 into the quoted string in the QB.EXE editor. CTRL+P+B puts an ASCII 2
 into a quoted string in QB.EXE. The ASCII 1 appears as a happy face
 symbol, and ASCII 2 appears as an inverse-video happy face.

    PRINT "< CTRL+P+A > < CTRL+P+B >"

 Depending upon your usage of the ASCII 1 or 2 byte, you can use any of
 the following to work around the problem:

 1. Use the CHR$ function as a workaround to embed ASCII 1 or 2 into a
    string variable. For example, the following program prints happy
    faces in both the QB.EXE editor and in an .EXE program in
    QuickBASIC versions 4.00, 4.00b, 4.50, BASIC compiler 6.00 and
    6.00b, and BASIC PDS version 7.00:

       HAPPY$=CHR$(1)+CHR$(2)
       PRINT HAPPY$ + " TEST " + HAPPY$

 2. The ASCII 1 or 2 bytes can be successfully embedded in quoted
    strings or remarks if you run in the QB.EXE version 4.00, 4.00b, or
    4.50 editor, or the QBX.EXE editor supplied with BASIC PDS version
    7.00.

 3. If the file is saved as Text instead of in Fast Load format, it
    compiles without error in BC.EXE in QuickBASIC 4.00, 4.00b, or
    4.50. This corrects the problem if you are just using ASCII 1 or 2
    in remarks (REM or ' statements) in the source code. However, the
    ASCII 1 or 2 character will be stripped from any quoted strings in
    your program if you run from an .EXE program.

 4. In QuickBASIC version 4.50 and BASIC PDS version 7.00, BC.EXE
    compiles the program correctly regardless of Fast Load format. This
    corrects the problem if you are just using ASCII 1 or 2 in remarks
    (REM or ' statements) in the source code. However, the ASCII 1 or 2
    character will still be stripped from any quoted strings in your
    program if you run from an .EXE program.

 Example 2
 ---------

 The following program is another demonstration of the problem. Type
 this program in the QB.EXE or QBX.EXE editor, and choose the Make EXE
 File command on the Run menu.

    ' In QB.EXE and QBX.EXE, CTRL+P can be used to embed control
    '   characters:
    A$ = "Press: CTRL+P+A" + "Press: CTRL+P+B"
    PRINT A$
    OPEN "JUNK.TST" FOR OUTPUT AS #1
    PRINT#1,A$
    CLOSE

 Running the .EXE version of this program shows that the ASCII 1 and 2
 happy face characters do not display on the screen or write to the
 file because they were stripped out at compile time. After running
 this program, perform the following command in DOS to display the
 characters written to the file:

    TYPE JUNK.TST

 A simple workaround is to replace the first line of the program with
 the following:

    A$ = CHR$(1) + CHR$(2)


 137. WIDTH Resets Colors to Black, White in 4.00, 4.00b

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q28046

 When the width of the screen is changed, the background and foreground
 colors are reset to the default of black and white. The problem occurs
 while running the program both in the QB.EXE editor and also as an .EXE
 executable program.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 The following is a code example:

    COLOR 15,1
    CLS
    INPUT i$
    WIDTH 40
    CLS
    INPUT a$
    end


 138. Repeated SOUND Statement Causes System Clock to Lose Time

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28048

 If the following program is run for two or three minutes, the system
 clock will lose time, that is, four to six seconds:

    starttime=TIMER
    WHILE (1)
       locate 1,1 : print using "#####.##"; TIMER-starttime
       ss=INT(201*RND)+37
       SOUND ss,3
    WEND

 The problem occurs whether compiled with BC.EXE or the QB.EXE
 environment. Further testing indicates that a duration of less than
 one second will stop the clock completely.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS
 (fixlist7.00).

 A similar problem occurs with the PLAY statement.


 139. QuickBASIC Hangs Using User-Defined Record Greater Than 64K

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 22-JAN-1990    ArticleIdent: Q28050

 QuickBASIC fails to trap a user-defined record type that exceeds 64K
 in size. It is not legal for a user-defined record to exceed 64K in
 size.

 The example program below will cause the system to hang.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 The following is a code example:

 type foo
    a as string*32500
    b as string*32500
    c as string *1000
 end type
 dim x as foo
 x.c=" "
 print x.c
 end

 Note: Dynamic arrays of user-defined records may exceed 64K in size
 provided that each record is less than 64K in size. When using an
 array larger than 64K (which requires the /AH option), it is also
 advisable to make the record-array element size a multiple (of any
 power of 2) that terminates exactly on 64K boundaries.


 140. "Device I/O Error" Error 57 with OPEN COM1:; Use ON ERROR GOTO

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom TAR55904 TAR61057
 Last Modified:  4-AUG-1989    ArticleIdent: Q28149

 When using the COM1: or COM2: serial communications port, a "Device
 I/O Error" (Error 57) normally occurs due to parity, framing, or data
 overrun problems.

 Sometimes, the "Device I/O Error" occurs in compiled QuickBASIC
 programs more often than in the Microsoft GW-BASIC Version 3.20 or
 other BASIC interpreters, especially when the programs are compiled
 with any of the event-trapping options (/V or /W).

 To alleviate this problem, trap the error 57 in an ON ERROR GOTO
 error-handler routine and RESUME execution of your program.

 This information applies to QuickBASIC Versions 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50 and to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2.

 The following should be checked when you get communication errors:

 1. Because a "Device I/O Error" normally occurs due to parity,
    framing, or data overrun problems, the following items must be
    checked:

    a. The communications cable should be checked for bad connections.

    b. The communications parameters specified in the OPEN "COM"
       statement must match the device and software on the other end of
       the communication line.

 2. If the signal time per bit differs between transmitter and
    receiver, such as when the processor clocks are slightly off, you
    can get a "framing error." Run tests on more than one computer
    system to see if the problem is a framing error specific to a given
    system.

 3. A "Device I/O Error" is also sometimes generated when there is
    information received prior to OPENing the file. The only control
    that you have is to trap the error with ON ERROR GOTO and then
    RESUME or RESUME NEXT.

 4. If a given program works successfully under the GW-BASIC or IBM
    BASICA Interpreter, but not under QuickBASIC (compiled as .EXE or
    in QB.EXE editor), the problem may be due to parity or framing
    differences between the products.

 In the following code example, to simulate a full duplex-modem
 transmission, press CTRL+A and CTRL+B to send a 128-byte packet
 consisting of all 128 extended ASCII codes. If the people on each
 computer simultaneously press CTRL+A or CTRL+B, 128-byte packets are
 sent and verified on each end.

 You need a null modem cable consisting of at least the following line
 connections:

    2 - 3
    3 - 2
    7 - 7

 Code Example
 ------------

 OPEN "com1:9600,n,8,,cs0,ds0,cd0,BIN,rb16000" FOR RANDOM AS #1
 ON ERROR GOTO etrap
 CLS
 GOSUB helpme

 myconst$ = ""
 FOR n = 128 TO 255      'set up a standard packet to send and receive
   myconst$ = myconst$ + CHR$(n)
 NEXT

 capture = 0   'don't capture any data
 buff$ = ""    'set up buffer
 dummyvar = FRE("")

 top:
 IF LOC(1) > 0 THEN
   i$ = INPUT$(1, #1)
   PRINT i$;
   IF i$ = CHR$(128) THEN capture = 1       'turn it on
   IF capture = 1 THEN buff$ = buff$ + i$
   IF i$ = CHR$(255) THEN
     capture = 0                            'turn it off
     GOSUB checkit
   END IF
 END IF

 o$ = INKEY$
 IF o$ <> "" THEN
   IF o$ = CHR$(1) THEN 'CTRL+A will send chars one at a time
     PRINT #1, ""
     FOR n = 128 TO 255
       PRINT #1, CHR$(n);
     NEXT
   ELSEIF o$ = CHR$(2) THEN 'CTRL+B will send chars all at one
     PRINT #1, ""
     PRINT #1, myconst$;
   ELSEIF o$ = CHR$(3) THEN
     END
   ELSEIF o$ = CHR$(4) THEN
     PRINT : PRINT "Performing garbage collection on String Heap...";
     dummyvar = FRE("")
     PRINT "Done": PRINT
   ELSEIF o$ = CHR$(27) THEN
     GOSUB helpme
   ELSE
     PRINT #1, o$;
     PRINT o$; 'local echo
   END IF
 END IF

 GOTO top

 etrap:
   PRINT "The error number is err #"; ERR
 RESUME

 checkit:
   IF myconst$ = buff$ THEN
     PRINT "Packet Sent OK"
   ELSE
     PRINT "Error in Sending Packet"
   END IF
   buff$ = ""
 RETURN

 helpme:
   PRINT
   PRINT "CTRL+A - Send a 128-byte Extended Ascii Packet one Byte at a time"
   PRINT "CTRL+B - Send a 128-byte Extended Ascii Packet all at once"
   PRINT "CTRL+C - End Program"
   PRINT "CTRL+D - Perform Garbage Collection on the String Heap"
   PRINT "ESC - Display this Help Message"
   PRINT
 RETURN


 141. RND and RANDOMIZE Alternatives for Generating Random Numbers

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_BasicInt B_GWBasicI B_MQuickB
 Last Modified: 26-JUN-1989    ArticleIdent: Q28150

 If you would like a substitute for RND and RANDOMIZE, you can use your
 own equation to generate random numbers as shown below.

 Microsoft BASIC offers the RND function to return random
 single-precision numbers between 0.000000 and 1.000000. The RANDOMIZE
 statement can be used to reseed (or initially start) a given sequence
 returned by RND. Microsoft BASIC uses the linear-congruential method
 for random-number generation in the RND function.

 This article applies to the following products:

 1. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 2. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00, 2.01,
    3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 3. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23 for
    MS-DOS

 4. Microsoft QuickBASIC Compiler for the Apple Macintosh

 5. Most other Microsoft BASIC interpreters and compilers for Apple
    Macintosh, MS-DOS, MS OS/2, XENIX, and CP/M-80

 Microsoft BASIC uses the linear-congruential method for random-number
 generation in the RND function. The following is an example of the
 linear-congruential method formula, similar to that used by RND in
 Microsoft BASIC:

    x1 = ( x0 * a + c ) MOD 2^24

 In the above example, the variables equal the following:

    x1=new number
    x0=previous number
    a=214013
    c=2531011

 (Note: the MOD operator in the formula above returns the integer
 remainder after an integer division.)

 The expression x1/(2^24) returns a floating-point number between 0.0
 and 1.0. Please refer to Code Examples 1 and 2 below for an
 illustration.

 For more random number generation algorithms, see Pages 353-364 of
 "Microsoft QuickBASIC Programmer's Toolbox," by John C. Craig,
 published by Microsoft Press (1988). Seven random number subprograms
 are documented, and a companion disk in MS-DOS format is also
 available from Microsoft Press.

 The programs in Craig's book are written for QuickBASIC Version 4.00
 for the IBM PC. Some programs, such as the random number programs, are
 general and can easily be modified to run in Microsoft QuickBASIC for
 the Apple Macintosh. When you run these programs, you may wish to
 reseed the random number sequence regularly (such as every few hundred
 invocations) for greater uniformity.

 Code Example 1
 --------------

 The following is an example of the linear congruential method for
 generating pseudo-random numbers:

 DEFDBL A-Z  ' Requires double-precision intermediate variables.
 a = 214013
 c = 2531011
 z = 2 ^ 24
 INPUT "Input any seed value: ", x0
 FOR count = 1 TO 25   ' print 25 random numbers between 0.0 and 1.0:
   temp = x0 * a + c
 ' Calculate (temp MOD z) and assign to x1:
   temp = temp / z
   x1 = (temp - FIX(temp)) * z
 ' Print the result as value between 0.0000000 and 1.0000000:
   result = x1 / z
   PRINT result
 ' Reseed the calculation before the next iteration:
   x0 = x1   ' x0 and x1 range from 0 to 16777216 (2^24)
 NEXT

 Code Example 2
 --------------

 The following is the same as Example 1, except the random numbers are
 plotted to illustrate their uniform distribution:

 DEFDBL A-Z     ' Requires double-precision intermediate variables.
 SCREEN 2  ' Remove this SCREEN statement to work in Macintosh BASIC
 a = 214013
 c = 2531011
 z = 2 ^ 24
 INPUT "Input seed value: ", x0
 FOR count = 1 TO 5000
   temp = x0 * a + c
   ' Calculate (temp MOD z) and assign to x1:
   temp = temp / z
   x1 = (temp - FIX(temp)) * z
   result = x1 / z  ' Result is between 0.000000 and 1.000000
   GOSUB 100       ' Plot Result
   x0 = x1   ' x0 and x1 range from 0 to 16777216 (2^24)
 NEXT
 END
 ' Plot the random points to see their uniform distribution:
 100 y = y + 1
     IF y > 200 THEN y = 0   ' Wrap plot at y=200 pixels.
     x = result * 500   ' Assumes screen mode <= 500 pixels wide.
     PSET (x, y)   ' PSET requires a graphics screen mode.
     RETURN


 142. Unexpected PRINT USING ".##" Rounding for .xx5

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-FEB-1991    ArticleIdent: Q28164

 This article describes a case where the PRINT USING statement appears
 to round numeric constants to unexpected values. This information
 applies to Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 for
 MS-DOS; to Microsoft BASIC Compiler versions 6.00, 6.00b for MS-DOS
 and MS OS/2; and to Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 For the following statement

    PRINT USING " ###.##"; .245, .255, .265, .275, .285

 the above BASIC versions give the following output

    0.25  0.25  0.26  0.28  0.28

 while you might have expected the following rounding

    0.25  0.26  0.27  0.28  0.29

 or with IEEE rounding (to the nearest even integral value), you would
 expect the following:

    0.24  0.26  0.26  0.28  0.28

 This behavior occurs because the internal representation of the
 numbers used by BASIC (IEEE floating-point format) differs slightly
 from the decimal numbers typed into the source code.

 IEEE floating-point format cannot accurately represent numbers that
 are not of the form 1.x to the power of y (where x and y are base 2
 numbers). The internal representation will be slightly more or
 slightly less than the decimal numbers typed into the source code.

 The internal representations are correctly rounded and displayed in
 the above program. This is not a software problem.

 If you want floating-point constants in the source code to be exactly
 stored, you can append the constant with the CURRENCY type-cast
 operator, an "at sign" (@) character. The CURRENCY data type is only
 found in Microsoft BASIC PDS 7.00 and 7.10. The following example
 rounds to 0.25, 0.26, 0.27, 0.28, 0.29 as you may have wanted:

    PRINT USING " ###.##"; .245@, .255@, .265@, .275@, .285@

 Note that the CURRENCY data type can store 19 digits, but only 4
 digits can be used after the decimal point.


 143. Long Integer Passed to SUB and Modified May Not Return OK

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28167

 When a long integer is passed to a subprogram as a parameter and its
 value is changed, the change is reflected only inside the subprogram
 in the code example below. When control is returned to the main
 section of the program, the variable incorrectly has its original
 value, instead of the changed value.

 The problem occurs only when running the program as an .EXE file;
 the program works correctly in the QB.EXE interpreter.

 This problem occurs in QuickBASIC Versions 4.00 and 4.00b, and in
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2
 (buglist6.00 and buglist6.00b). This problem was corrected in
 QuickBASIC Version 4.50 and in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2
 (fixlist7.00).

 The problem results from the passing of a long integer to the
 subprogram. If the variable type is changed (that is, b& becomes b!,
 which is a change from a long integer to a single-precision real
 number), the problem is corrected.

 The following are three workarounds:

 1. Put the long integer into a COMMON SHARED block instead of passing
    it as a parameter.

 2. In the subprogram, assign the VAL expression to a temporary
    variable and use this temporary variable in the reassignment of the
    long integer.

 3. Change the variable type to anything but a long integer.

 The following is a code example that demonstrates the problem:

 DECLARE SUB sub1 (b&, a$)
 a$ = "002": b& = 1
 b& = b& + VAL(a$)
 PRINT "main -- before: "; b&
 CALL sub1(b&, a$)
 'Output in editor is 5; from EXE is 3 (wrong):
 PRINT "main -- after: "; b&
 END
 SUB sub1 (b&, a$) STATIC
    PRINT "subprogram -- before: "; b&
    b& = b& + VAL(a$)
    PRINT "subprogram -- after: "; b&
 END SUB


 144. Selecting Text in QB.EXE with Nondedicated Cursors on Toshiba

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified: 18-JUL-1989    ArticleIdent: Q28169

 The cursor keys that are integrated into the numeric keypad on the
 Toshiba T1100 Laptop's 82-key keyboard cannot select text in the
 QuickBASIC QB.EXE editor unless you first press CTRL+ALT+BACKSPACE,
 which acts as a toggle to turn the selecting mode on and off.

 This toggle does not work with Toshiba keyboards that have separate,
 dedicated-cursor keys. For more information in this database about
 selecting text with this type of keyboard, query on the following
 keywords:

    Toshiba Dedicated

 The "Microsoft QuickBASIC 4.00: Learning and Using" manual explains
 the keystrokes necessary to edit and select text inside the QuickBASIC
 editor (see Chapter 5 and Appendix D). Due to differences between the
 Toshiba T1100 laptop's keyboard and the standard IBM keyboard, these
 editing commands do not work correctly on the Toshiba.

 On the Toshiba T1100 laptop, the CTRL+ALT+BACKSPACE key sequence acts
 as a toggle to allow the cursor arrow keys to select text. After the
 text is selected, you must press CTRL+ALT+BACKSPACE again to resume
 the original keyboard mode.


 145. Calling Interrupts to Program Microsoft Mouse from QuickBASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 17-FEB-1989    ArticleIdent: Q28171

 The software interrupt routines, CALL INTERRUPT and CALL INT86old,
 provide access to the DOS system services. These statements let you
 make calls to the Microsoft Mouse through interrupt 51 (i.e., 33 hex).
 Mouse function calls are useful for detecting the position of the
 mouse, detecting the status of the mouse buttons, changing the mouse
 cursor shape, changing the video page for the cursor, and other
 functions.

 Calling the mouse through interrupts as shown below is more flexible
 than calling the MOUSE routine from the MOUSE.LIB library on the
 Microsoft Mouse disk because you don't need to worry about MOUSE.LIB
 changing from version to version.

 This information applies to QuickBASIC Versions 4.00, 4.00b, 4.50 and
 the Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (real mode). The second example below can be used in QuickBASIC
 Version 2.00, 2.01, or 3.00 if you change the statement INT86old to
 INT86. INT86old is provided in QuickBASIC Versions 4.00, 4.00b, 4.50,
 and in the BASIC compiler Versions 6.00 and 6.00b for compatibility
 with earlier QuickBASIC programs that use INT86.

 CALL INTERRUPT and CALL INT86old can be used to access the ROM BIOS
 and DOS-system service routines. These routines provide a range of
 mouse, keyboard, video, and DOS services.

 The examples below let you draw in high-resolution graphics mode
 with the Microsoft Mouse. The mouse driver (MOUSE.COM) must be
 installed before running these programs. MOUSE.COM is provided with
 QuickBASIC.

 The INTERRUPT and INT86old routines are considered external
 subroutines by the compiler. The routines are located in the files
 QB.LIB and QB.QLB. Programs that execute a CALL INTERRUPT or CALL
 INT86old statement when compiled in the QB.EXE editor require the
 presence of the QB.QLB quick library. This means that QB.EXE must be
 invoked with the /L option. EXE programs that execute these statements
 must be linked with the file QB.LIB. More information on the use of
 CALL INTERRUPT and CALL INT86old can be found under the CALL statement
 in the "Microsoft BASIC Language Reference."

 Access to the software interrupts adds tremendous flexibility to BASIC
 programs. However, care should be taken because BASIC does no error
 checking for interrupt calls.

 The interrupt 51 for Microsoft Mouse Version 6.00 (and later) is
 documented in the following book:

 "Advanced MS-DOS Programming," Second Edition, by Ray Duncan
 (published by Microsoft Press, 1988). Pages 593-611. (The first
 edition, published in 1986, does not document the mouse interrupt.)

 More information regarding making mouse calls from BASIC can be found
 in the "Mouse Programmer's Reference Guide," which can be ordered from
 Microsoft Customer Service by calling (206) 882-8088.

 Note that you can invoke mouse interrupt 51 with function 29 (1D hex),
 "Select pointer page", to change the video display page for the mouse
 cursor. The valid page numbers depend on the current SCREEN mode. To
 change the video page of the mouse cursor in the examples below, CALL
 the MOUS subprogram as follows:

    pagenum%=0   ' Change to appropriate video page for current SCREEN.
    CALL mous (29, pagenum%, 0, 0)

 The following are two code examples:

 1. The following code example uses the CALL INTERRUPT statement to
    call the Microsoft Mouse in QuickBASIC Versions 4.00, 4.00b, 4.50
    or in the Microsoft BASIC Compiler Versions 6.00 or 6.00b for MS-DOS
    or MS OS/2 real mode:

 DECLARE SUB MOUS (m0%, m1%, m2%, m3%)
 DEFINT A-Z
 TYPE regtype
     ax AS INTEGER
     bx AS INTEGER
     cx AS INTEGER
     dx AS INTEGER
     BP AS INTEGER
     SI AS INTEGER
     DI AS INTEGER
     FLAGS AS INTEGER
     DS AS INTEGER
     ES AS INTEGER
 END TYPE

 SCREEN 2
 m0 = 0: m1 = 0: m2 = 0: m3 = 0: oldx = 0: oldy = 0
 CALL MOUS(m0, m1, m2, m3)             'initialize mouse
 m0 = 1
 INPUT "press any key to turn on mouse cursor:", x
 CALL MOUS(m0, m1, m2, m3)             'turn on mouse cursor
 END
 SUB MOUS (m0, m1, m2, m3) STATIC
   DIM inary AS regtype
   DIM outary AS regtype
   inary.ax = m0: inary.bx = m1: inary.cx = m2: inary.dx = m3
   CALL interrupt(51, inary, outary)
   m0 = outary.ax: m1 = outary.bx: m2 = outary.cx: m3 = outary.dx
 END SUB

 2. The following code example uses the CALL INT86old statement to call
    the Microsoft Mouse. (Note that the INT86old found in QuickBASIC
    Versions 4.00 and 4.00b is compatible with QuickBASIC Versions
    2.00, 2.01, and 3.00 programs that use INT86. You can run this
    program in QuickBASIC Versions 2.x and 3.00 by changing INT86old to
    INT86 and removing the DECLARE statement. (Conversely, you can run
    QuickBASIC Version 2.x or 3.00 programs in Version 4.00, 4.00b, or
    4.50 by changing INT86 to INT86old.)

 DECLARE SUB MOUS (m0%, m1%, m2%, m3%)
 DEFINT A-Z
 SCREEN 2
 m0 = 0: m1 = 0: m2 = 0: m3 = 0: oldx = 0: oldy = 0
 CALL MOUS(m0, m1, m2, m3)                   'initialize mouse
 m0 = 1
 INPUT "Press ENTER key to turn on mouse cursor:", x
 CALL MOUS(m0, m1, m2, m3)                   'turn on mouse cursor
 END
 SUB MOUS (m0, m1, m2, m3) STATIC
   DIM regs(7)
   regs(0) = m0: regs(1) = m1: regs(2) = m2: regs(3) = m3
   CALL int86old(51, regs(), regs())
   m0 = regs(0): m1 = regs(1): m2 = regs(2): m3 = regs(3)
 END SUB


 146. How to Derive Inverse (ARC) and Hyperbolic Trig Functions

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_BasicInt B_MQuickB B_BBasic
 Last Modified: 10-JAN-1991    ArticleIdent: Q28249

 From the BASIC functions LOG, COS, SIN, TAN, SGN, EXP, and SQR, you
 can derive the other transcendental functions as shown below.

 The following trigonometric and mathematical functions that are not
 intrinsic to BASIC can be calculated as shown:

 Function                  BASIC Equivalent
 --------                  ----------------

 Secant                    SEC(X) = 1/COS(X)
 Cosecant                  CSC(X) = 1/SIN(X)
 Cotangent                 COT(X) = 1/TAN(X)
 Inverse Sine              ARCSIN(X) = ATN(X/SQR(1-X*X))
 Inverse Cosine            ARCCOS(X) = -ATN(X/SQR(X*X-1)) + Pi/2
 Inverse Secant            ARCSEC(X) = ATN(X/SQR(X*X-1)) + (SGN(X)-1) * Pi/2
 Inverse Cosecant          ARCCSC(X) = ATN(1/SQR(X*X-1)) + (SGN(X)-1) * Pi/2
 Inverse Cotangent         ARCCOT(X) = -ATN(X) + Pi/2
 Hyperbolic Sine           SINH(X) = (EXP(X) - EXP(-X))/2
 Hyperbolic Cosine         CACHE(X) = (EXP(X) + EXP(-X))/2
 Hyperbolic Tangent        TANH(X) = (EXP(X) - EXP(-X))/(EXP(X) + EXP(-X))
 Hyperbolic Secant         SECH(X) = 2/(EXP(X) + EXP(-X))
 Hyperbolic Cosecant       CSCH(X) = 2/(EXP(X) - EXP(-X))
 Hyperbolic Cotangent      COTH(X) = EXP(-X)/(EXP(X) - EXP(-X)) * 2 + 1
 Inverse Hyperbolic Sine   ARCSINH(X) = LOG(X + SQR(X*X+1))
 Inverse Hyperbolic Cos    ARCCOSH(X) = LOG(X + SQR(X*X-1))
 Inverse Hyperbolic Tan    ARCCTANH(X) = LOG((1 + X)/(1 - X)) / 2
 Inverse Hyperbolic CSC    ARCCSCH(X) = LOG((SGN(X)*SQR(X*X+1)+1)/X)
 Inverse Hyperbolic Sec    ARCSECH(X) = LOG((SQR(1-X*X)+1) / X)
 Inverse Hyperbolic Cot    ARCCOTH(X) = LOG((X+1)/(X-1)) / 2

 The above general formulas may be used in Microsoft BASIC or any other
 language. Note that the constant Pi has the following approximate
 value:

    Pi# = 3.14159265359
    Pi# = 4.0# * ATN(1.0#)

 The above information applies to most Microsoft BASIC products,
 including the following:

 1. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01,
    3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and
    MS OS/2, and Microsoft BASIC Compiler versions 5.35 and 5.36 for
    MS-DOS

 3. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23

 4. Microsoft BASIC Interpreter versions 1.00, 1.01, 2.00, 2.10,
    and 3.00 for the Apple Macintosh

 5. Microsoft BASIC Compiler version 1.00 for the Apple Macintosh

 6. Microsoft QuickBASIC version 1.00 for the Apple Macintosh

 7. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2

 8. Microsoft Business BASIC Compiler versions 1.00 and 1.10 for MS-DOS
    (discontinued product)

 9. Microsoft BASIC Interpreter (BASIC86.EXE) version 5.28 for MS-DOS


 147. "Function Not Defined" or "Duplicate Definition" Fast Load

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  7-FEB-1990    ArticleIdent: Q28582

 When run in the QuickBASIC Version 4.00 or 4.00b editor, a certain
 large (1880-line) program saved in the Fast Load format can
 generate a "Function not defined" error message on the DIM statement
 for an array having the same name as another variable in the program,
 but of a different type. (The array is named F%() and the string is
 named F$, which is supposed to be legal.) This problem has not been
 demonstrated in smaller programs.

 In the case reported, you can work around the problem by renaming the
 array and the string.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS (buglist6.00, buglist6.00b). This problem was
 corrected in the QB.EXE environment in QuickBASIC Version 4.50 and in
 the QuickBASIC Extended (QBX.EXE) environment provided with Microsoft
 BASIC Professional Development System (PDS) Version 7.00 (fixlist7.00).

 This problem does not occur in QuickBASIC Version 3.00.

 Program AB10.BAS (not shown) is an 1880-line program containing many
 variables and many GOTO and GOSUB line labels. Two of the variables
 are F%() and F$. The program compiles correctly with BC.EXE.

 In the QB.EXE Version 4.00 or 4.00b editor, the program gives a
 "Function not defined" error when it reaches the DIM statement for F%.
 If the array is renamed to FOO%(), this error is resolved, but the
 program goes to where F$ first is used and gives a "Duplicate
 definition" error.

 If the program is completely deleted (except for a DIM F%(3)
 statement) the "Function not defined" error still occurs. If this
 smaller program is saved in text format and Opened again, the program
 runs correctly. However, if the small program is saved in Fast Load
 format, the error message still occurs when it is opened in the
 editor.

 This article may be useful to customers who are experiencing similar
 symptoms with Fast Load Format. The solutions in this particular case
 are either to upgrade to QuickBASIC 4.50 or BASIC PDS 7.00, to save in
 Text format instead of Fast Load Format, or to name all variables with
 different names.


 148. Pascal Subprogram "Invalid Format" Loaded as Quick Library

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 17-APR-1990    ArticleIdent: Q28588

 A Pascal subprogram that receives single- or double-precision numbers
 as parameters cannot be made into a Quick library. QuickBASIC gives an
 "invalid format" error when the Quick library is specified during the
 invocation of the QB editor (QB /L pascsub.QLB). This error does not
 occur if using a Pascal function instead of a Pascal subprogram.

 The same subprogram can be linked to a QuickBASIC main module and the
 resulting EXE file runs without any problems.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in the Microsoft BASIC Compiler Version 6.00 for
 MS-DOS and OS/2 (buglist6.00). This problem was corrected in
 QuickBASIC Version 4.50.

 Results of testing with previous versions indicate the same problem
 occurs with the release of QuickBASIC provided with the BASIC Compiler
 Version 6.00 for MS-DOS and OS/2.

 As a workaround, link the modules together instead of running in the
 QB.EXE editor.

 The following is sample code of the QuickBASIC main program (however,
 it never gets this far):

 DECLARE SUB PasSub (i!)    'Or i# gives the same results.
 i! = 100000
 CALL PasSub(i!)
 print i!

 The following is sample code for the the Pascal subprogram. There is
 a problem with both real4 (single) and real8 (double):

     module Pstuff;
      procedure PasSub(var b:real4);
        begin
          b := b + 1;
        end; {PasSub}
     end.


 149. BC.EXE "Argument-Count Mismatch" Compiling Underscore in CALL

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28591

 Inserting a line-continuation character (underscore) between the
 subprogram name and the argument list in a CALL statement produces an
 "Argument-count mismatch" message when compiled with Microsoft BASIC
 Compiler. If the subprogram is not DECLAREd, a "Syntax error" message
 results.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and OS/2 (buglist6.00 buglist6.00b). This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 If an underscore is inserted at any other point in the CALL statement
 (between the CALL and the subprogram name or in the argument list), it
 is properly recognized as a line-continuation character. This problem
 does not occur in the editor because the editor removes continuation
 characters.

 Note: DECLARE statements are not supported in earlier versions of
 QuickBASIC. If the DECLARE statement is removed and STATIC is added to
 the SUB statement, QuickBASIC Versions 2.00 and 3.00 handle the
 underscore properly.

 To work around the problem, move the continuation character to some
 other point in the CALL statement.

 The following example works correctly:

    CALL_
    a(b)

 The following code example shows the problem:

    DECLARE SUB a (b)
    CALL a_
    (b)

    SUB a (x)
    END SUB


 150. "Illegal Function Call" on Graphics GET in Subprograms

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28786

 While inside the QuickBASIC editor, use of the graphics GET statement
 in a separately compiled subprogram can produce an "Illegal Function
 Call" error message. This error message occurs only if the array
 referenced in the GET has not been previously used in that subprogram.
 Three workarounds are provided below.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the version of QuickBASIC released with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 QuickBASIC Version 4.50 and in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2
 (fixlist7.00).

 When the program below is run inside the QuickBASIC editor, the error
 message "Illegal Function Call" is generated. The compiler is unable
 to recognize that the a% used in the GET statement is an array. The
 compiler is assuming that a% is a scalar variable.

 The error message does not occur when the program is compiled, linked,
 and run from a .EXE file.

 The following are three workarounds for this problem:

 1. Explicitly reference the array variable in the GET statement as an
    array, as follows:

       GET (0,0)-(100,100), a%(0)

 2. Prior to the GET statement, identify the array variable as an array
    by using the array in any other executable statement, as follows:

       temp = a%(1000)
       GET (0, 0)-(100, 100), a%

 3. Place the array in COMMON as follows:

       DIM SHARED a%(1000)
       COMMON SHARED a%()

 The following code demonstrates the problem:

 ' Program MAIN.BAS - main module
 DECLARE SUB test ()
 SCREEN 2
 CALL test
 END

 ' Program SUB.BAS - separate subprogram module
 DIM SHARED a%(1000)

 SUB test STATIC
    'temp = a%(1000)                'workaround: execute this statement
    GET (0, 0)-(100, 100), a%       'illegal function call on this line
    PRINT "All done"
 END SUB


 151. EXE Size Using BCOM4x.LIB (Stand Alone) Versus BRUN4x.LIB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 30-JUN-1989    ArticleIdent: Q28842

 A compiled BASIC executable (.EXE) file compiled with the BRUN (i.e.,
 BRUN4x.EXE) option is much smaller on disk than an .EXE compiled with
 the BCOM option (i.e., compiled BC /O, or with the Stand-Alone option
 when using the Make EXE File... option from the QB.EXE editor's Run
 menu). This information applies to Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 and to Microsoft BASIC Compiler Versions 6.00 and
 6.00b.

 This occurs because a stand-alone .EXE file contains all the
 QuickBASIC language run-time support routines required by that
 program, whereas a non-stand-alone .EXE calls the run-time support
 from BRUN4x.EXE, a large separate file loaded into memory at run time.

 The decision to compile with BRUN or BCOM (stand-alone) involves the
 following trade-offs between disk space and speed:

 1. If you keep more than two or three compiled .EXE programs on a
    disk, you can save disk space by compiling with the BRUN option.
    (Please see the one-line example below.)

 2. If you want your program to run as quickly as possible, you should
    compile with the stand-alone (BCOM) option, which uses BCOM4x.LIB
    at compile time.

 If you must pass variables in COMMON between CHAINed programs, then
 you always must compile with the BRUN4x.EXE option.

 Note that this article only discusses the impact upon disk space
 usage, and not the impact on run-time memory usage. The .EXE load size
 in memory is usually larger than the .EXE file size on disk. The best
 way to determine run-time memory usage is by invoking the FRE(-1) and
 FRE("") functions at run time.

 In QuickBASIC you may create executable files with either the BRUN
 option or the BCOM option. Page 152 of the "Microsoft QuickBASIC 4.0:
 Learning and Using" manual gives a good comparison of run-time module
 programs (those compiled with BRUN) versus stand-alone programs (those
 compiled with BCOM).

 BRUN Option
 -----------

 The BRUN4x.EXE module, also loosely referred to as the "BRUN" module,
 has the following actual names, depending upon the version number:

    BRUN40.EXE for QuickBASIC Version 4.00
    BRUN41.EXE for QuickBASIC Version 4.00b
    BRUN45.EXE for QuickBASIC Version 4.50

 (The names are different for Microsoft BASIC Compiler 6.00 and 6.00b.)

 Programs compiled with the BRUN option need to load and access the
 run-time module BRUN4x.EXE at run time. BRUN4x.EXE contains code
 needed to implement the BASIC language.

 There are two methods to compile with the BRUN option: with the "EXE
 Requiring BRUN4x.EXE" option from QB.EXE's Make EXE File... item in
 the Run menu, or with BC.EXE with no /O switch.

 When compiled with BRUN, the EXE file size is smaller than when it is
 compiled with the BCOM option. To run that program, you must have the
 file BRUN4x.EXE present. Therefore, when a developer distributes his
 or her programs, both the .EXE application and BRUN4x.EXE must be
 placed on the distribution disk. In the case of the BCOM (stand-alone)
 version, only the application program's EXE file need be distributed.

 BCOM Option
 -----------

 There are two methods to compile with the "BCOM" option: with the
 "Stand-Alone EXE File" option from the QB.EXE's Make EXE File...
 item in the Run menu, or with BC.EXE with the /O switch.

 Modules compiled with the BCOM option do not require access to the
 run-time module BRUN4x.EXE because the support routines (contained in
 BCOM4x.LIB) are included at LINK time in the program's executable
 (.EXE) file.

 Any individual program compiled with the stand-alone (BCOM) option
 will have a larger EXE file size than when compiled with BRUN. All the
 run-time support needed by that program actually is a part of the
 executable file; it truly is a stand-alone program.

 One-Line Example of BCOM versus BRUN Disk Usage
 -----------------------------------------------

 In the specific case of a one-line program containing PRINT "Hello",
 the EXE size is 23,121 bytes when compiled with the BCOM (BC /O)
 option in QuickBASIC Version 4.00. (Other versions may differ.)

 When compiled with BRUN, the EXE size is 2979 bytes, but you must also
 consider the size of BRUN40.EXE (76,816 bytes). The combined size of
 the two files for the BRUN version is 79,795 bytes, which is
 considerably larger than that of the BCOM version. Three of these
 one-line programs compiled with BCOM would take less space on disk
 than the same program compiled with BRUN plus the BRUN40.EXE module.
 The relative file sizes will differ for larger programs.

 Disk Space Usage When CHAINing
 ------------------------------

 Developing a system of about three or four or more .EXE programs that
 CHAIN to each other can consume more disk space compiled with BCOM
 than compiled with BRUN. This is because each program compiled with
 BCOM has a copy of the run-time module attached, and the duplicate
 information uses up disk space.

 In contrast, all programs compiled with BRUN share only one copy of
 the run-time module (in BRUN4x.EXE). Therefore, the combined size on
 disk for four or more EXE files together usually is smaller when
 compiled with BRUN. Note that for one, two, or three small programs,
 the system may be smaller on disk when compiled with BCOM. All you
 need to do is compile with BCOM and BRUN and compare sizes.

 The only time you must compile with BRUN rather than BCOM is in the
 case of preserving COMMON variables across a CHAIN. CHAINed programs
 can share COMMON variables only if the two programs are compiled with
 BRUN. The COMMON portion of the run-time module remains resident in
 memory across the CHAIN.

 The BCOM run-time module is replaced in memory when CHAINing between
 BCOM programs, and no COMMON can be passed. The CHAIN and RUN
 statements behave identically in programs compiled with BCOM.


 152. Why QuickBASIC Does Not Support COM3: and COM4: Serial Ports

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-MAR-1990    ArticleIdent: Q28843

 Question:

 Why doesn't QuickBASIC support the COM3: and COM4: data communications
 ports?

 Response:

 Support for these two additional communications ports requires a
 larger code size for QuickBASIC in both the compiler and the run-time
 module. Therefore, the decision was made not to support COM3: and
 COM4:.

 The QuickBASIC compiler supports the use of serial communications
 ports COM1: and COM2: through the use of the OPEN "COM" statement.
 Information on how to access these ports can be found on Page 296 of
 the BASIC language reference manual for the following products:

 1. Microsoft QuickBASIC Versions 4.00 and 4.00b for MS-DOS

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 To access COM3: and COM4:, it may be possible for compiled BASIC to
 call third-party library routines, which are listed in catalogs such
 as the "Programmer's Connection Buyer's Guide" [in the United States,
 call (800) 336-1166; in Canada, call (800) 225-1166; to reach Customer
 Service, call (216) 494-8899]. For example, you may want to contact
 the company Software Interphase at (401) 274-5465 to determine if
 its product QuickComm supports COM3: and COM4: called from Microsoft
 compiled BASIC.

 For a list of other catalogs, search for the following words:

    programmer and tool and catalog


 153. CINT and Integer Assignments Round x.5 to Nearest Even Integer

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 25-APR-1989    ArticleIdent: Q28855

 When a numeric expression ending in .5 is assigned to an integer
 variable, a compiled BASIC program will round the expression to the
 nearest even integer. For example, .5 converts to 0, 1.5 converts to
 2, 2.5 converts to 2, and 3.5 converts to 4.

 This rounding to the nearest even integer occurs for the CINT function
 and for an integer division assigned to an integer variable. This
 behavior is a feature of the IEEE Floating Point Standard.

 This behavior occurs in any BASIC application that uses the IEEE
 Floating Point format, including the following products:

 1. Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50

 2. The coprocessor version of QuickBASIC Version 3.00: QB87.EXE

 3. The Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2 (when compiled with the BC /FPi option, where "i" stands
    for IEEE)

 This type of integer rounding complies with the following IEEE
 standard:

    "If the difference between the unrounded operand and the rounded
    result is exactly one half, the rounded result is even" (Section
    5.5 of the "IEEE Standard for Binary Floating-Point Arithmetic")

 The purpose of this behavior is to prevent an average upward (or
 downward) bias as various calculations are rounded. If the number was
 always rounded up, there would be an upward bias in calculations.
 Rounding to the nearest even number averages out; therefore, no
 rounding bias occurs.

 The compilers listed above store and manipulate numbers using IEEE
 format. This exclusive use of IEEE format for real numbers is
 necessary to enable compiled BASIC to CALL routines written in
 FORTRAN, Pascal, and C, all of which use IEEE format.

 B.EXE (noncoprocessor) Version 3.00 and QuickBASIC Versions 1.00,
 1.01, 1.02, 2.00, and 2.01 all store numbers in Microsoft Binary
 Floating Point format. Note that QB87.EXE, the coprocessor version of
 QuickBASIC Version 3.00, uses IEEE format. QuickBASIC Versions 1.x,
 2.00, and 2.01 do not support IEEE (or 8087, 80287, or 80387)
 coprocessors.

 Microsoft Binary format uses a standard different from that of IEEE
 for converting between floating point and integers. In particular,
 numbers with "5" as the least significant digit are always rounded up
 to the next integer. The result does not have to be an even number.
 Thus, the Microsoft Binary format has an upward rounding bias.

 Note that QuickBASIC Versions 3.00 and earlier cannot make
 interlanguage CALLs to FORTRAN, Pascal, or C.

 The following are two examples of the above rounding behavior:

 1. The following is an example of always rounding expressions ending
    in .5 to an even number by integer assignment:

    DEFINT A-Z
    INPUT "Type a whole number (1,2,3,4,5,6,...)",INUM
    IRESULT=INUM/2
    PRINT "If INUM/2 ends in .5, it rounds/truncates to even number:"
    PRINT IRESULT

 2. The following is an example of rounding of the CINT() function:

       a=.5
       b=1.0
       c=1.5
       d=2.0
       e=2.5
       cls
       print "CINT (0.5) = "; CINT(A)
       PRINT "CINT (1.0) = "; CINT(B)
       PRINT "CINT (1.5) = "; CINT(C)
       PRINT "CINT (2.0) = "; CINT(D)
       PRINT "CINT (2.5) = "; CINT(E)

 OUTPUT FROM:      B.EXE 4.00    |    B.EXE 3.00, 2.01, 2.00

 CINT (0.5) =           0        |         1
 CINT (1.0) =           1        |         1
 CINT (1.5) =           2        |         2
 CINT (2.0) =           2        |         2
 CINT (2.5) =           2        |         3


 154. Zero Passed or "Type Mismatch" in SUB; DEFtype Usage in QB.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 10-JAN-1991    ArticleIdent: Q28857

 Below are several general rules about using DEFtype statements
 (DEFINT, DEFLNG, DEFDBL, DEFSNG, and DEFSTR) in separate windows in
 the QB.EXE editor for QuickBASIC versions 4.00, 4.00b, and 4.50, in
 the QB.EXE editor in Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS, and in the QBX.EXE editor for Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS.

 This programming information is very important for avoiding parameter
 type mismatches that the compiler cannot warn you about. These
 mismatches can result in zeroed or garbled variables or a computer
 hang.

 For a related article, query in this Knowledge Base on the following
 words:

    DEFtype and SHARED and SUB

 1. A general rule is whenever you view a subprogram or FUNCTION
    procedure in a window in the QuickBASIC editor, if you see no DEFtype
    statement (DEFINT, DEFLNG, DEFDBL, DEFSNG, or DEFSTR), you can
    always assume that DEFSNG A-Z applies to all code in the procedure
    in that window.

    A similar rule holds for using the REM $DYNAMIC metacommand. If you
    don't see REM $DYNAMIC displayed in a procedure's window in the
    QB.EXE or QBX.EXE editor, you can assume that the default
    for that procedure is REM $STATIC for locally dimensioned
    arrays. However, note that arrays are always dynamic in non-STATIC
    SUB or FUNCTION procedures, regardless of metacommand usage. In SUB
    STATIC or FUNCTION STATIC procedures, locally dimensioned arrays
    can be either dynamic or static.

 2. If the DEFtype usage makes shared or passed variables differ in
    type between a calling routine and the SUB or FUNCTION procedures
    that it invokes, a "Type Mismatch" error may display, or zeroed or
    garbled variables may be passed at run time. The types of variables
    that are passed (integer, long integer, double precision, single
    precision, or string) must match between the CALL statement (or
    FUNCTION procedure invocation) and the formal parameter list in the
    SUB (or FUNCTION) statement.

 3. As you write or edit a program in the QB.EXE or QBX.EXE editor, the
    DEFtype statements (DEFINT, DEFLNG, DEFDBL, DEFSNG, and DEFSTR) should
    be added to the main program before adding any subprograms. If this is
    not done, the subprograms will default to DEFSNG A-Z (and you must
    explicitly add a different DEFtype, if needed).

    The DEFSNG A-Z default is not readily apparent, since the automatic
    DEFSNG A-Z above each subprogram is invisible in the QB.EXE or
    QBX.EXE editor. (The DEFSNG A-Z above each subprogram is visible only
    if you save the program in Text format and look at it in another text
    editor. An example is shown below, after Rule 5.)

 4. If you want to change the DEF type in a subprogram or FUNCTION
    procedure in the QB.EXE or QBX.EXE editor, add the desired DEFtype
    statement to the very first line in that window. Putting DEFtype
    statements in the middle of a program is not a good programming
    practice.

    Default variable types are defined in source code order. In other
    words, if the variable xxx is used both above and below a DEFtype x
    statement, you have created two different, mismatched xxx variables.
    To avoid this problem, place all DEFtype statements at the top of
    each procedure, before any variables are defined.

 5. Note that %, &, !, #, or $ appended to a variable name changes the
    type so that DEFtype statements have no effect on the type of that
    variable.

 The following steps illustrate the rules 1, 2, and 3 above (including
 the invisible default DEFSNG A-Z):

 1. Enter the following program into the QB.EXE or QBX.EXE editor:

       COMMON SHARED X
       X=3
       CLS
       PRINT X
       CALL SUB1
       SUB SUB1
         PRINT X
       END SUB

    Note: If you save the program at this point, the statement
    DECLARE SUB SUB1() is automatically added above the COMMON SHARED
    statement, but saving at this point is not necessary.

 2. Add the statement DEFINT A-Z before the COMMON statement but after
    the DECLARE statement (if any). [Note that if you add DEFINT A-Z
    before the DECLARE statement, running the program gives a "Type
    Mismatch" error because the procedure named SUB1 is declared with
    mismatched types in the DECLARE and SUB statements. Putting DEFINT
    A-Z after the DECLARE statement makes SUB1 default to single
    precision, thus matching the DEFSNG A-Z default in the SUB
    statement.]

 4. View the subprogram. Note: There is no DEFtype statement of any
    kind. We can assume it is DEFSNG A-Z, since QuickBASIC has not told
    us otherwise, according to rule 1 above.

 5. Run the program. The program prints 3 and 0, whereas 3 and 3 are
    expected if the type of the COMMON SHARED variable "x" is matched
    properly.

 6. When you use the TYPE command to display the program source file in
    DOS, the DEFSNG A-Z statement is visible above the SUB statement,
    even though it is invisible in the QB.EXE or QBX.EXE editor:

       DECLARE SUB SUB1 ()
       DEFINT A-Z
       COMMON SHARED X
       X=3
       CLS
       PRINT X
       CALL SUB1

       DEFSNG A-Z
       SUB SUB1
         PRINT X
       END SUB

 7. Note that if you load the program back into QuickBASIC and add a
    DEFINT A-Z statement above the SUB statement, DEFINT A-Z will
    always be visible in the QB.EXE or QBX.EXE editor (thus following
    rule 1 above). However, it will not be there when you use TYPE to
    display the source file in DOS (since DEFINT A-Z already appears in
    the main-level code, and the extra DEFINT A-Z would be redundant
    within that source file).

 All of the above behavior is consistent with QuickBASIC's design
 logic.


 155. BC Makes Smaller EXE than Make EXE File Using .LIB; e.g. Mouse

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  8-MAR-1989    ArticleIdent: Q28963

 Object (.OBJ) files linked to .LIB libraries from the DOS command line
 may produce a smaller .EXE file than will be created with the Make EXE
 File... option if you invoked QB.EXE Version 4.00 or 4.00b with the /L
 option to use a Quick library (.QLB) file.

 If the BC compiler options are the same for the two methods of making
 the .EXE file, then the .EXE size difference depends on the syntax of
 the LINK statement used to create the executable program, as follows:

 1. If the .LIB file is specified in the .OBJ list (the first argument)
    for LINK.EXE, then ALL routines in the .LIB file are linked into the
    .EXE.

    When you invoke QB.EXE Version 4.00 or 4.00b with the /L option
    to load a Quick library, the Make EXE File... option automatically
    puts the .LIB (that matches the Quick library) in the .OBJ list,
    often making a larger .EXE.

 2. If the .LIB file is specified in the .LIB list (the fourth
    parameter) for LINK.EXE, then just the external routines called from
    programs in the .OBJ list are pulled into the .EXE file from the .LIB
    file.

    QB.EXE Version 4.50 has been enhanced to do this automatically
    when you invoke with /L to load a Quick library and you choose
    the Make EXE File... option. This can make a smaller .EXE file if
    there are uncalled routines in the .LIB file.

 This information about LINK.EXE applies to QuickBASIC Versions 4.00,
 4.00b, and 4.50 and the BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and OS/2.

 The example program below, MOUS.BAS, uses the statement CALL INT86old
 to access the Microsoft Mouse through interrupt 51 (33 hex). INT86old
 is an external routine contained in QB.LIB. Programs that use CALL
 INT86old must be linked with the file QB.LIB (or run inside the
 QuickBASIC editor with QB /L QB.QLB).

 When the program MOUS.BAS is loaded into the QuickBASIC Version 4.00
 or 4.00b editor and the Make EXE File... option is selected from the
 RUN menu, the following LINK command is issued:

    LINK /EX /NOE MOUS+QB.LIB, C:MOUS.EXE, NUL,;

 Pressing the F4 key in the QB.EXE editor lets you toggle to view this
 command line because the editor covers the output screen by default
 after Make EXE.

 The resulting executable file (MOUS.EXE) has a size of 4213 bytes.
 However, if the same program is compiled from the DOS command line and
 then linked with the following command, the resulting executable file
 has a size of only 3925 bytes:

    BC MOUS;
    LINK /EX /NOE MOUS, C:MOUS.EXE, NUL, QB.LIB,;

 The size difference occurs because when the .LIB library files are
 specified as the fourth parameter in the LINK statement (as in the
 second LINK command above) the linker can be more "granular" than when
 the .LIB library files are included in the first parameter.
 Granularity refers to the ability of LINK.EXE to link in only those
 modules within the library file(s) that are actually referenced by the
 program. For example, if the library is composed of two object files,
 SUB1.OBJ and SUB2.OBJ, but only one of them is ever CALLed by the
 BASIC program, then only the one called will be linked into the EXE
 file.

 The following is the reason that Make EXE File... option in QB.EXE
 Version 4.00 and 4.00b puts the .LIB file (which correspond to a
 loaded Quick library) in the first parameter of the LINK syntax: the
 resulting EXE will more closely resemble the program as it executes
 inside the QuickBASIC editor.

 By popular request, the Make EXE File... option was changed in QB.EXE
 Version 4.50 to put the .LIB file in the library area for better
 granularity (i.e., smaller .EXE files).

 The following program CALLs the INT86old routine for drawing in
 high-resolution graphics mode with the mouse:

    DECLARE SUB MOUS (m0%, m1%, m2%, m3%)
    DEFINT A-Z
    SCREEN 2
    m0 = 0: m1 = 0: m2 = 0: m3 = 0: oldx = 0: oldy = 0
    CALL MOUS(m0, m1, m2, m3)
       'initialize mouse
    m0 = 1
    INPUT "press any key to turn on mouse cursor:", x
    CALL MOUS(m0, m1, m2, m3)
    'turn on mouse cursor
    END
    SUB MOUS (m0, m1, m2, m3) STATIC
    DIM regs(7)
            regs(0) = m0: regs(1) = m1: regs(2) = m2: regs(3) = m3
            CALL int86old(51, regs(), regs())
            m0 = regs(0): m1 = regs(1): m2 = regs(2): m3 = regs(3)
    END SUB

 The interrupt 51 (i.e., 33 hex) for Microsoft Mouse Version 6.00 (and
 later) is documented in the following book: "Advanced MS-DOS
 Programming," Second Edition, by Ray Duncan (published by Microsoft
 Press, 1988) on Pages 593-611. (The first edition published in 1986
 did not document the mouse interrupt.)

 More information regarding making mouse calls from BASIC can be found
 in the "Mouse Programmer's Reference Guide," which can be ordered from
 Microsoft Customer Service by calling (206) 882-8088.


 156. Defining "Intersegment Short Jump" (LINK Error L2002)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified: 24-MAR-1989    ArticleIdent: Q29918

 The L2002 linker error message is as follows:

    "fixup overflow near <number> in frame seg <segname> target seg
     <segname> target offset <number>."

 One possible reason for this error is that an assembler program
 contains an intersegment short jump or intersegment short call.

 LINK.EXE can also give this error if one of your compiled BASIC object
 modules is too large. The solution is to split the module into two or
 more separately compiled modules. This information applies to
 QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS, and to BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2.

 During the normal execution of a program, instructions residing in the
 current code segment are being executed in a sequential order. A
 program flows sequentially from one instruction to the next by
 incrementing the IP register as each instruction is executed.

 However, it is possible to alter this normal program flow. One method
 is to transfer control to instructions residing in a different
 segment. Referred to as an intersegment jump or intersegment transfer,
 it is accomplished by altering both IP and CS.

 If the size of the jump is less than 64K, but still involves
 transferring to a different segment, then this is called an
 intersegment short jump.

 This error is usually associated with assembly language routines. It
 usually doesn't occur with QuickBASIC programs.


 157. /MBF Fails When Variable x Used in Random file PUT#1,,x

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28977

 Programs compiled with the /MBF switch are not compatible with the new
 PUT syntax where a variable can be specified as the third parameter
 (PUT#n,,x).

 When a program compiled with the /MBF switch creates a random access
 file using the PUT statement with a variable in the third argument,
 the data file is not correctly read by subsequent programs which are
 also compiled with /MBF.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00 buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 This problem can be re-created by doing the following:

 1. Create a random access file with the following program:

       ' MKTEST.BAS - Compiled with /MBF option

       OPEN "r", 1, "test.dat"
       FOR n = 1 TO 5
       PUT #1, n, n
       NEXT
       CLOSE #1

 2. Read the data file TEST.DAT with the following program:

        ' RDTEST.BAS - Compiled with /MBF option

        OPEN "r", 1, "test.dat"
        FIELD #1, 4 AS a$
        FOR n = 1 TO 5
        GET #1, n
        PRINT CVS(a$)
        NEXT
        CLOSE #1

 If the following printed output does not appear from RDTEST.BAS, the
 output is incorrect:

    1 2 3 4 5

 However, if RDTEST.BAS is not compiled with the /MBF option (while
 MKTEST.BAS is still compiled with /MBF), the output is correct.

 One workaround is to avoid using the new variable (third) parameter
 with the PUT statement. This implies that a FIELD statement must be
 used in conjunction with the older two-argument PUT syntax. The above
 MKTEST.BAS would be modified in the following manner (it must be
 compiled with the /MBF switch):

    OPEN "r", 1, "test.dat"
    FIELD #1, 4 AS a$
    FOR i = 1 TO 5
    LSET a$ = MKS$(i)
    PUT #1, i
    NEXT i
    CLOSE #1
    END


 158. "NUL" Device Behaves Different in QB 4.x than 3.00 or GWBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 24-JAN-1990    ArticleIdent: Q28980

 The NUL device in QuickBASIC Versions 4.00, 4.00b, and 4.50 behaves
 differently than in previous versions of QuickBASIC (or in GW-BASIC
 3.20).

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 When the program below is run (either inside the QB.EXE editor or from
 an executable .EXE program), the (incorrect) output is as follows:

    third

 When run inside the QuickBASIC Version 3.00 editor or compiled to an
 EXE file with QB.EXE Version 3.00, or run in GW-BASIC Interpreter
 Version 3.20, the (correct) output is as follows:

    first
    secondthird

 With Version 4.00, the string BUFFER$ appears to be reinitialized with
 each PRINT #1 statement.

 If the device name is changed from NUL to anything else, for example
 FOO, then QuickBASIC Versions 3.00 and 4.00 produce the same (correct)
 output.

 The following is a code example for this problem:

    open "nul" for random as #1
    field #1, 65 as buffer$
    print#1,"first"
    print#1,"second";
    print #1,"third"
    print buffer$


 159. Compiled with BC, SHARED Long Integer Arrays Are Wrong in SUB

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q28981

 In the programs below, which are compiled with BC /o/d or BC, using
 SHARED long integer arrays in a subprogram causes variables or array
 elements to be set at zero (0) or incorrect negative values.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 You can work around this problem by placing line numbers in the
 program.

 Note: This problem does not occur in QuickBASIC Versions 1.x, 2.x, and
 3.x because these versions do not support long integers.

 The following two programs demonstrate this problem:

 Example 1
 ---------

 DECLARE SUB tvf (j%, tm$, w&)  'Order of arguments does not alter results.
 DEFLNG T
 'Declaring the array to be $STATIC or $DYNAMIC makes no difference.
 DIM SHARED te6(2), te5(2), te4(2), te2(2)
 te2(2) = 100&: te4(2) = 10000&: te5(2) = 100000: te6(2) = 1000000
 DO
   PRINT "Enter up to 8 digits"
   LINE INPUT a$
   CALL tvf(2, a$, w&)            'If the 2 is not passed, then it works.
   PRINT "Value of that is "; w&
   LOOP UNTIL a$ = ""
 END

 SUB tvf (j%, tm$, w&) STATIC            'Same problems if this is a function.
     PRINT te6(j%), te5(j%), te4(j%), te2(j%)     'This line always prints OK.
     q$ = RIGHT$("00000000" + tm$, 8)
     t = VAL(MID$(q$, 1, 2)) * te6(j%)  'If these lines are divided up, it
     t = t + VAL(MID$(q$, 3, 1)) * te5(j%)  'makes no difference, but if there
     t = t + VAL(MID$(q$, 4, 1)) * te4(j%)  'are line numbers on these lines,
     t = t + VAL(MID$(q$, 5, 2)) * te2(j%)  'IT WILL WORK!
     PRINT te6(j%), te5(j%), te4(j%), te2(j%)
     w& = t + VAL(MID$(q$, 7, 2))
 END SUB

 Example 2
 ---------

 '-------The program includes 1 subprogram
 DECLARE SUB logtran (ntn!)
 OPTION BASE 1
 COMMON SHARED cashp&, D&(), cash$, d1$
 DIM d&(1)
 OPEN "dt.dat" FOR RANDOM AS #1
 FIELD #1, 8 AS cash$, 4 AS d1$
 d&(1)=0
 cashp& = 0
 ntn! =1
 CALL logtran (ntn!)
 END

 SUB logtran (ntn!) STATIC
 PRINT "ntn!:";ntn!
 LSET cash$ = MKD$(CDBL(cashp&))
 PRINT "ntn!:";ntn!
 LSET d1$=MKS$(CSNG(d&(1)))
 PRINT "ntn!";ntn!
 CLOSE
 END SUB

 Output for the example 2:

 ntn! 1
 ntn! 1
 ntn! -5.965761E-30


 160. How Arrays of Fixed- and Variable-Length Strings Use Up Memory

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 19-JAN-1989    ArticleIdent: Q29010

 The following article is a general explanation of how arrays of fixed-
 and variable-length strings consume memory in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in the Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS OS/2 and MS-DOS.

 Programs should be compiled with the Debug (BC /D) option to trap
 array subscripting problems.

 The statement PRINT FRE("") displays the space available for storage
 of variable-length strings at any point in a program.

 The statement PRINT FRE(-1) displays the space available for far heap
 at any point in a program. Dynamic arrays of fixed-length strings
 utilize far heap (in both the QB.EXE editor and in compiled .EXE
 files) and can be larger than 64K if compiled with QB /AH or BC /AH.

 For a complete description of variable storage allocation, please read
 Pages 32 and 33 of the "Microsoft QuickBASIC 4.00: BASIC Language
 Reference." Arrays are stored in different places depending on whether
 the program is run from an .EXE file or the QB.EXE environment.

 The following statements dimension arrays of variable-length strings:

       DIM X(2000) AS STRING
       DIM W$(2000)

 Variable-length strings are always stored in DGROUP (the default data
 segment) that has less than 64K of memory free. The statement PRINT
 FRE("") can be placed at any point in the program to display at run
 time how much memory is available for strings in DGROUP at run time.

 Arrays of variable-length strings cannot use the far heap.

 The following statement dimensions an array of fixed-length strings:

    DIM Y(2000) AS STRING*10

 When you make an array of fixed-length strings dynamic instead of
 static, it will use far-heap space instead of DGROUP.

 The following are two ways to make Array Y dynamic:

 1. A variable (D%) in the array subscript in the following DIM
    statement makes Y dynamic:

       D%=2000
       DIM Y(D%) AS STRING * 10     ' Y is now a dynamic array.
       DIM Z(2000) AS STRING * 10   ' Z defaults to be a static array.

 2. Adding REM $DYNAMIC makes all subsequent arrays dynamic:

       REM $DYNAMIC
       DIM Y(2000) AS STRING * 10

 Dynamic arrays (except for arrays of variable-length strings) can be
 larger than 64K if you compile with QB /AH or BC /AH, and if the
 length of each array element can be divided into 64K (65,536) without
 a remainder (i.e., any power of two).

 The statement PRINT FRE(-1) displays how much memory is free at any
 given time in the far heap.

 In the following example, the FRE function displays how much memory
 remains in DGROUP and far heap space as dynamic arrays of variable and
 fixed-length strings are dimensioned:

 REM $DYNAMIC
 CLS
 PRINT FRE("")   ' DGROUP string space available.
 PRINT FRE(-1)   ' Far heap available.
 DIM x(2000) AS STRING      ' same as DIM X$(2000)
 PRINT FRE("")   ' DGROUP string space available.
 PRINT FRE(-1)   ' Far heap available.
 DIM y(2000) AS STRING * 2  ' Fixed-string dynamic array uses far heap.
 PRINT FRE("")   ' DGROUP string space available.
 PRINT FRE(-1)   ' Far heap available.

 Note: Static arrays of fixed-length strings that are not in COMMON are
 stored in the far heap in the QB.EXE editor. However, they are stored
 in DGROUP in compiled EXE programs. All static arrays in COMMON are
 stored in DGROUP in both the QB.EXE editor and in compiled EXE
 programs.

 Note that 1K is equal to 1024 bytes.


 161. FUNCTIONs and Subprograms Can Affect FIELDed Arrays in COMMON

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50
 Last Modified: 22-JAN-1990    ArticleIdent: Q29923

 An array that is in both a FIELD and a COMMON statement can be
 adversely affected if you pass it as a parameter to a FUNCTION or
 subprogram procedure.

 The program below has two FIELD statements that result in two arrays
 pointing to the same memory location. However, after a call to a
 FUNCTION that should not affect the arrays, they no longer point to
 the same place in memory. Compiling with debug (BC /D) does not help.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b), and in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 (buglist7.00). We are researching this problem and
 will post new information here as it becomes available.

 The program works correctly in QuickBASIC Version 3.00 if the FUNCTION
 is made into a subprogram. (QuickBASIC Version 3.00 does not support
 FUNCTION procedures.)

 The following is an example using a FUNCTION, but the problem also
 occurs if the FUNCTION is made into a subprogram:

 DECLARE FUNCTION Nothing% (any$)
 DEFINT A-Z
 COMMON SHARED /GLOBAL/ field1$(), field2$()
 DIM field1$(20), field2$(20)
 CLS
 OPEN "anyfile.tmp" FOR RANDOM SHARED AS #1 LEN = 10
 FIELD #1, 10 AS field1$(1)
 FIELD #1, 10 AS field2$(1)

 '** NOTE: At this point, field1$(1) and field2$(1) should point to    **
 '** the same storage location (buffer space) as verified below.       **

 LSET field1$(1) = "ABC"
 PRINT field1$(1); field2$(1)
 LSET field2$(1) = "DEF"
 PRINT field1$(1); field2$(1)

 x = Nothing(field1$(1))     '** prints field1$ but should not change it. **
 'x = Nothing((field1$(1)))  '** passes by value -- this works **

 '** Now notice that field1$(1) no longer points to the same storage as  **
 '** its counterpart, field2$(1), as verified below.                     **

 LSET field1$(1) = "ABC"
 PRINT field1$(1); field2$(1)
 LSET field2$(1) = "GHI"
 PRINT field1$(1); field2$(1)
 CLOSE
 END

 FUNCTION Nothing (any$)
         x$ = any$       '** so won't affect value of any$ **
         PRINT x$
 END FUNCTION


 162. SCREEN Function Gives COLOR Attribute; Foreground, Background

 Product Version(s): 1.00 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 15-JAN-1991    ArticleIdent: Q29943

 The SCREEN function can return the color attribute of a character on
 the screen. If the SCREEN function is invoked at a location where a
 character is printed, the color attribute returned is a combination of
 the foreground and background colors.

 If the character is not blinking (that is, the high-order, eighth bit
 is off), the foreground color can be obtained by taking the color
 attribute MOD 16, and the background color can be obtained by dividing
 the color attribute by 16. If the character is blinking, just turn off
 the eighth bit in the attribute byte before this calculation. For
 example:

    X% = SCREEN (1, 1, 1)
    X% = X% AND &H7F   ' Turns off bit 8.

 The following formula shows the relationship between the attribute and
 the foreground and background colors, taking into account all eight
 bits of the attribute:

    ATTRIBUTE = 128*(FOREGROUND\16) + BACKGROUND*16 + (FOREGROUND MOD 16)

 This information applies to Microsoft QuickBASIC versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2.

 The following is a bitmap of the attribute returned by the SCREEN
 function:

         BIT ->    7     6     5     4     3     2     1     0
                _________________________________________________
                |  0  |  1  |  0  |  0  |  0  |  0  |  0  |  1  |
                -------------------------------------------------
                   ^     ^     ^     ^     ^     ^     ^     ^
                   |     |     |     |     |     |     |     |
         Blinking --     -------------     |     -------------
                        |      Intensity --     |
      Background Color --                       -- Foreground Color

 Code Example
 ------------

 CLS
 COLOR 4, 1
 PRINT "hello";
 X% = SCREEN (1, 1, 1)
 PRINT "Attribute: "; X%
 X% = X% AND &H7F          ' Makes sure blinking bit (bit 8) is off.
 PRINT "Foreground: "; X% MOD 16
 PRINT "Background: "; X% \ 16


 163. LINK QB & C "Unresolved Externals"; How to Use LINK /NOE, /NOD

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified: 13-MAR-1990    ArticleIdent: Q30271

 The following article explains how to compile and link the example of
 linking QuickBASIC to Microsoft C shown on Page 391 of the "Microsoft
 QuickBASIC 4.0: BASIC Language Reference" manual for Versions 4.00 and
 4.00b, and Page 391 of the "Microsoft BASIC Compiler 6.0: BASIC
 Language Reference" manual for Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2.

 This article also explains how to use the LINK /NOE and /NOD options
 to eliminate error messages when linking to C.

 When linking BASIC to C (or to other Microsoft languages), please note
 the following information about using the LINK /NOE and /NOD options:

 1. Notes for using LINK /NOE Option are as follows:

    The LINK /NOE option is required for interlanguage calling to
    eliminate the following error message:

       xx.LIB : error L2044: __xxxxx : symbol multiply defined, use /NOE

    The Microsoft language libraries, such as LLIBCE.LIB from C and
    BRUN40.LIB from QuickBASIC, contain some of the same routines;
    thus, they require LINK /NOE.

    If you still get a "symbol multiply defined" message after using
    the LINK /NOE option, then the multiply defined symbols in your
    source code need to be renamed, recompiled, and relinked.

    The /NOE option is documented only in the README.DOC file on a disk
    in QuickBASIC 4.00 and 4.00b and in BASIC compiler 6.00 and 6.00b.
    In QuickBASIC Version 4.50, /NOE is documented on Page 365 of the
    "Microsoft QuickBASIC 4.5: Programming in BASIC" manual.

 2. Notes for using LINK /NOD Option are as follows:

    Note that an .OBJ file compiled with QuickBASIC 4.00, 4.00b, or
    4.50, or C 5.00 or 5.10 contains information telling the linker
    what .LIB file to look for at link time.

    If you use the LINK /NOD option, you are telling the linker not to
    search any specified library in the .OBJ file to resolve external
    references. Thus, if you use the /NOD option, you must explicitly
    specify the name of the .LIB language libraries for both C and
    QuickBASIC in the LINK command (even if the .LIB library has a path
    set to it with SET LIB=path). If you do not, LINK.EXE will give the
    following error:

       LINK : error L2029: Unresolved Externals

 Code Example
 ------------

 The following steps describe how to compile and link the code example
 shown at the bottom of this article (taken from Page 391 of the
 BASIC language reference manuals):

 1. Compile cf.bas and cfunc.c (shown farther below) as follows:

       BC CF.BAS;
       CL /C /AL CFUNC.C

    You may also use the C medium-memory model: CL /C /AM CFUNC.C. This
    example uses CL.EXE from Microsoft C Versions 5.00 and 5.10.

 2. Type SET at the DOS command line to make sure that you issued a
    statement similar to "SET LIB=C:\QB.400;C:\C.500" to tell LINK.EXE
    where to look for .LIB files at link time.

 3. Link the BASIC and C routines, specifying the BASIC routine first
    and using LINK.EXE Version 3.61 or later:

       LINK CF.OBJ+CFUNC.OBJ/NOE;

 CF.BAS
 ------

    REM  BASIC routine cf.bas:
    DEFINT A-Z
    DECLARE SUB cfunc CDECL (BYVAL x AS INTEGER)
    beforecall = SETMEM(-2048)
    cfunc (1024)
    aftercall = SETMEM(3500)
    IF aftercall <= beforecall THEN PRINT "memory not reallocated."
    END

 CFUNC.C
 -------

    /*  C routine cfunc.c:    */
    void far cfunc(bytes)
    int bytes;
    {
     char *malloc();
     char *workspace;
     workspace=malloc((unsigned) bytes);
     free(workspace);
    }


 164. BC.EXE "Syntax Error" Instead of CONST "Duplicate Definition"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q30313

 You will receive the message "Syntax Error" instead of "Duplicate
 Definition" if you use the same name for a CONST and a variable when
 using BC.EXE.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b); and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 When the following sample program is run inside the QB.EXE or QBX.EXE
 editor, you receive the expected "Duplicate Definition" error on the
 CONST statement. The same line produces a "Syntax Error" message when
 compiled using BC.EXE.

 QuickBASIC version 3.00 produces the error message "Constant
 assignment illegal" when compiled inside the QB.EXE editor or from the
 DOS command line.

 The following sample program demonstrates the inconsistent error
 message:

    'If this is compiled in the editor you get a "Duplicate Definition"
    'If this is compiled with BC.EXE you get a "Syntax Error"
    a = 5
    CONST a = 6


 165. PRINT SGN(a) AND SGN(b) Fails If Compiled with BC.EXE; 4.50 OK

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q30314

 The following statement fails to correctly output a zero (0) at run
 time when compiled with BC.EXE; however, it correctly outputs a zero
 in the QB.EXE interpreter:

    PRINT (SGN(a)) AND (SGN(b))

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 The following is a workaround for this problem:

 1. Assign SGN(a) and SGN(b) to intermediate variables.

 2. Use the intermediate variables in the AND operation as follows:

       x = SGN(a)
       y = SGN(b)
       PRINT (x) AND (y)

 When compiled with QuickBASIC Version 3.00, the correct output is
 generated when run from an EXE program or inside the QB.EXE editor.

 The following is a code example showing the problem:

 'It should print  0  -1   0  but the AND does not work with BC.EXE:
 a = 0
 b = -1
 PRINT SGN(a),
 PRINT SGN(b),
 PRINT (SGN(a)) AND (SGN(b))


 166. "Type Mismatch" Appears When Typing % to Respond to INPUT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q30357

 The error message "Type Mismatch" appears when you type a "%" (percent
 sign) in response to an INPUT statement receiving input into a numeric
 variable.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 The program works correctly using QuickBASIC Version 3.00.

 The following is a code example:

 INPUT "Enter an integer: ",I%   ' type just % in response to the input.
 PRINT I%


 167. "Type Mismatch" When "INPUT1" Is Elementname in TYPE Statement

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q30372

 A variable "type mismatch" error improperly occurs if the reserved
 word "INPUT" is embedded in an elementname in a TYPE...END TYPE
 statement.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in Microsoft BASIC Compiler Version 6.00 for MS-DOS
 and MS OS/2 (buglist6.00). This problem was corrected in QuickBASIC
 Version 4.50, in the compiled version of Microsoft BASIC Compiler
 Version 6.00b (fixlist6.00b), and in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2
 (fixlist7.00).

 The same syntax does not fail when it is not in a TYPE elementname.
 For example, the following two-line program runs properly:

    f.input1 = 123.2
    PRINT f.input1

 Please note that the TYPE...END TYPE statement is not supported in
 previous releases of the QuickBASIC compiler.

 To work around this problem, avoid using reserved words embedded
 within names used in the TYPE...END TYPE statement.

 The following is a code example:

 TYPE checkout1
        numa AS INTEGER
        input1 AS STRING * 10    'works ok if input1 is changed to out1
 END TYPE
 DIM f AS checkout1
 f.input1 = "abcdef"
 PRINT f.input1


 168. Parameters Incorrectly Passed in Nested Subprogram CALLs

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 22-JAN-1990    ArticleIdent: Q30393

 When making nested subprogram CALLs, the parameters passed in the CALL
 statements get mixed up in the example program below if they are
 compiled with BC.EXE from QuickBASIC Version 4.00. The program works
 correctly when run in the QB.EXE interpreter.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 This problem does not occur in QuickBASIC Version 3.00.

 The program below improperly passes the first parameter into the
 second parameter on the third nested CALL.

 The assembly listing (generated with the BC.EXE /A option) for the
 following sample program demonstrates that inside the SUB, the SI
 register is pushed twice onto the stack without being reset.

 When the sample program below is compiled without the debug (/d)
 option, the output from the EXE program is incorrect (you get the
 value -999 rather than 1).

 If compiled with the debug option, the run-time error message
 "Subscript out of range" appears after printing the first two lines of
 output.

 The program runs correctly if line numbers are added to the "subp3"
 subprogram and the program is then compiled with the debug option.

 The following is a sample program:

 ' The main program and three subprograms are contained in one source
 file:
 DEFINT A-Z
 CONST cnst1 = 40
         '  ARRAY DIMENSIONING
 DIM array2(cnst1), array1(cnst1)
 COMMON SHARED array2(), array1()
 d1$ = ""
 d2 = -999
 fi = 1
 PRINT "file.index = "; fi
 CALL subp1(d1$, d2, fi)

 SUB subp1 (dummy1$, dummy2, dummy3) STATIC  ' dummy3 = fi (file.index)
 dummy1$ = ""
 CALL subp3(dummy3)
 v1 = LOF(array2(dummy3)) / 2
 IF v1 >= dummy2 THEN
   array1(dummy3) = dummy2
   CALL subp2(dummy3)
 END IF
 END SUB

 SUB subp2 (dummy4) STATIC         ' dummy4 = dummy3 = fi (file.index)
 PRINT "Sub2. file.index = "; dummy4
 END
 END SUB

 SUB subp3 (dummy5) STATIC         ' dummy5 = dummy3 = fi (file.index)
 OPEN "r", dummy5, "dummy.fil", 128
 array2(dummy5) = dummy5
 PRINT "Sub3. file.index = "; dummy5
 END SUB

 'Output from editor:                    Output from EXE (without /d):

 ' file.index = 1                                file.index = 1
 ' Sub3. file.index = 1                  Sub3. file.index = 1
 ' Sub2. file.index = 1                  Sub2. file.index = -999


 169. Bad Math in EXE Using Dynamic Array of Long Integers: Use /D

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-NOV-1988    ArticleIdent: Q30397

 Microsoft recommends compiling with the debug option (BC /D) whenever
 arrays are being used. If a math problem involving arrays is corrected
 by compiling with the debug (/D) option, that program must be compiled
 with the debug option.

 When using dynamic long-integer arrays in some math calculations in
 the EXE program, the results may not be correct unless you compile
 with the BC.EXE debug option (BC /D). The example below demonstrates
 this behavior.

 Inside the QB.EXE environment, the debug option always is on (and
 cannot be disabled); this means the math problem does not occur when
 programs are run in QB.EXE.

 The sample program below demonstrates the importance of the debug (BC
 /D) option, which does the following:

 1. Generates debugging code for run-time error checking

 2. Enables the CTRL+BREAK command to break a program

 3. Executes array-boundary checking

 Compiling with the debug option in the sample program below is
 essential to making the program work correctly.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, and Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and OS/2.

 The sample program is as follows:

 DEFLNG A-Z
 ' $DYNAMIC
 DIM a(100) as LONG, b(100) as long
 a(1) = 25
 b(1) = 100
 r = 1
 x = -3
 CLS
 PRINT (r - x) * b(1) + a(1)
 PRINT a(1) + (r - x) * b(1)
 END


 170. INPUT Receives Nonzero Value When "&" Character Is Input

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q30402

 When you INPUT the ampersand (&) character into a numeric variable,
 the value input is nonzero. This result occurs in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2.

 Receiving the ampersand character in an INPUT statement should return
 zero, because the ampersand character denotes a long-integer constant.
 However, this character does not return zero.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 In the QB.EXE environment, a value of 203 is received when the
 ampersand character is INPUT. When running the same program from an
 EXE file, the value 233 is received. In an EXE program compiled with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, the value 259 is
 received.

 The INPUT statement correctly inputs a zero into a numeric variable
 when you input the ampersand character in QuickBASIC Version 3.00, or
 in BASIC PDS 7.00.

 The following is a code example:

    INPUT "Enter an integer : ", I%     ' Type in & character.
    PRINT I%


 171. BC.EXE Subprogram Error Occurs in ERROR GOTO in SELECT CASE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00B buglist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q30403

 Placing an ON ERROR GOTO statement in a SELECT CASE statement inside
 of a subprogram (SUB...END SUB) procedure will generate the message
 "Subprogram error," which is a compile-time error.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Compiler Version 7.00
 (fixlist7.00).

 This error does not occur in the QB.EXE environment or if the SELECT
 CASE statement is located in the main module.

 The following is a code example:

    DECLARE SUB testsub ()
    CALL testsub
    END

    errortrap:
    END

    SUB testsub
      i% = 1
      SELECT CASE i%
         CASE 1
             ON ERROR GOTO errortrap
         CASE ELSE
      END SELECT
    END SUB

 The following is the output of the compile from BC.EXE:

    Microsoft (R) QuickBASIC Compiler Version 4.00B
    Copyright (C) Microsoft Corp. 1982-1988. All rights reserved.
     006B   0006         CASE ELSE
                         ^ Subprogram error

    43108 Bytes Available
    42683 Bytes Free

        0 Warning Error(s)
        1 Severe  Error(s)


 172. How to Print CGA SCREEN 0, 1, or 2 Image to Epson Printer

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI appnote BQ0085
 Last Modified: 17-OCT-1990    ArticleIdent: Q30451

 Below are two methods for making a screen dump of SCREEN 0, 1, or 2
 (CGA modes) to an Epson or Epson-compatible printer. These methods
 also support all standard EGA and VGA SCREEN modes (SCREENs 7 through
 13) if you are using the GRAPHICS.COM provided in MS-DOS 4.00 or
 later.

 The examples below apply to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b; and to
 Microsoft BASIC PDS (Professional Development System) versions 7.00
 and 7.10 for MS-DOS. The program DUMP2.BAS below can be used with
 Microsoft QuickBASIC versions 2.00, 2.01, and 3.00 if you change CALL
 INT86OLD to CALL INT86.

 This article is one part of the application note titled "How to Print
 BASIC Video Screens to Epson Printers." A printed copy of this
 application note can be obtained by calling Microsoft Product Support
 Services at (206) 637-7096. This application note can also be obtained
 in separate parts in this Knowledge Base by querying on the following
 words:

    Epson and print and screen and QuickBASIC

 If you want further information about video graphics memory, please
 refer to the following book, which is available from bookstores or
 Microsoft Press by calling (800) 888-3303 or (206) 882-8661:

    "Programmer's Guide to PC and PS/2 Video Systems," by Richard
    Wilton (Microsoft Press, 1987)

 Printing CGA SCREEN Modes 0 Through 2
 -------------------------------------

 The following are two methods of performing a CGA screen dump to a
 graphics printer:

   Note: These methods will also support all standard EGA and VGA
   SCREEN modes (SCREENs 7 through 13) if you are using
   GRAPHICS.COM provided in MS-DOS 4.00 or later.

 1. You can manually execute a screen dump to a graphics printer of a
    CGA SCREEN 0, 1, or 2 in BASIC by doing the following:

    a. Run GRAPHICS.COM, which is a terminate-and-stay resident (TSR)
       program located on the DOS disk (run GRAPHICS.COM only once per
       boot session).

    b. Press SHIFT+PRINT SCREEN (that is, press the PRINT SCREEN key
       while holding down the SHIFT key).

       The above SHIFT+PRINT SCREEN screen dump also can print the
       screen in GW-BASIC, in IBM BASICA, or in most programs that use
       CGA text or graphics.

 2. A hardware interrupt 5 also can be invoked to perform a CGA screen
    dump to a graphics printer from a Microsoft BASIC program run on an
    IBM PC. To perform the screen dump, do the following:

    a. Run the GRAPHICS.COM program provided with the DOS disk (run
       GRAPHICS.COM only once per boot session).

    b. Once GRAPHICS.COM is resident in memory, using SHIFT+PRINT
       SCREEN or hardware interrupt 5 will print screens displayed by
       the IBM CGA card. In versions of MS-DOS earlier than 4.00, the
       IBM GRAPHICS.COM program does not support the printing of EGA or
       VGA screens, and only BASIC SCREENs 0, 1, and 2 can be printed.

 The following program, DUMP.BAS, shows the preferred method to CALL
 hardware interrupt 5 to perform a screen dump (this program can be
 compiled in QuickBASIC 4.00, 4.00b, or 4.50; in BASIC compiler 6.00 or
 6.00b; or in BASIC PDS 7.00 or 7.10 for MS-DOS):

    ' Dump.Bas
    TYPE Regtype
      AX AS INTEGER
      BX AS INTEGER
      CX AS INTEGER
      DX AS INTEGER
      BP AS INTEGER
      SI AS INTEGER
      DI AS INTEGER
      FLAGS AS INTEGER
      DS AS INTEGER
      ES AS INTEGER
    END TYPE
    DIM inary AS RegType
    DIM outary AS RegType
    CLS
    SCREEN 1
    PRINT "This goes to the printer"
    LINE (1,1)-(100,100)
    CALL interrupt (&H5, inary, outary)      ' Performs screen dump

 The program below, DUMP2.BAS, can be used with Microsoft QuickBASIC
 versions 2.00, 2.01, and 3.00 if you change CALL INT86OLD to CALL
 INT86. Otherwise, if you don't change CALL INT86OLD to CALL INT86,
 this program can be compiled as is in QuickBASIC 4.00, 4.00b, or 4.50;
 in BASIC compiler 6.00 or 6.00b; or in BASIC PDS 7.00 or 7.10:

    ' DUMP2.BAS
    DIM inary%(7), outary%(7)
    SCREEN 1
    PRINT "This goes to the printer"
    LINE (1,1)-(100,100)
    CALL int86old ( &H5, VARPTR(inary%(0)), VARPTR(outary%(0)) )

    ' The following syntax, which leaves out the VARPTR function,
    ' is also supported in QuickBASIC 4.00, 4.00b, 4.50, in BASIC
    ' compiler 6.00 and 6.00b, and in BASIC PDS 7.00 and 7.10:
    '         CALL int86old ( &H5, inary%(), outary%() )
    ' This INT86OLD syntax is given on Pages 86-88 of the "QuickBASIC
    ' 4.0: Language Reference" for 4.00 and 4.00b and on Pages 86-88 of
    '"BASIC Compiler 6.0: Language Reference" for 6.00 and 6.00b.

    'NOTE: The following syntax is ILLEGAL for CALL INT86 in
    'QuickBASIC 2.00, 2.01, or 3.00:
    '           CALL int86 ( &H5, inary%(), outary%() )

 To run the above DUMP.BAS or DUMP2.BAS program within the QB.EXE
 version 4.00, 4.00b, or 4.50 editor (or within QB.EXE from BASIC
 compiler 6.00 or 6.00b), you must invoke the editor with the QB.QLB
 Quick library, as follows:

    QB DUMP.BAS /L QB.QLB

 To make an EXE program from one of the above programs, you must LINK
 with QB.LIB as follows:

    BC DUMP.BAS;
    LINK DUMP.OBJ,DUMP.EXE,,QB.LIB;

 The above LINK creates DUMP.EXE, which is a program that can be
 executed from DOS by typing "DUMP".

 For BASIC PDS version 7.00 or 7.10, you must use QBX.EXE, QBX.QLB, and
 QBX.LIB (instead of QB.EXE, QB.QLB, and QB.LIB) in the above steps.

 DUMP.BAS cannot run in QuickBASIC version 2.00, 2.01, or 3.00;
 instead, you must use DUMP2.BAS. To run DUMP2.BAS in QB.EXE version
 2.00, 2.01, or 3.00, do the following:

 1. Make a USERLIB.EXE that contains INT86, as follows:

    a. In version 2.00 or 2.01, type the following at the DOS command
       line:

          BUILDLIB USERLIB.OBJ,userlib.EXE;

    b. In version 3.00, type the following at the DOS command line:

          BUILDLIB INT86.OBJ,userlib.EXE;

 2. Run GRAPHICS.COM (only once per boot session) if you will be
    printing graphics.

 3. Invoke QB.EXE as follows:

       QB DUMP2.BAS /L userlib.EXE

 4. Change INT86OLD to INT86 in DUMP2.BAS (since there is no INT86OLD
    in version 2.00, 2.01, or 3.00).

 5. Press CTRL+R to run the program in QB.EXE.

 To make DUMP2.BAS into DUMP2.EXE using QuickBASIC version 2.00, 2.01,
 or 3.00, do the following:

 1. Do ONE of the following:

    a. Create DUMP2.OBJ using the Compile command from the Run menu in
       the QB.EXE editor.

    b. You can also create DUMP2.OBJ using the separate compilation
       method, where you must end the QB command line with a semicolon
       (;), as follows:

          QB DUMP2;

 2. Do one of the following, depending on which version of QuickBASIC
    you are using:

    a. In 2.00 or 2.01, type the following at the DOS command line:

          LINK DUMP2+USERLIB.OBJ;

    b. In 3.00, type the following at the DOS command line:

          LINK DUMP2+INT86.OBJ;


 173. Why QB/QBX Editor Options Might Revert to Default; QB.INI File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-AUG-1990    ArticleIdent: Q30455

 In the QB.EXE environment of QuickBASIC version 4.50 or in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10, the settings in the Options menu (ALT+O)
 (Display, Set Paths, Right Mouse, Syntax Checking, Full Menus) are
 automatically saved to the QB.INI or QBX.INI file whenever the options
 are changed.

 Similarly, in the QB.EXE environment of QuickBASIC versions 4.00 and
 4.00b and of Microsoft BASIC Compiler versions 6.00 and 6.00b, the
 color, display attributes, tab, and scroll bar options in the View
 menu's Options command (ALT+V+O) are automatically saved to the QB.INI
 file whenever the options are changed.

 If the QB.EXE (or QBX.EXE) environment does not find a QB.INI (or
 QBX.INI) file in the current working directory or in the DOS PATH, the
 environment reverts to the default options. If you then change the
 default options, QB.EXE (or QBX.EXE) creates a QB.INI (or QBX.INI)
 file in the current directory (since a QB.INI or QBX.INI doesn't
 already exist along the PATH). If the name of your current directory
 is not displayed at the DOS prompt, typing CHDIR at the DOS prompt
 displays the name of your current working directory.

 To keep the QB.EXE (or QBX.EXE) options consistent, you should keep
 one QB.INI (or QBX.INI) file in your DOS PATH; this QB.INI (or
 QBX.INI) file will be updated each time you change the options.

 The following steps show that if QB.EXE (or QBX.EXE) does not find a
 QB.INI (or QBX.INI) file in the current working directory or in the
 DOS PATH, it creates a new QB.INI (or QBX.INI) file in the current
 directory:

 1. Type PATH in MS-DOS to see what directories lie in the PATH.

 2. Run QB.EXE (or QBX.EXE), and change one or more editor options.

 3. Exit QB.EXE (or QBX.EXE).

 4. Change to a different directory that is not in your PATH.

 5. Run QB.EXE (or QBX.EXE), and note that the environment reverts
    to the default options and does not reflect the option(s) you
    specified in Step 2.

 6. If you now change one or more editor options, a new QB.INI (or
    QBX.INI) file is created in the current directory.

 In Step 5 above, QuickBASIC reverts to its default options. This could
 make you incorrectly conclude that QuickBASIC forgot the changes that
 you made (if any) to the options.

 If QB.EXE finds QB.INI (or QBX.EXE finds QBX.INI) in the DOS PATH or
 in the current directory, the options are updated in that copy of
 QB.INI (or QBX.INI). To make the environment always use the same
 option preferences, use only one copy of QB.INI (or QBX.INI) in your
 DOS PATH.

 The DOS PATH is set with the PATH command. For example, the following
 DOS command sets your search path to the directory called QB.450 on
 Drive C:

    PATH C:\QB.450


 174. IBM 3270 PC Not Officially Supported by QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 25-APR-1989    ArticleIdent: Q30603

 The IBM 3270 PC computer combines an IBM PC with the capability to
 interface with a mainframe computer.

 The IBM 3270 PC is not on the list of IBM PC compatibles on which
 QuickBASIC compiler has been tested or guaranteed to run.

 It has been reported that system lockups can occur when running
 QuickBASIC Version 4.00 on the IBM 3270 PC.

 We recommend that you do not run QuickBASIC, or programs compiled in
 QuickBASIC, on the IBM 3270 PC.

 This information also applies to the IBM 3270 Workstation Program
 Version 1.0, which is a software package that emulates an IBM 3270 PC.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 and the Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and OS/2 (and their included copies of QuickBASIC).


 175. In QB.EXE, Save with "Too Many Files" Erases Source File

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 21-NOV-1988    ArticleIdent: Q30608

 When running in the QB.EXE editor, if a program opens all available
 DOS file handles and an error message such as "Division by Zero"
 appears, a subsequent Save command in the editor erases the file and
 the message "Too Many Files" is displayed.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the QuickBASIC that accompanies the Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2
 (buglist6.00, buglist6.00b). This problem was corrected in QuickBASIC
 Version 4.50.

 This problem does not occur in QuickBASIC Versions 2.00, 2.01, and
 3.00.

 You can work around this problem by doing either of the following two
 things:

 1. Issuing a CLOSE from the immediate window to free file handles
    before saving the program

 2. Performing a Selected Print from the file menu (ALT+F+P) before
    saving.

 Because DOS preallocates five file handles, only 15 are available for
 program use. (This occurs when you boot your DOS with the FILES=20
 statement in your DOS CONFIG.SYS file.)

 If a program terminates abnormally, these file handles may stay
 allocated to QuickBASIC, as in the example program below. Performing
 Shell or Save from the File menu in QB.EXE then fails when attempting
 to open the twenty-first file handle, as in the following example :

 1. Executing a Shell command from the File menu displays the following
    message:

       "Illegal Function Call"

 2. Executing a Save command from the File menu displays the following
    message and erases the file:

       "Too Many Files"

 Please note that Shell can be used as a test to determine if you have
 run out of file handles. If Shell is successful, you can Save freely
 without deleting the file.

 The following steps reproduce the problem:

 1. Boot with FILES=20 in your DOS CONFIG.SYS file.

 2. Run the following program (a "Divide By Zero" error message
    appears):

    FOR k = 1 TO 15
       OPEN "file" + STR$(k) FOR RANDOM AS #k
    NEXT k
    m = 0
    PRINT 1 / m

 3. Try to Save from the File menu in QB.EXE. A "Too Many Files" error
    message will appear.

 4. The program file is now erased and cannot be reopened in QB.EXE.


 176. Hercules SCREEN: PAINT Overspills Window after VIEW and CIRCLE

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  5-DEC-1989    ArticleIdent: Q30674

 The code below should PAINT a 90-degree slice of a disk on Hercules
 SCREEN 3. With certain coordinates given to the PAINT statement, the
 entire VIEW rectangle is incorrectly filled.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50.

 The problem occurs both as an .EXE and inside the QB.EXE environment.

 The following is a code example:

    SCREEN 3
    VIEW (1, 1)-(100, 100)
    CIRCLE (100, 100), 50
    'PAINT (95, 95) This correctly gives quarter-disk.
    PAINT(96,96) 'Incorrectly gives rectangle


 177. INKEY$ Returns Two-Byte String for Arrow and Function Keys

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-APR-1989    ArticleIdent: Q30844

 The INKEY$ function returns a one- or two-byte string. Alphanumeric
 keys return one-byte strings. The function keys and the directional
 keys return two-byte strings.

 If INKEY$ returns a two-byte string, then each byte needs to be
 examined to determine the key that was pressed. For two-byte strings,
 the first byte will always be null [an ASCII value of zero, CHR$(0)],
 and the second byte will be the key's scan code. The LEN function
 tells you the length of the returned string (one byte or two).

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, and to the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2.

 The keyboard scan codes are listed in the BASIC language reference
 manual in the KEY(n) statement section.

 Example 1

 The following sample code prints a message if the UP ARROW key is
 pressed:

 top:
 I$ = INKEY$
 'The scan code for the UP ARROW is &H48:
 IF I$ = CHR$(0) + CHR$(&H48) THEN
    PRINT "up arrow key pressed"
 END IF
 GOTO top

 Example 2

 The following code example shows how to print the ASCII value of any
 key pressed:

 REM     ASCII.BAS
 CLS
 PRINT "Hit F1 To Exit"
 PRINT:PRINT
 DO
    A$=INKEY$
    IF MID$(A$,1,1) <> "" THEN
       PRINT A$
       PRINT "ASCII Value = "; ASC(A$)
    END IF
    IF MID$(A$,2,1) <> "" THEN
       PRINT "ASCII Value = "; ASC(MID$(A$,2,1))
    END IF
 LOOP UNTIL MID$(A$,2,1) = CHR$(59)
 END

 Program note: The DO...LOOP statement is only supported in QuickBASIC
 3.00 or later. In earlier versions, you can rewrite this example to
 use a different loop, such as WHILE...WEND.


 178. How to Make MOUSE CALLs in Hercules Graphics Mode, SCREEN 3

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_Mouse H_DriverPR docerr
 Last Modified:  1-DEC-1989    ArticleIdent: Q30856

 You can design BASIC programs that make CALLs to the Microsoft Mouse
 driver on Hercules Monochrome SCREEN 3 in MS-DOS, but you must follow
 the steps below. (MOUSE CALLs let you change the mouse cursor, detect
 the mouse position, detect mouse-button status, etc.)

 Appendix D of the "Microsoft Mouse Programmer's Reference Guide"
 mentions three steps, but they are shown in the wrong order to work
 with QuickBASIC. The steps shown on Page D-1 should be performed in
 the following order for QuickBASIC:

    2, 3, 1

 The order 1, 2, 3 should be used for other languages.

 The following information applies to QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and Microsoft BASIC Compiler Versions 6.00 and 6.00b running
 under MS-DOS.

 When making CALLs to the Microsoft Mouse driver on a computer with a
 Hercules Monochrome Graphics Adapter, do the following:

 1. In the AUTOEXEC.BAT file, invoke the Microsoft MOUSE.COM driver
    before the QBHERC.COM or MSHERC.COM Hercules Graphics driver. If
    QBHERC or MSHERC is mistakenly loaded first, the Hercules graphics
    cursor appears as several small horizontal (broken) lines in the
    graphics screen (or it does not appear at all), and the graphics
    drawing boundaries are confined to 640 x 200 pixels. (Normal SCREEN
    3 resolution is 720 x 348.)

    MSHERC.COM is shipped with QuickBASIC Version 4.50. QBHERC.COM is
    shipped with Microsoft QuickBASIC Versions 4.00 and 4.00b and with
    Microsoft BASIC Compiler Versions 6.00 and 6.00b.

 2. Perform one of the following steps, but not both:

    a. Start QB.EXE by typing QB /L MOUSE to load the Quick Library
       MOUSE.QLB into memory.

       You can use LINK /Q to make MOUSE.QLB from the MOUSE.LIB that
       comes on a disk along with the "Microsoft Mouse Programmer's
       Reference Guide." This guide can be ordered by returning the
       card in the Microsoft Mouse package.

    -- or --

    b. Start QB.EXE by typing QB /L QB.QLB and use CALL INTERRUPT or
       CALL INT86OLD to access the mouse driver. To find out how to
       use CALL INTERRUPT or CALL INT86OLD to program the mouse,
       search for a separate article with the following words:

          INTERRUPT and INT86OLD and 51 and MOUSE

 3. To tell the mouse driver that you are in CRT Page 0, define the
    segment address (DEF SEG) at hex 40 and POKE a 6 into offset hex
    49. You must store 5 into memory offset hex 49 to use CRT Page 1.
    The following is an example:

       DEF SEG = &H40
       POKE &H49, 6          ' CRT page 0
       DEF SEG

 4. Call the mouse function 0 to initialize, as follows:

       CALL mouse(0,0,0,0)     '  initialize mouse

 5. Put the card into the graphics mode (i.e., change to SCREEN mode
    3), as follows:

       SCREEN 3, , 0, 0

 6. CALL the mouse to turn the mouse cursor on, as follows:

       CALL mouse(1, 0, 0, 0)     '  turn mouse cursor on

 QuickBASIC Versions 3.00 and earlier do not support Hercules
 Monochrome Graphics SCREEN 3.

 The techniques explained in this article do not work under the DOS box
 (real mode) of MS OS/2 (nor do they work in protected mode, which
 requires OS/2 MOU... API function calls from Microsoft BASIC Compiler
 6.00 or 6.00b to program the mouse). OS/2 normally loads its own mouse
 driver for the DOS box, and even if this driver isn't loaded, OS/2
 still reserves interrupt 33 for itself. If you install MOUSE.COM in
 the DOS box, OS/2 will tell you that the interrupt is owned by the
 system, and although a program can display the mouse cursor on
 Hercules SCREEN 3 (such as the Code Example below), the pointer will
 not move. You cannot program the mouse in Hercules graphics SCREEN 3
 in the DOS box (real mode) of MS OS/2. You can, however, program the
 mouse in other graphics screen modes in the DOS box of OS/2.

 Code Example
 ------------

 The following example can be compiled with QuickBASIC Versions 4.00,
 4.00b, and 4.50 and with Microsoft BASIC Compiler Versions 6.00 and
 6.00b in MS-DOS:

 DEFINT A-Z
 DEF SEG = &H40
 POKE &H49, 6               ' CRT page 0
 DEF SEG
 CALL mouse(0, 0, 0, 0)     ' Initialize Mouse
 SCREEN 3, , 0, 0           ' Switch to Hercules Graphics mode, page 0

 m1 = 1
 CALL mouse(m1, m2, m3, m4)   ' Turn on mouse cursor (m1 = 1)
 WHILE INKEY$="":WEND
 CALL mouse(2, 0, 0, 0)       ' Turn off mouse cursor
 END


 179. QuickBASIC 4.x Procedure Name Followed By Colon Not Executed

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 b_basiccom
 Last Modified: 20-SEP-1990    ArticleIdent: Q30858

 When you use the implied CALL syntax, a SUBprogram procedure name
 followed immediately by a colon is mistaken for a label name. This
 prevents the SUBprogram from being executed. The problem occurs both
 inside the QB.EXE environment and when compiled from BC.EXE.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler versions
 6.00 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2; and
 in Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 This is not an issue in QuickBASIC version 3.00 and earlier versions,
 because these versions require the CALL statement to execute
 SUBprogram procedures. The implied CALL syntax was added to QuickBASIC
 version 4.00. An "implied CALL" is where a procedure name is invoked
 without a preceding "CALL" statement, then followed by parameters
 passed in a list without surrounding parentheses.

 The following are two workarounds for this problem:

 1. Place the command following the procedure name on a new line so
    that the colon is not necessary.

 2. Use an explicit CALL statement to invoke the procedure.

 The following code example demonstrates the problem:

    DECLARE SUB subtest ()
    CLS
    PRINT "this is the main"
    subtest: PRINT "the end"

    SUB subtest
    PRINT "this is sub test"
    END SUB

 The procedure (SUBTEST) above will not be executed because the
 compiler mistakes the procedure name followed by a colon for a label
 name.

 The following code will execute correctly:

    DECLARE SUB subtest ()
    CLS
    PRINT "this is the main"
    call subtest: PRINT "the end"

    SUB subtest
    PRINT "this is sub test"
    END SUB


 180. "Internal Error" Using FUNCTION as Argument in POKE Statement

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  5-DEC-1989    ArticleIdent: Q30859

 Using a FUNCTION procedure as the second argument in a POKE statement
 will cause an "internal error" when compiling from BC.EXE. The same
 program works correctly when run in the QB.EXE editor environment.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem
 has been corrected in QuickBASIC Version 4.50.

 Note: QuickBASIC Version 3.00 and earlier versions do not support
 FUNCTION procedures.

 To work around this problem, assign the FUNCTION procedure to a
 temporary variable and then use the temporary variable in the POKE
 statement.

 The following is a code example:

 DEFINT A-Z
 DECLARE FUNCTION Location(ROW, COL)
 DECLARE FUNCTION ScreenAttrib(F, B)

 FUNCTION Location(ROW, COL)
   Location = 160 * ROW + 2 * COL - 162
 END FUNCTION

 FUNCTION ScreenAttrib(F, B)
   ScreenAttrib = -128 * (F > 15) + (F MOD 16) + (16 * (B MOD 8))
 END FUNCTION

 CLS
 DEF SEG=&hb800       'color graphics adapter seg addr
 F = 7                'white foreground
 B = 1                'blue background
 K$="X"               'poke an X onto the screen
  LOCA = Location(1,1)
  POKE LOCA, ASC(K$)
 'The next statement causes "Internal error near 1AFB":
  POKE LOCA+1, ScreenAttrib(F,B)

 'Use of a temporary variable eliminates internal error, as follows:
   SA = ScreenAttrib(F, B)
   POKE LOCA+1, SA
 END


 181. Program Aborts after SHELL on COMPAQ 386/20, COMPAQ DOS 3.31

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q30860

 A program quits prematurely after executing a SHELL command if it is
 running under COMPAQ DOS Version 3.31. The problem has been duplicated
 only on a COMPAQ 386 running at 20-megahertz speed.

 The problem occurs both in the QB.EXE editor and in a compiled .EXE
 program.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS.

 To work around this problem, use an older version of COMPAQ DOS, such
 as Version 3.20.

 The following code example demonstrates the problem:

    PRINT "START"
    SHELL "DIR A:"
    PRINT "FINISH"
    END

 The above program executes the SHELL and then ends without printing
 "FINISH".

 Microsoft is researching this problem and will post new information
 here as it becomes available.


 182. FIX(N!*10^2) Gives Different Results in .EXE and QB.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q30880

 The following code example using the FIX function produces different
 results inside the QB.EXE environment and as an executable EXE file.
 Compiling the program with the BC /O compiling option and the debug
 (/d) option does not affect the results.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in the Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This
 problem has been corrected in the Microsoft BASIC Compiler Version
 7.00 (fixlist7.00).

 The following code example demonstrates the problem:

    N! = -21
    PRINT FIX(N! * 10 ^ 2)

 The following is a workaround for the problem:

    N! = -21
    PRINT FIX(N!) * 10 ^ 2


 183. Default Stack Size for QuickBASIC Versions 3.00 and 4.00

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 19-JUN-1989    ArticleIdent: Q31037

 In QuickBASIC Version 3.00, the default stack size is 768 bytes. In
 QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS and the BASIC
 compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, the default
 stack size is 2K (2048 bytes).

 You can increase the stack size by using the CLEAR statement. However,
 the CLEAR statement should be used with caution. For additional
 information regarding the CLEAR statement, please refer to the BASIC
 language reference manual.

 You can also use the LINK /STACK option to change the stack size in
 QuickBASIC Version 4.00, the BASIC compiler Version 6.00, and later
 versions. The LINK /STACK option does not affect available stack size
 in QuickBASIC Version 3.00 programs.

 In QuickBASIC 4.x and the BASIC compiler 6.00, PRINT FRE(-2) displays
 a size much smaller than 2K (e.g. 1000 to 1600 bytes) because a
 program uses the stack when it is running. The FRE(-2) function to
 report unused stack space is not available in QuickBASIC Version 3.00
 or earlier versions.


 184. "Save As" Fails after "Disk Not Ready" Error in QB.EXE

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  5-DEC-1989    ArticleIdent: Q31046

 If the disk-drive door is open during an attempt to Save As... without
 specifying the drive name in the dialog box, the QB.EXE editor will
 respond with a "Drive not ready" message. When the door is closed and
 Retry is selected, the save appears to complete normally. However, the
 file is written to the root directory of the hard drive rather than to
 the floppy.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the QuickBASIC version distributed with the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2
 (buglist6.00,buglist6.00b). This problem was corrected in QuickBASIC
 Version 4.50.

 This problem occurs after one save has been made to the floppy disk.

 If you believe you have completely lost a source file, check the root
 directory of the hard drive; it may have been saved there.

 This problem has been tested and does not occur in the following
 QuickBASIC Versions:

    QuickBASIC Versions 3.00, 2.01, and 2.00

 This problem does not apply to QuickBASIC Version 1.x.

 You can work around this problem by canceling the "Drive not ready"
 error box, rather than Retrying. This process will produce a "Bad file
 name" error. To eliminate this, do the following:

 1. Cancel the "Bad file name" box.

 2. Close the drive door.

 3. Attempt the save again.


 185. QB.EXE "Path/File Access Error" Running Out of File Handles

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31053

 When running a program in the QB.EXE editor, simultaneously OPENing
 more file handles than are allowed in DOS generates the error message
 "path/file access error." An "illegal function call" error message is
 then displayed if the Shell command from the File menu is used.

 To get the QB.EXE editor to work correctly again, type "CLOSE" in the
 immediate window to free the open file handles.

 Note that when you use DOS Version 3.30, you can perform an interrupt
 hex 21, function CALL hex 67, to obtain more than 15 DOS file handles
 available to BASIC programs.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to the QB.EXE editor in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to the QBX.EXE editor in Microsoft BASIC PDS
 Version 7.00 for MS-DOS.

 MS-DOS Versions 3.30 and later allow more than 20 files when you use
 the FILES=20 statement in the DOS CONFIG.SYS file; however, QuickBASIC
 only recognizes up to 20 files by default.

 Because QuickBASIC reserves the five default MS-DOS file handles for
 standard input/output, a program cannot OPEN more than 15 files at one
 time. If no FILES=N statement exists in the DOS CONFIG.SYS file, the
 default is FILES=8, which leaves three files for the program.

 QuickBASIC uses the following five files by default:

 1. Standard input: INPUT from the console (CON:) by default

 2. Standard output: PRINT to the console (CON:) by default

 3. Standard error messages: to the console (CON:) by default

 4. Standard list: LPRINT to the printer (PRN:) by default

 5. Standard auxiliary (AUX:) devices, that is, communication ports (COM1
    or COM2) or printer ports (LPT1 or LPT2)

 To work around the DOS file-handle limitation, do the following:

 1. Make sure your DOS CONFIG.SYS file on the root directory of your
    boot disk includes the following statement:

       FILES=20

 2. In BASIC programs, CLOSE each file before OPENing the next one.

 3. Do not simultaneously OPEN more than the number of files
    established in the CONFIG.SYS file, minus five for DOS. The maximum
    number of OPEN files is 15 when you specify FILES=20 in the
    CONFIG.SYS file.

 4. When using DOS Version 3.30, you can perform an interrupt hex 21,
    function CALL hex 67, to obtain more than 20 file handles available
    to BASIC. For more information, query on the following words in this
    database:

       67 and 3.30 and 21 and files

 The following code example demonstrates the QuickBASIC QB.EXE editor
 (or QBX.EXE editor from BASIC PDS Version 7.00) problem that occurs
 when you exceed the DOS file-handle limit:

 REM This program will exceed the file handle limit and cause an error.
 FOR i = 1 TO 20
 OPEN "z" + CHR$(i + 64) FOR RANDOM AS i
 PRINT i
 NEXT i
 CLOSE    ' This CLOSE statement is never reached.

 After running this program, you must type the CLOSE command in the
 immediate window, or else SHELL will give you an "Illegal Function
 Call" error.


 186. QB.EXE "Bad File Mode" Using Merge of Fast Load Format File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31057

 In the QB.EXE editor (or QBX.EXE editor from BASIC PDS Version 7.00),
 the Merge command on the File menu will generate a "Bad File Mode"
 error if the file being merged from the disk was saved in Fast Load
 format. The Merge command requires that the external file be in Text
 format.

 During a merge, it is acceptable to have a Fast Load format program
 currently loaded in the QB.EXE editor (or QBX.EXE from BASIC PDS
 Version 7.00); however, the file to be merged must have been saved in
 Text format, not in Fast Load format.

 This information also applies to the QuickBASIC QB.EXE editor that
 comes with Microsoft BASIC Compiler Version 6.00 or 6.00b for MS-DOS
 and MS OS/2 and to the QBX.EXE editor that comes with Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.


 187. FUNCTION+NUM LOCK Toggle Remaps Cursor Keys on Toshiba T1200

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31072

 The Toshiba T1200 computer is not officially supported by QuickBASIC.

 The dedicated cursor keys on the Toshiba T1200 may not work correctly
 with the QB.EXE Versions 4.00, 4.00b, and 4.50 editors, except as
 explained in a separate article in this database. For more
 information, query on the following words:

    Toshiba and dedicated

 You can obtain an alternative set of working cursor keys on the
 Toshiba T1200 by using FUNCTION+NUM LOCK as a toggle to activate a
 10-key keypad in the middle of the regular keyboard, as shown below.

 Also, according to Toshiba Product Support, the Toshiba T1200 comes
 with a program called SETUP1.EXE or SETUP12.EXE that has a 101-key
 installation option that makes the cursor keys behave normally (even
 though the Toshiba only has 84 keys). The Toshiba T5100 and Toshiba
 T3100 come with the program TEST3.EXE, which serves the same purpose.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to the QuickBASIC editor that comes with Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to the QBX.EXE
 editor that comes with Microsoft BASIC PDS Version 7.0 for MS-DOS and
 MS OS/2.

 When running QB.EXE (or QBX.EXE from BASIC PDS Version 7.00) on the
 Toshiba T1200, you can activate a 10-key keypad in the middle of the
 typewriter keyboard by holding down the FUNCTION key and pressing NUM
 LOCK. Subsequently pressing NUM LOCK alone switches between numbers
 and cursor functions. To return to typewriter mode, press FUNCTION+NUM
 LOCK again.

 The numeric keypad is mapped as follows:

    Typewriter Keys      Numeric       Cursor
    ---------------      -------       ------

    7  8  9              7  8  9       HOME   UP    PGUP

    U  I  O              4  5  6       LEFT   ----  RIGHT

    J  K  L              1  2  3       END    DOWN  PGDN

    M  ,                 0  .          INS    DEL   ----

 Selecting text and performing other cursor-oriented features of
 QuickBASIC Version 4.00 works correctly using the above regular
 keyboard keys as your keypad, instead of using the dedicated cursor
 keys.


 188. "Path/File Access Error"; OPEN FOR APPEND ACCESS WRITE

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31151

 A "path/file access error" message occurs when OPENing with FOR APPEND
 ACCESS WRITE.

 The error occurs because the designated file needs to be READ in order
 to be APPENDed. If the file is OPENed with ACCESS WRITE, READing
 privileges have not been provided.

 To eliminate the error message, omit the ACCESS clause or change
 ACCESS WRITE to ACCESS READ WRITE.

 This information also applies to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC PDS
 Version 7.00 for MS-DOS and MS OS/2.

 The following code example demonstrates this behavior:

 OPEN "test1.dat" FOR APPEND ACCESS WRITE as #1   ' Incorrect.
 ' OPEN "test1.dat" FOR APPEND ACCESS READ WRITE as #1   ' Correct.
 FOR k = 1 TO 100
         WRITE #1, "hello", k
 NEXT k
 close #1


 189. How to Add Routines to Quick Libraries (.QLB Files)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 11-JAN-1990    ArticleIdent: Q31156

 The following information describes how to add routines to Quick
 libraries (.QLB files) using their corresponding .LIB library files or
 their original .OBJ files.

 Microsoft recommends that a .LIB file be maintained for every .QLB
 file. Maintaining a .LIB file makes it easier to maintain a .QLB file
 and to identify the Quick library's contents. Note that QLBDUMP.BAS,
 provided on the QuickBASIC release disk, displays the contents of a
 .QLB Quick library.

 This article applies to QuickBASIC Versions 4.00, 4.00b and 4.50, to
 the QuickBASIC compiler that comes with Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to the QBX.EXE
 editor that comes with Microsoft BASIC PDS Version 7.00 for MS-DOS and
 MS OS/2.

 Note: The LIB.EXE library manager utility takes .OBJ and .LIB files as
 input arguments and outputs restructured .LIB library files.

 The LINK.EXE linker program takes .OBJ and .LIB files as input
 arguments and gives .QLB Quick library files for output if you use the
 LINK /Q option.

 The following are three different methods (Examples A, B, and C) for
 adding a routine to a Quick library:

 Example A is as follows:

 To add a routine (from any supported language) to a Quick library if
 the Quick library's matching .LIB library file is present, do the
 following:

 1. Suppose you have an object module, FOO.OBJ, that you wish to add to
    the Quick library OLDLIB.QLB. OLDLIB.QLB was previously created from
    OLDLIB.LIB.

 2. Add the .OBJ file (FOO.OBJ) to the .LIB library file. For example,
    the following line adds the routine FOO.OBJ to OLDLIB.LIB and outputs
    NEWLIB.LIB:

       LIB OLDLIB.LIB+FOO.OBJ,,NEWLIB.LIB;

 3. Do one of the following:

    a. Create a Quick library (.QLB) from the NEWLIB.LIB file. For
       example, the following line produces NEWLIB.QLB:

          LINK /Q NEWLIB.LIB,,,BQLB40.LIB;

       Note: BQLB40.LIB is required for QuickBASIC Version 4.00.
       BQLB41.LIB is required to make Quick libraries in QuickBASIC
       Version 4.00b (and later) or the QuickBASIC which comes with
       the BASIC compiler Version 6.00 or 6.00b. QBXQLB.LIB is
       required to make Quick libraries for the QBX.EXE editor, which
       comes with BASIC PDS Version 7.00.

    b. The following is an equivalent alternative to the step above
       that also outputs NEWLIB.QLB:

          LINK /Q OLDLIB.LIB+FOO.OBJ,NEWLIB.QLB,,BQLB40.LIB;

       (Don't forget step 2, or else your .LIB file will contain
       different routines than your .QLB file.)

 Example B is as follows:

 To add an .OBJ module (from any supported language) to a Quick
 library, do the following:

 1. Compile (into .OBJ form) the routines(s) that are to be added. For
    example, the following line invokes the Microsoft FORTRAN compiler
    to produce FORSUB.OBJ, a FORTRAN subprogram:

       fl /c FORSUB.FOR

 2. In the LINK command line, add together the desired .OBJ and/or .LIB
    files (such as FORSUB.OBJ, FOO.OBJ, and OLDLIB2.LIB) to create a
    Quick library. For example, the following outputs FOO.QLB:

       LINK /Q FOO.OBJ+FORSUB.OBJ+OLDLIB2.LIB,,,BQLB40.LIB;

    Note: BQLB40.LIB is required for QuickBASIC Version 4.00.
    BQLB41.LIB is required to make Quick libraries in QuickBASIC
    Version 4.00b or in the version of QuickBASIC that comes with the
    BASIC compiler Version 6.00 or 6.00b. QBXQLB.LIB is required for
    the QBX.EXE editor, which comes with BASIC PDS Version 7.00.

 Example C is as follows:

 To add a BASIC routine to a Quick library, you may do the following
 (this is not relevant for adding non-BASIC routines):

 1. Invoke QuickBASIC and load the Quick library to be updated. For
    example, the following line loads the Quick library OLDLIB.QLB:

       QB /L OLDLIB.QLB

 2. Load all the BASIC subprogram (or FUNCTION) procedures to be added
    to the Quick library by choosing Load File from the File menu.

 3. Choose the Make Library command from the Run menu. The library name
    specified must be different from the one that was loaded when
    invoking QuickBASIC. In addition, the .LIB file corresponding to
    the .QLB file must exist or a LINK error will occur. Both the .LIB
    and .QLB files specified will be updated automatically.


 190. Use PRINT# to MS-DOS "CON" Device to Send ANSI Escape Codes

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 22-JAN-1990    ArticleIdent: Q31157

 Sending ANSI escape codes to the screen with the PRINT statement will
 not perform ANSI screen control because the PRINT statement (in the
 products below) circumvents DOS and its device drivers.

 To make ANSI escape sequences work properly, you must OPEN the DOS
 "CON" or "CONS:" (console) device instead, and use PRINT# for output.

 This information applies to the following products:

 1. QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00,
    4.00b, and 4.50 for IBM Personal Computers and Compatibles

 2. Microsoft BASIC Compiler Version 6.00 and 6.00b for MS-DOS

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 4. GW-BASIC Versions 3.20, 3.21, 3.22, 3.23

 5. IBM and Compaq versions of BASICA

 To make ANSI control characters work properly, do the following:

 1. Obtain the file ANSI.SYS from the DOS release disk. Put it on the
    root directory of your boot disk.

 2. Put the statement DEVICE=ANSI.SYS in the CONFIG.SYS file on the
    root directory of the boot disk.

 3. Reboot. If the message "ANSI.SYS Not Found" displays, the ANSI
    control codes will not work.

 4. In your BASIC program, OPEN the DOS "CON" (console) device for
    output as #n.

 5. Use PRINT#n to send output to the DOS "CON" (console) device.

 6. CLOSE#n at the end of the program.

 For a list of the ANSI escape sequences, refer to the following:

 1. The "Microsoft MS-DOS Version 3.20 User's Reference," Appendix C
    "Installable Device Drivers"

 2. IBM PC-DOS technical reference manual

 The following code demonstrates how to use ANSI screen control codes
 from BASIC:

 'The following example changes the background
 'and foreground color of the screen, sets blinking and bold characters,
 'and positions the cursor:
 CLS
 escape$ = CHR$(27) + "["
 attriboff$ = escape$ + "0m"
 blinkon$ = "5m"
 bold$ = "1m"
 reversv$ = "7m"
 red$ = "41m"
 green$ = "42m"
 blue$ = "44m"
 blackback$ = "40m"
 x = 30
 y = 10
 rowcol$ = MID$(STR$(y), 2) + ";" + MID$(STR$(x), 2) + "H"
 OPEN "CON" FOR OUTPUT AS 1
 PRINT #1, attriboff$;
 PRINT #1, escape$ + rowcol$ + "Locate the cursor with ansi.sys"
 PRINT #1, attriboff$;
 PRINT #1, escape$ + blinkon$ + "Blinking" + attriboff$;
 PRINT #1, escape$ + bold$ + "Bold" + attriboff$;
 PRINT #1, escape$ + reversv$ + "reverse"
 PRINT #1, escape$ + red$ + "red"
 PRINT #1, escape$ + green$ + "green"
 PRINT #1, escape$ + blue$ + "blue"
 CLOSE #1


 191. LINK Error L1002 "Unrecognized Option Name"; SET LIB=C:\LIB

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q31158

 An error will occur if the LIB environment variable is improperly set
 using a forward slash (/) instead of a backslash (\) in the SET line
 in DOS.

 The following line is incorrect:

 SET LIB=C:/LIB

 The following line is correct:

 SET LIB=C:\LIB

 QuickBASIC Version 3.00 generates the LINK "unrecognized switch"
 error message when this problem occurs.

 QuickBASIC Versions 4.00, 4.00b, and 4.50, the BASIC compiler Versions
 6.00 and 6.00b for MS-DOS and OS/2, and Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2 generate the LINK error message L1002
 "Unrecognized option name" when this problem occurs.


 192. "Out of Data Space

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q31159

    When a program is running, each file OPENed with the OPEN statement
 takes up memory for the file buffer in DGROUP. If you specify a large
 record length (with the LEN= clause), a corresponding large space will
 be taken up in DGROUP.
    When OPENed file buffers consume all of DGROUP memory at run time,
 one of the following error messages will display:

 Version   In QB.EXE Environment     From .EXE Compiled Program

 3.00      "Out of memory"             "Out of memory in module"
 4.00      "Out of data space"         "Out of memory in module"
 4.00b     "Out of data space"         "Out of memory in module"
 4.50      "Out of data space"         "Out of memory in module"

    The Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
 OS/2 will behave like QuickBASIC Version 4.00b.
    To work around this problem, do the following:

    1. CLOSE each file before OPENing the next. Closing the file will
 free up the DGROUP memory that it used.
    2. Use the CLEAR command to CLOSE all files and erase all
 variables.
    3. Reduce the record length size (LEN=reclen) in the OPEN
 statement.
    4. Make numeric arrays $DYNAMIC instead of $STATIC. This will leave
 more space in DGROUP.

    The following code demonstrates the problem:

 CLS : CLOSE
 PRINT "Amount of available string space";FRE("")
 OPEN "z1" FOR RANDOM AS 1
 OPEN "z2" FOR RANDOM AS 2 LEN = 5000;
 OPEN "z3" FOR OUTPUT AS 3
 OPEN "z4" FOR OUTPUT AS 4 LEN = 5000
 OPEN "z6" FOR BINARY AS 6
 PRINT "Amount of available string space";FRE("")


 193. POINT(0) and POINT(1) Problem after VIEW and WINDOW

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q31160

 After a VIEW statement, the graphics functions POINT(0) and POINT(1)
 do not yield the expected results if a previous WINDOW statement has
 been executed with its x1 (minimum x) argument set to a number that is
 not an integral multiple of 0.5.

 For example, after executing a statement such as WINDOW
 (0.7,12.0)-(0.0,12.0) in any graphics screen mode, the coordinates
 returned by the POINT() functions will be relative to the upper-left
 corner of the screen, rather than to the viewport, as expected. This
 problem is dependent upon only the x1 argument; none of the other
 argument values cause this problem. The problem occurs both in the
 QB.EXE editor and in compiled EXE programs.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Version 6.00
 (buglist6.00) and the QB.EXE mode of Version 6.00b for MS-DOS and OS/2
 (buglist6.00b).

 This problem was corrected in QuickBASIC Version 4.50 (both compiled
 and QB.EXE) and under compiled mode of Microsoft BASIC Compiler
 Version 6.00b (fixlist6.00b).

 This problem does not exist in QuickBASIC Version 3.00.

 The POINT() function works correctly for x1 values that are integral
 multiples of 0.5.

 To recreate the problem, do the following:

 1. Set up a viewport in the center of the screen.

 2. Draw a box around the viewport.

 3. Define a logical coordinate system using any x and y values.

 4. Draw a line to the center of the viewport.

 5. Use POINT() functions to get the current physical coordinates.

 The following code demonstrates the problem:

 SCREEN 9
 PXMIN = 200
 PXMAX = 400
 PYMIN = 100
 PYMAX = 200
 VIEW (PXMIN, PYMIN)-(PXMAX, PYMAX)
 LINE (0, 0)-(PXMAX - PXMIN, PYMAX - PYMIN), , B

 XMIN = -.37   '<---(MULTIPLES OF 0.5 HERE YIELD CORRECT RESULTS)
 XMAX = 1    '      (OTHER REAL NUMBERS  GIVE DIFFERENT RESULTS)
 YMIN = 0
 YMAX = 1
 WINDOW (XMIN, YMIN)-(XMAX, YMAX)

 X = (XMIN + XMAX) / 2
 Y = (YMIN + YMAX) / 2
 LINE (XMIN, YMIN)-(X, Y)

 X = POINT(0)
 Y = POINT(1)
 LOCATE 20, 25: PRINT "POINT(0)="; X; " POINT(1)="; Y;
 LOCATE 21, 25: PRINT "CORRECT = 100            50"

 Given the source code above, the following is a workaround for this
 problem, using the POINT (2) and POINT(3) functions in place of the
 POINT(0) and POINT(1) functions:

 X = (POINT(2) - XMIN) * (PXMAX - PXMIN) / (XMAX - XMIN)
 Y = (POINT(3) - YMIN) * (PYMAX - PYMIN) / (YMAX - YMIN)
 LOCATE 22, 11: PRINT "(WORK AROUND) POINT(0)="; X; " POINT(1)="; Y;

 DO: LOOP UNTIL INKEY$ <> ""
 SCREEN 0
 END


 194. LINE INPUT Avoids INPUT Statement's "Redo from Start" Error

 Product Version(s): 1.00 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_BasicInt B_GWBasicI B_MQuickB
 Last Modified: 28-DEC-1989    ArticleIdent: Q31161

 To avoid the "Redo from Start" error message encountered when
 incorrect input is entered in response to an INPUT statement, use the
 LINE INPUT statement instead. (The INPUT statement's "Redo from Start"
 error message cannot be trapped or handled with the ON ERROR GOTO
 statement.)

 However, because LINE INPUT accepts all characters until it encounters
 a carriage return, you must parse the input string yourself using
 string manipulation (for example, MID$, INSTR) and type conversion
 (for example, VAL).

 This information applies to the following Microsoft retail BASIC
 products:

 1. Microsoft BASIC Compiler Versions 5.35, 5.36, 6.00, and 6.00b for
    MS-DOS

 2. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 3. Microsoft BASIC Interpreter Version 5.28 for MS-DOS

 4. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 5. Microsoft BASIC Interpreter Versions 1.x, 2.x, and 3.00 for the
    Apple Macintosh

 6. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 7. QuickBASIC Version 1.00 for the Apple Macintosh


 195. Selecting Text in QB.EXE with Dedicated Cursor Keys on Toshiba

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  8-NOV-1990    ArticleIdent: Q31163

 The dedicated-cursor (arrow) keys on the Toshiba T1200 laptop computer
 (and probably on other Toshiba laptop computers that have
 dedicated-cursor keys) may not highlight text in the QB.EXE editor in
 Microsoft QuickBASIC version 4.00, 4.00b, or 4.50 or in Microsoft
 BASIC Compiler version 6.00 or 6.00b. Some key combinations, different
 than those normal for an IBM, may be possible to use for selecting
 text on Toshiba laptop computers.

 The Toshiba laptop computers are not included in the list of systems
 on which Microsoft has tested QuickBASIC, and we make no claims for
 compatibility with Toshiba laptop computers.

 Because the keyboard supplied with the Toshiba T1200 is not identical
 to an IBM keyboard, you must use a different sequence of keystrokes to
 highlight text in the QuickBASIC editor.

 Instead of using the SHIFT+<arrow key> combination, which is used to
 highlight text on an IBM machine, you must use the Toshiba special
 FUNCTION key in conjunction with the SHIFT key and the appropriate key
 from the numeric keypad. For example, to move the cursor down and
 highlight text, use the following key combination:

    FUNCTION+SHIFT+Keypad 2

 These key combinations work correctly only for the T1200-series
 computers, which use the special Toshiba 101-key-style keyboards. In
 addition, a customer with a Toshiba T5100 Laptop 386 reported that
 pressing FUNCTION+SHIFT+K (where the K key has numeral 2 on its
 horizontal face) also highlights text. These combinations do not work
 for other Toshiba laptop computers with smaller keyboards. One
 customer reported that the combinations work for Sharp 4501 and 4503
 Portables.

 One customer reported that another way to select text on the Toshiba
 T1200 (or T1000) laptop is to use SHIFT+CTRL+<A, S, D, F, E, or X>.
 The A and F let you select words in the left and right direction
 respectively; the S and D let you select single characters in the left
 and right direction respectively; the E and X let you select lines up
 or down respectively. Microsoft has not confirmed or tested this
 information.

 It has been reported that a Toshiba T3100 had to use an add-on keypad,
 with NUM LOCK activated, to select text. The Toshiba T3100 comes
 standard with dedicated cursor keys that, the report says, will not
 select text. According to another report, SHIFT+CTRL+<A, S, D, F, E,
 or X> successfully selects text on a T3100e laptop, which has a gas
 plasma display. Microsoft has not confirmed this information.

 Another customer reported that on the Toshiba 1000, you can run the
 SETUP10 program, supplied by Toshiba, to configure for a 101-key
 keyboard. After this program is run, pressing FUNCTION+NUM LOCK
 toggles on or off the arrow keys' ability to highlight text. You don't
 need to hold down the SHIFT key while selecting text with the arrow
 keys when highlighting mode is on. Press FUNCTION+NUM LOCK again to
 toggle off the highlighting mode. Microsoft has not confirmed this
 information.


 196. SELECT, IF, FOR, DO, WHILE, CASE, and SUB Structure Errors

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-DEC-1989    ArticleIdent: Q31170

    A common programming error is to incorrectly close one type of
 control structure inside another. In many cases, you may get an error
 message that does not seem to apply. However, if you look more
 closely, you will find a structure in the program that was not
 properly closed.
    The following are errors that you can receive in QuickBASIC when
 you have improperly nested control structures:

    1. CASE               without SELECT
    2. ELSE               without IF
    3. IF                 without END IF
    4. END IF             without block IF
    5. FOR                without NEXT
    6. NEXT               without FOR
    7. DO                 without LOOP
    8. LOOP               without DO
    9. WHILE              without WEND
   10. WEND               without WHILE
   11. SELECT             without END SELECT
   12. SUB/FUNCTION       without END SUB/FUNCTION
   13. END SUB/FUNCTION   without SUB/FUNCTION

    If one of the above errors occurs, one of the following situations
 has occurred:

    1. A control structure has been opened but never closed.
    2. A control structure has been closed but never opened.
    3. A control structure has been closed outside of the block it
 controls.

    The following program demonstrates the problem:

 REM This program executes correctly and does not
 REM produce any error messages. However, the nature of
 REM the code is complex enough that it can easily lead to
 REM an improper error message if the control structures
 REM are not terminated properly. For example, deleting any
 REM line of this program causes a control structure error.

 SUB MySub
  SELECT CASE x
     CASE 1
        IF 0 THEN
          FOR i = 1 TO x
             DO
                WHILE 0
                WEND
             LOOP UNTIL 0
          NEXT i
        ELSE IF 0 THEN x = 1
        END IF
     CASE ELSE
  END SELECT
 END SUB


 197. Use ERASE to Reinitialize Array of User-Defined TYPE Records

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31172

 To reinitialize a user-defined record TYPE, each element has to be
 reinitialized independently. Reinitializing each element is a lengthy
 task if the record has hundreds of fields (for example, an application
 using user-defined record TYPEs with GET# and PUT# with random access
 files).

 To quickly reinitialize a record of a user-defined TYPE, make it an
 array and ERASE it when desired.

 This information also applies to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and OS/2 and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 If a variable is DIMmed as an array of user-defined TYPEs with one or
 more elements, it can be ERASEd.

 ERASE reinitializes all elements to null (zero). Remember that if an
 ERASEd array was declared as $DYNAMIC, it must be REDIMmed or DIMmed
 to redeclare it as an array.

 The following code demonstrates reinitialization for $STATIC and
 $DYNAMIC arrays:

 TYPE FileType
 Client AS STRING * 20
 Age AS INTEGER
 Sex AS STRING * 1
 END TYPE

 REM ********* If $STATIC:       **********
 DIM DataStatic(1) AS FileType
 REM  Assign and use user-defined TYPE elements as needed in this part of
 REM program:
 Datastatic(1).Client="Client Name"
 Datastatic(1).Age=33
 Datastatic(1).Sex="M"
 ERASE DataStatic  ' Sets Client, Age, and Sex elements back to null.

 REM ********* If $DYNAMIC:   **********
 REM $DYNAMIC
 DIM DataDynamic(1) AS FileType
 REM  Assign and use user-defined TYPE elements as needed in this part of
 REM program:
 Datadynamic(1).Client="Client Name"
 Datadynamic(1).Age=33
 Datadynamic(1).Sex="M"
 ERASE DataDynamic    ' Erases array.
 DIM DataDynamic(1) AS FileType    ' Dimensions array again.

 Note that adding the OPTION BASE 1 statement to the above program
 makes the arrays start at element 1 instead of element 0. This will
 save memory if you do not intend to use element 0 of the array.


 198. INPUT X% Statement Gives No "Type Mismatch" for d, e, !, or #

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 21-SEP-1990    ArticleIdent: Q31273

 A "Type Mismatch" error does not occur if the INPUT statement receives
 any of the following noninteger-type symbols in an integer variable:

 1. d (double-precision exponential)

 2. e (exponential)

 3. ! (single-precision exponential)

 4. # (double-precision exponential)

 Instead, a value of 0 (zero) is input. QuickBASIC automatically
 converts the noninteger-type symbol to zero (0) instead of giving a
 "Type Mismatch" error message.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler
 versions 6.00, 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS
 OS/2; in Microsoft BASIC Professional Development System versions 7.00
 and 7.10 for MS-DOS and OS/2 (buglist7.00, buglist7.10); and in
 Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23
 (buglist3.20, buglist3.22, buglist3.23) for MS-DOS. We are researching
 this problem and will post new information here as it becomes
 available.

 Note: The "Type Mismatch" error message occurs in the above products,
 except for BASIC PDS 7.00 and 7.10, if you input only a percent sign
 ("%", which marks integer constants) in response to INPUT for an
 integer variable. In BASIC PDS 7.00 and 7.10, a % is correctly input
 with a value of zero.

 The following code demonstrates the above problem:

 ' A value of zero is input if the following noninteger-type
 ' characters are input into an integer variable: d (double exponential),
 ' e (single precision exponential), !, and #
 INPUT "ENTER AN INTEGER ",i%
 PRINT i%
 END

 Additional reference words: B_GWBasicI B_BasicCom


 199. QB 4.00b/BC 6.00 Now Offers Global ON ERROR Handling

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q34404

 This article discusses global error trapping, which is found in the
 following products:

 1. QuickBASIC Versions 4.00b and 4.50

 2. Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2, and the
    accompanying QuickBASIC Version 4.00a

 3. Microsoft BASIC Compiler Version 6.00b for MS-DOS and OS/2, and the
    accompanying QuickBASIC Version 4.00b

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2

 Global error trapping is not found in QuickBASIC Version 4.00 or
 earlier versions, in which error trapping is local to each separately
 compiled module.

 The following explains how global error trapping works:

 In a multiple-module program, an ON ERROR GOTO 0 statement turns off
 error handling only in that module. Error handlers activated in
 modules at any higher procedure CALL level remain active, and will
 trap the error.

 This feature localizes the impact of error handling to each module.
 This allows software vendors to deliver .OBJ modules that trap errors
 for their modules only. An error handler in the main program will
 handle errors in linked modules if those modules do not trap errors
 themselves.

 This behavior of error trapping differs from QuickBASIC Versions 4.00
 and earlier, in which modules at a given procedure CALL level do not
 handle errors that originate in separately-compiled modules at deeper
 CALL levels.

 The following code example is composed of a main program that is
 linked to a separately compiled subprogram. Error trapping is set up
 and turned on in the main program, and the subprogram is called. The
 subprogram turns off error trapping locally, and then forces an error
 to occur.

 When compiled in QuickBASIC Versions 4.00 or earlier, the
 program aborts with the error in the subprogram. When compiled in
 QuickBASIC Version 4.00b or the BASIC compiler Version 6.00 or
 later, the error is trapped by the main program's error handling
 routine because of the global error handling feature described
 further below.

 '===== Main module: MAIN.BAS =====
 DECLARE SUB sub1 (a!)
 ' The main module's (global) error handler is turned on as follows:
 ON ERROR GOTO 500
 CALL sub1(10)
 PRINT "End of test program."
 END
 'Main/Global error handler:
 500 PRINT "in main"
 PRINT ERR
 RESUME NEXT

 ' ===== module 2: SUB1.BAS =====
 ' This module is in a separate file on disk.
 'Module 2's error handler at line 400 is not turned on.
 400 PRINT "in mod 2"
 PRINT ERR
 RESUME NEXT
 SUB sub1 (a)
     ON ERROR GOTO 0   'turns off local error handling in module 2.
     PRINT "error off"
     c = 10
     g = 0
     PRINT c / g       'forces a "division by zero" error
 END SUB

 The following information about global error handling was taken from
 the UPDATE.DOC file on the QuickBASIC Version 4.00b release disk:

 Enhanced Error Handling in QuickBASIC 4.00b and BASCOM 6.00
 -----------------------------------------------------------

 Microsoft QuickBASIC Version 4.00b includes an important new
 error-handling feature for multiple-module programs. See Chapter 6 of
 "Programming in BASIC: Selected Topics" for a thorough discussion of
 error handling and event handling.

 In previous versions of QuickBASIC, an error in a module that did not
 contain an error handler caused the program to terminate immediately,
 even if an error handler was present in a different module. QuickBASIC
 4.00b first looks for an active error handler in the module where the
 error occurred, then in the module that invoked that module, and so
 on. QuickBASIC follows the chain of procedure invocations back until
 it finds an active error handler or reaches the program's main module.
 If QuickBASIC cannot find an error handler by this process, the
 program terminates with an error message.

 However, please note that if the error occurs in an event-handling
 routine, QuickBASIC does not search for an error handler beyond the
 module that invoked the event handler.

 This feature affects the behavior of the RESUME statement. In previous
 versions of QuickBASIC, RESUME caused the program to resume execution
 at the "current statement," meaning the statement that caused the
 error. In a QuickBASIC 4.00b multiple-module program, however, the
 "current statement" is the last executed statement in the module
 containing the active error handler.

 The new error-handling feature has a similar effect on the ERL
 function. In QuickBASIC Version 4.00b, the program line that the ERL
 function identifies as the source of an error is the line that
 contains the last executed statement in the module where the active
 error handler is located.


 200. Cannot LOCK Portions of File OPENed with Binary Access File

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q31277

 The LOCK statement should lock entire files, certain records within a
 random access file, or certain bytes within a binary access file.

 The LOCK statement successfully locks records within a random access
 file. However, if certain bytes within a binary access file are
 locked, the whole file is locked as well. This causes a "Permission
 denied" error when trying to access any part of the binary access
 file.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem was
 corrected in QuickBASIC Version 4.50 and in the Microsoft BASIC
 Compiler Version 7.00 (fixlist7.00).

 To work around this problem, open binary files as random files with a
 buffer size of 1 (OPEN X$ FOR RANDOM LEN=1).

 Note: QuickBASIC Versions 3.00 and earlier do not offer binary access
 files; they offer only random and sequential access files.

 The following code example demonstrates the problem:

 ' The DOS 3.x SHARE.EXE utility must be executed before running this
 ' program. The following program creates a random file and a binary
 ' file. It opens each file under two different numbers. A record in
 ' the random file can be locked successfully, but the binary file is
 ' completely locked.

 OPEN "test4" FOR RANDOM AS #2 LEN = 11  'Open same file as #3 and #2.
 OPEN "test4" FOR RANDOM AS #3 LEN = 11
 OPEN "test5" FOR BINARY AS #1  'Open the same file as #1 and as #4.
 OPEN "test5" FOR BINARY AS #4
 FIELD #3, 6 AS lastname$, 5 AS firstname$
 FIELD #2, 6 AS lastname$, 5 AS firstname$
 LOCK #2, 1                      'Lock a record in #2, but not #3.
 LOCK #1, 30 TO 32               'Lock some bytes in #1, not in #4.
 '
 a$ = "Like as the waves make toward the pebbled shore" '
 b$ = "So do our minutes hasten to their end."

 '
 PUT #1, , a$                         'Put some lines into "test5".
 PUT #1, , b$
 LSET lastname$ = "Martin"            'Put some stuff into "test4".
 LSET firstname$ = "Steve"
 PUT #2, 1
 LSET lastname$ = "Henry"
 LSET firstname$ = "John"
 PUT #2, 2
 GET #2, 2                             'Gets both records OK as #2.
 PRINT firstname$; lastname$
 GET #2, 1
 PRINT firstname$; lastname$

 GET #3, 2                             'Can get this record OK as #3.
 PRINT firstname$; lastname$
 'GET #3, 1                    'This record is properly locked to #3.
 'PRINT firstname$; lastname$
 'The following gives "Permission denied" if any part is locked by #1:
 a$ = INPUT$(4, #4)
 PRINT a$
 UNLOCK #1, 30 TO 32
 UNLOCK #2, 1
 CLOSE


 201. FOR...NEXT with 32767 or -32768 Index Fails to Stop Unless /d

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-DEC-1989    ArticleIdent: Q37646

 If you use an integer for a FOR...NEXT loop counter, and the top of
 the loop is 32767 (when STEP is positive) or the bottom of the loop is
 -32768 (when STEP is negative), an overflow error will be correctly
 generated by QB.EXE or by the EXE compiled with /d. Without the /d,
 the loop does not stop at the top/bottom; it wraps around and executes
 indefinitely.

 The problem occurs because overflow checking is only done when /d
 compiler switch is specified.

 The following is a code example:

 This program never finishes the FOR NEXT loop when compiled without /d.

 DEFINT A-Z
 FOR X = 1 TO 32767
   IF X MOD 100 = 0 THEN PRINT X
 NEXT X


 202. A GOTO Inside SELECT CASE Incorrectly Executes ELSE Block

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  5-DEC-1989    ArticleIdent: Q31297

 In a compiled .EXE program, if a GOTO statement is executed inside of
 a SELECT CASE block, when that CASE is executed as expected, the CASE
 ELSE is also (wrongly) executed.

 However, the program behaves correctly when run in the QB.EXE editor.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in the Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in the Microsoft BASIC
 Compiler Version 7.00 (fixlist7.00).

 The following code example demonstrates this problem:

      x=1
      select case x
       case 1
        print "one"
        goto 100
 100:   print "hundred"
       case 2
        print "two"
       case else
        print "else"
      end select

 The (incorrect) output from the above program as an .EXE is as
 follows:

    one
    hundred
    else

 The (correct) output when run in the QuickBASIC environment is as
 follows:

    one
    hundred

 You can work around the problem of using GOTO and a label in a CASE by
 ending that CASE with a GOTO to a label that is after the END SELECT
 statement, as follows:

      x=1
      select case x
       case 1
        goto 100
        print "never prints"
 100:   print "hundred"
        goto 200   ' This GOTO is the workaround solution.
       case 2
        print "two"
       case else
        print "else"
      end select
 200: print "After END SELECT"


 203. Subscript Out of Range Can Hang .EXE without /d Debug Option

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-DEC-1989    ArticleIdent: Q31301

 In an .EXE program compiled without the debug option (BC /d), a
 reference to an out-of-range array element can hang the machine. This
 occurs only in a compiled .EXE program.

 The QB.EXE editor correctly reports the "subscript out of range" error
 because the debug option is automatically active by default.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
 OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The "subscript out of range" error message is documented on Page 501
 of the "Microsoft QuickBASIC: BASIC Language Reference."  The /d
 (debug) option is documented on Page 210 of "Microsoft QuickBASIC:
 Learning to Use."

 When a program is compiled with the BC /d (debug) option, the error
 will be reported at run time.

 If the following program is compiled to an .EXE file without the BC /d
 option, it will hang the machine at run time:

 DIM x$(3)
 OPEN "junk" FOR RANDOM AS 1 LEN = 200

 FOR i% = 0 TO 10
 FIELD 1, i% * 10 AS pad$, 10 AS x$(i%)
 NEXT i%

 FOR i% = 0 TO 10
 LSET x$(i%) = "fld " + STR$(i%): PRINT x$(i%)
 NEXT i%


 204. BASIC Example Using SETMEM to Allocate Far Heap Memory; EXEMOD

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31308

 To allocate a reserved location in memory that compiled BASIC will not
 touch, you can deallocate some memory by using the SETMEM function
 (see the BASIC language reference manual and the example for SETMEM
 below). Then, using either CALL INTERRUPT or CALL INT86OLD, execute a
 DOS interrupt &H21 (33), function &H48 (72). Call with AX = &H4800 and
 BX = the number of paragraphs of memory needed (the number of bytes of
 memory needed, divided by 16).

 This information applies to QuickBASIC Versions 4.00, 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft
 BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 If the function succeeds, the flag is clear and AX returns the initial
 segment of the allocated block.

 If the function fails, the flag is set and AX either is 7 (if memory
 control blocks were destroyed) or 8 (if memory was insufficient, in
 which case BX gives the size of the largest available block).

 Please note that QuickBASIC Versions 3.00 and earlier do not have the
 SETMEM function.

 The following are two other methods of allocating areas of memory:

 1. A static array can be set aside instead as a block of memory that
    will not move. The VARPTR function returns the offset of the array.

 2. The EXEMOD.EXE utility provided with the Microsoft Macro Assembler
    allows you to modify the header of an .EXE to shorten the maximum
    upper load address of a program. By default, BASIC .EXE programs
    assume that all of RAM is available. If you make the load address
    smaller, you must make sure that there is enough room for the
    BASIC program's code and data. Microsoft does not encourage using
    EXEMOD with compiled BASIC programs. The SETMEM function should be
    used instead.

 The following is a SETMEM code example:

 REM $INCLUDE: 'qb.bi'
 REM For BASIC PDS 7.00 include QBX.BI
 DEFINT A-Z
 DIM InRegs AS RegType, OutRegs AS RegType
 DIM InRegsX AS RegTypeX, OutRegsX AS RegTypeX

 PRINT SETMEM(-1808)     'Have QuickBASIC free up some memory.
 InRegs.ax = &H4800
 InRegs.bx = 113         'Allocates a block of 113 paragraphs, or 113*16 bytes
 CALL INTERRUPT(&H21, InRegs, OutRegs)

 'Check results of the interrupt call.
 IF (OutRegs.flags AND 1) = 0 THEN
      PRINT "Eureka!   Memory allocated at"; OutRegs.ax
 ELSEIF OutRegs.ax = 7 THEN
      PRINT "ERROR!  Memory control blocks destroyed!"
      END
 ELSE
      PRINT "Insufficient memory!  Largest available block is: "; OutRegs.bx
      END
 END IF

 'Now deallocate the memory we just allocated.
 InRegsX.es = OutRegs.ax
 InRegsX.ax = &H4900
 CALL INTERRUPTX(&H21, InRegsX, OutRegsX)

 'Double check the outcome of the interrupt call.
 IF (OutRegsX.flags AND 1) = 0 THEN
      PRINT "Memory successfully deallocated."
 ELSEIF OutRegsX.ax = 7 THEN
      PRINT "ERROR!  Memory Control Blocks destroyed!"
 ELSE
      PRINT "ERROR!  Incorrect segment in ES!"
 END IF


 205. How to Extract .OBJ Routines from .LIB Files Using LIB.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q31339

 The following steps will guide you when trying to extract .OBJ
 routines from QB.LIB, using the library manager LIB.EXE. QB.LIB is
 provided on the QuickBASIC release disk.

 The following information applies to QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 1. Get a cross-reference listing file of QB.LIB to identify the name
    of the routine to be extracted. You can do this by using the
    library manager LIB.EXE as follows:

    LIB QB.LIB,listfile;

    If "CON" is used as the name of the list file, then the listing
    file will appear on the screen. The listing for QB.LIB looks like
    the following:

    ABSOLUTE..........absolute          INT86OLD..........int86old
    INT86XOLD.........int86old          INTERRUPT.........intrpt
    INTERRUPTX........intrpt

    absolute          Offset: 00000010H  Code and data size: cH
      ABSOLUTE

    intrpt            Offset: 000000e0H  Code and data size: 107H
      INTERRUPT         INTERRUPTX

    int86old          Offset: 000002a0H  Code and data size: 11eH
      INT86OLD          INT86XOLD
      ABSOLUTE

    intrpt            Offset: 000000e0H  Code and data size: 107H
      INTERRUPT         INTERRUPTX

    int86old          Offset: 000002a0H  Code and data size: 11eH
      INT86OLD          INT86XOLD

 2. To extract one of the .OBJ routines, use the library manager
    command "*module-name", where module-name is the name of the .OBJ
    routine inside the library. The following is an example:

    LIB QB.LIB *intrpt;

    Once executed, a copy of intrpt will be placed in the working
    directory with the same name and .OBJ extension. Remember, the
    routines are listed in lowercase.

 For additional Library Manager command symbols refer to Page 231 of
 the "Microsoft QuickBASIC: Learning to Use" manual.

 The Library Manager (LIB.EXE) is provided with the QuickBASIC Compiler
 Versions 4.00 and later; however, it is not provided with QuickBASIC
 Versions 3.00 and earlier versions. LIB.EXE is also provided with the
 Microsoft Macro Assembler.


 206. "Duplicate Definition" on STATIC Array in Second CALL to SUB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31426

 In the following sources, the example of using the STATIC statement
 does not clearly explain what will happen with a second call to the
 SUB:

 1. Page 80 of the "Microsoft QuickBASIC 4.0: Programming in BASIC:
    Selected Topics" manual for Versions 4.00 and 4.00b

 2. Page 70 of the "Microsoft QuickBASIC: Programming in BASIC" manual
    for Version 4.50

 If SubProg2 is called more than once, the DIM statement gives you a
 "Duplicate Definition" error message. This is because in a recursive
 procedure, arrays are always dimensioned dynamically (that is, at run
 time), and making the array retain its values between calls (with the
 STATIC statement) means that the array was already dimensioned at the
 second call.

 The example should be changed as follows:

 1. Declare an additional STATIC variable as a flag.

 2. Put the DIM in an IF...END IF block that executes only upon first
    call to the routine, and not on subsequent calls, as determined by
    the flag variable.

 This correction also applies to the following:

 1. Page 80 of "Microsoft BASIC Compiler Version 6.00 for MS OS/2 and
    MS-DOS: Programming in BASIC: Selected Topics" for the BASIC
    compiler Versions 6.00 and 6.00b

 2. Page 66 of "Microsoft BASIC 7.0: Programmer's Guide" for Microsoft
    BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 Removing the array from the STATIC statement also eliminates the
 "Duplicate Definition."

 The following code demonstrates how to avoid the "Duplicate
 Definition" error:

 DECLARE SUB dummy ()
 PRINT "call the subroutine"
 CALL dummy
 PRINT "call the routine again"
 CALL dummy

 SUB dummy
 STATIC a(), FirstPassFlag   ' STATIC retains values between CALLs
 ' FirstPassFlag assures that array gets DIMensioned only once.
 IF FirstPassFlag = 0 THEN
    DIM a(1)
    FirstPassFlag = 1
 END IF
 print "continuing on"
 END SUB


 207. Making Screen MODE Such as CO40 Remain After Program Is Run

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-DEC-1989    ArticleIdent: Q31428

 Screen attributes set with the SHELL "MODE CO40" command do not remain
 changed upon exiting the environment or ending program execution
 because QuickBASIC stores the original screen settings before the
 program executes. When execution terminates, all screen attributes are
 restored to their original conditions.

 By using the ANSI.SYS escape codes, screen settings such as text
 colors and background colors can be changed. The following example
 demonstrates how to change to screen mode 40.

 If the program is run while inside the QuickBASIC Version 3.00
 environment, the screen is restored to its initial condition, even if
 ANSI calls are made. QuickBASIC Versions 4.00 and later keep the
 changes in or out of the environment if the screen mode is changed.

 The following steps let you utilize ANSI control codes:

 1. Put the statement DEVICE=ANSI.SYS in the CONFIG.SYS file on the
    root directory of the boot-up disk.

 2. Reboot.

 3. OPEN the CONsole as a device for output.

 4. Redirect the OUTPUT to the CONsole device.

 5. Send the ANSI codes to change the screen attributes.

 6. CLOSE the CONsole when done.

 The following code demonstrates this process:

 CLS
 escape$ = CHR$(27) + "["

 screen0$ = "0h"  ' 40 X 25 - characters black and white
 screen1$ = "1h"  ' 40 X 25 - characters color
 screen2$ = "2h"  ' 80 X 25 - characters black and white
 screen3$ = "3h"  ' 80 X 25 - characters color
 screen4$ = "4h"  ' 320 X 200 - pixels   black and white
 screen5$ = "5h"  ' 320 X 200 - pixels   black and white
 screen6$ = "6h"  ' 640 X 200 - pixels   black and white
 screen7$ = "?7h" ' wrap at end line ?

 OPEN "CON" FOR OUTPUT AS 1
 PRINT #1, escape$ + screen1$ + "Wow, 40 by 25"
 CLOSE 1


 208. Maximum Communications Baud Rate for QuickBASIC Is 9600

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 28-DEC-1989    ArticleIdent: Q31431

 The maximum baud rate that can used for communications in a QuickBASIC
 program is 9600.

 Valid baud rates for QuickBASIC in bits per second (BPS) are as
 follows:

    75, 110, 150, 300, 600, 1200, 1800, 2400, 4800, 9600

 The default baud setting is 300 BPS. This information applies to the
 following products:

 1. QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50

 2. The Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 3. The Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 4. The Microsoft GW-BASIC Interpreter Version 3.20


 209. Communications "Device Timeout": Increase CS and DS Time Limit

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q31432

    When you get run-time error 24, "device timeout," you need to
 specify a greater time limit for CS (Clear To Send) and DS (Data Set
 Ready) in the OPEN statement.
    The default for CS and DS is 1000 milliseconds or one second. This
 value can range from 0 to 65535. If zero is specified, the status is
 not checked.
    This information applies to all versions of QuickBASIC and to the
 Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2.
    The following code will give a device time-out error if Clear to
 Send or Data Set Ready are not detected after two seconds:

    OPEN "COM1:9600,N,8,1,CS2000,DS2000" AS #1


 210. $INCLUDE Forces Extra Linefeeds in Print from QB.EXE File Menu

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q31471

 When you choose the Print option from the QuickBASIC editor's File
 menu to print the source listing of a QuickBASIC program that uses the
 REM $INCLUDE metacommand, blank lines are appended to the end of the
 printed listing. The number of blank lines added corresponds to the
 number of lines in the included file.

 Microsoft has confirmed this to be a problem in QB.EXE in QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and in the QB.EXE in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2 (buglist6.00,
 buglist6.00b). This problem has been corrected in the QBX.EXE of the
 Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 The following are two ways to view this problem:

 1. Load only the program module that contains the REM $INCLUDE
    statement into the editor; do not load the included file. Next,
    select the Print...Current Module option from the File menu.

    In addition to the printing of the program, there will be blank
    lines added to the end of the listing, one blank line for each line
    in the include file.

 2. The same problem occurs if the include file is also loaded.
    Multiple blank lines will be inserted between the printout of the
    program module and the include file. In this case, the option
    Print...All modules is selected from the File menu.

 In either of these two cases, if the included lines are being viewed
 (i.e., the option Included Lines has been chosen from the View menu),
 the files are printed without the insertion of blank lines. Results of
 testing with previous versions indicate that blank lines are not
 inserted when the program is printed from the QuickBASIC Version 2.00
 or 3.00 editor.

 As a workaround, invoke the Included Lines option from the View menu
 prior to printing. The following is a code example:

    ' Program TEST.BAS
    REM
    REM
    REM
    REM $INCLUDE: 'TEST.INC'
    REM
    PRINT "all done"

    ' This is the included file TEST.INC

    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"
    PRINT "in the include file"


 211. In 4.00b, PEN(0) Returns Zero in QB.EXE or Compiled BC /V

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 24-MAR-1989    ArticleIdent: Q31484

 PEN(0) always returns a value of zero when used within the QuickBASIC
 Version 4.00b editor or in a program that was compiled with the BC /V
 option. This problem occurs in QuickBASIC Version 4.00b and in the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2
 (buglist6.00, buglist6.00b).

 A workaround is to compile the program with BC.EXE without the /V
 option.

 This problem was corrected by QuickBASIC Version 4.50.

 Results of testing with earlier versions show that the PEN
 function in QuickBASIC Version 4.00 causes the system to hang (query
 on PEN for a related article within this database).

 PEN(0) works properly in QuickBASIC Versions 3.00, 2.01, and 2.00.

 The following is a code example:

    CLS
    PEN ON
    WHILE INKEY$ = ""
       FOR i% = 1 TO 10000
       NEXT i%  'Delay loop for readability
       PRINT PEN(0)
    WEND


 212. Fixed-Length String Illegal in FIELD; QB.EXE Wrongly Allows It

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  7-SEP-1989    ArticleIdent: Q31506

 When you use a fixed-length string variable in a FIELD statement (to
 define the buffer for a RANDOM access file), the BC.EXE compiler
 correctly gives the error message "Variable-length string required."
 However, the QB.EXE editor fails to warn you against using a
 fixed-length string in FIELD statement, and the program runs and
 ignores the fixed-length string variable in the FIELD statement.

 Microsoft has confirmed this to be a problem in the QB.EXE editor in
 QuickBASIC Versions 4.00 and 4.00b. This problem was corrected in
 QuickBASIC Version 4.50 where the "Variable-length string required"
 error message correctly displays in the QB.EXE editor as well as when
 compiled with BC.EXE, when you attempt to use a fixed-length string
 variable in a FIELD statement.

 Please note that QuickBASIC Versions 3.00 and earlier don't have
 fixed-length strings.

 Code Example
 ------------

 When you use the first DIM statement in the program below, QB.EXE
 fails to give an error message on the FIELD statement, and "lastname"
 is treated as a variable not connected with the FIELD statement and is
 completely ignored in the FIELD statement. The same DIM correctly
 gives a "variable length string required" error when compiled with
 BC.EXE. The code example is as follows:

 DIM lastname AS STRING * 6  ' Fixed-length string in FIELD is not OK.
 'DIM lastname AS STRING     ' OK, since AS STRING is variable-length.
 OPEN "Hunkfile" FOR RANDOM AS #1 LEN = 10
 FIELD #1, 6 AS lastname, 4 AS firstname$
 LSET lastname = "Cruise"
 LSET firstname$ = "Tom"
 PUT #1, 1
 LSET lastname = "Gibson"
 LSET firstname$ = "Mel"
 PUT #1, 2
 CLOSE #1
 OPEN "hunkfile" FOR RANDOM AS #1 LEN = 10
 FIELD #1, 6 AS lastname, 4 AS firstname$
 GET #1, 1
 PRINT firstname$; lastname
 GET #1, 2
 PRINT firstname$; lastname
 CLOSE #1


 213. More Than 15 Files Open at Once in DOS Versions 3.30 and Later

 Product Version(s): m4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  4-SEP-1990    ArticleIdent: Q31509

 To open more than 15 files at once in a program under MS-DOS, you must
 do the following:

 1. Run under MS-DOS version 3.30 or later. (You can double-check the
    DOS version number with the VER command at the DOS prompt.)

 2. Add the statement FILES=n in the DOS CONFIG.SYS file.

 3. Call interrupt 21 Hex with function 67 Hex from the BASIC program,
    as shown in the example further below.

 4. If you are using the SHARE.EXE utility, you must also invoke
    SHARE/F:nnnnn to increase the area for file-sharing information
    above the default of 2048 bytes. Please refer to your MS-DOS manual
    for more information about the SHARE utility.

    The following is an example of using SHARE/F:

       SHARE/F:16384

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS.

 This technique will retain the file handle table size across a CHAIN
 for programs compiled without the BC /O option. Programs that are
 compiled with the BC /O (stand-alone .EXE) option and CHAINed will
 revert to the original file handle table size.

 Please note that even if you follow the above steps and specify
 FILES=255 in the DOS CONFIG.SYS file, you may not be able to access
 that many files at once in your program because there may not be
 enough memory available inside the DGROUP data segment to allocate
 file buffers. Also note that five file handles are taken up by the DOS
 standard input/output devices.

 We recommend that you use the BASIC SETMEM function to reduce the size
 of memory available to BASIC as it loads. This method ensures the
 provision of more memory available to the operating system; therefore,
 more files can be opened at the same time.

 To call the "Set handle count" interrupt, load 67 Hex into the AX
 register and load the number of desired handles in the BX register.
 Under MS-DOS 3.30, you must use an odd number ranging from 21 to 255
 for the number of desired handles, since even numbers may make the
 interrupt fail under MS-DOS version 3.30. This problem is corrected in
 MS-DOS version 3.30a, where you can use even or odd numbers for the
 number of desired handles when doing interrupt 67 Hex.

 The following is a BASIC code example of the DOS interrupt necessary
 to access more than 20 DOS file handles:

 ' $INCLUDE: 'qb.bi'
 ' For BASIC PDS 7.00 include QBX.BI
 DIM InRegs AS RegType, OutRegs AS RegType

 InRegs.ax = &H6700         'SetFileHandles function
 ' Value in BX register must be odd in DOS 3.30; odd or even in later
 ' DOS versions; ranging from 21 to 255:
 InRegs.bx = x              'x is the number of files to open
 CALL INTERRUPT(&H21, InRegs, OutRegs)

 FOR I% = 1 TO x - 5   '5 file handles are reserved for DOS standard I/O.
   File$ = "Junk" + STR$(I%)
   OPEN File$ FOR OUTPUT AS I%
   PRINT I%
 NEXT
 END


 214. Variable Passed to Dynamic SUB Changes after Integer Division

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  8-DEC-1989    ArticleIdent: Q31511

 When run from a compiled .EXE program, the dynamic subprogram below
 prints an incorrect value for a passed parameter after an unrelated
 integer division. The program runs correctly in the QB.EXE editor.

 Compiling the program with the BC /D (debug) option or the BC /O
 option does not correct the problem.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in the Microsoft BASIC
 Compiler Version 7.00 (fixlist7.00).

 The following is a code example of the subprogram:

 DECLARE SUB box (x!, y!)

 REM $DYNAMIC
 CLS
 CALL box(50!, 2!)

 REM $STATIC
 SUB box (x!, y!)
   PRINT "x! = "; x!
   lf = (70 - x!) \ 2
   dn = (20 - y!) \ 2
   PRINT "x! = "; x!  ' This line prints incorrect value from .EXE program.
 END SUB


 215. Passing Array of TYPE or Fixed-Length Strings to SUBprogram

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q31557

 An array of fixed-length strings cannot be passed directly as a
 parameter to a SUBprogram or FUNCTION procedure (that is, the phrase
 AS STRING*n cannot be used in DECLARE, SUB, or FUNCTION statements).

 The following are three alternatives for passing an array of
 fixed-length strings to a procedure:

 1. Pass the array of fixed-length strings through COMMON SHARED.
    (Please see Example 1 below.)

 2. Convert the array of fixed-length strings to an array of
    user-defined type and pass the array AS that type. (Please see
    Example 2 below or the TORUS.BAS sample program provided on the
    release disk.)

 3. Convert the array of fixed-length strings to an array of
    user-defined type and pass that array through COMMON SHARED. (Please
    see Example 3 below.)

 This information applies to QuickBASIC Versions 4.00, 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
 OS/2, and to Microsoft BASIC Professional Development System (PDS)
 Versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Note that when you pass a simple fixed-length string variable to a
 procedure, it is always converted to a variable-length string. Thus,
 the variable-length STRING type is allowed in DECLARE, SUB, and
 FUNCTION statements, but the fixed-length STRING*n type is not.

 The following is an example (Example 1) of how to pass an array of
 fixed-length strings through COMMON SHARED:

    DECLARE SUB TEST()
    DIM X(1 TO 30) AS STRING*22
    COMMON SHARED X() AS STRING*22
    X(5)="THIS IS A TEST"
    CALL TEST
    END
    SUB TEST STATIC
       PRINT X(5)
    END SUB

 The following is an example (Example 2) of how to pass an array of
 user-defined type as a parameter to a procedure:

    DECLARE SUB sub1 (t() AS ANY)
    TYPE foo
      y AS STRING * 10
    END TYPE
    DIM t(10) AS foo
    CALL sub1(t())
    PRINT t(1).y
    END
    SUB sub1 (t() AS foo)
      t(1).y = "test"
    END SUB

 The following is an example of how to pass an array of user-defined
 type through COMMON SHARED:

    TYPE FOO
      FIRST AS STRING*25
    END TYPE
    DIM AR(9) AS FOO
    COMMON SHARED AR() AS FOO, TEMP AS INTEGER
    AR(5).FIRST="This is fifth element"
    TEMP=99
    CALL TEST
    END
    SUB TEST STATIC
      PRINT AR(5).FIRST
      PRINT TEMP
    END SUB


 216. INKEY$ Cannot Input Bytes for CTRL-BREAK Keystroke

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q31571

 The manuals below incorrectly state that a stand-alone program
 compiled without the /d (debug) option can read a CTRL-BREAK keystroke
 with the INKEY$ function. The INKEY$ function does not return bytes
 for CTRL-BREAK under any circumstances. The incorrect sentence in the
 manual should be deleted.

 This correction applies to the INKEY$ function documentation in the
 following reference manuals:

 1. Page 298 of the "Microsoft QuickBASIC Compiler" Versions 2.x and
    3.00 manual

 2. Page 218 of the "Microsoft QuickBASIC 4.00: BASIC Language
    Reference"

 3. Page 218 of "Microsoft BASIC Compiler Version 6.00 for MS OS/2 and
    MS-DOS: BASIC Language Reference"


 217. QuickBASIC/MASM Programs in "PC Magazine" Incorrect

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31573

 The sample QuickBASIC and MASM programs discussed in "PC Magazine"
 October 13, 1987, on Pages 389-399 will not correctly work with
 QuickBASIC Version 4.00.

 The modified programs are as follows:

    === QP.BAS ===

    'QPrint.Bas - quick print demonstration for QuickBASIC

    Test$ = STRING$(20 * 80, "X")              'make a long string
    Colr% = 7
    LOCATE 1, 1
    CALL QPrint(Test$, Colr%)

    === QP.ASM ===

    ;QPRINT.ASM - performs Quick Printing in the QuickBASIC
    ;Note: Assemble this with MASM (2.00 or later)
    ;Copyright 1987, Ziff Communications Co.

    Code        Segment Byte Public 'Code'
                Assume  CS:Code
                Public  QPrint

    QPrint      Proc    Far

    Begin:      Push  BP         ;save registers for BASIC
                MOV   BP,SP      ;* ADD THIS LINE
                PUSH  DS         ;* ADD THIS LINE
                PUSH  ES         ;* ADD THIS LINE

                Mov   AH,3       ;specify BIOS service to read cursor position
                Mov   BH,0       ;on text page zero
                Int   10h        ;this service returns row/column in DH/DL

                Mov   AL,DH      ;put the current row number into AL
                Mov   CL,160     ;multiply by 160 to get start address of row
                Mul   CL         ;do the multiplication, answer ends up in AX
                Mov   DH,0       ;clear DH for the Add below, we only want DL
                Add   AX,DX      ;add the column once for the character byte
                Add   AX,DX      ;and once more for the attribute byte
                Mov   DI,AX      ;now DI holds starting address on the screen

                Xor   DX,DX      ;zero out DX to look at low memory using ES
                Mov   ES,DX
                Mov   BX,0B000h     ;assume the mono screen segment for now
                Mov   AL,ES:[463h]  ;look at the video controller port address
                Cmp   AL,0B4h     ;is it mono?
                JZ    Get_Params ;yes, skip over adding 800h to video segment
                Add   BX,800h    ;no, adjust BX for a color monitor
                Push  BX         ;and save it because the EGA test destroys BX

                Mov   AH,12h     ;specify EGA BIOS EGA special function servic
                Mov   BL,10h     ;request EGA information
                Int   10h        ;call the BIOS
                Cmp   BL,10h     ;if BL is still 10h, there's no EGA
                JNZ   EGA        ;it is an EGA, skip ahead
                Mov   DX,3DAh    ;not EGA, specify port to check for retrace

    EGA:        Pop   BX         ;get the video segment again

    Get_Params: ;* Mov   BP,SP   ;get stack pointer so you can find variables
                Mov   ES,BX      ;move whatever segment is correct into ES

                Mov   SI,[BP+06] ;get the color that was passed
                Mov   AH,[SI]    ;and put it into AH for screen writing below
                Mov   SI,[BP+08] ;put descriptor to X$ into SI
                Mov   CX,[SI]    ;put Len(X$) into CX for loop counter
                JCXZ  Exit       ;if CX is zero it's a null string, exit now
                Mov   SI,[SI+02] ;put address of first character in X$ into SI
                Cld              ;clear the direction flag to move data forwar

    Check_Mon:  Cmp   DL,0       ;are we on a mono or EGA system?
                JZ    Mono       ;yes, skip over the retrace stuff

    No_Retrace: In    AL,DX      ;get the video status byte from port number D
                Test  AL,1       ;test just the horizontal retrace bit
                JNZ   No_Retrace ;if doing a retrace, wait until it's not

    Retrace:    In    AL,DX      ;get the status byte again
                Test  AL,1       ;are we doing a retrace now?
                JZ    Retrace    ;no, wait until we are

    Mono:       Lodsb            ;get the character from X$ and increment SI
                Stosw            ;store both the character and attribute
                Loop  Check_Mon  ;loop until CX is zero

    Exit:       POP   ES         ;* ADD THIS LINE
                POP   DS         ;* ADD THIS LINE
                Pop   BP         ;restore BP for BASIC
                Ret   4          ;return skipping the passed parameters

    QPrint      Endp
    Code        Ends
                End   ;* remove this label Begin


 218. Explanation of Critical Error Codes Returned by ERDEV

 Product Version(s): 2.00 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891127-3  B_BasicCom B_GWBasicI
 Last Modified: 17-OCT-1990    ArticleIdent: Q57368

 ERDEV is an integer function that returns an error code from the last
 device to declare a critical error. ERDEV is set by the critical error
 handler, interrupt 24Hex, when DOS detects a critical DOS call error.

 For block and character device errors, ERDEV will contain the error
 code from interrupt 24Hex in the lower 8 bits. For block devices only,
 bit positions 9 to 16 contain device-attribute information which is
 found in the device-driver header of the device that the error is
 coming from.

 The above information applies to Microsoft GW-BASIC versions 3.20,
 3.22, and 3.23; to Microsoft QuickBASIC versions 2.00, 3.00, 4.00,
 4.00b, and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS; and to Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS.

 When using Microsoft BASIC PDS version 7.00 or 7.10 for MS-DOS, ERDEV
 can also be set by a time-out error on the communications port and
 indicates which option in the OPEN COM statement (CD, CS, or DS) is
 experiencing the time-out.

 If ERDEV returns an error from a block device (such as a floppy disk
 drive or fixed disk) or from a character device (such as a terminal or
 printer), the low byte of ERDEV will return the DOS error code, a
 value between 0 and 12. The following is a list of these errors:

     0  write-protect error
     1  unknown unit
     2  drive not ready
     3  unknown command
     4  date error (CRC)
     5  bad request structure length
     6  seek error
     7  unknown media type
     8  sector not found
     9  printer out of paper
    10  write fault
    11  read fault
    12  general failure
    13  reserved
    14  reserved
    15  invalid disk change (MS-DOS version 3.0 only)

 For more information on DOS error codes, see INT 24H on Page 481 of
 "Advanced MS-DOS Programming, 2nd Edition," by Ray Duncan (Microsoft
 Press, 1988).

 If the device returning an error is a block device, the high byte of
 the integer returned by ERDEV will contain device attribute
 information. This device attribute information comes from the
 device-attribute word in the device header. The only bits from this
 word returned by ERDEV are bits 15, 14, 13, XX, 3, 2, 1, and 0, in
 that order. XX indicates that bits 12 through 4 of the
 device-attribute word will always return zero. The following is a
 description of the bits in the device-attribute word that are
 meaningful to ERDEV:

      Bit
    Position   Bit     Significance
    --------   ---     ------------

       8       15      0 if block device
       7       14      1 if IOCTL read and write supported
       6       13      1 if BIOS parameter block in boot sector
                         should be used to determine media
                         characteristics
                       0 if media ID byte should be used
       4        3      1 if current CLOCK$ device
       3        2      1 if current NUL device
       2        1      1 if driver supports 32-bit sector addressing
                         (MS-DOS 4.00)
       1        0      1 if current standard input device (stdin)

 For more information on device-attribute words, see Page 264 of the
 "Advanced MS-DOS Programming" Microsoft Press book.

 When using BASIC PDS version 7.00, ERDEV also returns information for
 COM time-out errors in the low byte. If there is a time-out, ERDEV is
 set to a value that indicates the signal line that timed out,
 according to the following table:

    ERDEV Value    Signal Line
    -----------    -----------

       128         Clear to Send (CTS) timeout
       129         Data Set Ready (DSR) timeout
       130         Data Carrier Detect (DCD) timeout

 The following program lines generate the DOS and COM time-out error
 codes (low byte) and device attribute information (high byte):

    x= ERDEV
    DosErrCode = x AND &HFF            'Low byte of ERDEV
    DevAttr = (x AND &HFF00) \256      'High byte of ERDEV

 The following example prints the values of ERDEV after the program
 tries to OPEN a read only file for OUTPUT:

 Example
 -------

 DEFINT A-Z
 ON ERROR GOTO ErrorHandler
 OPEN "C:\TheFile.DAT" FOR OUTPUT A #1   'TheFile is a read-only
                                         'file
 END

 ErrorHandler:
    x = ERDEV
    DosErrCode = x AND &HFF              'low byte of ERDEV
    PRINT "The DOS error code returned by ERDEV => "; x
 RESUME NEXT


 219. Modified CALL INT86OLD Program

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 20-DEC-1989    ArticleIdent: Q31776

 A correction should be made to Page 88 of the following manuals:

 1. "Microsoft QuickBASIC 4.00: BASIC Language Reference"

 2. "Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2:
    BASIC Language Reference"

 In the CALL INT86OLD sample program on Page 88, the following line is
 incorrect:

    INARY%(DX) = SADD("FOO.TXT" + CHR$(0))

 The line should be changed to the following:

    temp$ = "FOO.TXT" + CHR$(0)
    INARY%(DX) = SADD(temp$)

 In QuickBASIC Versions 4.00 and later, and in Microsoft BASIC Compiler
 Version 6.00, the SADD function only ACCEPTs a string variable as an
 argument, not a string expression.

 If you try to run the CALL INT86OLD sample program in the QB.EXE
 Version 4.00 editor, the "Expected: variable" error message appears
 unless you change the program as shown above.

 In QuickBASIC Version 3.00, the SADD function can take a string
 expression as its argument. In QuickBASIC Versions 4.00 and greater,
 the SADD function only can take a string variable (i.e. a simple
 string variable, or a single element of a string array).

 The example on Page 88 is a revised version of a program on Page 149
 of the QuickBASIC Version 3.00 manual.


 220. Accessing Network-Locked File After Power Failure

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q31926

 If a file is opened and locked with the LOCK statement and the power
 is cut off, the file can still be accessed after rebooting the
 machine. However, the portion of the file that was written after the
 file was last closed will be lost. Microsoft cannot guarantee the data
 integrity of a file left open when there is a power failure; some of
 the data may become corrupt.

 This information applies to QuickBASIC Versions 4.00, 4.00b and 4.50,
 to Microsoft BASIC Compiler Version 6.00 and 6.00b for MS-DOS and MS
 OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.


 221. Inverse of x$ = HEX$(n) Is VAL("&H"+x$); Inverse for Octal...

 Product Version(s): 1,x 2.x 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_BasicInt B_MQuickB
 Last Modified: 21-DEC-1989    ArticleIdent: Q31783

 The HEX$(n) function converts a number n to a string in hexadecimal
 notation.

 To convert a hexadecimal-notation string (x$) back to a numeric value
 from x$ = HEX$(n), use VAL("&H" + x$).

 The OCT$(n) function converts a number n to a string in octal notation.

 To convert a octal-notation string (x$) back to a numeric value from
 x$ = OCT$(n), use VAL("&O" + x$).

 These formulas apply to any of the following Microsoft BASIC products:

 1. Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Version 5.35 and 5.36 for MS-DOS

 3. Microsoft BASIC Compiler Version 6.00 and 6.00b for MS-DOS and MS
    OS/2

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 5. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23 for
    MS-DOS

 6. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh

 7. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 8. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh


 222. "Overflow" Error in Intermediate Integer Calculation

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 17-JAN-1991    ArticleIdent: Q31785

 Microsoft BASIC compilers make certain compile-time assumptions about
 the numerical types of intermediate results in mathematical
 expressions. These assumptions can sometimes lead to an "overflow"
 error at run time.

 The information below applies to QuickBASIC versions 4.00, 4.00b, and
 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 As an example of this behavior, if you run the following program in
 QuickBASIC, you might expect the output to be 36,000; however, an
 "overflow" error displays instead:

    x& = 6 * 6000
    PRINT x&

 QuickBASIC sees that the "6" and the 6000 are both short integers
 (that is, integers between -32,768 and +32,767), so it assumes that
 the intermediate multiplication result should also be a short integer.
 However, an "Overflow" error results because 36,000 is not in the
 range of short integers.

 To force the intermediate expression to be calculated as a long
 integer, make the constants into long integers in the first
 calculations performed in that expression. For example, the following
 two statements work without any error:

    x& = 1& * 6 * 6000   ' 1. & suffix makes a constant a long integer.
    x& = CLNG(6) * 6000  ' 2. CLNG forces type to be long integer.

 Using 1& in the multiplication of 1& * 6 creates an intermediate long
 integer variable that forces the subsequent multiplication (* 6000) to
 be done using long integer.

 Note that 6 * 6000 * 1& fails with an "overflow" because the first
 multiplication is done as short integer. The calculation 6 * (6000 *
 1&) avoids this "Overflow" error by changing the order of calculation
 so that a long integer intermediate variable is created before
 multiplying by the 6.

 Integer Data Type Notation Standards for BASIC
 ----------------------------------------------

 Note that the number 6 is the same as 6%, and 6000 is the same as
 6000% in BASIC's short integer notation. Appending the percent (%)
 symbol to a constant makes it explicitly a short integer. Appending
 the ampersand symbol (&) to a constant makes it explicitly a long
 integer. Constants whose types are not explicitly declared will
 default as shown in Chapter 2, "Data Types," of the BASIC language
 reference manual for QuickBASIC versions 4.00 and 4.00b, and Microsoft
 BASIC Compiler version 6.00 and 6.00b for MS-DOS and MS OS/2. This
 information is also found in Appendix B of the "Microsoft BASIC 7.0:
 Programmer's Guide" manual for BASIC PDS 7.00 and 7.10.


 223. QB.EXE Editor Printing Source Code to 132-Column Printers

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q35146

 To make the Print command on the QuickBASIC editor File menu default
 to 132 columns instead of 80 columns, you can issue the following DOS
 command:

    MODE LPT1:132

 You can reset the printer to 80 columns by executing the following DOS
 command:

    MODE LPT1:80

 This information applies to the QB.EXE editor in Microsoft QuickBASIC
 Compiler Versions 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to the QBX.EXE
 editor that comes with Microsoft BASIC PDS Version 7.00 for MS-DOS and
 MS OS/2.


 224. IF <expression> THEN NEXT / THEN WEND Not Supported

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q31787

 You cannot conditionally execute NEXT and WEND statements using the
 single-line IF...THEN...ELSE statement.

 The following two syntax examples, which are supported by GW-BASIC and
 QuickBASIC Version 2.01 and previous versions, are not supported by
 QuickBASIC Versions 3.00 and later:

    IF <boolean expression> THEN NEXT

    IF <boolean expression> THEN WEND

 Using this illegal syntax will give the following error message at
 compile time:

    "NEXT without FOR" or "WEND without WHILE"

 This situation is documented in the following manuals:

 1. Page 272 of the "Microsoft QuickBASIC 4.00: Learning and Using"
    manual.

 2. Page 272 of the "Microsoft BASIC Compiler Version 6.00 for MS-DOS
    and OS/2: Learning and Using QuickBASIC"

 3. Gray Page Update-57 of the "Microsoft QuickBASIC Version 3.00
    Update" manual.


 225. INITCB Correction Passing BASIC COMMON Block to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q31788

 CDECL is missing from the DECLARE statement in the BASIC source code
 example. The code segment should be changed to read as follows:

   '     BASIC SOURCE CODE
   '
             COMMON /Cblock/ n%, x#, y#
             DECLARE SUB INITCB CDECL (n%)
   .
   .
   .

 The correction above applies to Page 317 of the following manuals:

 1. "Microsoft QuickBASIC 4.00: Learning and Using"

 2. "Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2:
    Learning and Using Microsoft QuickBASIC"


 226. Converting between Decimal, Octal, and Binary Numbers

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_GWBasicC B_BasicInt B_BBasic
 Last Modified: 21-DEC-1989    ArticleIdent: Q31789

 The Microsoft BASIC code below demonstrates how to perform the
 following conversions between decimal, octal, and binary numbers:

 1. Convert an octal number to a decimal (base 10) number

 2. Convert a decimal number to an octal (base 8) number

 3. Convert a decimal number to a binary (base 2) number

 The following code example will perform the conversions:

 ' 1. Octal string to decimal Number:
 INPUT "INPUT Octal number:"; octal$
 PRINT VAL("&O" + octal$)

 ' 2. Decimal Number to octal string:
 INPUT "INPUT Decimal number:"; Decimal
 PRINT OCT$(Decimal)

 ' 3. Decimal Number to Binary string:
 Bin$ = ""
 INPUT "INPUT Decimal number:"; Decimal
 FOR i = 14 TO 0 STEP -1           ' Positive numbers only
   pow2 = 2 ^ i
   IF Decimal >= pow2 THEN
      Decimal = Decimal - pow2: Bin$ = Bin$ + "1"
   ELSE Bin$ = Bin$ + "0"
   END IF
 NEXT i
 PRINT Bin$

 The above information applies to most Microsoft BASIC products,
 including the following BASICs:

 1. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 2. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh

 3. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b and 4.50 for the IBM PC

 4. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 5. Microsoft BASIC Compiler Version 6.00 for MS-DOS and MS OS/2

 6. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 7. Microsoft GW-BASIC Interpreter Version 3.20

 8. Microsoft BASIC Compiler and Interpreter for the XENIX Operating
    System


 227. Structured Programming in Microsoft QuickBASIC - Modules

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 20-DEC-1989    ArticleIdent: Q31821

 Easy modular programming is possible with Microsoft QuickBASIC by
 using separately compiled modules. BASIC programs no longer have to be
 developed as one large program; they can be written as separate,
 functionally grouped sets of subroutines that can be used in other
 programs.

 A module consists of an optional "main program" and a set of
 subprogram procedures. Data can be passed between linked modules by
 using subprogram parameters or named COMMON SHARED blocks. The named
 COMMON SHARED statement allows different groups of variables and
 arrays to be shared among the various modules in a single program. An
 example of a common block named GRAF3D is shown below:

    DIM TRANSFORM3D(3,3) 'static array passed in COMMON
    COMMON SHARED /GRAF3D/ CURX, CURY, CURZ, TRANSFORM3D()

 The SHARED attribute of the COMMON statement shares that COMMON among
 all subprogram procedures in that particular module. The variables in
 a COMMON without the SHARED attribute are only available at the main
 program level.

 An unnamed (blank) COMMON statement can pass information between
 CHAINed programs. (Named COMMON blocks are not carried across when you
 CHAIN to another QuickBASIC .EXE program.)

 Subprograms, separate compilation, COMMON blocks, and program CHAINing
 make Microsoft QuickBASIC a useful language for developing large
 application systems.


 228. Structured Programming in QuickBASIC - Subprograms; SHARED

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 30-JUN-1989    ArticleIdent: Q31822

 Microsoft QuickBASIC for MS-DOS provides structured programming
 features that exceed BASICA's FOR/NEXT, WHILE/WEND, and GOSUB
 statements. True subprograms with scalar and array parameters are easy
 to use in QuickBASIC. All variables in subprograms are local unless
 they are declared as shared-global variables in the current module, as
 shown in the following example:

          bubbles = 10
          CALL MySort (howbig, Array())     'sort Array()
          END

          SUB MySort (limit, Sieve()) STATIC    'Sieve is 1-dim
          SHARED bubbles               'global variable
            ...  ' MySort subprogram body
          END SUB

 Note that the SHARED statement does not share variables across
 separately-compiled modules, it only shares with the main program
 level ("module level") of the current module. To share variables
 across separately-compiled modules, you must use the COMMON SHARED
 statement.


 229. Simplified Language for Compilers' Run-Time License Agreement

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_MQuickB B_BasicCom B_COBol
 Last Modified: 21-DEC-1989    ArticleIdent: Q31878

 As of June 1988, Microsoft offers the run-time license agreement shown
 below for its language compilers, including the following:

 1. QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for the
    IBM PC and compatibles

 2. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS, and
    Versions 6.00 and 6.00b for MS-DOS and MS OS/2

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 4. QuickBASIC Version 1.00 for the Apple Macintosh

 5. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 6. Microsoft COBOL Compiler Versions 2.00, 2.10, 2.20 for MS-DOS;
    Versions 3.00 and 3.00a for MS-DOS and MS OS/2; and Versions 2.10
    and 2.20 for XENIX

 The agreement allows you to distribute your programs on a royalty-free
 basis.

 You can read this agreement on the back of the "break-the-seal" disk
 envelope (paragraph number 2) for the compiler. The agreement reads as
 follows:

    DISTRIBUTION OF RUNTIME MODULES: Microsoft grants to you a
    royalty-free right to reproduce and distribute the runtime modules
    of the COMPILER provided that you: (a) distribute the runtime
    modules only in conjunction with and as a part of your own software
    product; (b) do not use Microsoft's name, logo, or trademarks to
    market your software product; (c) include Microsoft's copyright
    notice for the COMPILER on your product label and as part of the
    sign-on message for your software product; and (d) otherwise comply
    with this Agreement. The "run-time modules" are those files in the
    COMPILER that are identified in the documentation as required
    during execution of your compiled program. The runtime modules are
    limited to runtime files, install files, and ISAM and REBUILD
    files.

 If you are interested in receiving a complete copy of the latest
 run-time license agreement, contact the Microsoft Information Center
 by calling (800) 426-9400 or (206) 882-8088.


 230. DATA Statements Not Allowed in SUB or FUNCTION Procedures

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q31882

 The DATA statement should be included in the list of statements
 prohibited in procedure-level code on Page 50 of the following
 manuals

 1. "Microsoft QuickBASIC 4.0: Programming in BASIC: Selected Topics"

 2. "Microsoft BASIC Compiler 6.0: Programming in BASIC: Selected
     Topics"

 3.  Page 41 of the "Microsoft BASIC 7.0: Programmer's Guide"
     manual.

 The DATA statement documentation on Page 135 in the BASIC language
 reference manual correctly states that "DATA statements can only be
 entered in the module-level code."

 A module is defined as an individual source file, but "module level"
 is a special term with a different meaning. The glossary on Page 350
 of the "Microsoft QuickBASIC 4.0: Learning and Using QuickBASIC"
 manual defines "module-level code" as follows:

    (Module-level code is defined as) program statements within any
    module that are outside a SUB or FUNCTION definition. Error- or
    event-handling code and declarative statements such as COMMON,
    DECLARE, and TYPE can appear only at the module level.


 231. ON <Event> GOSUB Suspended Until INPUT or INPUT$ Is Satisfied

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_GWBasicC B_MQuickB B_BasicInt
 Last Modified:  8-NOV-1990    ArticleIdent: Q31885

 Execution of event trapping GOSUB routines is suspended in BASIC until
 an INPUT or LINE INPUT statement or INPUT$ function is satisfied.
 Events suspended during INPUT, INPUT$, or LINE INPUT include the
 following:

 1. ON TIMER(n) GOSUB
    (found in many Microsoft BASICs, including GW-BASIC, QuickBASIC
    for MS-DOS, and QuickBASIC for Macintosh)

 2. ON KEY(n) GOSUB
    (found in QuickBASIC and GW-BASIC for MS-DOS, but not in QuickBASIC
    for Macintosh)

 3. ON DIALOG GOSUB, ON MENU GOSUB, and ON MOUSE GOSUB
    (found in QuickBASIC for the Apple Macintosh, but not in QuickBASIC
    for MS-DOS)

 The suspending of event GOSUBs during INPUT, INPUT$, or LINE INPUT is
 an intentional design requirement and occurs in all Microsoft BASIC
 products that support event trapping, including the following
 products:

 1. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for MS-DOS

 2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS

 3. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2

 4. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23 for
    MS-DOS

 5. Microsoft QuickBASIC version 1.00 for the Apple Macintosh

 6. Microsoft BASIC Compiler version 1.00 for the Apple Macintosh

 7. Microsoft BASIC Interpreter versions 2.00, 2.10, and 3.00 for
    the Apple Macintosh (Event trapping is not supported in Microsoft
    BASIC Interpreter versions 1.00 and 1.01 for the Apple Macintosh.)

 Suppose you write a program with ON TIMER(5) GOSUB so that every five
 seconds a message is displayed on the screen. If an INPUT$ function or
 INPUT or LINE INPUT statement is executed that expects a value from
 the keyboard, the ON TIMER(5) GOSUB will not execute until the ENTER
 key is pressed to terminate the input. Only one TIMER event is
 remembered on the stack, no matter how much time passed during the
 INPUT$, INPUT, or LINE INPUT. An example of this event suspension is
 demonstrated in Program 1 below.

 If you want to trap events and also input from the keyboard, you can
 poll the INKEY$ function as shown in program 2 below instead of using
 INPUT$, INPUT, or LINE INPUT. The INKEY$ function returns one key
 press at a time, and allows event GOSUB traps to occur between
 invocations.

 BASIC checks between statements to see if an event has occurred. When
 the INPUT$, INPUT, or LINE INPUT executes, execution of the ON event
 GOSUB statement is suspended until the INPUT$, INPUT, or LINE INPUT is
 satisfied. This behavior is intentional and occurs in all Microsoft
 BASIC products that support event trapping.

 If you are using ON KEY(n) GOSUB to trap keys (in GW-BASIC or
 QuickBASIC for MS-DOS), only one key press during INPUT$, INPUT, or
 LINE INPUT will be remembered on the stack for a given defined KEY, no
 matter how many times that key is pressed. This behavior is by design
 (to prevent stack overflow).

 The following are code examples:

 Program 1
 ---------

 The following program shows that ON TIMER(n) GOSUB waits while the
 INPUT statement is pending:

    REM  Program 1, using the INPUT statement.
    ON TIMER(5) GOSUB MESSAGE     ' TRAP EVERY 5 SECONDS
    TIMER ON
    INPUT X$   ' NO GOSUB IS DONE UNTIL THIS INPUT IS SATISFIED.
    FOR I=1 TO 2000
     PRINT X$
    NEXT
    END
    MESSAGE:
        PRINT " FIVE SECONDS "
        RETURN

 Program 2
 ---------

 The following program polls the INKEY$ function for INPUT and lets the
 ON TIMER(5) GOSUB statement successfully perform the TIMER event trap
 every five seconds:

    REM  ********   Program 2, using the INKEY$ function.
    ON TIMER(5) GOSUB MESSAGE          ' TRAP EVERY 5 SECONDS
    TIMER ON
    CLS
    MOREIN:
       A$ = INKEY$
       IF A$ = "" GOTO MOREIN
       IF A$ = CHR$(13) GOTO DONE   'Input until ENTER key is pressed.
       X$ = X$ + A$: J = J + 1
       PRINT A$;
       IF J > 79 THEN PRINT "Exceeded 79 characters.": GOTO DONE
    GOTO MOREIN
    DONE:
        PRINT
        FOR I = 1 TO 2000
          PRINT X$
        NEXT
        END
    MESSAGE:
        PRINT " FIVE SECONDS "    ' DISPLAY MESSAGE AFTER 5 SECONDS.
        RETURN

 Note: The following Microsoft BASIC products do NOT support event
 trapping features, such as ON TIMER(n) GOSUB or ON KEY(n) GOSUB:

 1. Microsoft Business BASIC Compiler versions 1.00 and 1.10 for
    MS-DOS

 2. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS


 232. Underlining on Monochrome Display with POKE or INTERRUPT &H10

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q31886

 The easiest way to display underlined text on a monochrome display is
 by using the COLOR statement in SCREEN 0.

 Another method is to POKE screen attributes directly into monochrome
 video memory, which starts at address hex B000.

 A more complicated way to produce underlined screen output on a
 monochrome display from QuickBASIC is to invoke BIOS INTERRUPT hex 10,
 function 9, which displays a character with a specified attribute at
 the current cursor position. An example is shown below. A disadvantage
 of this service is that you must increment the cursor yourself, since
 function 9 does not increment the cursor. Refer to the entry for CALL
 INTERRUPT in the BASIC language reference manual for more information.

 This information applies to QuickBASIC Versions 4.00, 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (in real mode), and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS and OS/2 (in real mode).

 You can use the COLOR statement on SCREEN 0 on a monochrome monitor to
 easily generate text with different attributes, such as underlined,
 bold, and blinking. The following are two additional (more
 complicated) methods (1 and 2) to underline characters on a monochrome
 monitor in SCREEN 0:

 Method 1
 --------

 The following method lets you POKE monochrome attributes directly
 into monochrome video memory

 SCREEN 0
 DEF SEG=&HB000
 POKE (ROW*160)+(2*COLUMN)+1,ATTRIBUTE

 where ATTRIBUTE can be as follows:

 Effect                      ATTRIBUTE     Equivalent COLOR Statement
 ------                      ---------     --------------------------

 White on black (normal)        7              COLOR 7,0
 Black on black (no display)    0              COLOR 0,0
 Black on white (reverse)     112              COLOR 0,7
 Underline                      1              COLOR 1,0
 Intense                       10              COLOR 10,0
 Blinking                     130              COLOR 18,0
 Reverse blinking             240              COLOR 16,7
 Intense underline              9              COLOR 9,0
 Intense blinking             138              COLOR 26,0
 Underline blinking           129              COLOR 17,0
 Intense blinking underline   137              COLOR 25,0

 Method 2
 --------

 The following program CALLs INTERRUPT &H10, function 9 to underline a
 character output to the screen. To use this program, do the following:

 1. Invoke QuickBASIC by typing the following:

       QB /L QB.QLB
    or
       QBX /L QBX.QLB

    for BASIC PDS Version 7.00. (This procedure will also access the
    QB.QLB Quick library, which has the CALL INTERRUPT routines.)

 2. QB.BI must be used in the $INCLUDE metacommand (see below). QB.BI
    contains the user-defined types RegTypeX and RegType. Refer to the
    QB.BI text file for more information. For BASIC PDS 7.00 this file
    is called QBX.BI.

 3. If you are compiling and linking outside the environment, QB.LIB
    must be linked in. For BASIC PDS 7.00, you must link in QBX.LIB.

 This program allows a character to be printed to the screen at the
 location of the cursor by CALLing a subprogram named PrintUnderline.
 The character and the row and column position of the cursor are passed
 so the cursor can be updated (that is, moved one place to the right of
 the current position).

 The following is a code example of using hardware interrupts:

 DECLARE SUB PrintUnderline (char$, col!, row!)
 ' $INCLUDE: 'qb.bi'
 ' For BASIC PDS you must include 'qbx.bi'
 DIM SHARED inregs AS RegType, outregs AS RegType
 CLS
 col = 1: row = 1                     'current position of the cursor
 CALL PrintUnderline("a", col, row)   'CALL the subprogram with parameters
 END

 REM Subprogram PrintUnderline prints the underlined char$ to the screen at
 REM position col and row. Then the cursor is updated.
 REM
 SUB PrintUnderline (char$, col, row)
 inregs.ax = &H900 + ASC(char$)    'function 09 in the high part of the
                   'register and the ASCII code of char$ in the low part
 inregs.bx = &H1   'display page (0 is the current page) in the high part
                   'and the attribute (1 is underlined) in the low part
 inregs.cx = &H1   'number of times to display the character (1 in this case)
 CALL INTERRUPT(&H10, inregs, outregs)
 LOCATE row, col + 1  'relocate the cursor one place to the right for every
                      'character written to the screen
 END SUB


 233. How to Nest User-Defined TYPE Declarations in Compiled BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q31911

 The following is an example of how to nest user-defined type
 declarations. An element inside a TYPE...END TYPE declaration can be
 declared with a user-defined type.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 Code Example
 ------------

 ' Declare one type as follows:
 TYPE foo
   x AS INTEGER
   y AS STRING * 5
 END TYPE
 ' Declare an element of the following type with the above type (foo):
 TYPE txx
   n AS foo
 END TYPE
 ' Dimension variables with the nested type (txx):
 DIM t(10) AS txx
 DIM k AS txx
 ' Elements of the nested type variables can be used as follows:
 k.n.x = 3
 t(1).n.y = "test"
 PRINT k.n.x
 PRINT t(1).n.y


 234. I/O to a File OPENed as "NUL" or "NUL.xxx" Does Nothing

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_GWBasicC
 Last Modified: 21-DEC-1989    ArticleIdent: Q31939

 BASIC will allow input from or output to the DOS null device, which is
 a file named "NUL" or "NUL.xxx" (where "xxx" can be any set of none,
 one, two, or three alphanumeric letters). The DOS null device is
 always empty when you input from it and is never created on disk when
 you write to it.

 This information applies to the following products:

 1. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Version 6.00 for MS-DOS and MS OS/2

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2

 4. Microsoft GW-BASIC Interpreter Version 3.20

 The DOS command TYPE NUL will display nothing. The DOS command DIR NUL
 will give a "File Not Found" error. The DOS command COPY EXISTING.FIL
 NUL, which copies an existing file to the NUL device, will do nothing.

 The following program writes to and reads from a file called
 "NUL.DAT", which has been opened with random access. The file is never
 created on the disk, and nothing is retrieved from the file or printed
 on the screen:

 ' If you modify the OPEN statement to open a filename other than "NUL.xxx"
 ' or "NUL", then "the very first recor" and "the second record is" will
 ' display on the screen:
 CLS
 OPEN "NUL.DAT" FOR RANDOM AS #1
 FIELD #1, 20 AS Var1$
 LSET Var1$ = "the very first recor"
 PUT #1, 1
 LSET Var1$ = "the second record is"
 PUT #1, 2
 GET #1, 1
 PRINT Var1$
 GET #1, 2
 PRINT Var1$

 The following program, which inputs from a sequential access file
 called "NUL", properly gives an "Input Past End" error at run time:

 OPEN "NUL" FOR INPUT AS #1
 INPUT #1, x
 PRINT x
 CLOSE


 235. QB Program Can Hang If Coprocessor Switch Is Set Incorrectly

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  1-SEP-1989    ArticleIdent: Q32098

 QuickBASIC Versions 4.00b and 4.50, and programs compiled with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2 and
 MS-DOS or its copy of QuickBASIC, detect the presence or absence of a
 math coprocessor differently than QuickBASIC Version 4.00 does.

 QuickBASIC Version 4.00 loads and runs on a standard IBM PC even when
 the coprocessor switch on the PC motherboard is incorrectly set to
 indicate the presence of a math coprocessor when one is not actually
 present. Programs run in QuickBASIC versions later than 4.00 (in the
 QB.EXE editor or from an executable .EXE program) will hang under
 these same conditions.

 If you suspect that the hardware switch for the coprocessor is set
 incorrectly, type the following DOS command to turn off coprocessor
 checking and try the program again:

    SET NO87="Coprocessor has now been disabled."

 If the program now runs without hanging, then the hardware switch for
 the coprocessor is probably incorrectly set to indicate that a
 coprocessor is installed when one is not actually present. Another
 possibility is that the installed coprocessor wrongly has a speed
 (Megahertz) rating faster than the CPU (central processing unit) --
 the coprocessor's speed must be equal to or less than the speed of
 the CPU.

 Some customers have reportedly run QuickBASIC Version 4.00 without
 problems on older PCs and did not realize that the hardware switches
 were set incorrectly until they tried the QuickBASIC Version 4.00b
 upgrade and their machines hung.

 According to one customer, his original IBM documentation listed the
 coprocessor switch as unused, and two of his machines came from IBM
 with the switches set in what is now considered the incorrect
 position.

 One customer with an "original" PC 1 from IBM (with a BIOS dated
 10-27-1982, and 16/64K stamped on the motherboard) found that the IBM
 PC documentation was wrong for Switch Block One on the PC System
 Board. Switch number 2 must be ON in Switch Block One for a computer
 that has no coprocessor.

 Please refer to Page 457 of the following book for a correct list of
 all switch settings for the IBM PC:

    "The Programmer's PC Sourcebook" by Thom Hogan (published by
    Microsoft Press, 1988)

 This book contains reference tables for IBM PCs and compatibles, PS/2
 machines, and MS-DOS.


 236. BC.EXE "Internal Error" Using Function as Argument to INSTR

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q32099

 If a function is used as an argument to the INSTR function and the
 INSTR function is the expression in an ON <expression> GOTO statement,
 the BC.EXE compiler will give an "internal error" message. This error
 occurs with functions defined with the DEF FN method.

 Compiling with the BC /D (debug) option does not correct the problem.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 has been corrected in QuickBASIC Version 4.50 and in the Microsoft
 BASIC Compiler Version 7.00 (fixlist7.00).

 A workaround is to assign the result of the function to an
 intermediate variable and to use that variable as the argument to the
 function.

 This problem does not occur with QuickBASIC Version 3.00 using DEF FN
 functions. Please note that Version 3.00 does not support FUNCTION/END
 FUNCTION statements.

 The following code causes BC.EXE to generate an "internal error"
 message:

           DEF FNT$(A$) = CHR$(ASC(A$) AND &H5F)
           B$ = "z"
           on  INSTR("XYZ", FNT$(B$)) goto 1000
         print
      1000 print "this is a test"

 The following code works around the error:

           DEF FNT$(A$) = CHR$(ASC(A$) AND &H5F)
           B$ = "z"
            X$ = FNT$(B$)
           on  INSTR("XYZ", X$) goto 1000
     1000  print "this is a test"


 237. RANDOMIZE Results Differ in QB.EXE Versus Compiled .EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q32100

 The RANDOMIZE statement gives different results inside the QuickBASIC
 (QB.EXE) environment from the results it gives in an executable file
 (.EXE) using the same seed. This difference poses a problem for
 software developers using the QB.EXE environment who depend upon a
 given seed for the RANDOMIZE statement to make the RND function return
 the same series of random numbers as a compiled .EXE program.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Version 6.00 for
 MS-DOS and MS OS/2 (buglist6.00). This problem has been corrected in
 QuickBASIC Version 4.50 and in the Microsoft BASIC Compiler Version
 7.00 (fixlist7.00).

 This problem does not occur in QuickBASIC Version 3.00; the results
 obtained from within the QuickBASIC Version 3.00 environment and the
 results from the executable program are the same. Note: The differing
 random-number series using the same seed between QuickBASIC Version
 3.00 and Version 4.00 is expected and is not considered to be a
 problem.

 When a program is executed several times (with the same seed for the
 RANDOMIZE statement) from a given environment, the RND function
 returns the same number series every time (in all versions of
 Microsoft BASIC), which is expected behavior.

 The following code demonstrates the problem:

 RANDOMIZE 1000
 FOR i = 1 TO 10
         PRINT INT(RND * 10) + 1
 NEXT i
 END

 The following are the results (every time) when executed from inside
 the QuickBASIC Version 4.00b QB.EXE editor:

    7
    2
    4
    3
    2
    5
    1
    5
    4
    7

 The following are the results (every time) when executed from the .EXE
 file created by QuickBASIC Version 4.00b:

    8
    5
    7
    6
    2
   10
    3
    4
    7
    8

 The following are the results (every time) when executed from
 QuickBASIC Version 3.00 or an executable file compiled in Version
 3.00:

   10
    7
   10
    4
    3
    4
   10
    1
    3
    4


 238. No Error QB.EXE If DYNAMIC Array Wrongly DIMmed Before COMMON

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q32101

 The QB.EXE Versions 4.00 and 4.00b environments fail to generate an
 error if a DYNAMIC array is DIMensioned before it appears in a COMMON
 statement. For dynamic arrays, a DIM statement allocates memory for
 the array at run time, and is considered to be an "executable"
 statement.

 (Note: A STATIC array is required to be DIMensioned before it appears
 in a COMMON statement. For static arrays, a DIM statement is a
 "nonexecutable," as defined in Page 10 of the "Microsoft QuickBASIC
 4.0: BASIC Language Reference." This is a difference between static
 and dynamic arrays.)

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the version of QuickBASIC provided with the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem has been corrected in
 QuickBASIC Version 4.50 and in the QBX.EXE of the Microsoft BASIC
 Compiler Version 7.00 (fixlist7.00).

 BC.EXE Versions 4.00, 4.00b, and 4.50 (and QB.EXE 4.50) correctly trap
 the error at compile time and display the following message:

    COMMON and DECLARE must precede executable statements

 The following statement is from Page 117 of the "Microsoft QuickBASIC
 4.0: BASIC Language Reference" manual and refers to $DYNAMIC arrays
 that are also in COMMON:

    A dynamic array must be dimensioned in a later DIM or REDIM
    statement.

 QuickBASIC Versions 2.00 and 3.00 correctly generate a "COMMON Out of
 Order" error inside the QB.EXE environment for the following example:

 REM This program runs correctly in the QB.EXE 4.00 environment, but
 REM it should not. [Please remember that BASIC modules linked with
 REM Microsoft FORTRAN modules must use STATIC arrays, not DYNAMIC.]

 ' $DYNAMIC
 DIM x%(2048)
 COMMON SHARED /xxx/ x%()
 END


 239. "Too Many Files" When Using Make EXE Option in QB.EXE Editor

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q32103

 A "Too Many Files" error may occur when using the Make EXE File option
 from the Run menu to compile a multimodule program and a Quick library
 from the QB.EXE editor. The error message occurs immediately after you
 choose Make EXE File (or Make EXE And Exit) from the Run menu. The
 program can run successfully within the editor or can be compiled and
 linked successfully on the DOS level.

 The problem is caused by an overflow of the buffer containing the
 names and directories of the modules and the Quick library. The
 program will compile successfully if one or more of the module names
 are shortened, or if the directory names are shortened as shown in the
 formula below.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in the version of QuickBASIC provided with the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 QuickBASIC Version 4.50 and in QBX.EXE of the Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 The formula below can be used to determine if the buffer is full. You
 can successfully use Make EXE from the editor if the following holds
 true:

    A + B + C + D + E < 80

 In the formula above, the following is true:

 A = The total number of characters in all the module names loaded
     into the QuickBASIC editor. Do not count .BAS.

 B = The number of modules loaded into QuickBASIC.

 C = The total number of characters in the path QuickBASIC is
     invoked from. (Add up all the characters in all the directories
     and subdirectories.) For example, "C:\QUICK\SUBDIR" has 15
     characters in it.

 D = The number of directories and subdirectories in the path
     QuickBASIC is invoked from. For "C:\QUICK\SUBDIR", there is
     one root directory and two subdirectories, so D=3.

 E = The number of characters used to list the Quick library when
     QuickBASIC was invoked, e.g. in "QB /L foo" E = 3, and in "QB
     /L /testdir/roo/foo" E = 16. Please note that if the drive is
     also included, do not count the colon, therefore, for "QB /L
     a:foo" E = 4.

 The following steps demonstrate the "Too Many Files" problem:

 1. Create the following files:

       BASFILE1.BAS
       BASFILE2.BAS            (The code is not important. Each module
       BASFILE3.BAS             can just say PRINT "Hello".)
       BASFILE4.BAS
       BASFILE5.BAS
       BASFILE6.BAS
       BASFILE7.BAS
       B.BAS
       BA.BAS
       BAS.BAS
       BASF.BAS
       BASFI.BAS
       BASFIL.BAS

 2. Make B into a Quick library.

 3. Make an eight-character directory as follows:

       mkdir TESTDIR1

 4. Invoke QuickBASIC (QB.EXE) with the following command:

       C:\TESTDIR1>  QB /L B

 5. Load the seven BASFILEx.BAS files plus either [BASFIL.BAS, BAS.BAS,
    and BA.BAS] or [BASF.BAS and C.BAS].

 6. Choose Make EXE File... (or Make EXE And Exit) from the Run menu.

 7. A "Too Many Files" error may now appear.


 240. "Duplicate Definition" in QB.EXE; "Equals Missing" in BC.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32149

 If a line of code in the QuickBASIC editor begins with two occurrences
 of the same nonreserved word, the second word will be correctly
 flagged as a "Duplicate definition" when either the Start or Make EXE
 File command is chosen on the Run menu. If the same word is used as
 a variable elsewhere in the program, it will give a "Duplicate
 definition" error at that occurrence of the word.

 To generate the "Duplicate definition" message, enter "a a" in the
 QuickBASIC editor, then choose Start on the Run menu. Please note
 that the line "a a" generates a different message, "Equal sign
 missing," when compiled with BC.EXE.

 The "Duplicate definition" message occurs because the editor assumes
 the first "a" to be the name of a SUBprogram and the second "a" to be
 a parameter to be passed to the SUBprogram. Routines and variables
 must have different names.

 This information applies to QuickBASIC Versions 4.00, 4.00b and 4.50,
 to the QuickBASIC compiler that comes with Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to the QBX.EXE
 that comes with Microsoft BASIC PDS Version 7.00 for MS-DOS and MS
 OS/2.

 The following code example produces a "Duplicate definition" error on
 the second "a":

    a a

 The following code example produces a "Duplicate definition" error on
 the first line:

    a = 1
    a a


 241. QB.EXE Hang After Editing "Duplicate Definition" in SHARED

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q32151

 The sample program below demonstrates a problem in the QB.EXE editor
 after editing a variable in a SHARED statement that is the source of a
 "Duplicate Definition" error. Inconsistent problems can occur, such as
 hanging the editor or losing characters in the file after doing a
 Save.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the version of QuickBASIC provided with the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b) for MS-DOS and MS OS/2. This problem was corrected in
 QuickBASIC Version 4.50 and in the QBX.EXE of the Microsoft BASIC
 Compiler Version 7.00 (fixlist7.00).

 The following steps demonstrate the problem:

 1. Run the sample program below in the QB.EXE Version 4.00 or 4.00b
    editor. A "Duplicate Definition" error correctly displays.

 2. Delete the character "c" from "c%" in the second SHARED statement.

 It is now possible for the editor to hang or cause the source code to
 be incompletely saved when you perform a save.

 The following is a code example:

    DECLARE SUB testsub ()
    DIM c%(2, 2)
    CALL testsub

    SUB testsub
    SHARED a, b, c%()
    SHARED x$, c%()
    END SUB


 242. Corrections for LOCATE Statement

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom ptm336
 Last Modified: 20-DEC-1989    ArticleIdent: Q32152

 Corrections 1 and 2 below apply to the LOCATE statement on Page 255 of
 the following manuals:

    "Microsoft QuickBASIC 4.00: BASIC Language Reference"

    "Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2: BASIC
    Language Reference"

 1. The manuals incorrectly claim that any argument of the LOCATE
    statement can be omitted. For example, "Illegal function call"
    results if the "stop" parameter is specified while "start" is
    defaulted with a comma, as demonstrated in the example below.

 2. The following incorrect sentence on Page 256 should be deleted:

       "When 'start' is less than 'stop', LOCATE produces a two-part
        cursor."
    This sentence should be replaced with the following:

       "When 'stop' is less than 'start', LOCATE produces a two-part
        cursor."

 Note that Page 110 of the "Programming in BASIC: Selected Topics"
 manual correctly states that a "start" larger than "stop" makes LOCATE
 produce a split cursor. Helpful examples also are shown.

 The following is an example:

 CLS
 print "display the split cursor"
 locate ,,1,6,2
 print "the next line will result in an Illegal Function call error message"
 locate ,,1,,4
 print "end of the test"


 243. BASIC Example of CALL SetUEvent, ON UEVENT GOSUB Trapping

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32164

 The following products support user-defined event trapping with the
 statements ON UEVENT GOSUB, UEVENT ON, and SetUEvent:

 1. QuickBASIC Compiler Versions 4.00b and 4.50

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 Microsoft QuickBASIC Versions 4.00 and earlier do not support
 user-defined events.

 Below is a short example of how to trap a user-defined event.

 You can cause a user-defined event in a program by executing the CALL
 SetUEvent statement whenever a desired condition occurs. To CALL the
 SetUEvent routine in the QuickBASIC environment, you must invoke
 QB.EXE with the /L switch to load QB.QLB. For BASIC PDS 7.00 you must
 start QBX with /L to load QBX.QLB. An .EXE program that CALLs
 SetUEvent must be linked to QB.LIB because the SetUEvent routine is
 located in the QB.LIB library provided on the product disk. For BASIC
 PDS 7.00 you must link with QBX.LIB.

 The UEVENT ON statement turns on trapping of user-defined events. The
 < ON UEVENT GOSUB label > statement instructs a program where to go
 when a user-defined event occurs.

 The following example invokes the event handler if the value 5 is
 accepted from the keyboard:

 ON UEVENT GOSUB event1
 UEVENT ON
 INPUT "enter a number"; a
 IF a = 5 THEN CALL setuevent
 END
 event1:
    PRINT "invoked event handler with value"; a
    RETURN


 244. Error Code 2 Is "Syntax Error" at Both Compile and Run Time

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q32268

 Error code 2, "Syntax Error," needs to be added to the "Run-Time Error
 Codes" in Table D.1 on Page 476 of the following manuals:

 1. "Microsoft QuickBASIC 4.00: BASIC Language Reference"

 2. "Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2: BASIC
    Language Reference"

 D.1 "Run-Time Error Codes" lists errors in numerical order. The
 section following this table lists errors alphabetically and explains
 the conditions under which each error may occur.

 The following explanation for error code 2, "Syntax Error," is taken
 from Page 502:

    "Several conditions can cause this error. The most common cause at
     compile time is a mistyped BASIC keyword or argument. At run-time,
     it is often caused by an improperly formatted DATA statement."


 245. COMMON Variable Has Different Value with .EXE Versus QB.EXE

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q32270

 If a variable in COMMON and a variable in the body of a program have
 the same name but a different type specifier (%, !, #, or &), the
 QuickBASIC environment may make incorrect assumptions about the type,
 compared to the resulting .EXE file. An example is shown below, where
 the value of a variable is different when run in QB.EXE versus the
 compiled .EXE program.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and the QuickBASIC Compiler provided with BASIC
 compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). The problem does not occur with programs compiled with
 BC.EXE. This problem was corrected in QuickBASIC Version 4.50 and in
 the QBX.EXE environment of Microsoft BASIC PDS Version 7.00
 (fixlist7.00).

 The following program produces different results with BC.EXE versus
 QB.EXE:

    COMMON SHARED A
    A%=5
    CALL TEST
    END

    SUB TEST STATIC
      PRINT A
    END SUB

 When compiled with BC.EXE, the program correctly displays 0. When run
 in QB.EXE, the program incorrectly displays 5.

 This problem occurs because QB.EXE works on the premise that you
 really wanted the variable A in COMMON to be an integer instead of
 single precision.


 246. Passing Element of FIELDed Array to Subprogram UnFIELDs Array

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-AUG-1990    ArticleIdent: Q32271

 The following information applies to QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Passing an element of a FIELDed array to a subprogram unFIELDs the
 array, preventing the array from accessing the random file buffer.

 QuickBASIC Versions 3.00 and earlier do not unFIELD the array and
 allow you to access the random file buffer.

 The program below works without modification in QuickBASIC Versions
 3.00 and earlier. The program needs to be modified (to pass the array
 elements by value or by a temporary variable) in QuickBASIC Versions
 4.00 and later because arrays are handled differently.

 For QuickBASIC Versions 4.00 and later, when an array element is
 passed to a subprogram or function, the array element is copied to a
 temporary variable and passed to the subprogram. Upon returning from
 the subprogram, the temporary variable value is assigned to the array
 element. This process is performed in case the array moves during the
 execution of the subprogram or function; it also "unFIELDs" the array.

 Please note that in all versions of BASIC, FIELDed variables are
 "special" and have limited use. For example, you are not allowed to
 say INPUT B$, where B$ is a FIELDed variable. You also cannot say
 B$="test" and must instead say LSET B$="test" or RSET B$="test".

 This change in how the arrays are handled may affect any program that
 uses FIELDed arrays, including those applications that use Btrieve (a
 file-management system developed by SoftCraft, Inc.; Btrieve was later
 taken over by Novell, Inc.).

 The easiest workaround is to pass a temporary variable instead of an
 array element in the CALL statement.

 Another workaround for this problem is to put parentheses around the
 variable being passed in the CALL statement, thus causing it to be
 passed by value rather than by reference. An array passed by value is
 not unFIELDed. For example, the Code Example farther below could be
 changed as follows:

    CALL TEST((a$(i)))

 However, a disadvantage of passing by value is that if variables are
 large (such as a large string length), they could consume stack space
 quickly, possible leading to "Out of Stack Space" or "Out of Memory".

 The following code example demonstrates the unFIELDing of the array
 A$().

     DIM A$(2)
     OPEN "TEST.DAT" AS #1
     FIELD #1, 10 AS A$(0), 10 AS A$(1), 10 AS A$(2)
     K = 65
     FOR J = 1 to 2
        FOR I = 0 TO 2
         LSET A$(I)=STRING$(10,K)
         K = K + 1
        NEXT I
        PUT#1, j
     NEXT J
     CLOSE #1

     OPEN "TEST.DAT" AS #1
     FIELD #1, 10 AS A$(0), 10 AS A$(1), 10 AS A$(2)
     FOR J = 1 to 2
       GET#1, J
       FOR I = 0 to 2
           CALL TEST(a$(i))
       NEXT I
       print
     NEXT J
     END

     SUB TEST(b$) STATIC
       PRINT b$
     END SUB

 The output is as follows:

    AAAAAAAA
    BBBBBBBB
    CCCCCCCC

    AAAAAAAA
    BBBBBBBB
    CCCCCCCC

 As a workaround, the following modification can be made to the program
 to receive the desired output:

    GET#1, J
    FOR I = 0 to 2
        temp$=a$(i)
        CALL TEST(temp$)
        LSET a$(i)=temp$
    NEXT I

 The correct output is as follows:

    AAAAAAAA
    BBBBBBBB
    CCCCCCCC

    DDDDDDDD
    EEEEEEEE
    FFFFFFFF


 247. All Event Handling Is Disabled in an ON ERROR GOTO Handler

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32272

 The following information applies to QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b and 4.50, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 All event handling is suspended in an ON ERROR GOTO handler. The
 following types of events are suspended during an error trapping
 routine:

 1. Key trapping (ON KEY(n) GOSUB)

 2. Timer (ON TIMER(n) GOSUB)

 3. Communications (ON COM(n) GOSUB)

 4. Light Pen (ON PEN GOSUB)

 5. Joy Sticks (ON STICK GOSUB)

 6. User-defined events (ON UEVENT GOSUB); not available in QuickBASIC
    versions prior to Version 4.00b and Microsoft BASIC Compiler
    versions prior to Version 6.00.

 The events are enabled again as soon as the error trap is exited with
 the RESUME or RESUME NEXT statement.

 The following is a code example:

    ON ERROR GOTO trap
    ON KEY(1) GOSUB keytrap
    KEY (1) ON
    ERROR 5    ' Forces an error 5.
    END

    trap:
      PRINT "In the error trap, enter F1"
      while inkey$=""
      wend
      RESUME NEXT

    keytrap:
      Print "A key as pressed"
      return


 248. Do Not Use DOS Interrupts to Terminate Compiled Programs

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32274

 The following information applies to QuickBASIC Versions 4.00, 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 Some DOS interrupts should not be invoked from QuickBASIC programs.
 For example, "Terminate With Return Code" (Interrupt 21H, function
 4CH) can cause loss of the cursor the first time it is executed, then
 a hard hang on a subsequent CALL.

 QuickBASIC must control its own termination to correctly return to
 DOS. Please use the END statement in BASIC rather than a DOS interrupt
 to terminate a program.

 The following is a code example:

 'WARNING:
 'Execution of the following code will result in unpredictable results,
 'such as system lockup or loss of the DOS cursor in some instances.
 DIM inarray%(7), outarray%(7)
 inarray%(0) = &H4C00
 CALL int86old(&H21, inarray%(), outarray%())
 'The INT86OLD routine is located in QB.QLB and QB.LIB.


 249. Loading More Than Seven QuickLoad Files/$INCLUDE in Editor

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q32413

 When you save eight or more separate subprogram files (each containing
 an $INCLUDE metacommand) in QuickLoad format along with a main program
 in the QB.EXE Version 4.00 editor, the next time you load the main
 program into the editor, only the first seven subprogram files (listed
 in the .MAK file) will be automatically loaded.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b and in the version of QuickBASIC provided with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b) for MS-DOS and MS OS/2. This problem was corrected in
 QuickBASIC Version 4.50 and in the QBX.EXE environment of Microsoft
 BASIC PDS Version 7.00 (fixlist7.00).

 The following are two workarounds for the problem:

 1. Save the files in text format instead of in QuickLoad format.

 2. Manually load all files after the seventh listed in the .MAK file.

 The following code demonstrates the problem:

 ' This is the main program G.BAS:
 DECLARE SUB g1 ()
 DECLARE SUB g2 ()
 DECLARE SUB g3 ()
 DECLARE SUB g4 ()
 DECLARE SUB g5 ()
 DECLARE SUB g6 ()
 DECLARE SUB g7 ()
 DECLARE SUB g8 ()
 DECLARE SUB g9 ()
 DECLARE SUB g10 ()
 REM $INCLUDE: 'in.bas'
 PRINT "this is the main program"
 CALL g1
 CALL g2
 CALL g3
 CALL g4
 CALL g5
 CALL g6
 CALL g7
 CALL g8
 CALL g9
 CALL g10

 ' This is the separate $INCLUDE file IN.BAS:
 PRINT "hello"

 ' This is the separate file G1.BAS:
 SUB g1 STATIC
 REM $INCLUDE: 'in.bas'
 END SUB

 ' This is the separate file G10.BAS:
 SUB g10 STATIC
 REM $INCLUDE: 'in.bas'
 END SUB

 ' The other eight subprogram files G2.BAS through G9.BAS have the same
 ' structure as G1.BAS and G10.BAS shown above. All files should be
 ' saved in QuickLoad format to show the problem. In this case, all the
 ' files were loaded into the editor and a SAVE ALL was used to make
 ' the .MAK file (G.MAK).


 250. /C No Effect on Communications Receive Buffer in CHAINed Prog

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-MAR-1990    ArticleIdent: Q32473

 Programs can be given a new communications device receive buffer size
 using the /C:size option at compile time. This option sets up a new
 receive buffer size as specified, except for the program PROG2.EXE,
 when all of the following conditions are true:

 1. PROG2.EXE was compiled with the /C:size option.

 2. PROG1.EXE CHAINs to PROG2.EXE with the CHAIN statement.

 3. The CHAINing program (PROG1.EXE) was NOT compiled with the /C
    option.

 4. The programs (PROG1.EXE and PROG2.EXE) were both compiled with the
    "BRUN" run-time module (NOT compiled with /O).

 Thus, if you plan to change the default communications receive buffer
 size with the /C option in a CHAINed program (such as PROG2.EXE), you
 must compile the CHAINing program (PROG1.EXE) with the same /C option.

 The communications buffer is set when PROG1.EXE (the CHAINing program)
 and the BRUN library are loaded into memory at run time. During a
 CHAIN, the BRUN run-time module is not reloaded, so the buffer is not
 reset to the /C size that you specified for the CHAINed program
 (PROG2.EXE).

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b and 4.50, and to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and OS/2.

 An alternative, independent of the /C compile-time option, is to use
 the RB option to set the receive buffer size at run time in the OPEN
 COM statement in PROG2.EXE. The RB option to set the receive buffer
 size in the OPEN COM statement is introduced in QuickBASIC 4.00 and
 later versions, and is not available in QuickBASIC 2.00, 2.01, and
 3.00. Using the RB option lets a CHAINed program (PROG2.EXE) set the
 receive buffer size independent of the settings in the CHAINing
 program (PROG1.EXE).


 251. QB.EXE Visibility, IBM PS/2 Model 50,60,80, Monochrome Monitor

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 30-MAY-1990    ArticleIdent: Q34273

 The problem below was reported by a customer using QuickBASIC version
 4.00b on the IBM PS/2 models 60 and 80 (which have VGA graphics) with
 a monochrome monitor. (This problem probably also applies to the IBM
 PS/2 model 50 with a monochrome monitor.) Another customer reported a
 similar problem in QB.EXE in QuickBASIC version 4.50 and in QBX.EXE in
 Microsoft BASIC Professional Development System (PDS) version 7.00.
 Microsoft is researching this problem and will post new information
 here as it becomes available.

 When the QB.EXE version 4.00b editor is started with the /b switch (QB
 /b) on a IBM PS/2 model 60 or 80 with a monochrome monitor, it appears
 to start correctly. However, when a file is OPENed, QuickBASIC ignores
 the /b option and switches to color mode, causing the editor to be
 hindered by visibility problems. Also, when the DOS SHELL command is
 chosen from the File menu in QB.EXE, the text in MS-DOS is highlighted
 and blinking.

 To work around this editor visibility problem, execute the MODE BW80
 or MODE 80 command in DOS before running QB /b or QBX /b.

 This problem does not occur with QB.EXE version 4.00.

 The customer reported the above problem on the following equipment:

    IBM PS/2 models 60 and 80, both with 70-megabyte hard disks,
    ESDI controllers, and IBM monochrome monitors (type 8503-002)

 On the IBM PS/2 models 60 and 80 with the standard IBM PS/2 monochrome
 monitor, programs normally give different gray scales instead of
 color.

 For a related article, query on the following words:

    gray and scale and VGA and PS/2

 A customer has also reported a slightly different problem on an IBM
 PS/2 Model 70 with VGA graphics and a monochrome monitor. An executed
 program would not terminate when CTRL+BREAK was pressed and instead
 hung the computer. Executing a MODE BW80 command under DOS before
 running QB.EXE or QBX.EXE solved this problem.


 252. "No Symbolic Information" Debugging QuickBASIC with CodeView

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_CodeView
 Last Modified: 17-JAN-1991    ArticleIdent: Q32498

 To debug a QuickBASIC or BASIC compiler program with the CodeView
 debugger, the following is required:

 1. Save the BASIC (.BAS) source file in Text format before compiling.

 2. Compile the program with the /Zi option and link with the /CO
    option as follows:

       BC test.bas /Zi;

       LINK /CO test.obj;

 3. Make sure the BASIC (.BAS) file is in the current directory when
    CodeView is invoked.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler version 6.00 and 6.00b for MS-DOS and MS
 OS/2, and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 If one of the above steps is omitted, CodeView does not allow you
 to view your BASIC source code and issues the error message "No
 Symbolic Information."

 Following the above steps allows CodeView to find the proper symbolic
 information and allows you to do a source-level tracing of your BASIC
 program.

 You must use the Microsoft LINK.EXE program that comes with your copy
 of QuickBASIC or BASIC compiler (or a later version of LINK.EXE), or
 else you may get the "No Symbolic Information" error from CodeView.
 For example, if you use /CO with the older LINK.EXE that comes with
 MS-DOS Version 3.21, the linker gives no error (even though it doesn't
 support /CO), but CodeView gives you the "No Symbolic Information"
 error.


 253. PRINT Does Not Scroll Line 25 after a SHELL

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 12-DEC-1989    ArticleIdent: Q32499

 The code example below does not work correctly when compiled in
 QuickBASIC Versions 4.00 or 4.00b (in the environment or in an .EXE
 program) or in Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS
 OS/2 and MS-DOS.

 The first line printed after returning from a SHELL statement is
 printed on line 25 and does not scroll when something else is printed
 after it (i.e., the subsequent PRINT statements are printed above line
 25).

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC PDS
 Version 7.00 (fixlist7.00).

 The workaround is to send output to the console ("cons:") device using
 the PRINT# statement, as shown below.

 The following code demonstrates the problem:

 PRINT "before shell"
 SHELL
 PRINT "after shell1"
 PRINT "after shell2"
 INPUT a$
 PRINT a$
 END

 The workaround is to print to the console ("cons:") device, as in the
 following program:

 OPEN "cons:" FOR OUTPUT AS #1
 PRINT #1, "before shell"
 SHELL
 PRINT #1, "after shell1"
 PRINT #1, "after shell2"
 INPUT a$
 PRINT #1, a$
 END


 254. Problem Passing Array Element to SUB Compiled with No /Debug

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q32641

 The code sample below runs correctly when compiled with the debug
 option turned off (in either the QuickBASIC environment or in an .EXE
 file). The program passes an integer variable i and an array element
 number i to a non-STATIC subprogram.

 However, the program gives incorrect results at run time when compiled
 with BC /D or with debug selected from the Make EXE File command in
 the Run menu in QuickBASIC.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in the Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b).
 This problem has been corrected in the Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 The equivalent code works correctly in QuickBASIC Version 3.00 with or
 without the /D (debug) compiler option.

 The following code example demonstrates the problem:

 DECLARE SUB test (i AS INTEGER, j AS INTEGER)
 DIM a(2) AS INTEGER
 DIM i AS INTEGER
 a(1) = 1
 a(2) = 2
 i = 1
 CALL test(i, a(i))
 PRINT i, a(1), a(2)
 END

 SUB test (i AS INTEGER, j AS INTEGER)
 i = 2
 END SUB


 255. PEN Function Returns Mouse Cursor Position in BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32725

 If the Microsoft MOUSE.SYS driver is installed, the PEN function gives
 the Microsoft Mouse cursor position in both character (row and column)
 and graphics (pixel) coordinates. The following values for PEN are
 meaningful when using the mouse, but only if both buttons are pressed:

    PEN(4), PEN(5), PEN(8) and PEN(9)

 You need to test if PEN(3) equals -1 to verify that both buttons are
 pushed.

 This article applies to Microsoft QuickBASIC Versions 4.00, 4.00b and
 4.50, to Microsoft BASIC Compiler Version 6.00 for MS-DOS and MS OS/2,
 and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Pages 314 and 315 of the "Microsoft QuickBASIC 4.0: BASIC Language
 Reference" manual for Versions 4.00 and 4.00b describe the values
 returned by the PEN function when using the mouse.

 Please note that MOUSE CALLs provide a much better mouse interface to
 QuickBASIC than the PEN function. MOUSE CALLs are documented in the
 "Microsoft Mouse Programmer's Reference Guide," which can be ordered
 using the order blank enclosed in the Microsoft Mouse package.

 The following is a code example:

 CLS
 PRINT "Press both buttons to trap mouse position. Press any key to end."
 DO WHILE INKEY$ = ""
         IF PEN(3) = -1 THEN
                 LOCATE 10, 1
                 PRINT "Row:"; PEN(8)
                 PRINT "Column"; PEN(9)
                 PRINT "X Pixel"; PEN(4)
                 PRINT "Y Pixel"; PEN(5)
         END IF
 LOOP


 256. "Path/File Access" Opening a "NUL" File on a Novell Network

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32729

 It has been reported that opening a "NUL" file on a Novell Network
 gives a "Path/File access" error message if you are not running on the
 server machine.

 Another customer reported that opening a "NUL" file when the current
 drive is a server on a Token Ring Network gives a "Disk Not Ready"
 message. The same test on the IBM PC Network gives an "I/O error".

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 You can work around the problem as follows:

    OPEN "\DEV\NUL" FOR OUTPUT AS #1

 MS-DOS uses the "\DEV\" prefix for logical system filenames, and it
 does not attach a directory search path for the name. This applies
 only to the following system filenames: LPT1:, COM1:, COM2:, SCRN:,
 CON:, and NUL:. The colon (:) may be omitted when referencing the
 logical filename.

 Please note that Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and Microsoft BASIC
 PDS Version 7.00 are designed only for the IBM PC Network or networks
 compatible with the MS-Net standard. Compiled BASIC programs access
 the IBM PC Network and the MS Network with standard MS-DOS (Versions
 3.00 and later) network calls. Microsoft QuickBASIC and  Microsoft
 BASIC Compiler are not tested or supported on the Novell Network or
 IBM Token Ring Network.


 257. Use Logical AND to Determine Which Bits Are Set in an Integer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_GWBasicI B_BasicInt B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32730

 The CALL INTERRUPT or INT86OLD functions in QuickBASIC Version 4.00
 return information by setting certain bits in the AH or AL register.
 (In the $INCLUDE file QB.BI provided on the QuickBASIC Versions 4.00
 or 4.00b release disk, InRegs.AX is an integer variable, where the
 first byte represents AH (High) and the second byte represents AL
 (Low).)

 The logical "AND" operator can be used in BASIC to determine which
 bits are set. For example, the program below determines whether a bit
 has been set in the High or Low byte of a 2-byte integer variable.

 The example below applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50, to Microsoft BASIC Compiler Version 6.00 for MS-DOS and MS
 OS/2, to Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2, to
 GW-BASIC Interpreter Version 3.22, to previous versions of these
 products, and to Microsoft BASIC for XENIX and Macintosh.

 The following is a code example:

 INPUT x%
 PRINT "Bits set in the High byte of x%."
 IF x% < 0 THEN PRINT "Bit 7 set!"
 mask% = &H4000
 FOR i% = 6 TO 0 STEP -1
    IF x% AND mask% THEN PRINT "Bit"; i%; " set!"
    mask% = mask% \ 2
 NEXT
 PRINT "Bits set in the Low byte of x%."
 'For just the Low byte, mask% starts out as 128.
 FOR i% = 7 TO 0 STEP -1
    IF x% AND mask% THEN PRINT "Bit"; i%; " set!"
    mask% = mask% \ 2
 NEXT


 258. "Overflow," "Subscript Out of Range," >32,767 Array Elements

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr
 Last Modified: 26-FEB-1990    ArticleIdent: Q32787

 Page 156 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference"
 for Versions 4.00 and 4.00b and the "Microsoft BASIC Compiler 6.0:
 BASIC Language Reference" for Versions 6.00 and 6.00b for MS-DOS and
 MS OS/2 correctly states that an array dimension can have subscripts
 from -32,768 to 32,767. This is also stated on Page 103 of the
 "Microsoft BASIC 7.0: Language Reference" manual for Microsoft BASIC
 Professional Development System (PDS) Version 7.00. For example DIM
 Z%(-2000 TO 3000), which has 5001 elements, is legal.

 However, these pages fail to mention that the TOTAL NUMBER of elements
 in any one dimension of an array cannot exceed 32,767 (32K minus one).
 For example, the following DIM statements are not allowed because they
 make an array with more than 32,767 elements in one dimension:

    DIM X(-10000 TO 25000)  ' 35,001 elements is too many.
    DIM A%(0 TO 32767)  ' 32,768 elements is one too many.

 To make an array that exceeds 32,767 total elements, you must
 dimension it with two or more dimensions (making sure that no one
 dimension has more than 32,767 elements; you must also compile with
 the /AH option).

 Below is an explanation of array usages that could give one of the
 following errors:

    "Overflow," "Math Overflow," "Subscript Out of Range,"
    "Array Too Big," "Out of Memory"

 To dimension an array larger than 64K, you must make the array dynamic
 and compile with the /AH (huge array) option, as in the following
 example:

    REM This program must be compiled with the /AH option
    ' $DYNAMIC
    OPTION BASE 1
    DIM A%(20000, 2)  ' 40000 elements, taking 80000 bytes in memory.
    DIM B%(20000, 4)  ' 80000 elements, taking 160000 bytes in memory.

 The following is a list of array-related error messages and their
 possible causes:

 1. Compiling an array that has a subscript larger than +32,767 or
    smaller than -32,768 in the DIM statement causes an "Overflow"
    error in the QB.EXE editor. If you compile it with BC.EXE, you
    receive a "Math Overflow" error, as follows:

       ' $DYNAMIC
       DIM s%(33000)  ' produces "overflow" error in QB.EXE editor
                         ' and "math overflow" error in BC.EXE.

 2. A "Subscript out of range" error occurs in the QB.EXE editor at
    run time if you DIMension more than 32,767 elements in one
    dimension, as in the following example (invoke QB /AH):

       ' $DYNAMIC
       DIM X%(-10000 TO 25000) ' Cannot use 35,000 elements in
                                  ' one dimension.

    Compiling the above program with BC.EXE does not cause a compile
    error, but gives a "Subscript Out of Range" error at run time in
    the .EXE program. (Be sure to compile with the BC /D (debug) option
    to properly trap array-bounds errors.)

    Note that if the array has exactly 32,768 elements, the error will
    not occur on the DIM statement in QB.EXE or a compiled .EXE program;
    the error will occur only when an array element is used later:

    REM $DYNAMIC
    DIM Y%(0 TO 32767)  ' Cannot use 32768 elements in one dimension.
    PRINT Y%(2000)  ' "Subscript Out of Range" occurs here, not on DIM.

 3. An "Array Too Big" or "Subscript Out of Range" error will
    display if the array exceeds 64K, is not dynamic, and was not
    compiled with the /AH option. You must either make the array
    dynamic and compile with /AH or make the array smaller than 64K.
    If a dynamic array is larger than 128K, its array elements must
    have a size that is a power of 2 (2, 4, 8, 16, 32, 64, 128, 256,
    512, etc.) so that array elements do not overlap on boundaries
    that are divisible by 64K.

 4. An "Out of Memory" error means you have exceeded available RAM
    at run time. You should reduce the size of arrays or code, or
    try running the program as an .EXE program instead of inside the
    QB.EXE environment. You can use the FRE function to determine
    run-time memory usage.

 Note that QuickBASIC Versions 2.00, 2.01, and 3.00 are limited to
 arrays that do not exceed 64K in size or 32,767 elements per
 dimension.

 Note: 1K is equal to 1024 bytes.


 259. Example of Trapping CTRL+ALT+DEL Keys in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 22-DEC-1989    ArticleIdent: Q32788

 The correction below applies to the KEY statement on Page 236 of the
 following manuals:

 1. Page 236 of "Microsoft QuickBASIC 4.0: BASIC Language Reference"
    for Versions 4.00 and 4.00b

 2. Page 236 of "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" for Versions 6.00 and 6.00b for MS-DOS and MS OS/2

 3. Page 180 of the "Microsoft BASIC 7.0: Language Reference" manual
    for Microsoft BASIC PDS Version 7.00

 4. Page 198 of the "Microsoft QuickBASIC: BASIC Language Reference" manual
    for QuickBASIC Version 4.50

 The following phrase for the KEY(n) statement is incorrect:

    ...a keyboardflag value of &H12 would test for both CTRL and ALT
    being pressed.

 The keyboardflag value should be &H0C on a non-extended keyboard, not
 &H12, to test for both CTRL and ALT being pressed. The keyboardflag
 value should be &H8C on an extended keyboard. This example incorrectly
 uses decimal addition on hexadecimal numbers.

 The following BASIC program gives an example of trapping the
 CTRL+ALT+DEL key sequence for both extended and non-extended
 keyboards:

   ' This example works in QuickBASIC Versions 4.00 and later.
   ' &H80 = keyboard flag value to add for extended keyboard keys
   ' &H0C = keyboard flag for CTRL (&H04) plus ALT (&H08), pressed
   '        together.
   ' &H53 = scan code for DELETE (or DEL) key
   CLS
   KEY 15, CHR$(&HC) + CHR$(&H53)    '   Trap CTRL+ALT+DEL for
   ON KEY(15) GOSUB ctrlaltdelwhite  '   white DEL key
   KEY(15) ON
   KEY 16, CHR$(&H8C) + CHR$(&H53)   '   Trap CTRL+ALT+DELETE for
   ON KEY(16) GOSUB ctrlaltdelgrey   '   grey (extended) DELETE key
   KEY(16) ON
   DO
   LOOP UNTIL INKEY$ = "q"         '  Idle loop
   END
 ctrlaltdelgrey:
   PRINT "pressed CTRL+ALT+DELETE (grey DELETE key) on extended keyboard"
   RETURN
 ctrlaltdelwhite:
   PRINT "Pressed CTRL+ALT+DEL (white DEL key) on either keyboard"
   RETURN

 Please note that when you run this program, pressing CTRL+ALT+DEL will
 reboot the computer if any of the following key states are also
 active:

    SHIFT, NUM LOCK, or CAPS LOCK

 You must define separate ON KEY(n) statements for trapping
 CTRL+ALT+DEL in combination with the different states of the SHIFT,
 NUM LOCK, or CAPS LOCK keys. In the ON KEY(n) statement, n can be 15
 through 25; this limits you to 11 user-defined keys.

 The keyboardflag value &H0C in the KEY statement is obtained by adding
 together the keyboardflag values from Page 236 for the CTRL and ALT
 keys, as in the following example:

       &H04   +  &H08   =>  &H0C
       (CTRL)    (ALT)      (keyboardflag for KEY statement)

 When adding together keyboardflag values to trap different
 combinations of SHIFT, CTRL, ALT, NUM LOCK, CAPS LOCK, or
 Advanced-101-keyboard extended keys, it is important to remember that
 the values on Page 236 are in hexadecimal (base 16) notation, where
 numbers are preceded with &H. If you wish, you can convert the number
 to decimal notation (base 10) and use that value. Be sure not to use
 &H in front of the value in BASIC if the value is in decimal notation.


 260. Correction for COMMAND$ Function Example in Manual

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q32789

 The correction below applies to the example program for the COMMAND$
 function on Page 114 of the following manuals:

 1. "Microsoft QuickBASIC 4.0: BASIC Language Reference"

 2. "Microsoft BASIC Compiler 6.0: BASIC Language Reference"

 On Page 114, the SUB statement on line seven incorrectly reads as
 follows:

    SUB Comline(NumArgs, Args$(1), MaxArgs) STATIC

 This line should read as follows:

    SUB Comline(NumArgs, Args$(), MaxArgs) STATIC

 In brief, replace Args$(1) in the first statement with Args$().

 This information also applies to the example program on Page 61 of the
 "Microsoft BASIC 7.0: Language Reference" manual which comes with
 Microsoft BASIC PDS Version 7.00.

 On Page 61, the SUB statement on line five incorrectly reads as
 follows:

    SUB Comline(NumArgs,Args$,MaxArgs) STATIC

 This line should read as follows:

    SUB Comline(NumArgs,Args$(),MaxArgs) STATIC


 261. Problem Passing Array in COMMON Also in SUB Argument in .QLB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50
 Last Modified:  8-DEC-1989    ArticleIdent: Q32969

 If a string array is specified in a COMMON statement and also in the
 argument list of a subprogram in a Quick library, garbage characters
 will be displayed on the screen when that array is printed from the
 subprogram. Under QuickBASIC Versions 4.00 and 4.00b, this problem
 occurs only within the QB.EXE editor; the .EXE file runs without
 encountering any problems. Under QuickBASIC Version 4.50, the problem
 occurs both in the QB.EXE and the .EXE unless the library is created
 using the debug option (/D). When the /D switch is used to build the
 library, the program works correctly.

 Under QuickBASIC Versions 4.00, 4.00b, and 4.50, if the subprogram is
 not part of a Quick library, the program executes correctly from
 inside the QuickBASIC editor.

 Microsoft has confirmed this to be a problem in the QB.EXE editor in
 Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50, and in the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b) for MS-DOS and MS OS/2. This problem has been corrected
 in the Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 To work around this problem, do one of the following:

 1. Use the /D (debug) option when creating the Quick library.

 2. Compile the program as an executable file to run.

 3. Do not use a Quick library. (A separately loaded source file can be
    substituted in the QB.EXE editor.)

 The following code examples demonstrate the problem:

 The main program is as follows:

      DECLARE SUB qstnaire (question$())
      DEFINT I-N
      DIM question$(5)
      COMMON question$()
      CLS
      INPUT question$(1)
      CALL qstnaire(question$())
      END

 The subprogram in the Quick library is as follows:

      DEFINT I-N
      SUB qstnaire (question$()) STATIC
      PRINT question$(i);
      END SUB


 262. "Field Overflow" Using INPUT, ON ERROR to Set Record

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  6-DEC-1989    ArticleIdent: Q33032

 In the program below, using an ON ERROR trapping routine to correctly
 set the record length for a random file continually returns a "field
 overflow" error message.

 To work around this problem, initially use the correct record-length
 value.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b, and the Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b).
 This problem has been corrected in QuickBASIC Version 4.50 and in the
 Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 The following program will continually return a "field overflow" error
 message:

    COMMON SHARED c
    ON ERROR GOTO trap
    CLS
    OPEN "foofile" FOR RANDOM AS #1 LEN = 5
    FIELD #1, 5 AS a$
    b$ = "hello"
    LSET a$ = b$
    PUT #1, 1
    c = 6
    get$ = INPUT$(c, #1)
    print c
    PRINT get$
    END
    trap:
      PRINT ERR
      c = 5
      RESUME


 263. How to Trap CTRL+BREAK, CTRL+C on Standard & Enhanced Keyboard

 Product Version(s): 2.00 2.10 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q33034

 The scan code for the BREAK key is &H46 (listed as SCROLL LOCK on Page
 237 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual
 for Versions 4.00 and 4.00b). The CTRL+BREAK key combination is
 trapped differently, depending on whether or not the program is run on
 a standard or enhanced keyboard.

 This information also applies to Microsoft QuickBASIC 4.50, Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 For a standard keyboard, CTRL+BREAK is defined as follows

    KEY n, CHR$(&H04) + CHR$(&H46)

 where n is in the range 15 through 25 in QuickBASIC Version 4.00, and
 in 15 through 20 in QuickBASIC Versions 2.00, 2.01, and 3.00.

 On an enhanced keyboard, CTRL+BREAK is defined as follows:

    KEY n, CHR$(&H84) + CHR$(&H46)

 Please note that you must make separate user-defined KEY statements
 for trapping CTRL+BREAK in combination with the SHIFT, ALT, NUM LOCK,
 and CAPS LOCK keys. The keyboard flags for these other key
 combinations must be added together to define a given key sequence.

 Examples of trapping CTRL+BREAK and CTRL+C (when the SHIFT, ALT, NUM
 LOCK, or CAPS LOCK keys are NOT active) are shown below.

 Code Example 1
 --------------

 KEY 15, CHR$(&H84) + CHR$(&H46)  'Traps CTRL+BREAK on enhanced keyboard.
 KEY 16, CHR$(&H4) + CHR$(&H46)   'Traps CTRL+BREAK on standard keyboard.
 KEY(15) ON
 KEY(16) ON
 ON KEY(16) GOSUB trap
 ON KEY(15) GOSUB trap
 FOR i = 1 TO 500
    PRINT i
 NEXT
 END
 trap:
    PRINT "trapped"
    RETURN

 Code Example 2
 --------------

 Use the following code to trap a CTRL+C on either keyboard (standard
 or extended):

 KEY 18, CHR$(&H4)+CHR$(&H2E)    ' The &H4 is the CTRL Key
 KEY (18) ON            ' The &H2E is the C key
 ON KEY(18) GOSUB ctrlctrap
 10 : GOTO 10
 END
 ctrlctrap:
     PRINT "CONTROL+C Trapped"
     RETURN


 264. History On in Debug Menu Will Not Go through Event Traps

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q33035

 The History On feature in the Debug menu in QB.EXE Version 4.00 should
 allow you to trace backward and forward through the last 20 statements
 executed by your program. However, if the program moves to an
 event-trapping subroutine, History On will not record these statements
 and will act as if the trap never occurred.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in the QuickBASIC that comes with Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in QuickBASIC Version 4.50
 and in QBX.EXE of Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 The following is a sample code:

 'Turn on History On before running this program, and set a Breakpoint
 'either on the last line, or the next-to-last line. By pressing
 'SHIFT+F8 (History Back), the program will not step through the trap
 'routine, but just step through the FOR..NEXT loop.

 ON KEY(1) GOSUB KeyTrap        'Traps the F1 key.
 KEY(1) ON
 FOR i = 1 TO 100
   PRINT "hello there";
   PRINT i
 NEXT
 END
 KeyTrap:
      PRINT "I'm"
      PRINT "     in"
      PRINT "         a"
      PRINT "            trap!"   'Put Breakpoint here, or on the RETURN.
      RETURN


 265. Hanging Problems When QB.EXE Editor Loads Fast-Load Modules

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q33036

 A hanging problem can occur when the QB.EXE editor loads eight or more
 Fast-Load format modules (listed in a .MAK file) where each module
 uses at least one $INCLUDE file. A "Loading and parsing" message
 displays as usual, but then the computer may hang. The problem does
 not occur if the separate modules are saved as text instead of in the
 "Fast Load and Save" format.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the version of QuickBASIC provided with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 QuickBASIC Version 4.50 and in the QBX.EXE environment of the
 Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 Note: This problem does not occur in QuickBASIC Versions 2.00, 2.10,
 and 3.00; these versions do not support "Fast Load and Save" format or
 the loading of multiple separate modules.


 266. PEN(5) Function in SCREEN 9 Returns Only 0 or 1 with Mouse

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q33044

 The PEN(5) function returns only a value of 0 or 1 instead of the
 actual y pixel coordinate when using the Microsoft Mouse in SCREEN 9,
 10, 11, or 12 (which are screen modes with resolutions of 640 x 350 or
 greater). This problem occurs both inside the QB.EXE environment and
 as a compiled .EXE program.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 3.00, 4.00, 4.00b, and 4.50, in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS, and in
 Microsoft BASIC PDS Version 7.00 for MS-DOS (buglist7.00). We are
 researching this problem and will post new information here as it
 becomes available.

 The problem does not occur in SCREENs 1, 2, 7, 8, or 13, which have
 resolutions lower than 640 x 350.

 The following program hangs the machine in QuickBASIC 4.00:

 SCREEN 9
 CLS
 PEN ON
 true = -1
 WHILE true
    x = PEN(4)         'x pixel coordinate
    y = PEN(5)         'y pixel coordinate
    PRINT "X= "x, "Y= "y
 WEND


 267. QB.EXE Editor Deletes File if Saved with Insufficient Memory

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q33046

 If you attempt to save the current file in the QuickBASIC editor and
 there is no memory available, the file will be deleted.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and the version of QuickBASIC provided with the BASIC
 compiler Versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for
 MS-DOS and MS OS/2. This problem was corrected in QuickBASIC Version
 4.50 and QBX.EXE of the Microsoft BASIC Compiler Version 7.00
 (fixlist7.00).

 The following steps duplicate the problem:

 1. Enter QuickBASIC.

 2. Enter the following program:

       x=setmem(0)
       y=setmem(-x)

 3. Save the file.

 4. Run the program.

 5. Try to modify the program; you will receive an out of memory error.

 6. Try to save the file; you will receive an out of data space error.

 7. Leave QuickBASIC.

 8. The file will no longer be present; however, it usually can be
    "unerased" with Norton's Utilities.


 268. FUNCTION Procedures Cannot Be Invoked in I/O Statements

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  9-JUL-1990    ArticleIdent: Q33301

 You should avoid invoking (or nesting) a FUNCTION procedure in a BASIC
 statement that performs output to a file. Instead, the returned value
 of the FUNCTION procedure should be assigned to an intermediate
 variable, and the intermediate variable can then be used in the I/O
 statement. (A FUNCTION procedure is defined in a FUNCTION...END
 FUNCTION block.)

 This and other restrictions are described on Page 201 of the
 "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
 versions 4.00 and 4.00b, as follows:

    Because BASIC may rearrange arithmetic expressions for greater
    efficiency, avoid using FUNCTION procedures that change program
    variables in arithmetic expressions. Also avoid using FUNCTION
    procedures that perform I/O in I/O statements. Using FUNCTION
    procedures that perform graphics operations in graphics statements
    may also cause side effects.

 The same restriction is mentioned on Page 201 of the "Microsoft BASIC
 Compiler 6.0: BASIC Language Reference" for versions 6.00 and 6.00b
 for MS OS/2 and MS-DOS. It is also mentioned on Page 146 of the
 "Microsoft BASIC 7.0: Language Reference" manual.

 Please note that user-defined functions defined with the DEF FN
 statement do not have the above restrictions.


 269. Correction to Online Help Message for Error 70 in QB.EXE 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891226-7 docerr
 Last Modified: 17-JAN-1990    ArticleIdent: Q57747

 If you get an error 70 ("Permission denied" error) in the QB.EXE
 Version 4.50 environment and choose the Help button on the dialog box
 for error 70, the following partially incorrect Help message displays:

    Help: Permission Denied
       An attempt was made to write to a write-protected disk, a
       read-only file, or to access a locked file.
    ERR code: 70

 The phrase "a read-only file" should be removed in this explanation of
 error 70. This correction applies to the QB Advisor online Help system
 for QuickBASIC Version 4.50. The message should read as follows:

    Help: Permission Denied
       An attempt was made to write to a write-protected disk or to
       access a locked file.
    ERR code: 70

 This online Help documentation error was corrected in the QBX.EXE
 editor in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 To generate the Help message for error 70 in the QuickBASIC
 environment, execute the statement ERROR 70 in the immediate window
 and choose the Help button in the resulting dialog box.

 Note that if a program attempts to write to a read-only file, a
 "Path/File access error" (ERR code 75) will occur, not a "Permission
 denied" (ERR code 70) error. You can make a file read-only by using
 the MS-DOS ATTRIB command (for more information about ATTRIB, see an
 MS-DOS reference manual).


 270. QuickBASIC 4.00b UPDATE.DOC: Adds ON UEVENT to Trap Events

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q33488

 The following information was taken from the QuickBASIC Version 4.00b
 UPDATE.DOC file. It describes features that have been added since
 Microsoft QuickBASIC Version 4.00 was released.

 This information applies to Microsoft QuickBASIC Versions 4.00b and
 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00b, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 New Statement: ON UEVENT
 ------------------------

 Action: Defines an event trap for a user-defined event

 Syntax: ON UEVENT GOSUB {<linenumber>|<linelabel>}

 Remarks:

 In this syntax, <linenumber> or <linelabel> specifies the number or
 label of the first line in the event-trapping subroutine. The ON
 UEVENT statement allows your program to branch to an event-trapping
 subroutine when a user-defined event occurs. ON UEVENT is unlike other
 event-trapping statements in that it allows your program, not an
 external agent, to trigger the event that you expect to trap. For
 example, assume that your system contains a data acquisition device
 that generates an interrupt when data arrives. Most of your
 application is written in QuickBASIC. The main module contains an
 event-trapping subroutine that responds to a user-defined event (in
 this case, the arrival of data from the acquisition device). The
 following three assembly-language procedures are also linked into the
 program:

 1. An interrupt handler that responds to the interrupt generated by
    the acquisition device

 2. A routine that installs the interrupt handler in the chain of
    interrupts

 3. A routine that removes the interrupt handler from the chain of
    interrupts

 When the program begins, it calls the assembly-language routine that
 installs the interrupt handler. Then it executes an ON UEVENT
 statement to identify the QuickBASIC subroutine that will be executed
 when a user-defined event occurs. The final step in setting up the
 user-defined event trap is to execute a UEVENT ON statement. Once this
 is done, the BASIC program enters its main execution loop.

 When data arrives, the acquisition device generates an interrupt. The
 assembly-language interrupt handler, in turn, calls the routine
 SetUEvent. SetUEvent is a BASIC run-time-library routine that causes a
 user-defined event to occur in BASIC. This special routine can be
 called from any Microsoft language. References to SetUEvent are
 resolved when your program is linked with the run-time library. The
 user-defined event causes the program to branch to the QuickBASIC
 subroutine identified by the previous ON UEVENT statement. At this
 point, the event-trapping subroutine performs whatever processing is
 desired. Just before the application terminates, it calls the
 assembly-language routine that removes the interrupt handler from the
 chain of interrupts.

 New Statements: UEVENT ON, OFF, STOP
 ------------------------------------

 Action: Enable, disable, or suspend event trapping for a user-defined
         event

 Syntax: UEVENT ON
         UEVENT OFF
         UEVENT STOP

 Remarks:

 The effect of UEVENT parallels that of other event-trapping
 statements. For example, UEVENT ON enables a user-defined event trap
 that you previously set up with an ON UEVENT GOSUB statement.


 271. QB 4.00b UPDATE.DOC: Adds SLEEP Statement to Suspend

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q33489

 The following information was taken from the QuickBASIC Version 4.00b
 UPDATE.DOC file. It describes features that have been added since
 Microsoft QuickBASIC Version 4.00 was released.

 This information applies to Microsoft QuickBASIC Versions 4.00b and
 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 6.00b, and
 to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 New Statement: SLEEP
 --------------------

 Action: Suspends the execution of a BASIC program

 Syntax: SLEEP <seconds>

 Remarks:

 In this syntax the optional parameter <seconds> determines how many
 seconds to suspend the program. SLEEP suspends a QuickBASIC program
 until one of the following three events occurs:

 1. The time period specified in the SLEEP statement has elapsed.

 2. A key is pressed.

 3. An enabled QuickBASIC event occurs.

 A QuickBASIC event is one that you can trap with an ON <event>
 statement such as ON COM or ON KEY. Note that a QuickBASIC event does
 not interrupt the suspension caused by SLEEP unless its trap is active
 when the event occurs. That is, the trap must have been set up with an
 ON <event> statement, turned on with an <event> ON statement, and not
 disabled with <event> OFF or <event> STOP. Note, too, that SLEEP
 responds only to actual keystrokes that occur after the SLEEP
 statement executes; SLEEP ignores characters that were stored in the
 keyboard buffer before the SLEEP statement executes.

 If you execute SLEEP with a time period of 0 (zero), or without
 specifying any time period, the program is suspended for an indefinite
 period. In this case, only a keystroke or QuickBASIC event can
 interrupt the suspension.

 Example:

 The following program suspends its execution for 20 seconds. Because
 the sample program has no ON EVENT statement, the only way to
 interrupt its suspension prior to the end of the 20-second delay is by
 pressing a key.

    PRINT "Taking a twenty-second timeout..."
    SLEEP 20
    PRINT "Play ball!"


 272. "Illegal Function Call" on WIDTH 40 with Monochrome Screen

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q33620

 An "Illegal function call" error message is generated when trying to
 change the screen width to 40 columns using WIDTH 40 on a monochrome
 screen.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler versions
 6.00, 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2; and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 (buglist7.00, buglist7.10) for MS-DOS and MS OS/2. We are
 researching this problem and will post new information here as it
 becomes available.

 This problem does not occur in programs compiled with QuickBASIC
 versions 2.00, 2.01, and 3.00.


 273. "RETURN without GOSUB" When ON ERROR and CHAIN in 4.00b

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50
 Last Modified:  8-DEC-1989    ArticleIdent: Q33621

 If the following program is compiled in QuickBASIC Version 4.00b or
 4.50 or Microsoft BASIC Compiler Version 6.00 or 6.00b and CHAINed
 to/from another program, the error message "RETURN without GOSUB in
 line 10 of module" is generated. This problem does not occur when
 executed inside the QuickBASIC environment or if the two programs are
 compiled with the same switches or if A.BAS is compiled with /O
 switch.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00b and 4.50 and in Microsoft BASIC Compiler for MS-DOS and OS/2
 (buglist6.00, buglist6.00b). This problem has been corrected in
 Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 The following is a code example:

    ' A.BAS, the CHAINing program:
    CHAIN "B"

    ' B.BAS, the CHAINed-to program:
    ' Will give error message unless A.BAS was compiled with /E or /X.
    GOSUB sub1
    PRINT "It works!"
    END
    sub1:
          PRINT "Here I am!"
          ON 1 GOSUB sub2
          PRINT "I'm back!"
    10    RETURN                  'Says RETURN without GOSUB here when
                                  'compiled.
    sub2:
          PRINT "I'm down here!"
          RETURN
    sub3: ON ERROR GOTO OhNo      'Should never get to this line.
    OhNo: END                     'Never gets to this line.


 274. COMMON SHARED Problem when Period in Variable after CHAIN

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50
 Last Modified: 12-DEC-1989    ArticleIdent: Q33622

 When CHAINed inside the QuickBASIC Version 4.00b or Version 4.50
 editor, the following programs fail to pass the COMMON SHARED variable
 m$. There are no error messages at compile time or run time. The
 CHAINed program uses a period in an array name that appears to
 conflict with a separate user-defined type. Neither the array nor the
 user-defined type variable is passed in COMMON. The programs run
 correctly in QuickBASIC Version 4.00 or when run from an .EXE program
 compiled in Version 4.00b or Version 4.50.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00b and 4.50. This problem was corrected in the QBX.EXE environment
 of the Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 The following is a code example:

    'The CHAINing program, PROG1.BAS:
    COMMON SHARED m$
    m$ = "Nice to see you.  Sometimes I don't print, but I should!"
    CHAIN "prog2"

    'The CHAINed-to program, PROG2.BAS:
    COMMON SHARED m$
    TYPE t
      a AS INTEGER
    END TYPE
    DIM c.n(5)    'If the period is taken out, it works correctly.
    DIM d AS t    'If this line is taken out, or if d is DIMmed to
                  'something else, it works correctly.
    PRINT m$


 275. Assembly Routine Using STD Works in QB 3.00, Not 4.00

 Product Version(s): 3.00 4.00 4.00B 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  6-DEC-1989    ArticleIdent: Q33626

 An assembly-language subprogram that uses the STD instruction (sets
 the direction flag to indicate that strings will process down from
 high addresses to low addresses) may not print the string correctly in
 QuickBASIC Version 4.00 unless the flag is first cleared before
 returning, using the CLD instruction. Although this is the recommended
 way to program the assembly language subprogram, QuickBASIC Version
 3.00 prints the string correctly even if the flag was not cleared.

 The following is a code example:

 'This BASIC program calls the MASM subprogram RTrim, with a string variable
 'and an integer as variables. Rtrim looks at the given string and returns
 'the string's length, minus any trailing blank characters.

 DEFINT A-Z
 length = 0
 INPUT "String: ", x$         'Take a string, any string....
 x$ = x$ + STRING$(2, 32)     'Add two trailing blank characters.
 PRINT x$; LEN(x$)            'Print the string and its length.
 CALL RTrim(x$, length)
 x$ = LEFT$(x$, length)       'Chop off any trailing blanks.
 PRINT x$; LEN(x$)            'Print the new string and its new length.
 END

 .MODEL  MEDIUM
 .CODE
         PUBLIC RTrim
 RTrim   PROC
         push    bp
         mov     bp,sp
         push    es
         push    ds              ;Be sure ES and DS match.
         pop     es
         mov     bx,[bp+8]       ;Get the string's descriptor.
         mov     di,[bx+2]       ;DI points to the string.
         mov     cx,[bx]         ;Get the string's length in CX.
         jcxz    exit            ;Length = 0?  If it is, then exit.
         add     di,cx           ;DI points past the string.
         dec     di              ;DI now points to the last character in
                                 ;the string.
         std                     ;Direction: High to Low.
         mov     al,20h          ;Blank to look for.
         repe    scasb           ;Repeat until a character other than
                                 ;a blank is found.
         mov     bx,[bp+6]       ;Now get the word to store the length.
         jnz     go_on           ;If found then go ahead,
         mov     word ptr [bx],0 ;else store 0 in the word pushed as 2nd
         jmp     short exit      ;parameter, then exit.
 go_on:  inc     cx
         mov     [bx],cx         ;Store it in Arg1.
 exit:   cld                     ;****Need this to run with QuickBASIC 4.00.
         pop     es              ;Restore the initial values for ES and
         pop     bp              ;BP as required.
         ret     4               ;Pop off the two parameters before
 RTrim   ENDP                    ;returning to caller.
         END

    The following are the results without the CLD instruction in
 QuickBASIC Version 4.00:

    String: abcdefghijklmnopqrstuvwxyz
    abcdefghijklmnopqrstuvwxyz   28
    a8   zyxwvutsrqponmlkjif 26

    The following are the results in QuickBASIC Version 3.00, or with
 the CLD instruction in QuickBASIC Version 4.00:

    String: abcdefghijklmnopqrstuvwxyz
    abcdefghijklmnopqrstuvwxyz   28
    abcdefghijklmnopqrstuvwxyz 26


 276. SHELL in QuickBASIC Version 3.00 May Overwrite String Space

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 fixlist4.00 fixlist4.00b fixlist4.50
 Last Modified: 16-DEC-1989    ArticleIdent: Q33627

 The following program incorrectly prints x$(0) as "WExxxxx" instead of
 "xxxxxxx" after the SHELL in QuickBASIC Version 3.00. If you do a
 FRE("") before the SHELL statement, the problem goes away. The program
 runs correctly in QuickBASIC Version 4.00.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 3.00 in the editor or when compiled. This problem does not occur in
 Microsoft QuickBASIC Versions 4.00, 4.00b, or 4.50 for MS-DOS or in
 QBX.EXE which comes with Microsoft BASIC PDS Version 7.00
 (fixlist7.00) for MS-DOS and MS OS/2.

 The following is a code example:

    DECLARE SUB test (y$())
    OPEN "temp" FOR RANDOM AS #1 LEN = 10
    CLOSE #1
    OPEN "temp" FOR RANDOM AS #2 LEN = 1
    CLOSE
    a$ = CHR$(0) + CHR$(0)
    DIM x$(dumb)
    x$(0) = "xxxxxxx"
    CALL test(x$())

    SUB test (y$()) STATIC
    PRINT y$(0)               'prints "xxxxxxx".
    'p = fre(""): p=fre(-1)
    SHELL
    PRINT y$(0)               'prints "WExxxxx".
    END SUB


 277. LINK "Too Many Groups in One Module" with 30+ Named COMMONs

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q33628

 If a program has more than 30 named COMMON blocks, it will give the
 following error at LINK time:

    fatal error L1050:  too many groups in one module

 The program runs correctly inside the QuickBASIC editor.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 3.00, 4.00, and 4.00b; in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS OS/2 and MS-DOS (buglist6.00, buglist6.00b); and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS OS/2 and MS-DOS (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 In QuickBASIC version 3.00, the error message is as follows:

    Too many GRPDEFS in one module

 LINK.EXE is limited to support only 21 GRPDEF records per .OBJ module;
 BASIC needs to be better optimized to produce a minimum number of
 GRPDEF records per .OBJ module when using named COMMON blocks. This
 feature is under review and will be considered for inclusion in a
 future release.

 The following code example duplicates the problem:

    COMMON SHARED /Ann/ a1
    COMMON SHARED /Brent/ a2
    COMMON SHARED /Bill/ a3
    COMMON SHARED /Darren/ a4
    COMMON SHARED /Jeff/ a5
    COMMON SHARED /Jim/ a6
    COMMON SHARED /John/ a7
    COMMON SHARED /Kyle/ a8
    COMMON SHARED /LiKai/ a9
    COMMON SHARED /Michelle/ a10
    COMMON SHARED /Mike1/ a11
    COMMON SHARED /Mike2/ a12
    COMMON SHARED /Nancy1/ a13
    COMMON SHARED /Nancy2/ a14
    COMMON SHARED /Rich/ a15
    COMMON SHARED /Sholeh/ a16
    COMMON SHARED /Teri/ a17
    COMMON SHARED /Terri/ a18
    COMMON SHARED /Terry/ a19
    COMMON SHARED /Todd/ a20
    COMMON SHARED /Tom/ a21
    COMMON SHARED /Greg/ a22
    COMMON SHARED /Ziggy/ a23
    COMMON SHARED /Dudley/ a24
    COMMON SHARED /Beowulf/ a25
    COMMON SHARED /Daffy/ a26
    COMMON SHARED /Yoda/ a27
    COMMON SHARED /Peewee/ a28
    COMMON SHARED /Desslok/ a29
    COMMON SHARED /Mel/ a30
    COMMON SHARED /Harrison/ a31
    PRINT "OK!"


 278. "Illegal Function Call" SHELLing to More Than 124 Characters

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q33629

 The SHELL statement takes a string expression of 124 characters or
 less. QuickBASIC Versions 4.00 4.00b and 4.50 for MS-DOS, the BASIC
 compiler Version 6.00 and 6.00b for MS-DOS or MS OS/2, or Microsoft
 BASIC PDS Version 7.00 for MS OS/2 and MS-DOS give an "Illegal
 function call" error message for longer strings.

 In QuickBASIC Version 3.00, the same limitation applies; however, the
 string expression is truncated without any error message if it is
 longer than 124 characters. If the string is longer than 271
 characters in QuickBASIC Version 3.00, a "string space corrupt" error
 message results.


 279. "Illegal Function Call" Using SCREEN 0 Pages, then SCREEN 1

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  5-DEC-1988    ArticleIdent: Q33685

 When invoking multiple video pages (as in SCREEN 0) and then switching
 to a SCREEN that does not support multiple pages (SCREEN 1), the error
 "Illegal function call" will occur on the second SCREEN statement, as
 in the following example:

    SCREEN 0,,1,0
    SCREEN 1       'This gives "Illegal function call"

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in the Microsoft BASIC Compiler Version 6.00 for
 MS-DOS and MS OS/2 (buglist6.00). This problem was corrected in
 QuickBASIC Version 4.50.

 A workaround is to reset both pages to zero with another SCREEN
 statement just before changing screen modes, as in the following code
 example:

 SCREEN 0,,1,0
 SCREEN 0,,0,0  'Resets both pages to 0
 SCREEN 1


 280. Temporary Memory in SUBprogram Is Not Deallocated after CALL

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q33687

 In EXE form, the following program uses 8K of memory, not 4K as it
 should. The program does not seem to deallocate the temporary memory
 after calling the dynamic subprogram. The program works correctly
 inside the QB.EXE editor. To duplicate the problem, the array needs to
 be dimensioned after the COMMON block (to make it dynamic) and 4K of
 data needs to be assigned inside the subprogram, as shown.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00,
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 To work around the problem, declare the array as static instead of as
 dynamic. You can make the array static by dimensioning it before the
 COMMON statement.

 Note: This problem does not occur in QuickBASIC Version 3.00.

 The following code example demonstrates this problem:

    DECLARE SUB SaveWindow (WindowBuffer$)
    COMMON tmp$()
    DIM tmp$(10)
    PRINT FRE(""), FRE(-1)
    CALL SaveWindow(tmp$(5))
    PRINT FRE(""), FRE(-1),
    END
    SUB SaveWindow (WindowBuffer$)
      size% = 4000
      WindowBuffer$ = STRING$(size%, CHR$(0))
    END SUB


 281. Sample BASIC Code to Display ROM-BIOS Date for an IBM PC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_BasicInt B_GWBasicI H_Mach20
 Last Modified: 16-DEC-1989    ArticleIdent: Q33706

 Getting the ROM-BIOS (Read-Only Memory, Basic Input/Output System)
 date for a computer can be an important clue in diagnosing a variety
 of potential hardware- and software-compatibility problems.

 Page 60 of "The Peter Norton Programmer's Guide to the IBM PC"
 (published by Microsoft Press, 1985) provides the following BASIC
 program to display the ROM-BIOS date in month-day-year format for an
 IBM PC:

 DEF SEG = &HF000
 FOR i = 0 TO 7
   PRINT CHR$(PEEK(&HFFF5 + i));
 NEXT

 This sample program applies to most Microsoft BASIC products for the
 IBM PC, including the following:

 1. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02,
    2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 5.35, 5.36, 6.00, 6.00b, for
    MS-DOS.

 3. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS.

 If your IBM PC ROM-BIOS is dated prior to 10/27/82, then the following
 restrictions apply:

 1. You may not be able to address a full 640K -- only 544K or so
    may be available.

 2. The machine will not be compatible with the Microsoft MACH 20
    board.

 3. Because the ROM-BIOS is earlier than 10/27/82, you have an
    IBM PC 1 with a 16/64K motherboard (logic board).
    This machine does not support hard drives, and just supports
    floppies.

 4. IBM no longer offers the 10/27/82 ROM-BIOS upgrade for ROM
    versions earlier than 10/27/82 if you have a 16/64K motherboard.
    (IBM does currently upgrade the BIOS for the 64/256K motherboard.)

 5. Other BIOS-related restrictions or problems may occur.

 Another way to determine the age of your PC is to look on the
 front-left corner of your motherboard (logic board). IBM PC 1 machines
 are stamped with 16/64K. IBM PC 1 machines usually have ROM-BIOS
 Versions earlier than 10/27/82, and they don't support hard drives.
 IBM PC 2 machines are stamped with 64/256K on the motherboard and can
 optionally support hard drives.


 282. "Error R6000: Stack Overflow" in Non-Stand-Alone Program

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  7-FEB-1989    ArticleIdent: Q33707

 When certain programs that are heavily laden with $INCLUDE statements
 are compiled in BC.EXE without the /O option (not stand-alone), the
 following run-time error can repeatedly display on the screen for
 about 20 seconds, and then the computer can hang:

    R6000:Stack Overflow

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00b and 4.50, and in the Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). We
 are researching this problem and will post new information as it
 becomes available.

 The current workaround is to reduce the number of $INCLUDE statements.

 With QuickBASIC Version 4.00b and BASIC Compiler 6.00 and 6.00b, the
 problem usually does not occur if you compile with the BC /O
 (stand-alone) option. However, the error message occurs for both
 stand-alone and non-stand-alone programs with QuickBASIC Version 4.50.

 This problem does not occur in QuickBASIC Versions 4.00 or earlier.


 283. "Subscript Out of Range" DIM SHARED Dynamic Array in SUBmodule

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-FEB-1990    ArticleIdent: Q33712

 A "Subscript out of range" message displays at run time when a dynamic
 array is dimensioned using REM $DYNAMIC and DIM SHARED statements at
 the module level of a support (nonmain) module (composed of just
 subprogram or FUNCTION procedures). In contrast, if the DIM SHARED
 array is a statically dimensioned array instead of a dynamically
 dimensioned array, the program runs without the error message. This
 difference between dynamic and static arrays is not a problem with
 QuickBASIC, but occurs because a DIM for a dynamic array is an
 executable statement (processed only if encountered in the flow of
 control at run time), whereas a DIM for a static array is a
 nonexecutable statement (always processed at compile time).

 This information applies to QuickBASIC Versions 4.00b and 4.50 for
 MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and OS/2.

 A DIM for a dynamic array is only executed at run time if the
 program's control flows through that DIM statement. Since no
 executable statements are ever executed at the module-level of a
 support (nonmain) module, the DIM statements for dynamic arrays at the
 module level of a support module are ignored. "Subscript out of Range"
 displays for the first time an undimensioned array is referenced in
 the subprogram.

 In contrast, static arrays are allocated at compile time; and the DIM
 statement for a static array at the module-level of a support module
 is always recognized. A DIM statement for a static array is a
 compile-time, nonexecutable statement.

 When compiling to an EXE file, be sure to produce debug code (that is,
 compile with the /D switch) to catch array problems.

 To work around the compiler's ignoring of DIM SHARED for dynamic
 arrays at the module level of support modules, dimension the dynamic
 array in the main module (source file), and pass the array to the
 second module (separate source file) using the COMMON SHARED statement
 in both modules.

 The following code fails with a "Subscript out of range" error when an
 element of the array is assigned to a value:

 Module #1
 ---------

    DECLARE SUB test()
    CALL test

 Module #2
 ---------

    REM $DYNAMIC            'will work if this is commented out
    DIM SHARED a(10,30,30)
    SUB test STATIC
    a(1,1,1) = 4           'Subscript out of range error
    PRINT a(1,1,1)
    END SUB

 The following code successfully shares the dynamic array with the
 procedure in the support module:

 Module #1
 ---------

    DECLARE SUB test()
    REM $DYNAMIC
    COMMON SHARED a()
    DIM a(10,30,30)
    CALL test

 Module #2
 ---------

    COMMON SHARED A()
    SUB test STATIC
    a(1,1,1) = 4
    PRINT a(1,1,1)
    END SUB


 284. Passing Strings to Assembler Routines Written for GW-BASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 21-JUN-1989    ArticleIdent: Q33714

 Assembler routines that are written to run with Microsoft GW-BASIC (or
 with IBM BASICA or Compaq BASICA) and are passed a string variable as
 an argument will not run properly when called from QuickBASIC compiled
 programs. This problem arises because the length of the string
 descriptor for QuickBASIC strings (4 bytes) is 1 byte longer than the
 string descriptor for the GWBASIC.EXE or the BASICA interpreter (3
 bytes).

 One solution to this problem is to simulate a GW-BASIC string in
 QuickBASIC and pass this simulated string to the assembler routine.
 The assembler routine does not need to be modified when this method is
 used.

 Note that many other more complicated factors (such as memory
 management of code and data) may also prevent assembler routines that
 were designed for GW-BASIC or BASICA to be successfully called from
 compiled BASIC. Many assembler routines may require rewriting.

 This information applies to QuickBASIC Versions 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50 and to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2.

 The following program shows how to simulate a GW-BASIC string in
 QuickBASIC and pass it to an assembly routine that is expecting a
 GW-BASIC string:

 DIM a AS STRING * 11  'The length of this fixed-length string should be
                       'the maximum number of characters to pass to the
                       'assembly routine plus 3 (8 + 3 in this case).
 DIM c%(&H20)          'Reserves an area into which an assembly program
                       'may be loaded.
 COMMON c%()           'Causes the array to be in the default data segment
                       'when running in the editing environment.
 CLS
 BLOAD "gwstr.bin", VARPTR(c%(0))  'Load assembly routine into reserved area
 st$ = "printer"        'String to pass to the assembly routine
 addr% = VARPTR(a)      'Get the address of the fixed length string
 addr% = addr% + 3      'Compute the address of the actual string data

                        'This line creates a 3-byte header and combines
                        'that with the actual string data
 a = CHR$(LEN(st$)) + CHR$(addr% MOD 256) + CHR$(addr% \ 256) + st$

                        'Passes to the assembly routine a pointer to
                        'the simulated GW-BASIC string.
 CALL absolute(BYVAL VARPTR(a), VARPTR(c%(0)))
 END

 Programming Notes
 -----------------

 To simulate the GW-BASIC string, a fixed-length string is used. The
 first three characters of the fixed-length string are used to simulate
 the 3-byte string descriptor used in GW-BASIC. (Note that a
 fixed-length string has no string descriptor, thus VARPTR points to
 the actual string.)

 In GW-BASIC or BASICA, the first byte of the descriptor is the length
 of the string data and the next two are the offset of the string data.
 Because we are putting the string data into the fixed-length string in
 the characters following the 3-byte header, we can compute the offset
 of the string data by getting the offset of the fixed-length string
 and adding 3 to it.

 The offset of the string data is put into low byte-high byte format
 and placed into the second and third bytes of the string descriptor.
 The offset to the fixed-length string is passed to the assembly
 routine. Because the first three characters of the fixed-length string
 simulate a GW-BASIC string descriptor, the assembly routine thinks it
 is receiving a GW-BASIC string. It does not matter that the descriptor
 and string data are contiguous in memory.


 285. "Floating Point Error" with Inboard 386 Configured Incorrectly

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  7-DEC-1989    ArticleIdent: Q33715

 A "Floating Point Error" may occur when using an Inboard 386 that does
 not have a math coprocessor with QuickBASIC Version 4.00b or 4.50. The
 error occurs when the Inboard 386 is configured as though it has a
 math coprocessor when it does not have one. Configuring the board
 properly solves the problem.

 This information also applies to the Microsoft BASIC Compiler Version
 6.00b for MS-DOS and MS OS/2.

 The "Floating Point Error" does not occur with QuickBASIC Version 4.00
 because the presence of the coprocessor is detected differently than
 it is in Versions 4.00b and 4.50.


 286. COM1 and COM2: Communications Device Default Buffer Size

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 11-JUN-1990    ArticleIdent: Q33732

 The receive and transmission buffer sizes for COM1 and COM2 default to
 512 bytes in Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50, and
 in Microsoft BASIC Compiler versions 6.00 and 6.00b [and in Microsoft
 BASIC Professional Development System (PDS) version 7.00, as described
 in a separate article].

 A sentence under the /C:buffersize option (in the section "Using BC
 Command Options") on Page 210 of the manuals listed below incorrectly
 states the following: "the default receive-buffer size is 256 bytes
 total for both ports." The default receive-buffer size is actually 512
 bytes for both the COM1 and COM2 communications ports. The affected
 manuals are as follows:

 1. Page 210 of "Microsoft QuickBASIC 4.0: Learning and Using
    QuickBASIC" for QuickBASIC 4.00 and 4.00b

 2. Page 210 of "Microsoft BASIC Compiler 6.0: Learning and Using
    QuickBASIC" for Microsoft BASIC Compiler versions 6.00 and 6.00b

 The section "Using BC Command Options" on Page 354 of the following
 manual incorrectly states that "the transmission buffer is allocated
 128 bytes for each communications port" and should be changed to say
 that 512 bytes is the default transmission buffer size:

    Page 354 of "Microsoft BASIC 4.5: Programming in BASIC" manual for
    QuickBASIC version 4.50

 Note that the default receive buffer size (512 bytes) is CORRECTLY
 documented in the following places:

 1. Page 298 in the "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" manual for versions 4.00 and 4.00b

    This page correctly documents the RB[n] and TB[n] options for the
    OPEN COM statement. RB[n] changes the receive buffer size and TB[n]
    changes the transmission buffer size in the OPEN COM statement. The
    RB option overrides the receive buffer size specified by the /C
    option (if any). There is no compile-time option (including /C)
    that affects the transmission buffer size; TB is instead used in
    the OPEN COM statement at run time.

 2. Page 151 of "Microsoft QuickBASIC 4.5: Learning to Use" manual for
    version 4.50

 3. Page 354 of "Microsoft QuickBASIC 4.5: Programming in BASIC" manual
    for version 4.50


 287. CHAIN, RUN, and KILL Statements Do Not Use MS-DOS Search PATH

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_BasicInt B_GWBasicI B_BBasic
 Last Modified: 16-DEC-1989    ArticleIdent: Q33736

 The CHAIN "FILESPEC", RUN "FILESPEC", and KILL "FILESPEC" statements
 do not use the search path of the MS-DOS PATH (or APPEND) command to
 find the specified file. Therefore, the file that a BASIC program
 wants to CHAIN, RUN, or KILL either must be on the default disk or
 directory, or the explicit path must be specified in the "FILESPEC"
 argument. Non-compliance results in the error message "File not
 Found."

 This information applies to all versions of Microsoft BASIC, including
 the following:

 1. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 3. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 5. Microsoft GW-BASIC Interpreter Versions 3.20 and later

 6. Microsoft BASIC Interpreter Version 5.28 for MS-DOS

 The MS-DOS PATH command may be used to specify the search path for the
 compiled BASIC run-time module, BRUNxx.EXE.

 Normally, all programs that are CHAINed or RUN together are put in the
 same directory. This works even if they use different BRUNxx.EXE files
 (taken from different compiler versions) for programs that are
 executed with RUN "FILESPEC", but does not work for CHAIN "FILESPEC".

 If you specify the explicit disk and directory path in the CHAIN or
 RUN statement in the program source code, the program will have to be
 recompiled if the CHAINed or RUN program is moved to a different disk
 and/or directory.


 288. GOTO a Labeled ELSE Fails in QB.EXE 4.00 and 4.00b Editor

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  4-DEC-1988    ArticleIdent: Q34015

 A QuickBASIC .EXE program compiled with BC.EXE Versions 4.00 or 4.00b
 allows a jump to a labeled ELSE statement in an IF...END IF block.
 However, in the QB.EXE Version 4.00 or 4.00b environment, control
 falls through to the END IF.

 To work around this problem, do not use a labeled ELSE.

 Microsoft has confirmed this to be a problem in Versions 4.00 and
 4.00b. This problem has been corrected in QuickBASIC Version 4.50.

 Note: in QB.EXE and QB87.EXE from QuickBASIC Version 3.00, the
 statements after the ELSE are correctly executed.

 The following code example demonstrates the problem:

 IF x = 0 THEN
         PRINT "this is before else"
         GOTO 100
 100 ELSE
         PRINT " this is after else"
 END IF


 289. "Internal Error" Using Fixed String in First TYPE Element

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b B_BasicCom fixlist4.50
 Last Modified: 12-DEC-1989    ArticleIdent: Q34078

 When the first element in the user-defined TYPE in the program below
 is a fixed-length string, BC.EXE gives an "Internal error near xxxx"
 at compile time.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00 and buglist6.00b). This
 problem does not occur in the QB.EXE environment. This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC PDS
 Version 7.00 (fixlist7.00).

 Note that the TYPE...END TYPE statement is not found in QuickBASIC
 Versions 3.00 or earlier.

 The following code example demonstrates the problem:

      Declare sub initialize (e as any)   'declares sub initialize

      Type  REC
       a as string * 32
       b as long
       c as long
      End Type

      Dim e as REC
      Call initialize(e)
      Print e.c
      print results

      Sub initialize (s as rec)
         s.b =64
         s.c = s.b
      End sub


 290. Use CONST N=45, Not CONT N=45, Documentation Error in 4.00

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q34113

 The following correction applies to Page 25 of the following manuals:

 1. "Microsoft QuickBASIC Version 4.0: BASIC Language Reference"
    manual for Versions 4.00 and 4.00b

 2. "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
    Versions 6.00 and 6.00b for MS-DOS and MS OS/2

 The example for the symbolic constant on Page 25 should read

    CONST N=45

 instead of:

    CONT N=45

 This information was corrected in the documentation for Microsoft
 QuickBASIC 4.50 and Microsoft BASIC PDS 7.00.


 291. "Wrong Number of Dimensions" When Declaring Arrays in COMMON

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q34114

 The program below, when run inside the QuickBASIC Version 4.00 or
 4.00b editor, gives a "Wrong number of dimensions" error message and
 points to where the array w() is declared COMMON SHARED.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in the QB.EXE that comes with the Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00
 and buglist6.00b). This problem was corrected in QuickBASIC Version
 4.50 and in QBX.EXE of the Microsoft BASIC Compiler Version 7.00
 (fixlist7.00).

 The program runs correctly if compiled with BC.EXE.

 The program runs correctly if one of the following workarounds is
 used:

 1. Variables and arrays in the second COMMON statements are in reverse
    order.

 2. Arrays are made $DYNAMIC.

 3. Size of the arrays is changed.

 4. z19 is moved in front of w().

 The problem does not occur in QuickBASIC Version 3.00.

 The following is a code example:

    DIM a(202), b(202), c(202), d(202), e(202)
    DIM f(202), g(202), h(202), j(202), k(202)
    DIM l(202), m(202), o(202), p(202), q(202)
    DIM r(202), s(202), t(202), u(202), v(202)
    DIM w(20), x(10)
    COMMON z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, a(), b(),_
           c(), d(), e(), f(), g(), h(), j(), k(), l(), m()
    COMMON z11, z12, z13, z14, z15, z16, z17, z18, o(), p(),_
           q(), r(), s(), t(), u(), v(), w(), z19, x()
    PRINT "Got this far ....."


 292. Complete Listing of SCREEN Modes for Compiled BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR#891130-1156 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q51858

 Below is a complete listing of the modes of the SCREEN statement for
 Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and
 Microsoft BASIC PDS Version 7.00 for MS-DOS.

 This information can also be found in the BASIC language reference
 manuals for the above products, in the QB.EXE 4.50 (but not 4.00 or
 4.00b) on-line Help screen, and in the QBX.EXE 7.00 on-line Help
 screen.

 The color adapter acronyms are defined as follows.

    MDPA = IBM Monochrome Display and Printer Adapter
    MCGA = IBM Multicolor Graphics Array
    HGC  = Hercules Graphics Card
    CGA  = IBM Color Graphics Adapter
    EGA  = IBM Enhanced Graphics Adapter
    VGA  = IBM Video Graphics Array

 Note: See the WIDTH statement documentation for more information about
 changing the number of rows and columns on the display

 The PALETTE statement works only on systems equipped with the EGA,
 VGA, or MCGA adapters. The PALETTE statement is not supported in
 screen modes 3 or 4.

 The following information briefly summarizes each of the screen modes.

 MDPA, CGA, MCGA, EGA, Hercules, Olivetti, or VGA Adapter Boards
 ---------------------------------------------------------------

 SCREEN 0

 *  Text Mode only.
 *  Either 40 x 25, 40 x 43, 40 x 50, 80 x 25, 80 x 50 text format with
    character-box size of 8 x 8 (8 x 14, 9 x 14, or 9 x 16 with EGA or
    VGA).
 *  Assignment of 16 colors to either of 2 attributes.
 *  Assignment of 16 colors to any of 16 attributes (CGA and EGA).
 *  Assignment of 64 colors to any of 16 attributes (EGA and VGA).

 CGA, EGA, VGA, or MCGA Adapter Boards
 -------------------------------------

 SCREEN 1

 *  320 x 200 pixel medium-resolution graphics.
 *  40 x 25 text format with character-size of 8 x 8.
 *  Assignment of 16 background colors and one of two sets of 3
    foreground colors assigned using COLOR statement with CGA.
 *  Assignment of 16 colors to 4 attributes with EGA, VGA, or MCGA.
 *  Note: If you want to have a choice of color for text on the CGA
    adapter you can use BIOS interrupt 10 Hex, with function 9 (write
    character and attribute at cursor), to output text characters in
    various colors.

 SCREEN 2

 *  640 x 200 pixel high-resolution graphics.
 *  80 x 25 text format with character-box size of 8 x 8.
 *  Two colors (black and white) with CGA.
 *  Assignment of 16 colors to 2 color attributes with EGA or VGA.

 Hercules Graphics Card (HGC)
 ----------------------------

 SCREEN 3

 *  Hercules adapter required, monochrome monitor only.
 *  720 x 348 graphics.
 *  80 x 25 text format, 9 x 14 character box.
 *  Two screen pages (only one, if a second display adapter is installed).
 *  PALETTE statement not supported

 Olivetti and AT&T Graphics
 --------------------------

 SCREEN 4 (Supported in QuickBASIC 4.00b and 4.50, but not in 4.00.)
          (Supported in BASIC PDS 7.00 and the BASIC compiler 6.00b, but
          not in 6.00.)

 *  Supports Olivetti (R) Personal Computers models M24, M240, M28,
    M280, M380, M380/C, M380/T.
 *  Supports AT&T (R) Personal Computer 6300 series.
 *  640 x 400 graphics.
 *  80 x 25 text format, 8 x 16 character box.
 *  One of 16 colors assigned as the foreground color (selected by the
    COLOR statement); background is fixed at black.
 *  WARNING: Olivetti computers running in real mode (DOS 3.x box)
    under OS/2 must avoid SCREEN 4.

 EGA and VGA Adapter Boards
 --------------------------

 SCREEN 7

 *  320 x 200 pixel medium-resolution graphics.
 *  40 x 25 text format, character box 8 x 8.
 *  32K page size. Page ranges are 0 to 1 (64K adapter memory), 0 to 3
    (128K adapter memory), or 0 to 7 (256K adapter memory).
 *  Assignment of 16 colors to any of 16 color attributes.

 SCREEN 8

 *  640 x 200 pixel high-resolution graphics.
 *  80 x 25 text format with character-box size 8 x 8.
 *  64K page size. Page ranges are 0 (64K adapter memory), 0 to 1
    (128K), or 0 to 3 (256K).
 *  Assignment of 16 colors to any 16 color attributes

 SCREEN 9

 *  640 x 350 pixel enhanced-resolution graphics.
 *  80 x 25 or 80 x 43 text format with character-box size of 8 x 14 or
    8 x 8.
 *  For 64K page size, page range is 0 (64K).
 *  For 128K page size, page range is 0 for 128K adapter memory or 0 to
    1 for 256K adapter memory.
 *  Assignment of 16 colors to 4 attributes (64K adapter memory), or 64
    colors assigned to 16 attributes (more than 64K of adapter memory).

 EGA and VGA Adapter Boards with Monochrome Display Only
 -------------------------------------------------------

 SCREEN 10

 *  640 x 350 enhanced-resolution graphics.
 *  80 x 25 or 80 x 43 text format with character-box size of 8 X 14 or
    8 x 8.
 *  128K page size, page range 0 (128K adapter memory) or 0 to 1
    (256K).
 *  Up to 9 shades of gray (pseudocolors) assigned to 4 attributes.

 VGA and MCGA Adapter Boards
 ---------------------------

 SCREEN 11

 *  640 x 480 pixel very high-resolution graphics.
 *  80 x 30 or 80 x 60 text format with character-box size of 8 x 16 or
    8 x 8.
 *  Assignment of up to 256K colors to 2 attributes.

 SCREEN 13

 *  320 x 200 pixel medium-resolution graphics.
 *  40 x 25 text format with character-box size of 8 x 8.
 *  Assignment of up to 256K colors to up to 256 attributes.
 *  Note: This mode offers the best color range available on the VGA.

 VGA Only
 --------

 SCREEN 12

 *  640 x 480 pixel very high-resolution graphics.
 *  80 x 30, 80 x 60 text format with character-box size of 8 x 16
    or 8 x 8.
 *  Assignment of up to 256K colors to up to 16 attributes.
 *  Note: This mode offers the best resolution with most colors
    available at that resolution.


 293. Cannot Pass More Than 21 Dynamic Array Elements to Subprogram

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q34279

 Passing more than 20 individual elements of a dynamic array to a
 subprogram or function procedure will produce the compiler error "Too
 many arguments in function call." This limitation occurs for all types
 of dynamic arrays. Either the whole array should be passed, or each
 item should be copied to a temporary variable and then passed to the
 subprogram or function.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50, to the Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 This limitation occurs because of special handling done for dynamic
 arrays. When a subprogram is called, there is no way of ensuring that
 the dynamic array will not move. Therefore, when individual array
 elements are passed by reference, each is copied into a temporary
 location. These temporary locations are passed to the routine and then
 reassigned to the array when the routine is exited. There is a limit
 of 20 temporary locations.

 The following is a complete code example:

 DECLARE SUB test2 (a1!, a2!, a3!, a4!, a5!, a6!, a7!, a8!, a9!,_
                    a10!, a11!, a12!, a13!, a14!, a15!, a16!, a17!,_
                    a18!, a19!, a20!, a21!)
 x = 30
 DIM a(x)
 CALL test2(a(1), a(2), a(3), a(4), a(5), a(6), a(7), a(8), a(9),_
            a(10), a(11), a(12), a(13), a(14), a(15), a(16), a(17),_
            a(18), a(19), a(20), a(21))
 END

 SUB test2 (a1!, a2!, a3!, a4!, a5!, a6!, a7!, a8!, a9!, a10!, a11!,_
            a12!, a13!, a14!, a15!, a16!, a17!, a18!, a19!, a20!, a21!)

     PRINT "hello"

 END SUB

 The following is the compiler output:

 Microsoft (R) QuickBASIC Compiler Version 4.00b
 Copyright (C) Microsoft Corp. 1982-1988. All rights reserved.
  0053   0006  ...a(18),a(19),a(20),a(21))
                                    ^ Too many arguments in function call

 43059 Bytes Available
 37660 Bytes Free

     0 Warning Error(s)
     1 Severe  Error(s)


 294. QB "String Space Corrupt" Using a CONST in a FIELD Statement

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q34280

 If a CONST constant is used as a variable in a FIELD statement and the
 program is run more than once in the QuickBASIC Environment (QB.EXE),
 a "String Space Corrupt" error will be generated.

 BC.EXE correctly flags this programming error at compile time with the
 message "Variable required."

 Microsoft has confirmed this to be a problem in the QB.EXE in
 Microsoft QuickBASIC Versions 4.00 and 4.00b, and in the version of
 QuickBASIC shipped with the Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS OS/2 and MS-DOS (buglist6.00 and buglist6.00b). This
 problem was corrected in QuickBASIC Version 4.50 and in the QBX.EXE
 environment of the Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 To duplicate the problem, run the following sample program twice in
 the QuickBASIC Environment (QB.EXE):

    const x="x"
    open "test" as #1
    field #1, 10 as x$

 If this program is compiled with BC.EXE, the compiler correctly flags
 the programming error as follows:

 Microsoft (R) QuickBASIC Compiler Version 4.00b
 Copyright (C) Microsoft Corp. 1982-1988. All rights reserved.
  0030   0006    field #1, 10 as x$
                                 ^ Variable required

 43059 Bytes Available
 42804 Bytes Free

     0 Warning Error(s)
     1 Severe  Error(s)


 295. BC Hangs on a POKE with a FUNCTION Passed a Dynamic Array

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q34283

 BC.EXE hangs at compile time when compiling the program below. This
 program uses a POKE statement that directly invokes a FUNCTION
 procedure that is passed a dynamic-array element as an argument.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00 and buglist6.00b). This
 problem has been corrected in QuickBASIC Version 4.50 and in
 Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 The following are several workarounds for this problem:

 1. Make the array STATIC instead of DYNAMIC.

 2. Use a temporary variable to pass the array element to the FUNCTION
    procedure.

 3. Use a temporary variable to receive the value returned from the
    FUNCTION and POKE that temporary variable.

 Note that Page 201 of the "Microsoft QuickBASIC 4.0: BASIC Language
 Reference" manual gives the following related information:

    "Because BASIC may rearrange arithmetic expressions for
     greater efficiency, avoid using FUNCTION procedures that
     change program variables in arithmetic expressions."

 The following code example demonstrates the problem:

 REM This program demonstrates the problem at compile-time in BC.EXE
 DEFINT A-Z
 DECLARE FUNCTION charOff (row)
 REM $DYNAMIC
 DIM SHARED a(4)  AS INTEGER
 ' Poke a value returned by a function that is passed a dynamic
 ' array element:
 POKE charOff(a(1)), 210
 END

 FUNCTION charOff (row)
 END FUNCTION


 296. CLEAR Can Cause READ/DATA "Syntax Error" in Non-Stand Alone

 Product Version(s): 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q34285

 A CLEAR statement will not correctly restore the DATA for a READ
 statement in a program compiled with the BRUNxx.LIB run-time library
 in QuickBASIC Version 4.00b, or in Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2. When run, the program will give
 a "Syntax error" message at the first READ statement.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.00b and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 (buglist6.00 and buglist6.00b). This problem does not occur when run
 in the QB.EXE editor environment. This problem was corrected in
 QuickBASIC Version 4.50 and in Microsoft BASIC Compiler Version 7.00
 (fixlist7.00).

 The following are two workarounds for the problem:

 1. Compile in BC.EXE Versions 4.00b or 6.00b as a stand-alone program
    instead of with the BRUNxx.LIB run-time library.

 2. Insert a RESTORE statement after the CLEAR statement.

 If the RESTORE statement is inserted, the following program will run
 correctly. Otherwise, when compiled and run, you will receive a
 "Syntax error on line 30" error message:

 10 CLEAR
    'RESTORE
 20 DATA 1, 2
 30 READ a, b
 40 PRINT a, b
 50 INPUT ; r$
 60 IF r$ <> "q" THEN GOTO 10    'Type "q" to end program.


 297. Coprocessor Is Slower in QuickBASIC 4.00b, 4.50 than in 4.00

 Product Version(s): 3.00 4.00 4.00 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 fixlist4.00b SR# S890119-106
 Last Modified:  7-FEB-1989    ArticleIdent: Q34405

 Programs compiled in QuickBASIC Version 4.00 (or the coprocessor
 version of QuickBASIC 3.00) generally run faster on a coprocessor than
 when compiled in later QuickBASIC Versions (4.00b or 4.50) or in BASIC
 Compiler Version 6.00 or 6.00b. There is little speed difference
 between versions when run on a computer that has no coprocessor.

 This behavior occurs because the coprocessor math routines in Version
 4.00 of QuickBASIC are different than the coprocessor math routines
 used in later versions of QuickBASIC (4.00b or 4.50) or in the
 Microsoft BASIC Compiler 6.00 or 6.00b. The math routines were updated
 to correct certain problems in the earlier routines. Additional
 coprocessors were required to wait in the new routines, which can
 cause slower program-execution time in programs that take advantage of
 an installed math coprocessor.

 In a benchmark test of floating-point calculations on a computer
 equipped with an 80287 coprocessor, QuickBASIC Version 4.00b is
 anywhere from 5- to 30-percent slower than QuickBASIC Version 4.00,
 depending on the type of coprocessor used. There is no appreciable
 speed difference for computers without a coprocessor.

 This speed reduction is necessary in Version 4.00b to correct some
 erroneous results associated with coprocessor timing-coordination
 problems in QuickBASIC Version 4.00 and the coprocessor version
 (QB87.EXE) of QuickBASIC Version 3.00.

 Microsoft confirmed the timing problems in QuickBASIC Versions 3.00
 and 4.00. The problems were corrected in QuickBASIC Version 4.00b (and
 later) and in the BASIC Compiler Version 6.00 (and later) and its
 copy of QuickBASIC.

 A consequence of correcting the timing coordination problems is slower
 coprocessor speed in QuickBASIC Version 4.00b or 4.50 than in Version
 3.00 or 4.00.

 The following benchmark example can be used to compare various
 versions of QuickBASIC:

 start = TIMER
 FOR k% = 1 TO 10000
         u = 1000.45 - 88998.2
         m = 99999! + 23.5
         x = 1.03 * 99.5
         y = 456.3 / 9876.345
         z = 10.3 ^ 2.3
 NEXT k%
 PRINT "elapsed time="; TIMER - start


 298. BSAVE/BLOAD File Format Explained for BASIC; 7-Byte Header

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified:  9-JAN-1991    ArticleIdent: Q34407

 A file saved with the BSAVE statement has a 7-byte header with the
 following hexadecimal format:

    ww xx xx yy yy zz zz

    ww:     A signature byte equal to 253, which tells DOS and other
            programs that this is a BASIC BSAVE/BLOAD format file.
    xx xx:  The segment address from the last BSAVE.
    yy yy:  The offset address from the last BSAVE.
    zz zz:  The number of bytes BSAVEd.

 This information applies to Microsoft QuickBASIC versions 3.00, 4.00,
 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 This information is provided as is. The BSAVE format is not guaranteed
 to be the same in a future release.

 Microsoft GW-BASIC Interpreter (versions 3.20, 3.22, and 3.23) uses
 the same 7-byte header string, and also repeats the 7-byte string,
 appending it after the final data byte. BASICA (provided in IBM or
 Compaq ROM on some computer models) does not repeat the 7-byte string
 at the end. GW-BASIC and BASICA both terminate the file with ASCII 26,
 also known as a CTRL+Z character (hex 1A). QuickBASIC and Microsoft
 BASIC Compiler don't append CTRL+Z or repeat the 7-byte string at the
 end.

 To determine whether a file was BSAVEd by GW-BASIC, BASICA, or
 QuickBASIC, compare the length of the memory saved against the file
 length. The difference is 15 bytes in GW-BASIC, 7 bytes in QuickBASIC,
 and 8 bytes in BASICA.

 Despite the slight format differences, files BSAVEd under any of the
 three above BASIC dialects correctly BLOAD into each other BASIC.


 299. WRITE# Statement Works with Semicolon Despite BC.EXE Error

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q34610

 Microsoft does not recommend linking object modules that produced one
 or more severe error messages at compile time. The behavior of such
 programs cannot be guaranteed to work in future product versions, or
 even to work at all.

 An example is shown below for the case of improperly using a WRITE#
 statement with a trailing semicolon with the intent to suppress a
 carriage return. PRINT# is intended for this purpose, not WRITE#.

 This information applies to QuickBASIC Versions 4.00 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 According to Page 455 of the "Microsoft QuickBASIC 4.0: BASIC Language
 Reference" manual for QuickBASIC Versions 4.00 and 4.00b, the WRITE#
 statement should not allow a semicolon at the end of its arguments.
 QB.EXE correctly displays an "Expected:Expression" error message on
 the WRITE# statement at run time. A "Syntax Error" is correctly
 produced when the BC.EXE compiler tries to compile the following
 program, which has a semicolon at the end of a WRITE statement:

 open "data" for output as #1
 write #1, str$(5);    ' This line is not allowed to have a ";"
 write #1, str$(5)
 close #1

 Despite the "severe" error message at compile time, BC.EXE produces an
 object module that can be linked into an executable program. This
 program executes as you might expect a WRITE# with a semicolon at the
 end to work (i.e., no carriage return or linefeed). However, this
 behavior cannot be guaranteed for future versions.

 Note that the PRINT# statement can be used in place of the WRITE#
 statement if you wish to use a trailing semicolon to suppress the
 carriage return, as shown in the following program:

 open "data" for output as #1
 PRINT#1, CHR$(34) + STR$(5) + CHR$(34) + ", ";    'This is allowed.
 write #1, str$(5)
 close #1

 The WRITE# statement delimits output arguments with commas, and also
 places double quotation marks around string arguments.


 300. Communications (COM1:, COM2:) Receive Buffer Lost During CHAIN

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  8-FEB-1990    ArticleIdent: Q34682

 The communications receive buffer is cleared when chaining to another
 module; at this point, data can be lost. This problem occurs only in a
 compiled .EXE program, and does not occur in the QB.EXE editor.
 Compiling with the BC /d (debug) option does not help. Data received
 at the communications port after the CHAIN operation is received
 normally.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).

 The programs below demonstrate the problem:

    ' File: P1.BAS
    OPEN "com1:1200,e,7,1,cs,ds" FOR RANDOM AS #2
    for x=1 to 10000 :next
    y=loc(2)
    print y;
    CHAIN "p2"    'Chain to second program and print out buffer size

    ' File: P2.BAS
    a$=input$(loc(2),2)
    print a$;

    ' File:P.bas
    'This program will send the characters
    open "com1:1200,e,7,1,cs,ds" for random as #1
    print "start"
    for x=1 to 10000
    print #1, x;
    next x
    close #1


 301. QB.EXE Search and "Change..." on Line Label in IF...GOTO Hangs

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q34810

 The QB.EXE editor hangs when using the Change option from the Search
 menu to replace a line label that is contained in an IF <cond> GOTO
 <linelabel> statement.

 You can work around this problem by putting a THEN in the IF...GOTO
 statement (i.e., IF...THEN GOTO) before selecting Change from the
 Search menu.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b and the QuickBASIC editor that comes with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 QuickBASIC Version 4.50 and in QBX.EXE of Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 When the Change feature proceeds to the line containing the searched
 line label or number, it prompts you with "Change, Skip, Quit." When
 you press "C" to change the highlighted item, the line label
 disappears and the computer hangs.

 The following code example demonstrates the problem:

 10 a = a + 1
 20 PRINT a
 30 IF a < 10 GOTO 10
 40 PRINT "A = 10!"

 In the above program, perform Change from the Search menu on the line
 number 10. It will change the first 10, but will hang on the second
 one.

 To work around the problem, insert a THEN into the IF statement as
 follows:

 30 IF a < 10 THEN GOTO 10


 302. "Type Not Defined" after Saving Program in QB.EXE; Use AS ANY

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q34813

 A user-defined variable type is defined with a TYPE...END TYPE
 statement. You must place a TYPE...END TYPE statement at the top of
 each separate module that uses that type.

 Note that a "Type Not Defined" error occurs if a DECLARE statement
 mentions a user-defined type (y AS usertype) above the TYPE...END TYPE
 definition. This condition can occur after a Save in QB.EXE
 automatically adds a DECLARE statement (for a separately-loaded
 module) at the top of the main module.

 To eliminate the "Type Not Defined" error, move the DECLARE statement
 below the TYPE...END TYPE statement, or change the type in the DECLARE
 statement to "ANY", as follows:

 DECLARE SUB temp (y AS ANY)

 This information applies to QuickBASIC Versions 4.00 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Note that if the SUBprogram is in the same module as the main program,
 AS ANY is automatically added in the DECLARE statement during a Save
 in QB.EXE, and the "Type not defined" error does not occur.

 If the SUBprogram is in a different module (i.e., a separate source
 file) than the main program, a Save or Save All automatically adds a
 DECLARE statement in the main program, which can cause a "Type not
 defined" error, as shown in the following steps:

 1. Run QB.EXE, enter the following program, and save it as TEST.BAS:

    ' This is the main module.
    TYPE config
       TROW  AS INTEGER
    END TYPE
    DIM x AS config
    CALL temp(x)

 2. Choose the Create File command from the File menu, enter the module
    name TEMP.BAS, and enter the following program:

    ' This is TEMP.BAS, a subprogram module in a separate disk file.
    TYPE config
       TROW  AS INTEGER
    END TYPE
    SUB temp (y AS config) STATIC
    PRINT "test"
    END SUB

 3. Choose Start from the Run menu to show that the program runs
    correctly.

 4. Choose Save All from the File menu. During the Save, QB.EXE
    automatically adds a DECLARE statement in TEST.BAS as follows:

    DECLARE SUB temp (y AS config)
    ' This is the main module.
    TYPE config
       TROW     AS INTEGER
    END TYPE
    DIM x AS config
    CALL temp(x)

 5. Now, when you choose Start from the Run menu, the above DECLARE
    statement will give a "Type not defined" error. The error occurs
    because the DECLARE statement uses the "config" type before it has
    been defined (immediately below). (The compiler passes just once
    from top to bottom through the source to define variables.)

 6. To eliminate the "Type not defined" error, move the DECLARE
    statement below the TYPE...END TYPE statement, or change "config"
    in the DECLARE statement to "ANY", as follows:

    DECLARE SUB temp (y AS ANY)


 303. QB.EXE "String Space Corrupt" Editing First Label in SUB

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 12-DEC-1989    ArticleIdent: Q34913

 The QuickBASIC QB.EXE editor displays the error message "String Space
 Corrupt" when you perform the following steps:

 1. Run QB.EXE and type the following subprogram:

    sub anyname
    label:

 2. Position the cursor on the first column of the line that contains
    the label, then press the BACKSPACE key. The "String Space Corrupt"
    error message displays, control drops back to DOS, and the computer
    hangs, forcing you to restart it.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b, and in the QuickBASIC editor that comes with
 the Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). Microsoft has corrected this
 problem in QuickBASIC Version 4.50 and in the QBX.EXE environment of
 the Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 This problem does not occur if the subroutine has parameters, or if the
 first line in the subprogram contains anything other than a label.


 304. PRINT to Viewport Has Screen's Background Color Not Viewport's

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q34917

 When PRINTing text to a viewport that has a different color than the
 main screen, the background color of the text will be the same as the
 background color of the screen, not the viewport. This is expected
 behavior.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 If you have one window on the screen, you can use the following
 method:

 1.  Switch to graphics mode.

 2.  Change the background color to be the color of the window.

 3.  Paint the screen the actual background color.

 4.  Draw the window.

 5.  Print the text.

 Note that steps 2 and 3 will cause a flash on the screen. This cannot
 be avoided. The following is a code sample:

 SCREEN 9
 COLOR 7, 1
 VIEW (0, 0)-(639, 349), 2
 VIEW (100, 100)-(300, 300), 1
 LOCATE 20, 20: PRINT "This is a test"
 WHILE INKEY$ = "": WEND

 The following is a code example of the undesired result:

 REM  This is a sample program that demonstrates printing
 REM  text to a viewport. The background color of the text
 REM  printed to the viewport is the same as that of the
 REM  screens.
   CLS
   SCREEN 9
 REM Screen has green foreground and light blue background:
   COLOR 10, 11
 REM Set up first viewport with red background:
   VIEW (10, 10)-(600, 200), 12, 11
 REM Print is green with light blue background:
   LOCATE 1, 11: PRINT "Outer viewport"
 REM Set up second viewport with purple background:
   VIEW SCREEN (50, 50)-(350, 150), 5, 7
 REM Print is green with light blue background:
   LOCATE 9, 9: PRINT "Inner viewport"
   END


 305. "Expected End of Statement," Line Label with Leading Numeric

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q34981

 QuickBASIC Versions 4.00, 4.00b and 4.50 do not allow a leading
 numeric character in a line label. QuickBASIC assumes that any line
 label starting with a number to be a line number followed by an
 executable statement. If such a line label is entered within the
 QuickBASIC Version 4.00 or 4.00b editing environment, an "Expected
 End of Statement" error message is displayed. For a detailed
 explanation, refer to Page 9 of the "Microsoft QuickBASIC Compiler
 4.0: BASIC Language Reference" manual.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 QuickBASIC Version 3.00 does allow leading numbers in a line label. To
 convert a QuickBASIC Version 3.00 program to QuickBASIC Version 4.00,
 4.00b or 4.50, select the Change option in the Search menu to replace
 all occurrences of the improper label with a valid line label or line
 number.

 The following program generates an "Expected End of Statement" error:

 PRINT "hello"
 GOTO 2line
 2line:
         PRINT "goodbye"


 306. Using GOSUB, GOTO, ON Event GOSUB, ON ERROR GOTO in Modules

 Product Version(s): Ox2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35143

 A normal GOSUB Label or GOTO Label statement must be at the same level
 of code as the label. For example, if a GOSUB Label statement occurs
 inside a SUB...END SUB (or FUNCTION...END FUNCTION) procedure block,
 the label must also occur within that block.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 Only the BASIC compiler 7.00 has an enhanced form of local error
 trapping in which the label may be local to the current SUB or
 FUNCTION, as the following example shows:

 SUB SUB1
      ON LOCAL ERROR GOTO errorhandler

 EXIT SUB
 errorhandler:
      RESUME NEXT
 END SUB

 However, the following statements must have their labels at the module
 level:

    ON ERROR GOTO Label
    ON Event GOSUB Label (where "Event" may be COM, KEY, PEN, PLAY,
                         STRIG, or TIMER)

 The "module level" is defined as the area in a source file that is
 outside all subprogram or FUNCTION procedure blocks.

 Once the ON Event GOSUB Label and Event ON statements are executed,
 event trapping continues until an Event OFF is executed (where "Event"
 may be COM, KEY, PEN, PLAY, STRIG, or TIMER).

 In QuickBASIC Versions 2.00, 2.01, 3.00, and 4.00, the ON ERROR GOTO
 Label statement must be established for each module; otherwise, an
 error occurring in that module will not be trapped, and the program
 will stop.

 In contrast to earlier versions, QuickBASIC Versions 4.00b and 4.50
 and Microsoft BASIC Compiler Versions 6.00, 6.00b, and 7.00 for MS-DOS
 and MS OS/2 offer global handling of ON ERROR (as explained in the
 UPDATE.DOC disk file). With global error-handling, an ON ERROR handler
 in the main program handles errors occurring in separate modules when
 those modules do not have their own ON ERROR handlers.

 For related information query on the following words:

    subprogram and module and error and resume and QuickBASIC

 The following is a code example:

 ' MODULE 1
 DECLARE SUB mod2sub2 ()
 DECLARE SUB mod1sub1 ()
 DECLARE SUB mod2sub1 ()
 ON ERROR GOTO errhand1  ' Sets first error handler in main module
 KEY 15, CHR$(0) + CHR$(1)  ' Sets up trapping of ESCAPE key.
 KEY(15) ON                 ' Turns on trapping of ESCAPE key.
 ON KEY(15) GOSUB lower     ' "lower" label is at module level
 PRINT "in main"
 GOSUB lower    ' You may GOSUB or GOTO a label in this module
                ' only at the level of the main module.
 CALL mod1sub1
 CALL mod2sub1  ' Establishes an error handler for mod2
 CALL mod2sub2
 ERROR 3
 END
 lower:
   PRINT "This gosub/label can be reached";
   PRINT " only from main level mod1 or"
   PRINT "by pressing the ESCAPE key the";
   PRINT " first time in mod2 sub1": PRINT
   RETURN
 errhand1:
   PRINT "take care of error on main level mod 1": PRINT
   RESUME NEXT
 SUB mod1sub1
     GOSUB localLabel  ' localLabel must be local to the subroutine
     GOTO done:
   localLabel:
     PRINT "I am here in mod1 sub1 simulating error in mod1 subprog1"
     ERROR 1    'this error is handled ok
     RETURN
   done:
 END SUB

 ' MODULE 2
 mod2: PRINT "this does not get activated/ mod2 main "
 mod2main:
   PRINT "simulating error in nextmod mod2 main called from subprog2"
   ERROR 1
   RETURN
 errhand2:
   PRINT " took care of the error in mod2 top level":PRINT
   RESUME NEXT
 SUB mod2sub1
    ON ERROR GOTO errhand2
 '  Must get new direction once per module in
 '  QuickBASIC 3 AND 4. However, in QuickBASIC
 '  4.00b and BASIC Compiler 6.00, errhand1 will still trap the error
 '  but RESUME NEXT resumes at the END SUB.
    PRINT "simulating an error "
    ERROR 1
    PRINT "press escape"    ' ESCAPE here causes jump
    FOR i = 1 TO 10000: NEXT ' to routine defined in main
    ON KEY(15) GOSUB mod2main ' but after this
    PRINT "press escape again" ' ESCAPE now causes jump
    FOR i = 1 TO 10000: NEXT    ' to nextmod
 END SUB
 SUB mod2sub2
    ERROR 2  'this is ok if mod2sub1 is called first
 END SUB


 307. "String Space Corrupt" If Drive Door Open, & QB.INI Not Found

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b B_BasicCom fixlist4.50
 Last Modified:  8-DEC-1989    ArticleIdent: Q35145

 When all of the following conditions are true, invoking the QuickBASIC
 editor from the DOS command line will give a "String Space Corrupt"
 error and hang your machine:

 1. The Drive A or Drive B door is open.

 2. A:\ or B:\ is in the DOS search path, for example:

       PATH=A:\;B:\

 3. The QB.INI file is not present in the current directory or in any
    directory appearing in the search path before A:\ or B:\.

 Microsoft has confirmed this to be a problem in the QB.EXE editor that
 comes with Microsoft QuickBASIC Compiler Versions 4.00 and 4.00b and
 with Microsoft BASIC Compiler Versions 6.00 (buglist6.00) and 6.00b
 (buglist6.00b) for MS-DOS and MS OS/2. This problem was corrected in
 QuickBASIC Version 4.50 and in QBX.EXE of Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 QB.INI is a file that automatically is created when the settings in
 the QB.EXE editor are changed with the Options command from the View
 menu.

 The QuickBASIC environment automatically looks for the QB.INI file
 immediately upon start-up. If the file is not in the current
 directory, QuickBASIC uses the search path in its attempt to find the
 file.

 If a floppy drive (Drive A or Drive B) is in the DOS search path and
 the drive door is open, QB.EXE fails to stop the hardware error, and a
 "String Space Corrupt" error occurs. A warm boot (CTRL+ALT+DEL)
 usually must be used to restart the computer.

 The following are three ways to work around the problem:

 1. Remove the floppy specification in the search path.

 2. Make sure there is a disk in the floppy drive and that the door is
    closed.

 3. Create a QB.INI file in your QuickBASIC directory.

 In QuickBASIC Versions 3.00 and earlier, if the drive door is left
 open, the following DOS error message is correctly generated:

    "Not Ready Error Reading Drive A:
    Abort, Retry, Ignore, Fail?"


 308. Capturing Paintbrush and FRIEZE Screens with QuickBASIC BSAVE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 22-OCT-1990    ArticleIdent: Q35147

 With the Microsoft Mouse Paintbrush package you can create graphic
 images that can be displayed on the screen with the FRIEZE
 terminate-and-stay resident program. This article explains how to save
 a copy of a Paintbrush graphic image in a form that can be used in
 Microsoft BASIC.

 You can invoke FRIEZE with hardware interrupt 5 from a Microsoft BASIC
 program. With FRIEZE versions 7.25 and earlier, you can load a
 Paintbrush image into video memory. The BSAVE statement in BASIC lets
 you write a video memory image into a disk file, which can be used by
 the BASIC BLOAD command. BLOAD lets you load images from a
 BSAVE-format disk file back into video memory.

 This information only applies to FRIEZE versions 7.25 and earlier.
 This article does not apply to FRIEZE versions 8.05 or later, which do
 not have a load option.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS.

 An easier technique to create BLOAD format graphics files (from file
 formats used by a variety of graphics programs) is to use the
 PICEM.EXE freeware program. PICEM.EXE is described in a separate
 article, which can be found by querying for the following words:

    PICEM and freeware

 The following steps demonstrate this process:

 1. Load the FRIEZE program into memory. (FRIEZE is a TSR, a
    terminate-and-stay-resident program, provided with the Microsoft
    Mouse PaintBrush program.)

 2. Run BASIC Program 1 (below), which invokes hardware interrupt
    number 5. This interrupt activates FRIEZE, which appears as a
    horizontal menu in the upper-left corner of the screen. Execution
    of BASIC Program 1 is now suspended by the interrupt.

 3. Using the Load option in the FRIEZE menu, load the desired
    PaintBrush image.

 4. Immediately after the image loads, the BASIC Program 1
    automatically resumes running and executes the BSAVE statement. The
    BSAVE statement saves the current screen to a disk file. Program 1
    then stops.

 5. You may run Program 2 at any later time to display the image that
    is stored in the IMAGE.PIC disk file.

 Code Examples
 -------------

 Program 1
 ---------

    REM The QB.BI definition file is found on the QuickBASIC release disk:
    REM For BASIC Compiler 7.00 and QBX.EXE you must include 'QBX.BI'
    REM $INCLUDE: 'qb.bi'
    DIM regs AS RegType
    SCREEN 3   ' Use SCREEN 3 for Hercules display adapter.
    CALL INTERRUPT(&H5, regs, regs)   ' Invokes hardware interrupt 5.
    DEF SEG = &HB000 ' Monochrome video memory starts at address &HB000
    ' If you have a CGA display, change the previous SCREEN and DEF SEG
    ' statements to the following:
    ' SCREEN 1
    ' DEF SEG = &HB800  ' Starting Video memory address for CGA is &HB800
    BSAVE "image.pic", 0, 32767
    DEF SEG   ' Returns segment pointer to default data segment.

 Program 2
 ---------

    SCREEN 3   ' Use SCREEN 3 for Hercules display adapter.
    DEF SEG = &HB000
    ' If you have a CGA, change the previous two statements to the
    ' following:
    ' SCREEN 1
    ' DEF SEG = &HB800
    BLOAD "image.pic", 0
    DEF SEG


 309. Underline, Reverse, Intense, Blinking in Monochrome SCREEN 0

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 16-DEC-1989    ArticleIdent: Q35148

 On the Hercules Graphics Adapter (HGA) or the IBM Monochrome Display
 Adapter (MDA), the foreground and background arguments of the COLOR
 statement support underlined, reverse-video (highlighted), blinking,
 or high-intensity characters. Reverse/underline and intense/reverse
 combinations are not supported by HGA or MDA.

 The following 11 combinations of COLOR statement foreground and
 background values are available on monochrome, SCREEN 0 (text)
 displays:

    FORMAT                  COLOR Statement       ATTRIBUTE

 White on black (normal)       COLOR 7,0              7
 Black on black (no display)   COLOR 0,0              0
 Black on white (reverse)      COLOR 0,7            112
 Underline                     COLOR 1,0              1
 Intense                       COLOR 10,0            10
 Blinking                      COLOR 18,0           130
 Reverse blinking              COLOR 16,7           240
 Intense underline             COLOR 9,0              9
 Intense blinking              COLOR 26,0           138
 Underline blinking            COLOR 17,0           129
 Intense blinking underline    COLOR 25,0           137

 This information applies to the following products:

 1. Microsoft QuickBASIC Compiler Versions 4.00, 4.00b, 4.50

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 4. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and later

 In SCREEN 0 with a color card (CGA, EGA, or VGA), the COLOR statement
 is used to change the foreground and background colors that are
 displayed. The COLOR statement also lets you select intense or
 blinking options for the foreground color. Underlining is not
 supported on color monitors.

 In text mode (SCREEN 0), two consecutive bytes are used to store each
 character in screen memory. One byte contains the ASCII value of a
 character, and the following byte contains ATTRIBUTE information for
 that character. Attributes can be calculated with the following
 formula:

 ATTRIBUTE = 128*(FOREGROUND\16)+BACKGROUND*16+(FOREGROUND MOD 16)

 [Note: The backslash character (\) is the integer division operator.]

 See Pages 79-81 of "The Peter Norton Programmer's Guide to the IBM PC"
 (published by Microsoft Press, 1985) for more information about
 attributes.

 The following book from Microsoft Press describes video details more
 completely:

    "Programmer's Guide to PC & PS/2 Video Systems," by Richard Wilton
    (1987). Chapter 3 describes the alphanumeric video modes.

 The following is a code example:

 'This program will display all of the character formats resulting from
 'each of the 32 foreground colors available for any of the 8
 'recognized background colors with a monochrome card in SCREEN 0 (text
 'mode).

    DEFINT A-Z
 5  CLS
    LOCATE 20, 15
    COLOR 7, 0
    liner = 0
    INPUT "background="; back
    FOR fore = 0 TO 31
         IF liner = 16 THEN
                 liner = 0
         END IF
         liner = liner + 1
         LOCATE liner, 1 + (20 * (fore \ 16))
         PRINT fore; back;
         COLOR fore, back
         PRINT "A"
         COLOR 7, 0
    NEXT fore
    WHILE INKEY$ = "": WEND
    GOTO 5


 310. WYSE 1400 Keyboard Input Is Not Recognized by QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 17-OCT-1990    ArticleIdent: Q35151

 It has been reported that the WYSE 1400, a computer based on the Intel
 8086 processor, is not compatible with QuickBASIC version 4.00 because
 the keyboard cannot be accessed by compiled programs. Although the
 screen is recognized by QuickBASIC, any INPUT or INKEY$ reportedly
 hangs the system. OPENing the "KYBD:" device name as a file does not
 correct the problem.

 This information may also apply to Microsoft QuickBASIC versions 4.00b
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS version 7.00.

 Microsoft has not confirmed or tested this information. Corrections to
 this information can be reported to Microsoft Product Support
 Services.


 311. No Underlining on Color Display in BASIC Text Mode, SCREEN 0

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 12-DEC-1989    ArticleIdent: Q35153

 There is no way to display underlined characters in text mode (SCREEN
 0) on a color display. Only an IBM Monochrome Display Adapter (MDA) or
 a Hercules Graphics Adapter (HGA) which is connected with a monochrome
 display device can display underlined characters in SCREEN 0. This is
 a result of the way that the video attributes are encoded in video
 memory and is a limitation of the hardware, not BASIC.

 Note that in graphics mode, you may draw lines wherever desired, and
 you can emulate the monochrome underlining capability.

 This information applies to the following products:

 1. Microsoft QuickBASIC Compiler Versions 2.00, 2.01, 3.00, 4.00, and
    4.00b

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
    OS/2 and Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 3. The Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and later
    (Note that on Hercules or monochrome adapters, GW-BASIC can use
    text SCREEN 0 but does not support graphics screen modes.)

 See Pages 79-81 of "The Peter Norton Programmer's Guide to the IBM PC"
 (published by Microsoft Press, 1985) for more information about text
 mode attributes.

 The following book from Microsoft Press describes video details more
 completely:

 "Programmer's Guide to PC & PS/2 Video Systems," by Richard Wilton
 (Microsoft Press, 1987). Chapter 3 describes the alphanumeric video
 modes (i.e., SCREEN 0).


 312. On IBM PS/2 MCGA, SCREEN 1 and 2 Are Monochrome

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35240

 The Multi-Color Graphics Array (MCGA) adapter is the video subsystem
 integrated into the IBM PS/2 Models 25 and 30. MCGA combines modes of
 both the Color Graphics Adapter (CGA) and the Video Graphics Array
 (VGA) graphic display cards.

 The modes of the MCGA have colors and attributes, but its
 CGA-emulation modes have no way to assign colors to attributes within
 BASIC programs. In other words, there are effectively no colors for
 SCREEN 1 and 2 on the MCGA (or CGA) in BASIC -- the output is white on
 black.

 Note that the color capabilities for SCREEN 11 and SCREEN 13 are
 identical for MCGA and VGA.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 The following book from Microsoft Press describes video details more
 completely:

    "Programmer's Guide to PC & PS/2 Video Systems: Maximum Video
    Performance from the EGA, VGA, HGC, and MCGA" by Richard Wilton (1987)


 313. Using Dual Video Display Cards and Monitors with QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35241

 QuickBASIC allows limited use of two video-display system cards within
 the same application if the host computer has both a color video card
 and monitor, plus a monochrome card and monitor. Only the default
 display (the one that was active when QuickBASIC was invoked) has a
 cursor and graphics capability.

 The method requires OPENing "CONS:" FOR OUTPUT AS #n, POKEing the
 video-mode specifier of the desired output screen into memory location
 449 hex, then using a PRINT #n to display text on the desired output
 monitor. It is important to use "CONS:", not "SCRN:" in the OPEN
 statement. "SCRN:" is always associated with the default display.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 There is no practical way to put graphics images on the secondary
 display in QuickBASIC. See Pages 54 and 55 of "The Peter Norton
 Programmer's Guide to the IBM PC" (published by Microsoft Press, 1985)
 for a list of settings for the video mode. The following code example,
 which uses 7 (for a monochrome adapter) and 3 (for 80-column text, 16
 colors), works with a computer that has a Hercules-compatible
 monochrome adapter and an EGA color display:

 OPEN "cons:" FOR OUTPUT AS #1
 DEF SEG = 0
 PRINT #1, "This should be on the DEFAULT Screen."
 POKE &H449, 7
 PRINT #1, "This should be on the MONO Screen."
 POKE &H449, 3
 PRINT #1, "This should be on the COLOR Screen."


 314. To Suppress Linefeed, OPEN "lpt1" BINARY or "LPT1:BIN" RANDOM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890508-55
 Last Modified: 12-DEC-1989    ArticleIdent: Q35244

 When the LPRINT statement sends CHR$(13) (a carriage return) to the
 printer, it automatically adds a linefeed, CHR$(10). This automatic
 linefeed prevents the ability to overtype or underline a previously
 printed line.

 The following methods let you suppress the automatic linefeed, as
 shown in complete programs further below:

 1. OPEN "LPT1:BIN" FOR RANDOM AS #n
    WIDTH#n,255

 2. OPEN "lpt1" FOR BINARY #n
    [Note that this method requires the "lpt1" device name to have
    no colon (:).]

 These methods should also be used if you want to send control
 characters to your printer, such as for printer-graphics mode.
 Otherwise, the programs below can create garbled graphics output [e.g.
 the extra linefeed is printed after byte values of 13, and ASCII
 values of 9 (horizontal tab) are converted to 8 spaces].

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 You cannot suppress the LPRINT statement's linefeed that is
 automatically sent along with a carriage return. Instead, you must use
 PRINT#n to send output to special device names as shown in the
 examples below.

 The following programs demonstrate how to print a carriage return (the
 ASCII character 13) without an automatic linefeed.

 Example of Using "LPT1:BIN" Device Name FOR RANDOM Output
 ---------------------------------------------------------

 OPEN "LPT1:BIN" FOR RANDOM AS #1
 WIDTH#1,255
 PRINT #1, "This is a test to do underlining.";
 PRINT #1, CHR$(13);
 PRINT #1, "_________________________________";
 PRINT #1, CHR$(13);
 CLOSE #1

 Example of Using "LPT1" Device Name FOR BINARY Output
 -----------------------------------------------------

 REM  This sample program overprints on one line,
 REM  allowing you to underline the text "Seattle Times".
 C$ = CHR$(13)         ' 13 = ASCII code for carriage return
 LPRINT
 OPEN "lpt1" FOR BINARY AS #1
 LPRINT "Seattle Times";
 PUT #1, , C$
 LPRINT "_______ _____"
 CLOSE #1
 END

 Overprinting Using "LPT1:", "LPT1:BIN", and "LPT1:" in Sequence
 ---------------------------------------------------------------

 ' This works in QuickBASIC but not in GW-BASIC.
 ' This program should output the following:
 ' program output: hello world
 ' "hello" should print over itself twice.
 CLS
 OPEN "lpt1:" FOR OUTPUT AS #1
 PRINT #1, "program output:  "
 CLOSE
 OPEN "lpt1:bin" FOR OUTPUT AS #1
 FOR I = 1 TO 3
    PRINT #1, CHR$(&HD);    ' Carriage Return with no Line Feed
    PRINT #1, "hello";
 NEXT
 CLOSE
 OPEN "lpt1:" FOR OUTPUT AS #1
 PRINT #1, " world."
 CLOSE
 PRINT "done printing"
 END


 315. Fixed-Length Strings Are Initialized to NULL (0), Not Blanks

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q35245

 The information below about fixed-length string arrays should be
 inserted in the following manuals:

 1. "Microsoft QuickBASIC 4.0: BASIC Language Reference"

 2. "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
    Versions 6.00 and 6.00b for MS OS/2 and MS-DOS

 On Pages 156, 174, and 352, under the DIM, ERASE, and REDIM
 statements, the above manuals state that elements of string arrays are
 initialized to null strings (strings of zero length). However, this is
 not the case with fixed-length strings. Fixed-length strings are
 initialized as a string of null bytes (with ASCII value of 0). The LEN
 function always returns the complete length of the fixed-length
 string. If a fixed-length string is initialized to "" (the null
 string), it is completely filled with blank spaces (ASCII value of
 32).

 This documentation error was corrected in the QuickBASIC 4.50 and
 Microsoft BASIC PDS 7.00 documentation.

 The following is a code example:

 DIM j AS STRING * 4
 c$ = CHR$(0) + CHR$(0) + CHR$(0) + CHR$(0)
 CLS
 PRINT "j is printed between the stars:  *"; j; "*"
 PRINT "j looks like a string of blanks, but it's not."
 IF j = c$ THEN PRINT "j equals CHR$(0) + CHR$(0) + CHR$(0) + CHR$(0)."
 IF j <> "" THEN PRINT "j does not equal "; CHR$(34); CHR$(34);
 IF j <> "    " THEN PRINT " or "; CHR$(34); "    "; CHR$(34); "."
 PRINT "But if I set j to "; CHR$(34); CHR$(34);
 j = ""
 IF j = "    " THEN
    PRINT " then j will equal "; CHR$(34); "    "; CHR$(34); "."
 END IF

 The following is the output from the program above:

 j is printed between the stars:  *    *
 j looks like a string of blanks, but it's not.
 j equals CHR$(0) + CHR$(0) + CHR$(0) + CHR$(0).
 j does not equal "" or "    ".
 But if I set j to "" then j will equal "    ".


 316. QB.EXE "Bad File Mode" if First Character Extended ASCII

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 13-DEC-1989    ArticleIdent: Q35247

 The error "Bad File Mode" will occur while opening or loading a
 document file in the QB.EXE editor if an extended ASCII character is
 the very first character in the file. To avoid this error, put a space
 or a blank line before the extended ASCII character so that it is not
 the first character in the file. This error does not occur in the
 QB.EXE editor which comes with Microsoft QuickBASIC Version 4.50 or in
 the QBX.EXE environment that comes with Microsoft BASIC PDS Version
 7.00.

 In the QB.EXE editor in QuickBASIC Versions 2.00, 2.01, and 3.00,
 extended ASCII characters are not allowed within the first 80 bytes of
 the loaded file. (The same is true for QB87.EXE in Version 3.00.)

 Extended ASCII bytes have values from 128 to 255.


 317. No Data Type for 80-Bit Precision IEEE Real Numbers in BASIC

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35248

 QuickBASIC's implementation of the ANSI/IEEE Standard 754-1985 for
 binary floating-point arithmetic includes two types of real numbers:

    Single-precision numbers, which use 32 bits (4 bytes)
    Double-precision numbers, which use 64 bits (8 bytes)

 The ANSI/IEEE standard also describes an 80-bit (10-byte)
 floating-point format called Double Extended. QuickBASIC's
 intermediate calculations are performed in the 80-bit format for
 greater accuracy, but the results are stored in single- or
 double-precision variables. There is no data type in QuickBASIC
 associated with the 80-bit format.

 This article applies to the following products, which use IEEE binary
 floating-point arithmetic:

 1. Microsoft QuickBASIC Versions 3.00 (QB87.EXE only), 4.00, 4.00b,
    and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 ANSI is an acronym for the American National Standards Institute. IEEE
 is an acronym for the Institute of Electrical and Electronics
 Engineers, Inc., which can be reached at the following address:

    IEEE
    345 East 47th Street
    New York, NY 10017 USA


 318. Correction for MHex$ Real Number Format Example

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 12-DEC-1989    ArticleIdent: Q35249

 Page 19 in certain copies of the "Microsoft QuickBASIC 4.0: BASIC
 Language Reference" gives four incorrect statements in the source code
 for MHex$. MHex$ is a user-defined FUNCTION that displays the internal
 format for real numbers.

 The incorrect statements give an integer overflow message because a
 "multiply by 256" should actually be an "integer divide by 256." The
 correction is shown below.

 This documentation error has been corrected in the QuickBASIC 4.50 and
 Microsoft BASIC PDS 7.00 documentation.

 The following is the correct text:

 line 6: ' --the AND removes unwanted bits; dividing by 256 shifts
 line 7: ' the value right 8 bit positions.
 line 10:    Bytes(I)=AsLong& AND &HFF&
 line 11:    AsLong& \ 256&

 This correction is only necessary in certain early copies of the
 manual shipped with QuickBASIC Version 4.00, and is not necessary in a
 later edition of the manual shipped in the Version 4.00 package.

 The following is the incorrect text in earlier QuickBASIC Version 4.00
 manuals:

 line 6: 'Note that dividing shifts the bytes right, and the AND
 line 7: ' removes unwanted bits.
 line 10:      Bytes(I) = AsLong& \ Shift& AND &HFF&
 line 11:      Shift&=Shift&*256


 319. "Subscript Out of Range" Using SGN Function Compiled BC /d

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q35282

 An incorrect "Subscript out of range" error can occur at run time when
 a program using the SGN function in a formula is compiled with the
 debug (BC /d) option. To correct the problem, assign the SGN function
 to a temporary variable and use the temporary variable in the formula.

 The program below demonstrates the problem on machines with or without
 a coprocessor:

 a(1) = (b(1) + 1) * SGN(c)

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in QuickBASIC Version 4.50 and in Microsoft
 BASIC Compiler Version 7.00 (fixlist7.00).

 The problem happens more frequently on machines with coprocessors,
 although the problem may occur on machines without them. The problem
 seems to occur when a program has the following characteristics:

 1. The program is compiled to an executable .EXE program.

 2. The program is compiled using the debug option (/d).

 3. The program contains an assignment statement with the following
    features:

    a. The assignment is made to a real number array element.

    b. The SGN expression is used in a formula that contains a
       reference to an array element and another operation of some
       kind.


 320. QB.EXE Single Step Is Not Reliable with $INCLUDE Lines

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified:  8-DEC-1989    ArticleIdent: Q35354

 When using the F8 key in the QuickBASIC editor to single step through
 a program that has included lines, the current line is not always what
 it should be. QuickBASIC will not single step through the second
 include file.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b and in the QB.EXE editor that comes with the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in
 QuickBasic Version 4.50 and in QBX.EXE of the Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 The following program can be used to demonstrate this problem:

 ' Include file INC1.H:
   GOTO 900

 ' Include file INC2.H:
   900 PRINT "At 900"
   905 PRINT "At 905"
   908 END

 ' QuickBASIC program INCTEST.BAS:
   REM $INCLUDE: 'INC1.H'
   REM $INCLUDE: 'INC2.H'

 To reproduce the problem using the above program, do the following:

 1. Choose the Included Lines option on the View menu.

 2. Choose the Restart option on the Run menu.

 3. Press F8 to single step.

 The current line is at 908, not at 900 as expected.


 321. SCREEN 0 "Illegal Function Call," MCGA Only Supports 4 Pages

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q35356

 The "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual states
 on Page 380 under Table R.12 that the IBM MCGA graphics card supports
 eight pages in screen mode 0 (text mode). However, an "Illegal
 Function Call" will result when trying to access video pages 4 through
 7.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and OS/2 (buglist6.00, buglist6.00b). This problem was
 corrected in QuickBASIC Version 4.50 and in Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 Note that versions of Microsoft QuickBASIC earlier than Version 4.00
 do not support the MCGA.

 The following is a code example:

 for i=0 to 7
 Screen 0,,i
 next i


 322. BLOAD Can Fail with Older Monochrome Cards; Newer Cards OK

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-FEB-1991    ArticleIdent: Q35357

 On older monochrome cards, BLOAD may not work correctly. The symptoms
 are that BLOAD displays only the first four lines of the screen and
 then garbage or nothing else. These symptoms are caused by a problem
 in the monochrome card. Updating the monochrome display card should
 solve the problem.

 With Microsoft QuickBASIC versions 4.00 and 4.00b and Microsoft BASIC
 Compiler versions 6.00 and 6.00b, the problem occurs when loading
 either text (SCREEN 0) or graphics (Hercules SCREEN 3) with BLOAD. One
 customer also reported this behavior for Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10.

 Code Example
 ------------

 'Note that this problem can also occur in screen 0:
 DEF SEG = &HB000   ' &HB000 is starting paragraph of monochrome memory
 SCREEN 3, , 0, 0
 LINE (100, 100)-(300, 300)
 BSAVE "test.img", 0, &H8000  ' &H8000 hex is 32,767 decimal
 CLS
 BLOAD "test.img", 0


 323. "Divide by Zero" PRINT USING Double-Precision Format Overflow

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 11-DEC-1989    ArticleIdent: Q35432

 When a double-precision number with an exponent between 99 and 154
 overflows the format of a PRINT USING statement, a "Divide by zero"
 error can display instead of the percent (%) sign, indicating format
 overflow, or the program may hang without displaying an error. If the
 exponent is between 255 and 260, no error message displays, and an
 incorrect number is printed out. Similarly, if a double-precision
 number has an exponential power between -129 and -260, an incorrect
 number is printed, usually a number followed by a line of zeroes.

 The problems occur when run either in the QuickBASIC environment or
 from a compiled .EXE. The symptoms may include getting the "Divide by
 zero" error message, hanging, missing the percent sign, or getting
 incorrect PRINT USING output.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in QuickBASIC Version 4.50 and in  Microsoft
 BASIC Compiler Version 7.00 (fixlist7.00).

 To work around this incorrect handling of PRINT USING overflow, you
 can use a format large enough that does not overflow, as shown in a
 comment in the sample program below.

 The following code example shows the problem:

 'The following program prints 1.5*10^i, where i ranges from -308 to 308.
 'It should print in a uniform stream, but errors will occur when i
 'goes from -260 to -130, 99 to 154, and 255 to 260.
 ON ERROR GOTO foo
 FOR i = -308 TO 308
    a# = 1.5# * (10# ^ i)
    PRINT i; a#;
    PRINT USING "###.###"; a#  ' This line shows problem.
    ' PRINT USING "##.###^^^^^"; a#  ' Workaround: use ^ format.
 NEXT
 END
 foo:
   PRINT "***************************************", ERR
   'When i is between 99 and 154, you get ERR 11, "Division by zero".
   RESUME NEXT


 324. "Bad Record Length" if PUT#1,,x$ where x$ Length = Buffer Size

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35654

 The following information about random file I/O with a variable-length
 string as the third parameter to a GET or PUT was taken from the
 UPDATE.DOC file for QuickBASIC Version 4.00b:

    "The PUT statement encodes the length of the string and
     stores it as the first two bytes of the string. The GET
     statement uses this encoded value to determine how many
     characters to read."

 This behavior of PUT and GET applies to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b and for MS-DOS and MS OS/2, to Microsoft
 QuickBASIC Versions 4.00b and 4.50 for MS-DOS, and to Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 This behavior of PUT and GET is different than in QuickBASIC Version
 4.00, where the string length is not recorded by PUT or used by GET.
 This behavior only applies to variable-length strings, not
 fixed-length strings. The third argument of the PUT and GET statements
 was introduced in QuickBASIC Version 4.00, and is not found in earlier
 versions.

 Note: You will get a "Bad Record Length" error at run time in a
 QuickBASIC Version 4.00b or 4.50 program that uses a variable-length
 string with a length equal to the record length of the OPENed
 random-file buffer as the third parameter of the PUT statement.
 Because the two-byte string length is written to the file in addition
 to the string itself, the record length specified in the "LEN=" clause
 in the OPEN statement must be at least two bytes longer than the
 variable-length string used as the third argument in a PUT.

 Using a third parameter on the PUT or GET statement is not supported
 in versions of QuickBASIC earlier than Version 4.00.

 When you PUT with a third parameter in a QuickBASIC Version 4.00
 program, the length of the string variable is not written; thus you
 can PUT a string that is equal in length to the random-file buffer
 size without error. However, to ensure compatibility with later
 versions, you should add two bytes to the OPENed random-file buffer
 size.

 The following example works in QuickBASIC Version 4.00, but gives a
 "Bad Record Length" error at run time if compiled in QuickBASIC
 Version 4.00b or 4.50, or in Microsoft BASIC Compiler Version 6.00,
 6.00b or 7.00:

 OPEN "junk.dat" FOR RANDOM AS #1 LEN = 15
 FOR k = 1 TO 5   'The following string is 15 characters long:
    a$ = "123456789012345"
    PUT #1, k, a$
 NEXT k

 The following example, which adds two to the record-length value in
 the LEN= clause, works correctly in QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and in Microsoft BASIC Compiler Versions 6.00, 6.00b and
 7.00:

 OPEN "junk.dat" FOR RANDOM AS #1 LEN = 17
 FOR k = 1 TO 5   'The following string is 15 characters long:
    a$ = "123456789012345"
    PUT #1, k, a$
 NEXT k

 This technique should be used to ensure compatibility with releases
 later than Version 4.00.

 If you use a variable-length string as the third argument of a PUT
 statement to write to a random access file in QuickBASIC Version 4.00,
 then reading that record in QuickBASIC Version 4.00b or 4.50 may give
 you a "Bad Record Length for GET" error, or string input of the wrong
 length. This occurs because GET in QuickBASIC Versions 4.00b and 4.50
 interprets the first two bytes after the variable-length string as the
 length, but Version 4.00 did not put the expected two bytes there. To
 work around this compatibility issue, you can modify your Version
 4.00b or 4.50 program to GET into a fixed-length string of the correct
 length.


 325. "Array Already Dimensioned" if 2nd DIM for Static Array in IF

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q35658

 Static arrays are dimensioned at compile time, regardless of whether
 or not the DIM statement is in the program flow of control. For
 example, if the DIM for a static array occurs in an IF statement that
 would never be executed at run time, the array will still be
 dimensioned at compile time. If you attempt to dimension a given
 static array more than once in a source file, you will get an "Array
 Already Dimensioned" error on the second DIM statement at compile
 time, as in the following example:

 10 x = 1
 20 IF x = 2 THEN DIM array(14)
 25 IF x = 1 THEN DIM array(25)  ' "Array Already Dimensioned" compile-time
 30 array(21) = 4
 40 PRINT array(21)

 This behavior occurs in all versions of Microsoft QuickBASIC for the
 IBM PC, in the Microsoft BASIC Compiler Versions 5.35 and 5.36 for
 MS-DOS and Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and in
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The QuickBASIC compiler allocates static arrays as they are
 encountered in one top-to-bottom pass through the source file at
 compile time. In contrast, dynamic arrays are dimensioned only when
 the flow of control reaches a DIM statement at run time.

 By default, arrays are static in the above compilers, unless you DIM
 them with a variable in the subscript. Adding the REM $DYNAMIC
 metacommand to the top of the program makes the arrays default to
 dynamic. Note that arrays are always dynamic in the Microsoft
 GW-BASIC, IBM BASICA, and Compaq BASICA Interpreters.

 The program below is another illustration. The compiled program will
 run without any error message, since the DIM for the static array is
 allocated at compile time. If you added a REM $DYNAMIC statement to
 make all arrays default to dynamic, the compiled program would give a
 "Subscript out of Range" error message at run time:

 10 x = 1
 20 IF x = 2 THEN DIM array(14)
 30 array(11) = 4
 40 PRINT array(11)

 The above program will give a "Subscript out of Range" error in the
 GW-BASIC Version 3.20 interpreter, since the DIM for the dynamic array
 in the IF statement is not executed at run time, and the array in line
 30 defaults to only ten elements.


 326. "Out of Memory" in MS-DOS 4.00, OK in MS-DOS 3.x; 30K Impact

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35662

 MS-DOS Versions 4.00 and later take 30K or more memory than MS-DOS
 Versions 3.x. As a result, a memory-intensive application that
 successfully compiled and executed under MS-DOS Versions 3.x may fail
 to run under MS-DOS Version 4.00.

 You can check if the problem is caused by memory limitations by adding
 a SETMEM(-30000) to the beginning of the program and running under
 MS-DOS Versions 3.x. If the program runs out of memory with this test,
 it may fail with MS-DOS Version 4.00.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.


 327. Create Your Own Non-ASCII Graphics Characters in CGA Graphics

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q35664

 The program below demonstrates how to create your own non-ASCII
 characters for use in CGA screens 1 and 2. This way you can make
 characters such as 1/3, or foreign letters and symbols not found in
 the ASCII or extended-ASCII character set.

 This information applies to Microsoft QuickBASIC Versions 4.00 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 In graphics mode, the bit patterns for ASCII character codes 128
 through 255 are obtained from a table located in RAM. The address of
 this table is located in the Interrupt Vector Table at location
 0000:007C (the vector for interrupt 1F). This location can be modified
 to install modified character sets. Note, that on a standard IBM PC or
 compatible, ASCII characters 0 through 127 are contained in the ROM
 BIOS and cannot be replaced. (The IBM PCjr, which is not supported by
 QuickBASIC, handles these characters differently.)

 To create your own character set, you would create a table of
 characters and replace the current address in the Interrupt Vector
 Table with the address of your table. Keep in mind that the segment
 and offset are stored "backwards" in the table. The following example

    F000: FF54

 would be stored as follows:

    54 FF 00 F0

 The information stored in the table should be an 8 x 8 bitmap for each
 character desired. For example, the following character would be
 represented by the following eight decimal values:

 Character         Decimal Value
 ---------         -------------

 11110000              240
 10010000              144
 10010000              144
 11111110              254
 10010010              146
 10010010              146
 10011110              158
 00000000                0

 The decimal value is the binary value for each line converted to
 decimal.

 Code Example:
 ------------

 The three DATA statements hold the binary coding for the characters to
 be represented. They are a small triangle, a sigma, and a 1/3. In
 binary, the data looks like the following:

 Triangle          Sigma             1/3
 --------          -----             ---

 00000010        11111110          10000100
 00000110        00100000          10001000
 00001110        00010000          10011110
 00011110        00001000          10100010
 00111110        00010000          01000110
 01111110        00100000          10000010
 11111110        11111110          00001110
 00000000        00000000          00000000

 DATA 2,6,14,30,62,126,254,0
 DATA 254,64,32,16,32,64,254,0
 DATA 132,136,158,162,70,130,14,0

 DIM table(100)
 COMMON SHARED table()

 location = VARPTR(table(0))
 segment = VARSEG(table(0))

 DEF SEG = 0: SCREEN 1
   A = PEEK(124)         'Save this information and restore it when done.
   B = PEEK(125)
   C = PEEK(126)
   D = PEEK(127)
   POKE 124, location MOD 256 'This is where the address of the graphics
   POKE 125, location \ 256   'screen characters are stored. The program
   POKE 126, segment MOD 256  'changes this so now it thinks the graphics
   POKE 127, segment \ 256    'characters are stored in the table() array.
 DEF SEG

 FOR I = 1 TO 24
    READ A%                   'Place the created characters into the new
    POKE location + I, A%     'graphics table
 NEXT I

 FOR I = 128 TO 130           'Print the new characters out.
    PRINT CHR$(I) + " ";
 NEXT

 DEF SEG = 0             'Restore to the original graphics character set.
   POKE 124, A
   POKE 125, B
   POKE 126, C
   POKE 127, D
 DEF SEG


 328. INPUT, INKEY$, or INPUT$(n) Don't Accept All ASCII Characters

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q35665

 Extended ASCII characters have values from 128 through 255, and can be
 typed by holding down the ALT key and pressing three digits on the
 numeric keypad. However, there are some extended ASCII characters that
 the INKEY$, INPUT$(1), and INPUT statements/functions cannot accept.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in Microsoft BASIC Compiler
 Version 7.00 (fixlist7.00).

 The only three ALT+KEY combinations that don't display are ALT+244,
 ALT+240 and ALT+253.

 The following is a code example:

 'This program will trap some of the ASCII characters entered with the
 'ALT+xxx method, but not all. For example: ALT+205 will print a 'Í' on
 'the screen, but ALT+253 will not print a superscript 2 on the screen.

 CLS
 CASA:
   a$=INKEY$
   IF a$ <> "" THEN PRINT a$;
   GOTO CASA
 END


 329. In QB.EXE, Improper FOR NEXT Control after NEXT Is Inserted

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q35666

 In the QB.EXE editor, when a NEXT statement is inserted inside a
 nested FOR NEXT loop after a "FOR WITHOUT NEXT" error has occurred,
 loop control is incorrectly executed.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and in the QB.EXE that comes with the
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 (buglist6.00, buglist6.00b). This problem was corrected in the
 Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 To duplicate this problem, do the following:

 1. Enter the following code in the QuickBASIC editor:

       CLS
       FOR k = 1 to 5
         FOR l = 1 to 2
           PRINT k

       NEXT

    Running this will give the FOR WITHOUT NEXT error.

 2. Insert another NEXT statement after the "PRINT k" and run the
    program again.

    The output should be as follows:

       1   1   2   2   3   3   4   4   5   5

    However, it is as follows:

       1   1   2   2

    If the NEXT is inserted after the already existing NEXT, the
    program runs correctly.


 330. OP Parameter Fails to Make OPEN "COM1:" Wait Indefinitely

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q35667

 The manuals listed below incorrectly state that if the OP serial
 communications parameter is specified without a value, the OPEN COM
 statement will wait indefinitely for the port to be opened. The OPEN
 COM statement will actually wait only 10 seconds.

 This correction applies to the following manuals on Pages 298 and 299:

 1. "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
    Versions 4.00 and 4.00b

 2. "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
    Versions 6.00 and 6.00b for MS OS/2 and MS-DOS

 This error also occurs on Page 255 of "Microsoft QuickBASIC 4.5: BASIC
 Language Reference" for Version 4.50.

 This error has been corrected in the Microsoft BASIC PDS Version 7.00
 documentation.

 Code Examples:
 -------------

 The following program demonstrates that you still get a time-out using
 the OP parameter:

 DEFINT A-Z
 PRINT "wait for open"
 OPEN "com1:19200,n,8,,OP,rb4048" FOR RANDOM AS #1
 PRINT "opened"
 .
 .
 .
 END

 As a workaround, you can use the following program, which will wait
 indefinitely with the error handler returning to the OPEN COM line
 until it is opened:

 ON ERROR GOTO check
 trial = 0
 OPEN "com1:9600,n,8,,OP,rb4048" FOR INPUT AS #1
 PRINT "opened...."
 END
 check:
         IF ERR = 24 THEN
                 trial = trial + 1
                 PRINT "open attempt#"; trial
                 RESUME
         ELSE
                 PRINT "fatal error abort"
                 END
         END IF


 331. INPUT Hercules Cursor 2 Pixels High in GWBASIC, 1 in QB 4.50

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 14-DEC-1989    ArticleIdent: Q35716

 When executing an INPUT or LINE INPUT statement in QuickBASIC Version
 4.00 or in Microsoft GW-BASIC Version 3.20, 3.22, or 3.23 on a machine
 with a Hercules monochrome adaptor, the prompt (cursor) is 2 pixels
 high.

 However, the cursor is only 1 pixel high on a Hercules monochrome
 adaptor for the INPUT or LINE INPUT statement in QuickBASIC Version
 4.00b and 4.50, in Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS, and in Microsoft BASIC PDS Version 7.00 for MS-DOS. This
 is behavior is by design.

 On CGA, EGA, VGA, or other nonmonochrome systems, the INPUT and LINE
 INPUT cursor always defaults to one pixel high in all of the product
 versions mentioned in this article.

 You can use the LOCATE statement to change the cursor height if desired,
 as shown in the following example:

 LOCATE 1,1,,10,12  ' Scan lines 10 through 12 define cursor height.
 INPUT a$

 This article assumes that you are in SCREEN 0 (text mode).

 Try running the following code on a Hercules adaptor in GW-BASIC, and
 compare the starting (default) cursor height to QuickBASIC 4.00b or
 4.50. GW-BASIC defaults to a 2-pixel cursor height, QuickBASIC 4.00b or
 4.50 defaults to a 1-pixel cursor height.

 Code Example
 ------------

 CLS
 INPUT x  ' This first INPUT shows default cursor height.
 LOCATE 1, 1, , 10, 10
 INPUT x  ' Compare with a one-pixel high cursor.
 LOCATE 1, 1, , 10, 11
 INPUT x  ' Compare with a two-pixel high cursor.
 LOCATE 1, 1, , 10, 12
 INPUT x  ' Compare with a three-pixel high cursor.


 332. Undocumented BC.EXE Metacommands That Affect .LST Listing

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr
 Last Modified: 17-OCT-1990    ArticleIdent: Q35825

 Placing the following metacommands into your source file affects the
 list (.LST) file generated by the compiler:

    REM $List
    REM $linesize
    REM $title
    REM $subtitle
    REM $page
    REM $pagesize

 These metacommands are correctly documented in the "Microsoft
 QuickBASIC Compiler" version 1.0x manual, and are used by the
 BASCOM.EXE compiler in QuickBASIC versions 1.00, 1.01, and 1.02. Note
 that these metacommands do not apply to QuickBASIC versions 2.00,
 2.01, and 3.00, which do not output a source-listing .LST file.

 The above metacommands work with the BC.EXE compiler that is provided
 with Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; with
 Microsoft BASIC Compiler versions 6.00 and 6.00b; and with Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. However, these metacommands need to be added to
 the following manuals:

 1. "Microsoft QuickBASIC 4.0: BASIC Language Reference," Appendix C,
    "Metacommands," for versions 4.00 and 4.00b

 2. "Microsoft QuickBASIC 4.5: BASIC Language Reference," Appendix C,
    "Metacommands," for version 4.50

 3. "Microsoft BASIC Compiler 6.0: BASIC Language Reference," Appendix C,
    "Metacommands," for versions 6.00 and 6.00b

 4. "Microsoft BASIC 7.0: BASIC Language Reference" (metacommands are
    listed alphabetically) for BASIC PDS versions 7.00 and 7.10.

    REM $LIST{+ -}

 The $LIST metacommand turns on and off portions of the source listing
 generated by the compiler. The $LIST metacommand has no effect on
 whether or not a source code listing is produced; it only affects what
 parts of the source code are placed in the listing. A source code
 listing is produced only if you request it when you start the
 compiler. To turn source code listing off at any point in the program,
 add the following line:

    REM $LIST-

 To turn source code listing on at any point in the program, add the
 following line:

    REM $LIST+

 The following metacommand sets the width of the listing output. Its
 default is 80 characters:

    REM $LINESIZE:n

 The following is an example of how to set the list file to 132
 columns:

    REM $LINESIZE:132

 The following metacommand places a title on each page of the list
 (.LST) file:

    REM $TITLE:'text'

 The following metacommand places a subtitle on all pages except the
 first:

    REM $SUBTITLE:'text'

 The following metacommand forces a new page in the compiler listing
 file:

    REM $Page

 The following metacommand forces a new page in the compiler listing
 after n minus 6 lines have been printed.

    REM $Pagesize:n


 333. No Support for Color Hercules Graphics Adapters in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G880920-3454 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q35830

 The Hercules graphics driver in QuickBASIC only supports monochrome
 graphics (720 X 348 pixel resolution). Hercules color cards are not
 supported and have not been tested with QuickBASIC; therefore, the
 color cards may or may not work. For displaying color, QuickBASIC
 supports IBM CGA, EGA, and VGA graphic adapters.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50, the version of QuickBASIC that comes with Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and Microsoft
 BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Microsoft has received reports that QB.EXE will hang on a computer
 with a Hercules color card installed. However, Microsoft has not
 tested or verified this since QuickBASIC does not officially support
 Hercules color cards.


 334. LONG INTEGER Overflow Is Not Detected in EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q35885

 The program below, when run in the QB.EXE or QBX.EXE editor, correctly
 generates an "Overflow" message. However, the EXE program incorrectly
 prints a -2 (even when compiled with the /D (debug) option).

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2; and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 (buglist7.00, buglist7.10) for MS-DOS and MS OS/2. We are
 researching this problem and will post new information here as it
 becomes available.

 The following is a code example:

    a& = 2147483647     ' Largest positive long integer
    b& = 2
    x& = a& * b&
    PRINT x&            ' EXE version prints a -2


 335. BC.EXE "Internal Error" Using GOTO 0; Don't Use Linenumber 0

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q35887

 The following program runs in the QB.EXE editor, but BC.EXE gives an
 "Internal error near xxx" message at compile time (where the address
 xxx may vary). This problem occurs in Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Compiler Version 7.00
 (fixlist7.00).

 As stated on Page 9 of the "Microsoft QuickBASIC 4.0: BASIC Language
 Reference" manual for Versions 4.00 and 4.00b, using 0 (zero) as a
 line number is not recommended. The error ceases if you change the
 line number to a number or label other than 0.

 Compiling with or without the BC /O (stand-alone) option or BC /D
 (debug) option does not correct the problem.

 The following is a code example:

 PRINT "Seattle Seahawks are going to the Superbowl!"
 GOTO 0
 PRINT "NOT PRINTED"
 0 PRINT "Don't you agree?"


 336. CTRL+PRINT SCREEN Fails in EXE Compiled with BCOM Library

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q35888

 CTRL+PRINT SCREEN works correctly from a program compiled with the
 QuickBASIC BRUN4x.LIB library or run in the QB.EXE editor but fails to
 send output to the printer in a program compiled to a stand-alone
 module with the BC /O option (BCOM4x.LIB). The problem worsens if you
 compile with the Debug option in addition to /O; pressing CTRL+PRINT
 SCREEN then causes subsequent screen output to be truncated, and no
 output goes to the printer.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS (buglist6.00, buglist6.00b). This problem was
 corrected in Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 The problem does not occur in programs compiled in QuickBASIC Version
 3.00. CTRL+PRINT SCREEN works correctly in QuickBASIC Version 3.00.
 Pressing CTRL+PRINT SCREEN in MS-DOS normally acts as a toggle to turn
 on (or off) the redirection of screen output to the printer.

 The following is a code example:

 10 PRINT "Please press CTRL-PRTSC (or CONTROL+PRINT SCREEN):"
 15 FOR i = 1 TO 5
 20 INPUT "Enter text:"; a$
 25 NEXT


 337. How to Force CAPS LOCK On or Off with PEEK and POKE

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 12-DEC-1989    ArticleIdent: Q35919

 This article describes how to programmatically force the CAPS LOCK key
 on or off without actually pressing the CAPS LOCK key.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.02,
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 GW-BASIC Versions 3.20, 3.22, and 3.23 for MS-DOS, to Microsoft BASIC
 Compiler Versions 6.00 and 6.00 for MS-DOS, and to Microsoft BASIC PDS
 Version 7.00 for MS-DOS.

 You can determine the state of the CAPS LOCK key with the following
 PEEK command:

    DEF SEG = 0
    X = PEEK(1047) AND 64

 If CAPS LOCK is off, the value of "X" will be "0". If CAPS LOCK is on,
 the value will be 64.

 To force the CAPS LOCK off, use the following command:

    DEF SEG = 0
    POKE 1047, PEEK(1047) AND 191

 To force the CAPS LOCK on, use the following:

    DEF SEG = 0
    POKE 1047, PEEK(1047) OR 64

 Each bit of location 1047 reflects the status of a keyboard flag. This
 includes NUM LOCK, SCROLL LOCK, CAPS LOCK, INSert mode, and whether or
 not the LEFT SHIFT and RIGHT SHIFT keys, the ALT key, or the CTRL
 (Control) key is currently pressed or not. See the following table:

 Bit No.         Decimal value           Keyboard flag

 0               1                       RIGHT SHIFT
 1               2                       LEFT SHIFT
 2               4                       CTRL (Control)
 3               8                       ALT
 4               16                      SCROLL LOCK
 5               32                      NUM LOCK
 6               64                      CAPS LOCK
 7               128                     INSert mode

 To determine the state of any flag, the following statement will
 return "0" if the flag is clear (off or not pressed), and will return
 <bval> if the flag is set (on or pressed):

    PEEK(1047) AND <bval>
    (where <bval> is the decimal value of the bit that represents
    the flag you want)

 To force the flag on (which applies only to the LOCK keys and the
 INSert mode), you need to set the appropriate bit. You can do this
 with the following POKE statement:

    POKE 1047, PEEK(1047) OR <bval>
    (where <bval> is the decimal value of the flag you want to set)

 To force the flag off, you can use the following similar statement:

    POKE 1047, PEEK(1047) AND (255 - <bval>)

 Note that simply poking the bit value into 1047 would effectively set
 the flag, but would also clear all other flags. Thus, be sure to
 retain the previous values of the other flags by using the above
 strategies.

 This information is outlined in the book "Advanced MS-DOS" by Ray
 Duncan (Copyright 1986 by Microsoft Press).

 Note that instead of using PEEK, you may also get the status of
 keyboard flags with IBM ROM BIOS interrupt 16 hex, using function
 number 2. This interrupt returns the ROM BIOS flags byte that
 describes the state of the following keyboard toggles and SHIFT keys:
 RIGHT SHIFT or LEFT SHIFT key down, CTRL key down, ALT key down,
 SCROLL LOCK on, NUM LOCK on, CAPS LOCK on, INSert on. QuickBASIC and
 the BASIC Compiler have a CALL INTERRUPT statement (not found in
 GW-BASIC) which can call this interrupt.


 338. Passing BASIC Dynamic Arrays of Fixed Strings to MASM 5.x

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q35964

 This article contains a code example of passing a dynamic array of
 fixed-length strings to an assembly routine that copies the array to
 another array passed back to BASIC.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00 4.00b and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 Please note that it is necessary to pass the segment and the offset of
 a dynamic array being passed to assembly using VARSEG and VARPTR
 respectively.

 'The following BASIC program passes two arrays to a routine called
 'MASM. The MASM routine copies the first array to the second array,
 'passing it back to BASIC through a parameter.
 REM $DYNAMIC
 DECLARE SUB Masm (
        BYVAL StrLength AS INTEGER,_
        BYVAL Length AS INTEGER,_
        BYVAL SegAddr1 AS INTEGER,_
        BYVAL Addr1 AS INTEGER,_
        BYVAL SegAddr2 AS INTEGER,_
        BYVAL Addr2 AS INTEGER)
 CONST Size% = 20%     'Size of the array (# of elements)
 CONST StrSize% = 11%  'Size of strings stored in array
 CLS
 DIM inArray(1 TO Size%) AS STRING * strsize%
 DIM outArray(1 TO Size%) AS STRING * strsize%

 'Load inArray with a 11 character string " *inArray* ":
 FOR i = 1 TO Size%
   inArray(i) = " *inArray* "
 NEXT i

 ' Masm will copy the contents of inArray to outArray:
 CALL Masm(StrSize%,_
           Size%,_
           VARSEG(inArray(1)),_
           VARPTR(inArray(1)),_
           VARSEG(outArray(1)),_
           VARPTR(outArray(1)))

 ' Print the inArray:
 PRINT
 PRINT
 PRINT "inArray: "
 FOR i = 1 TO Size%
   PRINT inArray(i);
 NEXT i

 ' Print the outArray to see that the contents of inArray
 ' were copied to it:

 PRINT
 PRINT "outArray: "
 FOR i = 1 TO Size%
   PRINT outArray(i);
 NEXT i
 END

 The following is the assembly routine that copies the array:

 ;***********************************************************
 ; The routine 'Masm' copies a dynamic string array of any
 ;   length to another string array.
 ; Warnings:
 ;   -- Arrays must be adequately dimensioned.
 ; Masm takes six parameters from the BASIC routine:
 ;   1 - Size of strings in array to be copied (BX)
 ;   2 - # of elements in Array
 ;   3 - Segment of source array
 ;   4 - Offset of first element of source array
 ;   5 - Segment of destination array
 ;   6 - Offset of first element of destination array
 ;***********************************************************

 .MODEL MEDIUM
 .CODE
 PUBLIC Masm

 Masm    PROC
      push   bp
      push   si
      mov    bp, sp

      mov    bx, [bp+16]   ; Size of strings in array -> bx
      mov    ax, [bp+14]   ; Elements in array -> ax
      mul    bx     ; multiply ax by bx and put answer in ax
      mov    cx,ax  ; Number of bytes in array -> cx

      mov    es, [bp+12]   ; Segment of first array (inArray)
      mov    bx, [bp+10]   ; Offset of first element in first
                           ; array
 ; body
      mov    si,0 ; initialize first array index (inArray)
 again:
      mov    al,es:[bx] ; Load byte to copy to second array
                        ;  in al
      push   bx         ; save bx
      push   es         ; save es
      mov    es, [bp+8] ; Segment of second array (outArray)
      mov    bx, [bp+6] ; Offset of second arrays first
                        ; element
      add    bx,si ; Get correct offset into 2nd array from
                   ; index
      mov    es:[bx],al ; Move the byte into the second array
      pop    es ; restore es
      pop    bx ; restore bx
      add    bx,1 ; point to next element in first array
                  ; (inArray)
      add    si,1 ; increment second array (outArray) index
      loop    again ; Loop until cx is 0
      pop    si
      pop    bp
      ret
 Masm ENDP
      END

 The two programs shown below demonstrate how a Microsoft BASIC program
 can pass a two-dimensional, fixed-length string array to assembly
 language.

 Code Example
 ------------

 The following BASIC program is BTWOFIX.BAS, which passes an
 uninitialized two-dimensional array of fixed-length strings to an
 assembly routine that initializes the array:

    DECLARE SUB TwoFix(BYVAL ASeg AS INTEGER, BYVAL AOff AS INTEGER)

    DIM FixArray(1 TO 2, 1 TO 3) AS STRING * 9

    CALL TwoFix(VARSEG(FixArray(1, 1)), VARPTR(FixArray(1, 1)))
    FOR row% = 1 TO 2
       FOR col% = 1 TO 3
          PRINT FixArray(row%, col%)
       NEXT
    NEXT
    END

 The following program is ATWOFIX.ASM, which initializes a
 two-dimensional array of fixed-length strings passed from BASIC:

 .MODEL MEDIUM, BASIC
 .DATA
         Fix11 DB 'String 11'     ; allocate string data
         Fix21 DB 'String 21'
         Fix12 DB 'String 12'
         Fix22 DB 'String 22'
         Fix13 DB 'String 13'
         Fix23 DB 'String 23'
 .CODE
         PUBLIC TwoFix
 TwoFix  PROC
         push bp
         mov bp, sp               ; set stack frame
         push es
         mov es, [bp+8]           ; segment of string array
         mov di, [bp+6]           ; offset of string array
         mov si, OFFSET Fix11     ; get offset to string data
         mov cx, 54               ; length of all string data
         rep movsb                ; copy string data to array
         pop es
         pop bp
         ret 4
 TwoFix  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BTWOFIX.BAS;
    MASM ATWOFIX.ASM;
    LINK BTWOFIX ATWOFIX;

 BTWOFIX.EXE produces the following output:

    String 11
    String 12
    String 13
    String 21
    String 22
    String 23


 339. Which BASIC Versions Can CALL C, FORTRAN, Pascal, MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C H_Fortran S_PasCal H_MASM S_QuickASM S_QuickC
 Last Modified: 22-OCT-1990    ArticleIdent: Q35965

 Certain versions of Microsoft QuickBASIC and Microsoft BASIC Compiler
 can CALL routines from certain other Microsoft languages (and pass
 parameters), depending upon the product version number, as explained
 below.

 Microsoft BASIC Professional Development System (PDS) version 7.10 can
 be linked with Microsoft C PDS version 6.00 or QuickC version 2.50 or
 2.51.

 The following application note, which can be requested from Microsoft
 Product Support Services, is required if you wish to perform BASIC
 7.10 mixed-language programming with C 5.10, FORTRAN 5.00, or Pascal
 4.00:

    "How to Link BASIC PDS 7.10 with C 5.10, FORTRAN 5.00, or
     Pascal 4.00" (application note number BB0345)

 QuickBASIC 4.50 and BASIC PDS 7.00 (but not earlier versions) can
 create .OBJ modules that can be linked with .OBJ modules from
 Microsoft FORTRAN version 5.00 and Microsoft QuickC version 2.01.

 QuickBASIC versions 4.00b and 4.50, Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and MS OS/2, and Microsoft BASIC PDS version
 7.00 for MS-DOS and MS OS/2 create .OBJ modules that can be linked
 with .OBJ modules from the following languages:

 1. Microsoft Pascal version 4.00.
 2. Microsoft FORTRAN version 4.10.
 3. Microsoft C version 5.10 and QuickC versions 1.01 and 2.00.
 4. Microsoft Macro Assembler (MASM) version 5.00 or later recommended,
    but earlier versions should also work.

 For more information on interlanguage CALLing between Microsoft C and
 BASIC, query in this Knowledge Base on the word "BAS2C".

 For more information on interlanguage CALLing between Microsoft MASM
 and BASIC, query in this Knowledge Base on the word "BAS2MASM".

 For more information about using the CALL statement to pass parameters
 from BASIC to other languages, query in this Knowledge Base on the
 following words:

    CALL and (PASSING or PASS) and [language name]

 QuickBASIC 4.00
 ---------------

 QuickBASIC version 4.00 creates .OBJ modules that can be linked with
 .OBJ modules from the following languages (Microsoft has performed
 successful interlanguage test suites for QuickBASIC version 4.00 with
 these language versions):

 1. Microsoft C version 5.00, QuickC version 1.00.
 2. Microsoft FORTRAN version 4.00.
 3. Microsoft Pascal version 4.00.
 4. Microsoft Macro Assembler (MASM) versions 4.00 and later
    recommended, but earlier versions should also work.

 Note that QuickBASIC version 4.00b might link with these earlier
 language versions, but Microsoft cannot guarantee success because the
 4.00b test suites were performed only on the later language versions
 mentioned further above in this article.

 QuickBASIC 1.x, 2.x, 3.00
 -------------------------

 In QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, and 3.00, you can
 link only to .OBJ modules from Microsoft Macro Assembler (versions
 1.2x, 2.x, or later) or the given version of QuickBASIC. In other
 words, QuickBASIC versions 3.00 and earlier can CALL only QuickBASIC
 subprograms or assembly routines.

 Important Information About Interlanguage CALLing
 -------------------------------------------------

 To be compatible with compiled BASIC, programs should be assembled or
 compiled using the medium, large, or huge memory model, and BASIC must
 be linked first (as the main module).

 When you link compiled BASIC to other compiled BASIC modules, compiler
 versions should not be mixed. For example, an .OBJ module compiled in
 QuickBASIC version 4.00 should not be linked with an .OBJ module
 compiled in QuickBASIC version 4.00b or 4.50 or Microsoft BASIC
 Compiler version 6.00 or 6.00b or Microsoft BASIC PDS version 7.00 or
 7.10.

 As an alternative to the CALL statement for interlanguage invocation,
 you may use the SHELL statement to invoke most (non-TSR) .EXE, .COM,
 or .BAT programs that you can also invoke from DOS. SHELL works
 differently than CALL. SHELL invokes another copy of the DOS
 COMMAND.COM command processor before running a requested executable
 program.


 340. Using LIB.EXE to Add, Modify, and Combine .LIB; Quick Library

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q35966

 You cannot directly add, delete, or modify routines in an existing
 Quick library (.QLB file). However, you can easily re-create Quick
 libraries using a parallel .LIB file.  You can add, delete, or modify
 routines in the .LIB file using the Library Manager (LIB.EXE) utility,
 as shown below under "More Information". You can then convert the .LIB
 file into a .QLB Quick library file with the /Q option of the linker
 (LINK.EXE).

 This article applies to Microsoft QuickBASIC Versions 4.00, 4.00b, and
 4.50 and to the QuickBASIC that comes with the Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2. This also
 applies to QBX.EXE which is supplied with Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 To "add" an .OBJ module to a .QLB file, you must first add the module
 to your parallel .LIB file with the Library Manager (LIB.EXE), as
 follows:

    LIB YourLib.LIB + YourMod.OBJ;

 If the module already exists in the library, but you want to replace
 it with your new module, use the following command:

    LIB YourLib.LIB -+ NewMod.OBJ;

 To remove a module from your library, first remove it from your .LIB
 file with the following:

    LIB YourLib.LIB - YourMod;

 This will delete the module completely. If you want to keep a copy of
 the .OBJ file, you can create one as you delete it from your library
 with the following:

    LIB YourLib.LIB -* YourMod;

 You can also combine entire libraries using LIB.EXE, as follows:

    LIB FirstLib.LIB + NextLib.LIB;

 This will "add" the routines in NextLib.LIB to the FirstLib.LIB file.

 Once you have modified your .LIB files as you wish, you can create a
 Quick library from the .LIB file with the following LINK command line:

    LINK /Q YourLib.LIB, QuickLib.QLB, NUL, BQLB41.LIB;

 When making a Quick library, BQLB40.LIB is required (instead of
 BQLB41.LIB) for QuickBASIC Version 4.00. BQLB41.LIB is required for
 QuickBASIC Version 4.00b, or the QuickBASIC which comes with the BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2 or BASIC PDS
 7.00 for MS-DOS and MS OS/2. The BQLB4x.LIB file comes on the release
 disk.


 341. CALL SetUEvent in Assembly Routine to Disable PRINT SCREEN

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q35968

 This article provides an example of calling BASIC's SetUEvent routine
 from an assembly-language interrupt routine to disable the screen dump
 performed by the PRINT SCREEN key (found on enhanced IBM keyboards) or
 the SHIFT+PRSCR or SHIFT+PRTSC key (found on earlier, nonenhanced IBM
 PC keyboards).

 Special steps must be taken when triggering BASIC's user-defined
 events from assembly-language interrupt routines. Primarily, the
 assembly routine needs to make sure that the DS register points to
 BASIC's default data segment before making the call to SetUEvent.
 Also, the interrupt routine should be disabled before, and re-enabled
 after, a CHAIN or RUN statement. This information applies to Microsoft
 QuickBASIC Versions 4.00b and 4.50, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 Note: The SetUEvent routine is not provided in QuickBASIC Version 4.00
 or earlier. SetUEvent was introduced in QuickBASIC Version 4.00b and
 the BASIC compiler Version 6.00 and later.

 BASIC user-defined interrupts are triggered by a call to SetUEvent.
 This routine can be called from an external assembly routine, usually
 an interrupt handler. However, in QuickBASIC 4.00b, in the BASIC
 compiler 6.00 and 6.00b, and in BASIC PDS 7.00, SetUEvent assumes that
 DS is pointing to BASIC's default data segment; if it isn't, the call
 to SetUEvent will not trigger the BASIC interrupt routine. To ensure
 that DS is pointing to the correct place, save the value of DS in a
 location accessible to the interrupt routine when installing it. Then,
 in the interrupt routine, place that value in DS directly before
 making the call to SetUEvent. In QuickBASIC Version 4.50, you don't
 have to set DS equal to the BASIC Data Segment.

 When CHAINing or RUNning other BASIC programs that use the same
 interrupt routine, the first BASIC program must deinstall the
 interrupt handler, CHAIN (or RUN) the second program, and reinstall
 the handler again. The sample program below demonstrates how to
 install, deinstall, and properly CALL SetUEvent in an interrupt
 handler situation.

 The following is a BASIC code example:

 DECLARE SUB PrScr ()
 DECLARE SUB DeInst ()
 ON UEVENT GOSUB handler
 UEVENT ON
 CALL PrScr
 PRINT "Screen Dump interrupt has been disabled."
 PRINT "Press PRINT SCREEN (or SHIFT+PRTSC) key to trigger event."
 PRINT "Press any other key to end program."
 WHILE i$ = ""
   i$ = INKEY$
 WEND
 CALL DeInst
 PRINT "Screen Dump interrupt has been re-enabled."
 END
 handler:
   PRINT "Screen dumps are currently disabled."
   RETURN

 The following is an assembly-language program that redefines the
 interrupt that occurs when you press the PRINT SCREEN (or SHIFT+PRTSC)
 key:

 ; PRSCR.ASM
 cr      equ     0dh
 lf      equ     0ah
 .model  medium
 .code
         extrn   SetUEvent:proc
         public  prscr

 tsr_active      db      0
 old_seg         dw      ?
 old_off         dw      ?
 bds             dw      ?

 handler proc    far
       sti
       push      ax
       push      bx
       push      cx
       push      dx
       push      si
       push      di
       push      bp
       push      ds
       push      es                  ;save regs
         cmp     cs:tsr_active, byte ptr 0  ;are we already up?
         je      do_int                  ;no, go display message
         jmp     ex_int                  ;yes, get out!

 do_int: mov     cs:tsr_active, byte ptr 1  ;okay, we're up now...
         mov     ax,bds
         mov     ds,ax                   ;set DS = BASIC's data segment
         call    SetUEvent               ;trigger the user event
         mov     cs:tsr_active, 0        ;re-activate interrupt

 ex_int: pop     es
         pop     ds
         pop     bp
         pop     di
         pop     si
         pop     dx
         pop     cx
         pop     bx
         pop     ax
         cli             ; CLI corresponds to STI at Handler beginning.
         iret
 handler endp

 prscr   proc    far
         push    bp
         mov     bp, sp
         push    ds
         push    es
         mov     cs:bds,ds               ;put BASIC's DS here
         mov     ax, 3505h               ;get interrupt vector
         int     21h                     ;for PrScr
         mov     cs:old_seg,es
         mov     cs:old_off,bx           ;save it
         mov     dx, seg handler
         mov     ds,dx
         mov     dx, offset handler      ;reset interrupt 5
         mov     ax, 2505h               ;to point to handler
         int     21h
         pop     es
         pop     ds
         pop     bp
         ret                             ;back to BASIC
 prscr   endp

         public  deinst
 deinst  proc    far                ;to de-install our Prscr interrupt
         push    bp
         mov     bp,sp
         push    ds
         mov     dx,cs:old_seg
         mov     ds, dx
         mov     dx,cs:old_off           ;get old INT 5 vector
         mov     ax, 2505h
         int     21h                     ;and restore it
         pop     ds
         pop     bp
         ret
 deinst  endp
 END


 342. Do Not Mix Arrayname AS Type and % Type Suffix in DIM/COMMON

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 13-DEC-1989    ArticleIdent: Q35969

 Do not mix the use of "AS Type" declaration syntax with explicit type
 declaration suffixes (%, &, !, #, and $) with a given array name that
 occurs in both DIM and COMMON statements. Programs should be run in
 the QuickBASIC QB.EXE editor to catch such a mismatch error.

 If you compile Example Program 1 (below) with the BC /D (debug)
 option, then the .EXE file will produce an error at run time. If you
 do not compile with BC /D (debug) option, then the mismatched
 DIM/COMMON declaration will not be detected, and the resulting .EXE
 file will hang the machine, requiring a cold boot.

 This article applies to Microsoft QuickBASIC 4.00, 4.00b, and 4.50 and
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b) for MS-DOS and MS OS/2. This problem was corrected in
 Microsoft BASIC PDS Version 7.00 (fixlist7.00) for MS-DOS and MS OS/2.

 ----------------

 For the example program below, BASIC PDS 7.00 produces the following
 message for this error:

 COMMON SHARED /x/ x() AS INTEGER   ' AS INTEGER used for type declare.
                          ^ AS clause required on first declaration

 In Example Program 1, the array x% is treated as different from array
 x.  Because the AS clause takes precedence over the "%" type suffix,
 BC.EXE declares the array x in COMMON as a dynamic array, replacing
 the static array x% that was dimensioned with the DIM statement. Thus,
 when the final .EXE is run, array bounds are exceeded, and the machine
 hangs (without BC /D) or gives a run-time error (with BC /D).

 When run in the QB.EXE editor, the following program gives the error
 "AS Clause required in first declaration" due to illegal mixing of
 type declaration methods:

 ' Example Program 1
 DIM x%(100)    ' % used for type declaration
 COMMON SHARED /x/ x() AS INTEGER   ' AS INTEGER used for type declare.
 FOR i% = 0 TO 99
   PRINT "i% = "; i%
   x%(i%) = 1
 NEXT i%

 The following program shows a correct method for type declaration:

 ' Example Program 2
 DIM x%(100)
 COMMON SHARED /x/ x%()
 FOR i% = 0 TO 99
   PRINT "i% = "; i%
   x%(i%) = 1
 NEXT i%

 The following program shows another correct method for type declaration:

 ' Example Program 3
 DIM x(100) AS INTEGER
 COMMON SHARED /x/ x() AS INTEGER
 FOR i% = 0 TO 99
   PRINT "i% = "; i%
   x(i%) = 1
 NEXT i%


 343. How to BSAVE/BLOAD EGA SCREENs 7, 8, 9, 10 in QB 2.x, 3.0, 4.x

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q36022

 Below is a code example that uses BSAVE and BLOAD to store and
 retrieve a screen image in EGA SCREEN modes 7, 8, 9, and 10 to and
 from disk. This BSAVE and BLOAD technique required for EGA screens is
 not as straightforward as for CGA or Hercules SCREEN modes, since EGA
 memory is stored in discontinuous color planes.

 The code example further below works in the following products:

 1. Microsoft QuickBASIC Versions 3.00, 4.00, 4.00b, and 4.50

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    Microsoft BASIC PDS Version 7.00 for MS-DOS
    (Note that EGA SCREENs are not supported in the protected mode of
    OS/2.)

 QuickBASIC Versions 2.00 and 2.10 do not support SELECT CASE, and the
 program below needs to be modified to use IF statements instead.

 QuickBASIC Versions 1.00, 1.01, and 1.02 do not support the EGA SCREEN
 modes (7, 8, 9, and 10), and cannot use this program.

 This program can also be found in the May 12, 1987 issue of "PC
 Magazine" on Pages 403-404.

 For an example of BLOAD and BSAVE of VGA screen modes (11, 12, and 13)
 (for QuickBASIC 4.x and the BASIC compiler 6.00 and 6.00b and BASIC
 PDS 7.00) in addition to EGA modes, query on the word BSAVEVGA for a
 separate article in this database.

 The EGA memory is broken into color planes. The program below is
 designed to save a given EGA screen into separate disk files: one file
 for each EGA color plane.

 For more technical information about EGA memory, please refer to the
 following book, which is available from bookstores or from Microsoft
 Press by calling (800) 638-3030 or (206) 882-8080:

    "Programmer's Guide to PC and PS/2 Video Systems," by Richard
    Wilton. Published by Microsoft Press (1987).

 Code Example
 ------------

 ' HOW TO BLOAD AND BSAVE EGA SCREENS 7, 8, 9, and 10.
 SCREEN 9  ' Invokes EGA 640 x 350 16-color mode.
 FOR i = i TO 200  '  Draw some random lines in random colors:
 x1 = INT(640 * RND)
 y1 = INT(350 * RND)
 x2 = INT(640 * RND)
 y2 = INT(350 * RND)
 co = INT(15 * RND)
 LINE (x1, y1)-(x2, y2), co
 NEXT i

 ' Save EGA video memory from video memory to disk:
 filename$ = "TEST"
 mode = 9
 RW = 0
 CALL EGA(filename$, mode, RW)
 CLS
 INPUT "Hit <ENTER> to restore screen:", a$

 'Load EGA video memory from disk to video memory:
 RW = 1
 CALL EGA(filename$, mode, RW)
 END

 SUB EGA (filename$, mode, RW) STATIC
 ' filename$=filename
 ' mode=video mode (EGA SCREEN number)
 ' RW=read/write EGA from/to disk R=T, W=F

 'Determine amount of video memory for display mode:
 SELECT CASE mode
 CASE 7
   Total = 8000
 CASE 8
   Total = 16000
 CASE 9 TO 10
   Total = 28000
 CASE ELSE
   PRINT "ERROR: NonEGA Graphics Mode!"
   GOTO NOEGA
 END SELECT

 'Cycle through each video plane of EGA
 IF mode = 10 THEN cycle = 1 ELSE cycle = 3
 DEF SEG = &HA000    ' Segment of EGA video memory
 FOR i = 0 TO cycle
   IF RW = 1 THEN
     ' Set EGA register for write to each plane:
     OUT &H3C4, 2
     OUT &H3C5, 2 ^ i

     F$ = filename$ + CHR$(i + 48) + ".EGA"
     BLOAD F$, 0
   ELSE
     ' Set EGA register for read from each plane:
     OUT &H3CE, 4
     OUT &H3CF, i
     F$ = filename$ + CHR$(i + 48) + ".EGA"
     BSAVE F$, 0, Total
   END IF
 NEXT i
 DEF SEG
 NOEGA:
 END SUB


 344. "Statement Illegal in TYPE block" Due to Line Identifier

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q36023

 Line labels and line numbers are not permitted within TYPE ... END
 TYPE statement blocks. A "Statement illegal in TYPE block" error
 message appears if this is attempted.

 Under the TYPE ... END TYPE  statement (listed alphabetically) in the
 "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
 QuickBASIC Versions 4.00 and 4.00b, in the "Microsoft QuickBASIC 4.5:
 BASIC Language Reference" manual for QuickBASIC Version 4.50, and in
 the "Microsoft BASIC Compiler 6.0: BASIC Language Reference" manual
 for Microsoft BASIC Compiler Versions 6.00 and 6.00b, it needs to
 mention that line identifiers are forbidden in TYPE ... END TYPE
 statements.

 This documentation omission has been corrected in the "Microsoft BASIC
 7.0: Language Reference" for Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The BC.EXE compiler correctly gives the following error message in all
 of the above products when you compile the code example farther below:

  10        partnumber AS STRING * 6
  ^ Identifier expected
  ^ Skipping forward to END TYPE statement
  DIM stockrecord AS stockitem
                     ^ TYPE not defined

 Code Example
 ------------

 'This gives "Statement illegal in TYPE block message,
 'due to the presence of line identifiers.
 TYPE stockitem
 10        partnumber AS STRING * 6
           description AS STRING * 20
           unitprice AS SINGLE
 abcd:     quantity   AS INTEGER
 END TYPE
 DIM stockrecord AS stockitem


 345. .EXE "String Space Corrupt" Actually Is "Duplicate Definition"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q36028

 In the program below, the QuickBASIC QB.EXE environment correctly
 gives a "Duplicate Definition" error message, but the BC.EXE
 command-line compiler does not give the error. This may cause run-time
 problems in the .EXE program, such as hanging or "string space
 corrupt" error messages.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC PDS Version 7.00
 (fixlist7.00).

 To work around this problem, you can run the program in the QB.EXE
 environment to check for errors that the BC.EXE compiler misses.

 The problem occurs in the .EXE regardless of whether or not you
 compile with the BC /D (debug) option.

 The following is a code example:

      DEFINT A-Z
      DECLARE SUB TestRoutine ()
      TYPE XDef
         Area AS STRING * 10
      END TYPE
      COMMON SHARED /XYZ/ X AS XDef
      X.Area = "1234567890"
      TestRoutine
      PRINT X.Area
      END

      SUB TestRoutine STATIC
      DIM X AS STRING        ' "Duplicate Definition" in QB.EXE editor.
      X = "abcdefghi"        ' "String Space Corrupt" error here in .EXE
      END SUB


 346. QuickBASIC Uses File Handles, Not File Control Blocks (FCBs)

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q36030

 MS-DOS supports two distinct but overlapping sets of file and record
 management services:

 1. File control blocks (FCBs) (introduced in MS-DOS Versions 1.x)

 2. File handles (introduced in MS-DOS Version 2.00)

 The OPEN statement in the following products opens a file handle, not
 an FCB: Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.10,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS, and Microsoft BASIC PDS Version
 7.00 for MS-DOS.

 A QuickBASIC or BASIC compiler program can indirectly use FCBs by
 calling an assembly language routine or DOS interrupts to perform the
 FCB manipulations.

 The Microsoft BASIC Compiler Versions 5.35 and 5.36 both use File
 Control Blocks. These versions of the compiler were designed to
 operate under DOS 1.x and, therefore, always use FCBs to access files.

 The handle-oriented MS-DOS functions use null-terminated (ASCII)
 filenames and 16-bit file identifiers, called handles, which are
 returned by MS-DOS after a file is opened or created. File handles
 allow names that may include paths that show the location of the file
 within the hierarchical directory structure. The following file-handle
 information is maintained in a table internal to MS-DOS:

    The current read/write pointer for the file

    The date and time of the last write to the file

    The file's read/write permissions, sharing mode, and attributes

 In contrast, the FCB-oriented MS-DOS functions use a 37-byte structure
 called a file control block, located in the application program's
 memory space, to specify the name and location of the file. After a
 file is opened or created, the FCB is used to hold other information
 about the file, such as the current read/write file pointer, while
 that file is in use.

 Because FCBs predate the hierarchical directory structure introduced
 in MS-DOS Version 2.00, the FCB functions cannot be used to access
 files that are not in the current directory. FCBs also do not support
 the file and record locking functions that are essential to network
 applications.

 This information about FCB's and file handles is taken from "The
 MS-DOS Encyclopedia" (Published by Microsoft Press, Copyright 1988).


 347. How to Use REM or ' Comments in DATA Statements without Error

 Product Version(s): 1.00 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_MQuickB B_GWBasicI B_BasicInt
 Last Modified: 13-DEC-1989    ArticleIdent: Q36395

 If you want to append a comment [using REM or an apostrophe (')] to a
 DATA statement, you must put a colon (:) in front of the REM or
 apostrophe on the DATA line.

 This information applies to QuickBASIC Versions 1.00, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2; Microsoft
 BASIC PDS Version 7.00 for MS-DOS and MS OS/2; to GW-BASIC Versions
 3.20, 3.22, and 3.23 for MS-DOS; to QuickBASIC Version 1.00 for the
 Apple Macintosh; to Microsoft BASIC Interpreter Versions 1.00, 1.01,
 2.00, 2.10, and 3.00 for the Apple Macintosh; and to Microsoft BASIC
 Compiler Version 1.00 for the Apple Macintosh. It may also apply to
 other versions of Microsoft BASIC not listed here.

 In QuickBASIC for MS-DOS, in Microsoft BASIC Compiler for MS-DOS and
 MS OS/2, and in GW-BASIC for MS-DOS, a READ statement that is accepted
 into a non-string variable produces a "Syntax error" if it encounters
 a comment [a REM or an apostrophe(')] without a preceding colon (:) in
 a DATA statement line.

 In QuickBASIC for Macintosh, you get a "Type Mismatch" error if you
 READ the comment (without a preceding colon) into a non-string
 variable when you run the program.

 In all above versions of BASIC (for all operating systems), the READ
 statement treats the comment as additional string data for input when
 it reads into a string variable.

 Correct Example
 ---------------

 Separating the DATA statement from the REM (or apostrophe) with a
 colon (:) lets the program run correctly, as in the following example:

    DATA abc,,def:  rem The second item is null.
    DATA 1,,2:      ' The second item is null.
    READ a$, b$, c$    ' Note that b$ is assigned to null string ("")
    PRINT a$, b$, c$
    PRINT
    READ d, e, f       ' Note that e is assigned to 0
    PRINT d, e, f
    END

 Incorrect Example
 -----------------

 In the following program, the first READ statement reads the DATA
 statement's comment into c$ along with the last element ("def") of the
 DATA statement, which is not what the programmer may have wanted. The
 second READ statement produces a "Syntax error" in QuickBASIC, the
 BASIC compiler, and GW-BASIC for MS-DOS, and produces "Type Mismatch"
 in QuickBASIC and BASIC for the Apple Macintosh when it attempts to
 mistakenly read a (string) comment into a numeric variable:

    DATA abc,,def  rem The second item is null. [This becomes data.]
    DATA 1,,2      ' The second item is null. [This becomes data.]
    READ a$, b$, c$    ' Note that b$ is assigned to null string ("")
    PRINT a$, b$, c$
    PRINT
    READ d, e, f       ' This READ gives error while reading in f.
    PRINT d, e, f
    END


 348. Must Use A$=INKEY$ after SLEEP to Clear Keyboard Buffer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q36397

 The SLEEP statement was introduced in QuickBASIC Version 4.00b and
 in Microsoft BASIC Compiler Version 6.00 for MS-DOS and MS OS/2.
 SLEEP does not clear the buffer when a key is pressed. Therefore, the
 next input statement will read the pressed keys to clear prior SLEEP
 commands.

 This information applies to Microsoft QuickBASIC Versions 4.00b and
 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 The following code example demonstrates the problem with a workaround:

 CLS
 FOR i = 1 TO 5
   PRINT "press a key please"
   SLEEP
 ' If you want to clear the buffer, insert the following statement:
 '   x$ = INKEY$
 NEXT
 CLS
 '  If you do not clear the buffer, this INPUT prompts with a print
 '  of the 5 characters pressed in the FOR loop above, and the value of
 '  a$ will be those 5 characters plus any entered at the prompt.
 INPUT a$
 PRINT a$


 349. "Bad File Mode" Loading 4.50 Fast Load Format File into 4.00

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-DEC-1989    ArticleIdent: Q36578

 Files saved in the (default) Fast-Load-and-Save format of Microsoft
 QuickBASIC Version 4.50 cannot be used (are not downwards-compatible)
 with QuickBASIC Version 4.00 or 4.00b. The error message "bad file
 mode" indicates that the QuickBASIC Version 4.50 tokenized file is
 different than expected by Version 4.00 or 4.00b. You will need to
 first save QuickBASIC Version 4.50 files as text before loading them
 into QuickBASIC Version 4.00 or 4.00b.

 Fast-Load-format files saved by QuickBASIC Version 4.00 are generally
 upwardly compatible with Version 4.50, but it is recommended to always
 have a backup in ASCII text format for all files.

 Microsoft Product Support does not recommend using Fast-Load-and-Save
 format. Instead, always save with Text format, to avoid the chance of
 problems. To read about possible problems, query on QuickBASIC, your
 version number, and the following words:

    fast and load and save and format

 Similarly, files saved in the (default) Fast-Load-and-Save format of
 QBX.EXE, which comes with BASIC PDS Version 7.00, cannot be used (are
 not downwards-compatible) with QuickBASIC Version 4.00, 4.00b or 4.50
 and will produce the "Bad File Mode" error message as well. QBX.EXE
 can, however, read files saved in the Fast-Load-format of Versions
 4.00, 4.00b and 4.50. As stated before, the Fast-Load-and-Save formats
 are upwardly compatible.

 The QuickBASIC Version 4.50 Help screens do not indicate that the Fast
 Load formats are different for the various versions of QuickBASIC.

 Note that QuickBASIC versions earlier than 4.00 do not have a Fast
 Load format (just text mode).


 350. RANDOMIZE Statements Reseed but Don't Restart RND Sequence

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_BasicInt B_GWBasicI B_MQuickB
 Last Modified: 11-JAN-1990    ArticleIdent: Q36736

 The first invocation of the RANDOMIZE statement determines a given set
 of random numbers returned from successive calls to the RND function.
 Not invoking the RANDOMIZE statement in a program is equivalent to
 invoking RANDOMIZE 0 before invoking RND. Note that a second (or
 subsequent) RANDOMIZE x statement does not restart the number sequence
 from the beginning of the set for a given x, but it randomly changes
 (reseeds) the sequence from what it would have been from that point
 on. This behavior is by design. Example 2 below illustrates this in
 detail.

 If you want to return the same sequence of random numbers several
 times within a given program run, you can invoke the RND function with
 the exact same negative number argument followed by a sequence of RND
 invocations with a positive argument or no argument. Invoking RND with
 a negative argument eliminates the effect of a previous RANDOMIZE
 statement. Please see Example 1 below for further illustration.

 This behavior of the RANDOMIZE statement and the RND function occurs
 in most versions of Microsoft BASIC, including the following:

 1. Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 3. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 5. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23 for
    MS-DOS

 6. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh

 7. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 8. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh

 Other BASICs may behave differently.

 If you would like an alternative to this behavior of RND and
 RANDOMIZE, you may use your own formula to generate random numbers as
 shown in a separate article. (Query in this database for the keywords
 RANDOM and EQUATION.)

 The following is Example 1:

 (This example of invoking RND once with a negative argument always
 returns the same sequence of random numbers for subsequent invocations
 of RND.)

 CLS
 RANDOMIZE TIMER   ' Ignored unless you remove RND(-1) below.
 FOR j = 1 TO 2
  ' Passing a negative value to the RND function supersedes the effect
  ' of the previous RANDOMIZE TIMER statement:
  PRINT RND(-1)   ' Remove this line for a different sequence on every
                  ' loop iteration. Otherwise, each j loop iteration
                  ' (and separate program run) returns the same
                  ' three-number sequence for the inner i loop.
  FOR i = 1 TO 3
     PRINT RND
  NEXT I
  PRINT
 NEXT J

 The following is Example 2:

 FOR k = 1 TO 5
   PRINT RND
 NEXT k

 Below is the default random number set output from the above program,
 when run with QB.EXE Version 4.00 on an IBM PC. The following sequence
 of random numbers varies with different versions of Microsoft
 QuickBASIC and BASIC Compilers:

    .7107346
    .99058
    .8523988
    .3503776
    4.363585E-02

 The following code shows the effect of RANDOMIZE 0 at start-up:

 PRINT  "Set the seed to zero at startup"
 RANDOMIZE 0
 FOR k = 1 TO 5
   PRINT RND
 NEXT k
 PRINT "Again, reset the seed to zero"
 RANDOMIZE 0
 FOR k = 1 TO 5
   PRINT RND
 NEXT k

 The above program has the following output:

    Set the seed to zero at startup
     .7107346
     .99058
     .8523988
     .3503776
     4.363585E-02
    Again, reset the seed to zero
     .7987763
     .6497337
     .5426014
     .9642789
     8.590406E-02

 Note: The second invocation of RANDOMIZE 0 does not restart the
 sequence from the beginning. This is by design. If you remove the
 second RANDOMIZE 0 statement and run the program again, the 6th
 through 10th numbers are different than above. This shows that
 multiple RANDOMIZE statements reseed the sequence (and change the
 random number set displayed), but they do not restart the sequence
 from the beginning.


 351. Longer Variable Names Take No Extra Space in .EXE Program

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q36737

 In programs compiled by BC.EXE, you will not change the generated code
 size by using shorter variable names instead of longer ones. The
 generated .OBJ and .EXE file sizes are independent of the length of
 variable names.

 Although BC.EXE uses variable names at compile time to allocate memory
 and translate BASIC statements to machine code, these symbolic names
 are not embedded in the code produced by the compiler.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50; to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2; and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Source code can be much more readable if you use fully-descriptive
 names in naming variables. QuickBASIC allows variable names up to 40
 characters in length. Consider the following choices of variable
 names:

    mfp     versus      MeanFreePath
    n$      versus      LastName$
    vo      versus      Volts
    vl      versus      Volume
    vc      versus      Velocity

 The names in the right column generate no more code than those on the
 left side.

 However, within the QB.EXE program development environment, all text
 in the source file occupies memory, including long variable names.


 352. Third-Party TSR for Printing Hercules Graphics Screens

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q36738

 The GRAPHICS.COM utility [a terminate-and-stay-resident (TSR) program]
 provided with MS-DOS Versions 2.x through 3.x supports printing of
 graphics in CGA SCREEN modes 1 and 2 to Epson-compatible printers, but
 does NOT support printing Hercules graphics SCREEN 3. [While
 GRAPHICS.COM provided with MS-DOS 4.00 supports screen dumps to Epson
 printers for EGA and VGA SCREEN modes (7 through 13), it still doesn't
 support Hercules.]

 A TSR can be obtained from Hercules Computer Technology that may
 enable printing Hercules graphics screens. Details on obtaining this
 TSR are given below.

 This article applies to QuickBASIC Versions 4.00, 4.00b, and 4.50, to
 Microsoft BASIC Compiler Version 6.00 and 6.00b for MS-DOS, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS.

 Once you have installed GRAPHICS.COM, the graphics screen dump ability
 is enabled for the PRINT SCREEN key (or SHIFT+PRINT SCREEN on
 nonenhanced keyboards) and for the equivalent CALL to hardware
 interrupt 5. However, GRAPHICS.COM doesn't support Hercules graphics
 SCREEN 3. Hercules memory is arranged in a fashion incompatible with
 GRAPHICS.COM.

 Hercules Computer Technology provides two TSR software drivers that
 allow dumping either page of Hercules graphics memory to a printer.
 HGC and HPRINT are available as a combined set by calling Hercules
 Technical Support at (415) 540-0749. These drivers work correctly with
 the IBM EGA or VGA graphics.

 Microsoft has not officially tested these products with QuickBASIC and
 makes no guarantees of compatibility. According to customers who have
 these drivers, they work properly with QuickBASIC Version 4.00. As
 always, you should be careful using any memory-resident program with
 QuickBASIC.

 As an alternative to the above products, if you would like a
 QuickBASIC program that can perform a Hercules graphics screen dump,
 search for the following words:

    Hercules and Epson and screen and print and QuickBASIC

 Note: QuickBASIC versions earlier than Version 4.00 have no support
 for Hercules-monochrome graphics adapters.

 Hercules-compatible monochrome graphics is provided in QuickBASIC 4.00
 and later. Hercules graphics mode is invoked with SCREEN 3. To invoke
 SCREEN 3, the Hercules support-driver must be loaded. This driver is
 called QBHERC.COM in QuickBASIC Versions 4.00 and 4.00b and in the
 BASIC compiler Versions 6.00 and 6.00b. This driver is called
 MSHERC.COM in QuickBASIC 4.50 and in BASIC PDS 7.00.


 353. Softkey String for KEY 10 Has 5-Character Maximum Display

 Product Version(s): 1.00 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q36806

 The following manuals incorrectly specify that the first six
 characters of the softkey string expression will be shown when the
 KEY ON statement is invoked. This is true, except for KEY 10. For KEY
 10, only the first 5 characters are shown:

 1. Page 233 of "Microsoft QuickBASIC 4.0: BASIC Language Reference" for
    Versions 4.00 and 4.00b

 2. Page 233 of "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" for Versions 6.00 and 6.00b for MS-DOS and MS OS/2

 3. "Microsoft QuickBASIC 4.5: BASIC Language Reference" for Version 4.50

 4. "Microsoft BASIC 7.0: BASIC Language Reference" for BASIC PDS Version
     7.00

 This is a design limitation. The display of KEY 10 uses 2 character
 spaces to display the number "10". This second digit uses the first
 available space of the string expression and leaves only 5 character
 spaces for that string expression.

 The following is a code example:

    KEY 9, "ABCDEF"
    KEY 10, "abcdef"
    KEY ON
    10 goto 10   ' Press CTRL+BREAK to quit.

 The following function key labels display on the bottom of the screen:

    1      2      3  . . .   8      9ABCDEF10abcde


 354. Line Number 65,529 Is the Maximum Supported by QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  3-MAY-1989    ArticleIdent: Q36808

 The maximum allowed line number is 65,529; therefore, line numbers
 above 65,529 should not be used. Descriptive line labels can be used
 as a substitute.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, and to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2.

 If a block IF THEN ENDIF statement begins on a line with a line number
 greater than 65,539, BC.EXE will produce a "Must be first statement on
 the line" error message. The program will run properly inside the
 environment. Also, BC.EXE will NOT produce the error if the source
 file is saved as text rather than in Fast Load format.

 The sample program below will work properly inside the editing
 environment. However, if the program is saved using the Fast Load
 format and compiled using BC.EXE, the error message "Must be first
 statement on line" is produced on line 79,000. Also, the END IF
 statement will generate a "END IF without block IF" error message.

 If the file is saved in text format, BC.EXE compiles the program
 correctly. Also, if the line number is changed to a number less than
 65,540, the program will compile, regardless of the save format.

 The following is a code example:

 GOSUB 79000
 END
 79000  IF x < 0 THEN   ' This line causes the error in BC.EXE
         BEEP
        END IF
 RETURN


 355. Do Not Nest FOR/NEXT Loops with Same Counter Index Variable

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 28-DEC-1989    ArticleIdent: Q36809

 Nesting FOR...NEXT loops that use the same counter index variable is
 not legal in compiled BASIC.

 BC.EXE properly gives you a "FOR index variable already in use" error
 message when you nest FOR...NEXT loops with the same counter index
 variable. However, the QB.EXE environment will mistakenly allow a
 program to run.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 The program below will run without any error message inside the QB.EXE
 editing environment (and also in the GW-BASIC Interpreter Versions
 3.20, 3.22, and 3.23). The result is an infinite loop, because T% is
 always equal to "6" upon exiting the inner loop and never makes it to
 20 to terminate the outer loop.

 BC.EXE correctly produces the error message "FOR Index variable
 already in use" when it attempts to compile this program. This is not
 a warning error, but a severe error. When you choose the Make EXE
 File command in the QB.EXE environment, the link step is skipped and
 no .EXE file is produced.

 Microsoft QuickBASIC Versions 3.00 and earlier correctly do not allow
 nested loops with the same index variable, either inside the
 environment or when compiled using the separate compilation method.

 The following code example shows the illegal counter-index (T%) usage:

    10 FOR T% = 1 TO 20
    20   PRINT "t% =";T%
    30   FOR T% = 1 TO 5
    40     PRINT "Inside loop, t% =";T%
    50   NEXT T%
    60 NEXT T%


 356. CTRL+Z Embedded in Source Truncates BC.EXE Compilation

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-JUL-1990    ArticleIdent: Q36576

 The QB.EXE versions 4.00, 4.00b, and 4.50 editors allow you to embed
 control characters into a source file by pressing CTRL+P followed by
 CTRL+<desired key>. This is mentioned in a table on Page 135 of the
 "Microsoft QuickBASIC 4.0: Learning and Using" manual for versions
 4.00 and 4.00b, and on Page 204 of the "Microsoft QuickBASIC 4.5:
 Learning to Use" manual for version 4.50.

 When using this technique, do not type CTRL+Z into the source file if
 the file is saved as text. For a file saved as text, CTRL+Z marks the
 end of the file (EOF) for BC.EXE and other Microsoft compilers. (This
 feature is a carryover from the end-of-file standard required for text
 files in MS-DOS versions 1.x.) You must save in fast load format for
 BC.EXE to accept embedded CTRL+Z characters.

 A CTRL+Z byte appears on the screen as a right-arrow symbol. To print
 a right-arrow symbol on the screen, use the statement PRINT CHR$(26)
 instead of embedding a CTRL+Z in a string constant.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) version 7.00 for MS-DOS and MS OS/2.

 BC.EXE stops compiling text source files when it reaches a CTRL+Z
 (ASCII value 26) byte. The program below demonstrates this behavior
 and terminates BC.EXE with a "Label Not Defined" error message.

 GOSUB lab
 PRINT "Here is a right-arrow character:"
 PRINT "[Press CTRL+P followed by CTRL+Z here in the QB.EXE 4.00 editor.]"
 END
 lab: PRINT "Test"
 RETURN

 The following equivalent program compiles successfully in BC.EXE:

 GOSUB lab
 PRINT "Here is a right-arrow character:"
 PRINT CHR$(26)
 END
 lab: PRINT "Test"
 RETURN


 357. Predefined Key ON KEY(n) GOSUB Trap Supersedes User-Defined

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q36894

 If a predefined key (such as a key from n=1 through 14) is turned on,
 the associated ON KEY(n) GOSUB statement is executed regardless of the
 status of the keyboardflag. In other words, a predefined key is
 trapped whether or not the key is pressed alone or in conjunction with
 the CAPS LOCK, NUM LOCK, SHIFT, CTRL, or ALT keys. The key trap occurs
 even if the same key also is defined with a specific keyboardflag
 value in a user-defined KEY statement. (User-defined keys are from
 n=15 through 20 in QuickBASIC Versions 3.00 and earlier, and from n=15
 to 25 in QuickBASIC Versions 4.00 and later and BASIC compiler
 Versions 6.00 and 6.00b for MS-DOS and OS/2.)

 Unlike trapping predefined keys, trapping user-defined keys IS
 dependent on the status of CAPS LOCK, NUM LOCK, SHIFT, CTRL, or ALT
 key.

 In the code example below, the user-defined key trap for CTRL+F1
 initially works as expected. If you press F2 and turn on the trapping
 of predefined function KEY (1), then the user-defined key trap for
 CTRL+F1 is ignored. The ON KEY (1) GOSUB trap for predefined function
 key 1 takes priority. This behavior is by design.

 This information applies to all versions of QuickBASIC, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The following is a code example:

 ON KEY(1) GOSUB got1
 KEY(1) OFF
 ON KEY(2) GOSUB swapper
 KEY(2) ON
 KEY 16, CHR$(4) + CHR$(&H3B)
 ON KEY(16) GOSUB got16
 KEY(16) ON
 print "Press an F1, CTRL-F1, or F2 key"
 WHILE 1
 WEND
 END

 got16:
   PRINT "found user-defined CTRL-F1 "
 RETURN

 got1:
   PRINT "found predefined F1 "
 RETURN

 swapper:
    INPUT "set Predefined on (Y/n) ", a$
    IF a$ = "N" or a$="n" THEN
       KEY(1) OFF
    ELSE
       KEY(1) ON
    END IF
 RETURN


 358. CTRL+INSERT to Copy Selected Text May Fail in QB.EXE 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50
 Last Modified: 17-NOV-1989    ArticleIdent: Q36898

 In the QuickBASIC Version 4.50 editor, the CONTROL+INSERT (CTRL+INS)
 key combination does not work correctly on the NCR 286 machines with
 NCR BIOS Versions 4.50 or 4.60, as well as some other machines.
 Specifically, the CONTROL+INSERT will not work at all if the NUM LOCK,
 SCROLL LOCK, or CAPS LOCK key is toggled on. The equivalent COPY
 command from the Edit menu works correctly on these same machines.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information here as it
 becomes available.

 You can work around this problem by using the COPY command from the
 QuickBASIC Version 4.50 Edit menu.

 This problem does not occur in QuickBASIC Versions 4.00 and 4.00b.


 359. QB.EXE 4.50 ALT+File+Load File Command Doesn't Recognize D Key

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q36900

 The Load File command on the File menu of the QuickBASIC Version 4.50
 editor does not allow the D key to load a document. Instead, the
 cursor will move to the Document option when D is pressed, but will
 not select the Document option.

 To work around this problem, you can press the SPACEBAR to select the
 Document option after the cursor is tabbed over to the Document
 option. Another workaround is to use the mouse to click on the
 Document option.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50. This problem was corrected in the QBX.EXE environment of
 Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 In QBX.EXE, "D" is no longer the access key for "Document". "T" is now
 used for selecting "Document". In QBX.EXE, the access keys for
 "Module", "Include" and "Document" are also highlighted.

 The following key strokes (while in edit mode) duplicate the problem:

    ALT  F  L  TAB  TAB  TAB

 Pressing the M or I keys at this point will produce expected results,
 but pressing the D key will not.


 360. Numerical Calculations and Loops Are Faster with Integers

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom floating point
 Last Modified: 28-DEC-1989    ArticleIdent: Q36901

 The time needed to process numbers as floating-point numbers is
 significantly longer than with integers. Since the default data type
 is single-precision floating-point numbers, it is quite common for
 people to use a floating-point variable to represent a number that
 could be represented as an integer or long. A FOR-NEXT loop that does
 nothing takes approximately six times as long to run when the index
 variable is specified as a single-precision number rather than as an
 integer.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 In the following code example that multiplies zero by zero, the
 version that uses integer variables runs five times as fast as the
 version using floating-point variables if the computer has an 80x87
 coprocessor or 25 times as fast with no coprocessor.

 The results of testing with a previous version of QuickBASIC is as
 follows:

 The integer loop is only three times as fast under QuickBASIC Version
 3.00.

 The following is a code example:

 ' The following loop uses the default data type, single precision:
 CLS
 x1 = TIMER
 FOR i = 1 TO 30000
   j = j * j
 NEXT i
 x2 = TIMER
 ' The following loop uses integer variables:
 DEFINT I-K
 FOR ii = 1 TO 30000
    k = k * k
 NEXT
 x3 = TIMER
 PRINT "default loop ="; x2 - x1
 PRINT "integer loop  ="; x3 - x2


 361. LOCATE Draws Cursor Differently on Monochrome Versus Color

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q36902

 The statement LOCATE ,,,8,8 will create a cursor that will appear
 differently on different screens. With a monochrome card, there will
 be a single-line cursor one-third of the way up from the lowest level
 of the line. When using a normal color display, the cursor will be at
 the lowest level of the line. But this same command on an IBM PS/2
 model 25 or 30 will cause the cursor to be at the top of the line. You
 may LOCATE ,,,7,7 on the PS/2 model 25 or 30 to create the cursor on
 the bottom of the line.

 This information applies to QuickBASIC Versions 3.00, 4.00, 4.00b, and
 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS
 OS/2.

 The following is a code example:

 CLS
 DEF SEG = 0
 IF PEEK(&H449) = 7 THEN
    b = 12
 ELSE
    b = 7
 END IF
 LOCATE 10, 10, 1, b, b
 PRINT "Bottom line cursor including ps/2 model 25 or 30"
 LOCATE 10, 15, 1, b, b
 WHILE INKEY$ = "" :WEND


 362. "Invalid Constant" Using Variable for Length of Fixed String

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37029

 The length of a fixed-length character string variable must be
 specified as a integer constant or as a CONST integer constant. The
 run-time error "Invalid Constant" results if the number in a "STRING *
 number" clause of a DIM or REDIM statement is a variable, or a
 constant of a non-integer type.

 The length of a fixed-length string must not be negative. A
 fixed-length string must have a length of at least one.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 QuickBASIC versions earlier than Version 4.00 do not support
 fixed-length string variables.

 The following is a code example:

 'This program will correctly give "Invalid Constant" when x is replaced
 'by y or z in the DIM statement.
    DEFINT A-Z
    CONST x = 11
    CONST y = 11.0
    z = 11
    DIM a AS STRING * x
    a = "hello there"
    PRINT a
    END


 363. BASIC Memory Model: Determining Segment Sizes with LINK /MAP

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G881013-4601 B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37030

 QuickBASIC uses a medium memory model plus dynamic and huge (larger
 than 64K) dynamic arrays supported in far heap. With this model, a
 program may contain multiple code segments (up to 64K per module) and
 one 64K shared data segment (known as DGROUP). The space that is not
 used by the code and DGROUP at run time is left for allocation of
 dynamic and huge dynamic arrays.

 The LINK .MAP file can be used to determine the size of the code
 segment(s) and the static portion of the DGROUP segment, as shown
 below. However, the FRE function is easier to use than the LINK .MAP
 file for getting information about data allocation.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS 7.00 for
 MS-DOS and MS OS/2.

 Note that allocating longer variable-length strings consumes more
 DGROUP space at run time than is indicated by the initial, static
 DGROUP allocation shown in the LINK .MAP file.

 Rather than using the LINK .MAP file, a better method to determine
 data usage is to invoke the FRE function within a program at run time.
 FRE("") returns the amount of dynamic space free for strings and
 dynamic arrays in DGROUP. FRE(-1) returns the amount of space free for
 dynamic arrays in far heap.

 To generate a link map, use the /MAP switch for the linker (LINK
 /MAP). The following link map is generated by linking a module called
 DOG.OBJ and is explained further below:

        Start  Stop   Length Name                   Class
        00000H 00050H 00051H DOG_CODE               BC_CODE
 (Code  00060H 00297H 00238H _TEXT                  CODE
  here) 00298H 008C5H 0062EH LOADRTM                CODE
 ----------------------------------------------------------------
 (Data  008D0H 0167FH 00DB0H BR_DATA                BLANK
  here) 01680H 01680H 00000H BR_SKYS                BLANK
        01680H 01680H 00000H COMMON                 BLANK
        01680H 01689H 0000AH BC_DATA                BC_DATA
        0168AH 0168FH 00006H NMALLOC                BC_VARS
        01690H 01690H 00000H ENMALLOC               BC_VARS
        01690H 01690H 00000H BC_FT                  BC_SEGS
        01690H 0169FH 00010H BC_CN                  BC_SEGS
        016A0H 016A2H 00003H BC_DS                  BC_SEGS
        016A4H 016A4H 00000H BC_SAB                 BC_SEGS
        016A4H 016ABH 00008H BC_SA                  BC_SEGS
        016ACH 016ACH 00000H _DATA                  DATA
        016ACH 016C7H 0001CH CDATA                  DATA
        016C8H 016C8H 00000H XCB                    DATA
        016C8H 016CBH 00004H XC                     DATA
        016CCH 016CCH 00000H XCE                    DATA
        016CCH 016CCH 00000H XIFB                   DATA
        016CCH 016CCH 00000H XIF                    DATA
        016CCH 016CCH 00000H XIFE                   DATA
        016CCH 016CCH 00000H XIB                    DATA
        016CCH 016CCH 00000H XI                     DATA
        016CCH 016CCH 00000H XIE                    DATA
        016CCH 016CCH 00000H XPB                    DATA
        016CCH 016CCH 00000H XP                     DATA
        016CCH 016CCH 00000H XPE                    DATA
        016CCH 016CCH 00000H XCFB                   DATA
        016CCH 016CCH 00000H XCF                    DATA
        016CCH 016CCH 00000H XCFE                   DATA
        016CCH 016CCH 00000H XOB                    BSS
        016CCH 016CCH 00000H XO                     BSS
        016CCH 016CCH 00000H XOE                    BSS
        016D0H 01ECFH 00800H STACK                  STACK

  Origin   Group
  008D:0   DGROUP

 In the above example, a source module called DOG.BAS was compiled and
 linked, resulting in a code segment name of DOG_CODE, which is limited
 to a maximum of 64K in size (if other compiler limitations are not
 exceeded first). DOG_CODE has the class name of BC_CODE. If your code
 module is approaching 64K in size, you should break it into SUBprogram
 and/or FUNCTION procedures in separate modules that can be compiled
 separately and then linked with the main module.

 The first three lines in the above map are the code segments. Each
 segment named can be up to 64K in size. Their classes are usually
 BC_CODE, CODE, and ENDCODE.

 The Origin section at the bottom of the link map tells you the
 position where the default data segment (DGROUP) starts, relative to
 the start of the .EXE code. The sum of the length of the items in
 DGROUP cannot exceed 64K. Items in DGROUP start at 008D:0 in the above
 map [which means offset 0 from the (16-byte) paragraph address 008D
 hex].

 For other programs, you may find another group, FMGROUP, whose origin
 is listed at the bottom of the link map (not shown in the above
 example). This group is used when you compile with the /AH option.
 FMGROUP is used for allocation tables and messages relating to far
 data. Arrays in far heap are not allocated space until run time.

 Note that the addresses given in the link map are not absolute load
 addresses -- instead, they are relative to the start of the code in
 the relocatable .EXE file. Only at run time does MS-DOS decide the
 absolute address where the .EXE program is loaded in memory. The
 VARPTR and VARSEG statements can then be used within a BASIC program
 to determine absolute addresses of variables and arrays at run time.
 Debuggers such as Microsoft CodeView, provided with the BASIC compiler
 Versions 6.00 and 6.00b, may also be used to determine absolute load
 locations at run time.


 364. Printer Error Can Hang; CALL INTERRUPT to Check Printer Status

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G881012-4545 B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37031

 Detecting printer errors with the ON ERROR GOTO statement is usually
 very slow. While the printer is waiting to time-out due to an error,
 the program may appear to be hung. Depending on the type of computer,
 MS-DOS or a QuickBASIC program may take from 20 seconds to more than
 two minutes before displaying a printer time-out error. This is
 expected behavior. The printer time-out period is determined by the
 BIOS of your computer.

 A printer time-out error is one of the most likely reasons for a
 QuickBASIC hanging problem. (If you wait more than a few minutes
 without getting an error message, then printer time-out is probably
 not the problem.)

 As an alternative to waiting for the printer time-out, you can check
 the status of the printer periodically throughout a program using BIOS
 Interrupt 17 Hex, function 2, as shown further below.

 This information applies to all versions of Microsoft QuickBASIC for
 the IBM PC and compatibles, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 The easiest way to check for printer errors is to send output to the
 printer and trap any errors with an ON ERROR GOTO statement. This
 method is slow and not always reliable, such as in the case where you
 send out less than a full buffer to the printer. When a program sends
 out less than a full buffer to the printer, an error may go undetected
 by the program until it fills the buffer later, at which point it
 appears to hang until it times out.

 If you print a file from MS-DOS or a QuickBASIC program when the
 printer is off line, it will take up to a couple of minutes for an
 error to be returned. The time allowed for a response varies from
 version to version of the ROM BIOS.

 However, you can check the status of the printer periodically
 throughout a program by using the BIOS Interrupt 17 Hex, function 2.
 This interrupt returns the printer status in the AH register. Each bit
 returned in AH represents the following printer conditions:

    Bit     Condition
    ---     ---------

    Bit 7   Printer Not Busy (0 = Busy)
    Bit 6   Acknowledge
    Bit 5   Out of Paper
    Bit 4   Printer Selected
    Bit 3   I/O Error
    Bit 2   Unused
    Bit 1   Unused
    Bit 0   Timed-Out

 For example, to determine if the printer is out of paper, the
 interrupt could be called and bit 5 could be examined. To call DOS
 interrupts through QuickBASIC, the CALL INTERRUPT routine is used.
 This routine is discussed on Pages 89-91 of the "Microsoft QuickBASIC
 4.0: BASIC Language Reference" manual.

 The following is a sample BASIC program that uses CALL INTERRUPT to
 check the printer status when the F1 key is pressed or after a BASIC
 error:

    DECLARE SUB PrinterStatus ()
    DEFINT A-Z
    REM $INCLUDE: 'qb.bi'
    ' For BASIC PDS, include 'qbx.bi'
    CLS
    ON ERROR GOTO trap
    ON KEY(1) GOSUB CheckPrinter
    KEY(1) ON
    OPEN "lpt1:" FOR OUTPUT AS #1
    FOR i = 1 TO 1000
        PRINT #1, "dflkgjsaklfajds;lfk"
    NEXT i
    END

 The following is a checkprinter program:

    CALL PrinterStatus
    INPUT "Hit Any Key to Continue"; a$
    RETURN

 The following is a trap program:

    PRINT "err = "; ERR
    CALL PrinterStatus
    INPUT "Hit Any Key to Continue"; a$
    RESUME

 SUB PrinterStatus STATIC
    DIM ina AS RegType, outa AS RegType
    DIM INFO$(7)
    ina.ax = &H200
    ina.dx = &H0
    CALL INTERRUPT(&H17, ina, outa)
    outah = outa.ax \ 256
    FOR i = 7 TO 0 STEP -1
        result = (outah) AND (2 ^ i)
        IF result = 0 THEN
           INFO$(i) = "OFF"
        ELSE
           INFO$(i) = "ON"
        END IF
    NEXT i
    PRINT "Bit 7 - Printer Not Busy : "; INFO$(7)
    PRINT "Bit 6 - Acknowledge : "; INFO$(6)
    PRINT "Bit 5 - Out of Paper : "; INFO$(5)
    PRINT "Bit 4 - Printer Selected : "; INFO$(4)
    PRINT "Bit 3 - I/O Error : "; INFO$(3)
    PRINT "Bit 2 - Unused : "; INFO$(2)
    PRINT "Bit 1 - Unused : "; INFO$(1)
    PRINT "Bit 0 - Timed-Out : "; INFO$(0)
 END SUB


 365. Toggling DTR Handshaking Line (Pin 20) with OUT Statement

 Product Version(s): 2.00 2.01 3.00 4.OO 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q37093

 The communications port DTR line (Pin 20) can be toggled with an OUT
 statement. The OUT statement should access the modem control register
 in the UART. The modem control register can be accessed by the
 following statements:

 For COM1, the statement is as follows:

    OUT &H3FC, INP(&H3FC) OR 1   ' Sets low bit to turn DTR on.
    OUT &H3FC, INP(&H3FC) AND &HFE  ' Clears low bit to turn off DTR.

 For COM2, the statement is as follows:

     OUT &H2FC, INP(&H2FC) OR 1   ' Sets low bit to turn DTR on.
     OUT &H2FC, INP(&H2FC) AND &HFE  ' Clears low bit to turn off DTR.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 Other information concerning hardware addresses for serial
 communications can be found in "The Programmer's PC Sourcebook" by
 Thom Hogan (Microsoft Press, 1988).

 Code Example
 ------------

 '------------------------- DTR.BAS ------------------------------
 '
 '    This program shows how to toggle on and off the DTR line for
 '    the RS-232 serial communications line in compiled BASIC.
 '
 '    The DTR (Data Terminal Ready) line is controlled by the lowest
 '    bit in the modem control register, which is located at port
 '    address 3FC Hex for COM1: or 2FC Hex for COM2:.
 '
 OPEN "Com1:9600,n,8,,CS0,DS0,CD0" FOR RANDOM AS 1
 CLS
 PRINT "Press d for DTR on, OR o for DTR off"
 DO UNTIL keyinput$ = CHR$(27)
     keyinput$ = INKEY$
     IF (keyinput$ = "d") OR (keyinput$ = "D") THEN
        OUT &H3FC, INP(&H3FC) OR 1   ' Sets low bit to turn DTR on.
     ELSEIF (keyinput$ = "o") OR (keyinput$ = "O") THEN
        OUT &H3FC, INP(&H3FC) AND &HFE  ' Clears low bit to turn off DTR.
     END IF
 LOOP


 366. WIDTH Clears the Screen When Setting EGA 43-Line Mode

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q37094

 The WIDTH statement blanks the screen when the following command is
 executed in an EGA screen mode (such as SCREEN 9):

    WIDTH 80,43

 The screen clears because the information that was stored in the
 previous 25-line (default) screen is no longer in a valid format to be
 redisplayed in EGA 43-line mode.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC PDS (Professional Development
 System) Version 7.00 for MS-DOS.


 367. How to INPUT Text without CTRL+BREAK Stopping Execution

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37163

 When an INPUT or LINE INPUT statement is pending to accept text, the
 program will always stop if you press CTRL+BREAK. CTRL+BREAK aborts
 the program even when the program is compiled without the /D (debug)
 option. [Pressing CTRL+BREAK will not stop programs compiled without
 /D (debug) if no INPUT or LINE INPUT statement is currently pending.]

 Also, events such as ON KEY(n) GOSUB key trapping and ON ERROR GOTO
 error handling are suspended until the INPUT or LINE INPUT statement
 is satisfied by pressing the ENTER key.

 This behavior applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50; to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2; and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 You will need to use a method other than INPUT and LINE INPUT to both
 suppress CTRL+BREAK and allow input, and to allow events to be handled
 while input is taking place. The easiest method to use is a loop
 structure that monitors the value of the INKEY$ function and makes the
 appropriate changes to the input string. Below is an example of how to
 write your own INPUT statement. For another example of how to write
 your own INPUT statement, query on the following words:

    QuickBASIC and buffered and keyboard and input and cursor

 The program listing below demonstrates how to use INKEY$ in a loop to
 simulate the operation of INPUT or LINE INPUT. The program checks the
 value of INKEY$, and acts on the value accordingly, such as handling
 backspaces, carriage returns, and non-printable characters. This
 routine can easily be modified to allow other features, such as
 filling the edit field to the specified size with a fill character,
 recognizing function keys to perform various functions, etc.

 THe following is a code example:

 '--- INPUT.BAS
 '--- Copyright (c) 1988 Microsoft Corporation
 '--- This program demonstrates the subprogram TextInput as a
 '--- substitute for BASIC's INPUT and LINE INPUT statements.
 '--- When compiled without the /D (debug) option, pressing
 '--- CTRL+BREAK will not stop this program.
 DECLARE SUB TextInput (text$, MaxLen%)
 text$ = "This is a sample"
 PRINT "Enter some text:";
 TextInput text$, 45
 PRINT "The line you entered:"
 PRINT text$
 END

 '--- TextInput
 '--- Accepts a line of text from the user
 '
 '--- Text$   : Default string/destination string input by user
 '--- MaxLen% : Maximum length of destination string, up to 80 chars
 '
 SUB TextInput (text$, MaxLen%) STATIC
   '--- Set up cursor, line, and maximum characters to enter:
   y% = CSRLIN
   LOCATE , , 1
   IF MaxLen% > (79 - POS(0)) THEN MaxLen% = (79 - POS(0))
   '--- Display default text:
   PRINT text$;
   '--- Do the input loop:
   DO
     i$ = INKEY$
     SELECT CASE LEFT$(i$, 1)
       CASE CHR$(8)                      '--- Handle a backspace
         IF text$ > "" THEN
           text$ = LEFT$(text$, LEN(text$) - 1)
           LOCATE y%, POS(0) - 1
           PRINT " ";
           LOCATE , POS(0) - 1
         END IF
       CASE CHR$(32) TO CHR$(255)        '--- Valid characters
         IF LEN(text$) <= MaxLen% THEN
           PRINT LEFT$(i$, 1);
           text$ = text$ + LEFT$(i$, 1)
         ELSE
           BEEP
         END IF
       CASE "", CHR$(13)                 '--- Null or carriage return
       CASE ELSE                         '--- Non-printables, etc.
         BEEP
     END SELECT
   LOOP UNTIL i$ = CHR$(13)
   LOCATE , , 0
   PRINT
 END SUB


 368. INT86OLD & INT86XOLD Not in QB 4.50 or BASIC 7.00 Help, Manual

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891226-2 docerr B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q57385

 The "Microsoft BASIC 7.0: BASIC Language Reference" manual fails to
 document the INT86OLD and INT86XOLD routines.

 Also, CALL INT86OLD and CALL INT86XOLD are not documented in the
 online Help systems for either QB.EXE in QuickBASIC 4.50 or for
 QBX.EXE, which comes with Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 A complete description of INT86OLD and INT86XOLD are provided below
 for owners of BASIC PDS 7.00, and for owners of QuickBASIC 4.50 who do
 not own a copy of the "Microsoft QuickBASIC 4.5: BASIC Language
 Reference."

 This information applies to Microsoft BASIC PDS 7.00 for MS-DOS and to
 Microsoft QuickBASIC 4.50 for MS-DOS.

 Note that CALL INT86OLD and CALL INT86XOLD are documented in the
 "Microsoft QuickBASIC 4.5: BASIC Language Reference" manual for
 QuickBASIC 4.50. The following description of INT86OLD and INT86XOLD
 is taken from Page 72 of that manual [additional comments are in
 brackets ([])]:

                       CALL INT86OLD Statements

 ACTION: Allows programs to perform DOS system calls

 SYNTAX: CALL INT86OLD (intno, inarray(), outarray())
         CALL INT86XOLD (intno, inarray(), outarray())

 REMARKS: The CALL INTERRUPT statement provides an easier way to make
          DOS system calls. See the entry for CALL INTERRUPT for more
          information. The following list describes the arguments to
          INT86OLD and INT86XOLD:

 Argument    Description
 -----------------------
 intno       The DOS interrupt to perform. It is an integer between 0
             and 255. See your DOS documentation for the interrupt
             numbers.

 inarray()   An integer array specifying the register values when the
             interrupt is performed.

             INT86OLD uses an eight-element array, while INT86XOLD
             uses a ten-element array. Table R.1 lists the array
             elements and the corresponding registers.

 outarray()  Contains the post-interrupt register values. It has the
             same structure as inarray().

 If an error occurs, intno = -1 and values in outarray are
 unchanged. Errors are caused by in_no not being in the range 0 - 255.

 Table R.1 INT86OLD and INT86XOLD Register Values
 ------------------------------------------------
 Array Element         Register
 ------------------------------------------------
 inarray(x)              AX
 inarray(x+1)            BX
 inarray(x+2)            CX
 inarray(x+3)            DX
 inarray(x+4)            BP
 inarray(x+5)            SI
 inarray(x+6)            DI
 inarray(x+7)            FLAGS
 inarray(x+8)*           DS
 inarray(x+9)*           ES
 ------------------------------------------------
 *  These array elements are used only by INT86XOLD. To use the
    current run-time values of DS and ES, assign the value -1 to array
    elements 8 and 9.

 The INT86OLD and INT86XOLD routines alter all registers except
 BP and DS.

 INT86OLD and INT86XOLD provide compatibility with older [QuickBASIC
 2.00, 2.01, or 3.00] programs using INT86 and INT86X. Like the INT86
 and INT86X routines, INT86OLD and INT86XOLD are distributed in a Quick
 library [QB.QLB for QB.EXE and QBX.QLB for QBX. EXE] and in a
 conventional library [QB.LIB for QuickBASIC 4.x and QBX.LIB for BASIC
 PDS 7.00] on the distribution disks. The disks also contain a header
 file [QB.BI for QuickBASIC 4.x or QBX.BI for BASIC PDS 7.00] for use
 with the procedures. See the disk-contents list for specific
 information.

 Note that INT86OLD and INT86XOLD do not require the use of VARPTR.
 Also, the register values are stored in the arrays beginning with the
 first array element.

 EXAMPLE
 -------

 'This example uses INT86OLD to open a file and place some text in it.

 ' Note: To use CALL INTERRUPT, you must load the Quick library QB.LIB
 '       with QuickBASIC. The program also uses the QB.BI header file.

 ' Include header file for INT86OLD, etc.
 $INCLUDE:'QB.BI'

 DIM INARY%(7),OUTARY%(7)          'Define input and output
                                   'arrays for INT86.
 '
 ' Define register-array indices to
 ' make program easier to understand.
 CONST AX=0, BX=1, CX=2, DX=3, BP=4, SI=5, DI=6, FL=7
 '
 INARY%(AX) = &H3C00               'DOS function to create a file.
 INARY%(CX) = 0                    'DOS attribute for created file.
 TEMP$="FOO.TXT"+CHR$(0)
 INARY%(DX) = SADD(TEMP$)
                                   'Pointer to file-name string
                                   'with zero byte termination.

 CALL INT86OLD(&H21,INARY%(),OUTARY%())
                                   'Perform the creation.
 '
 INARY%(BX) = OUTARY%(AX)         'Move created file handle for write.
 INARY%(AX) = &H4000               'DOS function to write to file.
 TEXT$ = "hello, world"+CHR$(13)+CHR$(10)
                                   'Define text to write to file.
 INARY%(CX) = LEN(TEXT$)           'Get length of text string.
 INARY%(DX) = SADD(TEXT$)          'Get address of text string.
 CALL INT86OLD(&H21,INARY%(),OUTARY%())
                                   'Perform the write.
 '
 INARY%(AX) = &H3E00               'DOS function to close a file.
 CALL INT86OLD(&H21,INARY%(),OUTARY%())
                                   'Perform the close.


 369. LONG Integer Parameter Passed to SUB Fails after Assignment

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q37305

 A problem can occur in an .EXE program when you pass a LONG integer
 parameter to a subprogram and then assign that parameter to a local
 short integer. The long integer parameter becomes corrupted; the
 program should have only changed the local short integer. This problem
 does not occur inside the QuickBASIC QB.EXE environment.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler Versions 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS OS/2. This problem
 was corrected in Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 This problem does not occur when the program is compiled with the
 debug option (BC /D). To work around the problem, compile with the
 debug option.

 The following steps will demonstrate this problem:

 1. Pass an integer to a subprogram whose formal parameter is declared
    to be a LONG integer.

 2. Within the subprogram, initialize a temporary, short-integer
    variable, and assign the LONG integer parameter to it. This forces
    a type conversion from LONG to short integer.

 3. Immediately print out the LONG integer parameter. Even though the
    program was not designed to change the LONG variable, it is
    corrupted (i.e., an unexpected value appears). The temporary,
    short-integer variable prints correctly.

 The program code example below will work as expected inside the
 QuickBASIC QB.EXE environment. However, when compiled into an
 executable (.EXE file), the problem occurs. Note that all three PRINT
 statements should return the same values (4).

 The following is a code example:

 DECLARE SUB foo (long1&, long2&)
 CLS
 CALL foo(4&, 4&)  ' Long or short integer constants both show problem.

 SUB foo (long1&, long2&)
 PRINT "initial parameters: ", long1&, long2&
 temp1% = 0
 temp2% = 0
 temp1% = long1&   ' It is here where the type conversion takes place
 temp2% = long2&   ' and long1& and long2& are corrupted.
 PRINT "Parameters after assignment: "; long1&, long2&
 PRINT "Temporary variables after assignment: "; temp1%, temp2%
 END SUB


 370. "Device I/O Error" If Keyboard Buffer Filled During "COM1"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q37306

 When the keyboard buffer becomes full while serial communications are
 executing, a "Device I/O error" (error 57) may occur.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50, in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b), and in
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS and MS OS/2 (buglist7.00). This problem was corrected in BASIC
 PDS version 7.10 (fixlist7.10).

 To work around this problem, use the INKEY$ function to poll the
 keyboard so that any keyboard input will be flushed. This process is
 shown below.

 When the program code example below is run without any keyboard
 interference, the program runs to completion. However, if you type
 enough to fill the keyboard buffer, a "Device I/O error" occurs.

 The following is a code example:

    DEFINT A-Z
    OPEN "COM1:1200,n,8,1,cs0,ds0" FOR RANDOM AS #1
    ON COM(1) GOSUB emptycom
    COM(1) ON
    FOR i = 1 TO 10000
      '  WHILE INKEY$<>"": WEND   ' Used to Empty the Keyboard buffer
      PRINT #1, "a"
    NEXT i
    CLOSE
    END

    emptycom:
      '  WHILE INKEY$<>"": WEND  '  Used to Empty the Keyboard buffer
      INPUT #1, s$
      PRINT s$,
      RETURN


 371. Conditionally Loading QBHERC Hercules Support from QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37307

 You will encounter some limitations if you wish to conditionally load
 QBHERC.COM or MSHERC.COM from within a QuickBASIC program.

 The only way to invoke QBHERC.COM or MSHERC.COM from within a
 QuickBASIC program is with the SHELL statement. QBHERC.COM and
 MSHERC.COM are terminate-and-stay resident (TSR) graphics drivers. TSR
 programs will fragment MS-DOS memory when loaded with the SHELL
 statement. You can only unfragment the memory by rebooting the
 computer. Fragmentation can drastically reduce the memory available to
 subsequent programs run in MS-DOS. This fragmentation problem can be
 serious, and it is best to avoid SHELLing to QBHERC.COM or MSHERC.COM
 or any TSR program.

 Note that the BASIC run-time routines must know at initialization time
 (that is, when the program is started) whether or not QBHERC.COM or
 MSHERC.COM has been loaded. This means a program (or batch file) that
 loads QBHERC.COM or MSHERC.COM must RUN or CHAIN (or invoke) the .EXE
 program that will use Hercules graphics.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and
 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The following is a possible scenario for conditionally executing
 QBHERC.COM or MSHERC.COM:

 1. Run a batch file that starts an assembler program that tests if a
    Hercules card is installed.

 2. Test to see if a Hercules graphics card is installed, and pass this
    information back to the batch file by using batch ERRORLEVEL (or
    information written in a text file). (Note that a QuickBASIC
    program does not let you return ERRORLEVELs to batch files, because
    it always resets the ERRORLEVEL to zero for normal termination.)

 3. If necessary, invoke QBHERC.COM from the batch file.

 4. Invoke the QuickBASIC QB.EXE program. The compiler's run-time
    system now reinitializes to take advantage of QBHERC.COM or
    MSHERC.COM, which is now resident in memory.

 Normally you would run QBHERC.COM or MSHERC.COM manually or from a
 batch file before invoking a graphics program that takes advantage of
 SCREEN 3 on a computer with a Hercules graphics adapter installed.

 Hercules support was introduced in QuickBASIC Version 4.00. For more
 information, please see the README.DOC file for QuickBASIC Versions
 4.00 and 4.00b.


 372. Graphics GET and PUT Require Integer or LONG Array; Example

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37308

 Page 208 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference"
 manual states the following:

    Unless the array type is integer or long, the contents of an array
    after a [graphics] GET appear meaningless when inspected directly.

 This statement also applies when saving the elements of the array to a
 file. Unless the array type is integer or long, the resulting picture,
 when read back from disk, will be distorted.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 The program below will display a picture, save it to disk, read it
 back from disk, and re-display the picture. If the "picture()" array
 is of integer type, the program will work as expected. If it is of
 single type, the resulting picture will be distorted.

 The following is a code example:

 CONST picSize = 16383
 DIM picture(picSize) AS SINGLE   ' Change to INTEGER

 SCREEN 3  ' SCREEN 3 is for Hercules. Use SCREEN 2 for CGA card.
 FOR x = 1 TO 150 STEP 2.5          ' Draw a simple picture
   LINE (x + 300, x)-(300 - x, 300 - x), 7, B
 NEXT

 GET (30, 0)-(450, 300), picture

 OPEN "temp.pic" FOR OUTPUT AS #1   ' Save the picture
 FOR i = 0 TO picSize
   PRINT #1, picture(i)
 NEXT i
 CLOSE #1

 OPEN "temp.pic" FOR INPUT AS #1    ' Load the picture back
 FOR i = 0 TO picSize
   INPUT #1, picture(i)
 NEXT i

 CLS
 PUT (5, 5), picture                ' Display the picture


 373. QB 2.x and 3.00 INT86 Requires VARPTR, but Not 4.00 INT86OLD

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |  B_BasicCom
 Last Modified:  4-SEP-1990    ArticleIdent: Q37309

 The interrupt routines INT86OLD and INT86XOLD are meant to emulate the
 INT86 and INT86X routines found in earlier versions, but they are
 invoked differently, as described in this article.

 INT86 and INT86X routines are found only in QuickBASIC versions 2.00,
 2.01, and 3.00. The INT86OLD and INT86XOLD are included in Microsoft
 QuickBASIC versions 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS; and in Microsoft BASIC PDS
 versions 7.00 and 7.10 for MS-DOS.

 In QuickBASIC versions 2.x and 3.00, the offset of the register arrays
 must be passed to INT86 and INT86X using the VARPTR function. For
 INT86OLD and INT86XOLD (found in later versions), VARPTR is not
 required. [This difference is noted on Page 87 in the "Microsoft
 QuickBASIC 4.0: BASIC Language Reference" manual for versions 4.00 and
 4.00b, and on Page 87 in the Microsoft BASIC Compiler 6.0: BASIC
 Language Reference" manual for versions 6.00 and 6.00b.]

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The newer versions of BASIC listed above have replaced the INT86 and
 INT86X statements with the following easier-to-use routines: CALL
 INTERRUPT and CALL INTERRUPTX. For more information about these newer
 routines, query in this Knowledge Base on the following word:

    QB4INT

 The syntax for INT86 and INT86X (used in QuickBASIC versions 2.00,
 2.01, and 3.00) is as follows:

    CALL INT86 (int_no, VARPTR(in_array(x)), VARPTR(out_array(y)))
    CALL INT86X (int_no, VARPTR(in_array(x)), VARPTR(out_array(y)))

 The syntax for INT86OLD and INT86XOLD (used in later versions for
 backwards statement-compatibility) is as follows:

    CALL INT86OLD (int_no, in_array(), out_array())
    CALL INT86XOLD (int_no, in_array(), out_array())


 374. LPRINT Forced to Screen Using OPEN in FUNCTION Procedure

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37310

 You should avoid invoking a FUNCTION procedure that performs I/O in
 I/O statements.

 For example, if a FUNCTION procedure that opens a file is invoked in
 an LPRINT statement, the printing occurs on the screen instead of the
 printer in the example below. The simplest way to work around this
 limitation is to assign the FUNCTION procedure value to a temporary
 variable and then LPRINT the temporary variable. You can also
 eliminate the problem by taking the OPEN statement out of the FUNCTION
 procedure.

 This behavior applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 This limitation for the FUNCTION statement is documented on Page 201
 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
 Versions 4.00 and 4.00b. The following information appears in this
 manual:

    Because BASIC may rearrange arithmetic expressions for greater
    efficiency, avoid using FUNCTION procedures that change program
    variables in arithmetic expressions. Also avoid using FUNCTION
    procedures that perform I/O in I/O statements. Using FUNCTION
    procedures that perform graphics operations in graphics statements
    may also cause side effects.

 To work around this problem, assign the value of the FUNCTION
 procedure to a temporary variable, then use the temporary variable in
 the arithmetic expression, I/O statement, or graphics statement.

 Versions of QuickBASIC earlier than 4.00 do not have the FUNCTION
 statement.

 The following example, which LPRINTs a temporary variable, works
 correctly:

    DECLARE FUNCTION code$ (a!)
    CLS
    x$=code$(a)
    LPRINT x$; "stuff to print"
    END
    FUNCTION code$ (a)
       OPEN "temp" FOR RANDOM AS #1 LEN=1
       code$="abcd"
       CLOSE #1
    END FUNCTION

 The following example, which LPRINTs a FUNCTION procedure that uses
 the OPEN statement, incorrectly prints to the screen:

    DECLARE FUNCTION code$ (a!)
    CLS
    LPRINT code$(a); "stuff to print"
    END
    FUNCTION code$ (a)
       OPEN "temp" FOR RANDOM AS #1 LEN=1
       code$="abcd"
       CLOSE #1
    END FUNCTION


 375. QB.EXE Editor Fails to Flag Extra ELSE Clause as Syntax Error

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50
 Last Modified: 28-DEC-1989    ArticleIdent: Q37319

 In the program code example below, the QB.EXE environment fails to
 detect an extra ELSE clause in an IF statement as being a syntax
 error. Instead, the number 0 is displayed as well as number 2.

 The BC.EXE compiler successfully flags the extra ELSE clause as a
 syntax error. It is logically illegal to use two or more ELSE clauses
 in an IF statement. Only one ELSE clause is allowed in an IF
 statement. (The ELSE clause can also be left out of an IF statement.)

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50. This problem is corrected in the QBX.EXE
 environment that comes with Microsoft BASIC PDS Version 7.00
 (fixlist7.00).

 The following is a code example:

 a = 0
 IF a = 0 THEN
   PRINT a
 ELSE
   PRINT 1
 ELSE
   PRINT 2
 END IF


 376. MS-DOS QuickBASIC 4.00 Differs from XENIX BASIC Compiler 5.70

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q37340

 This article compares Microsoft BASIC Compiler versions 5.70 and 5.70a
 for XENIX 286 to the following compilers:

 1. Microsoft QuickBASIC versions 4.00, 4.00b, 4.50 for MS-DOS

 2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS

 Microsoft BASIC Compiler for XENIX 286 provides a library for ISAM
 file handling that is not available with the above Microsoft BASIC
 compilers for MS-DOS.

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 provide ISAM file support under MS-DOS (and under MS OS/2 in
 BASIC 7.10). BASIC PDS 7.00 and 7.10 offer additional features beyond
 those found in 6.00 and 6.00b.

 The BASIC compilers for MS-DOS have a graphic capability not found in
 the XENIX BASIC compiler.

 Compilers under both XENIX and MS-DOS have SUB...END SUB structures
 for defining subprograms, which can be called with the CALL statement.

 Note: All support and upgrades for Microsoft BASIC Compilers and
 Interpreters for XENIX have been assumed by SCO (the Santa Cruz
 Operation). For more information on XENIX BASIC and SCO, query on the
 following words:

    SCO and XENIX and BASIC and support

 The list below outlines commands that differ between the BASIC
 compiler for XENIX versus the BASIC products for MS-DOS.

 An asterisk (*) marks words that are reserved, but not functionally
 implemented in the compiler.

 Reserved words in Microsoft BASIC Compiler version 6.00b for MS-DOS or
 QuickBASIC version 4.50 that are not found in Microsoft BASIC Compiler
 version 5.70a for XENIX are as follows:

    ACCESS      ALIAS       ANY         BEEP      BINARY
    BLOAD       BSAVE       BYVAL       CASE      CDECL
    CIRCLE      CLNG        COLOR       COM       COMMAND$
    CONST       CSRLIN      CVDMBF      CVSMBF    DECLARE
    DEFLNG      DO          DOUBLE      DRAW      ELSEIF
    ENVIRON     ENVIRON$    ERDEV       ERDEV$    EXIT
    FILEATTR    FREEFILE    FUNCTION    INP       INTEGER
    IOCTL       IOTCL$      IS          KEY       LCASE$
    * LIST      LOCAL       LONG        LOOP      LTRIM$
    MKDMBF$     MKL$        MKSMBF$     OFF       OUT
    PAINT       PALETTE     PCOPY       PEN       PLAY
    PMAP        PRESET      PSET        RANDOM    REDIM
    RTRIM$      SCREEN      SEEK        SEG       SELECT
    SETMEM      SHARED      SIGNAL      SINGLE    SLEEP
    SOUND       STATIC      STICK       STRING    TYPE
    UCASE$      UNTIL       VARPTR$     VARSEG    VIEW
    WINDOW

 Reserved words in Microsoft BASIC Compiler version 5.70a for XENIX
 that are not reserved in Microsoft BASIC Compiler version 6.00b for
 MS-DOS or QuickBASIC version 4.50 are as follows:

    * DELETE
    * EDIT
    * USR


 377. How to Create Your Own Font in Character Mode for EGA Text

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q37341

 The code example below shows a method of creating a user-defined text
 font for use with an EGA or VGA monitor. This method allows a person
 to define a specified number of new characters that are in order
 starting at a specified position in the table. Only those characters
 in the character set that are overwritten by the new fonts are
 changed. In the example below, the three new characters are printed
 and the fourth character from the original set is printed.

 This code example applies to QuickBASIC Versions 4.00, 4.00b, and
 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS,
 and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 Note: Microsoft BASIC PDS Version 7.00 comes with a library of
 routines that allow loading and displaying of bitmapped fonts. BASIC
 PDS 7.00 comes with several font files, and the font library routines
 can load and display any of the Microsoft Windows bitmapped fonts.

 The following is a code example:

 ' $INCLUDE: 'qb.bi'
 DIM RegS AS RegType, RegL AS RegTypeX
 DIM table(100)
 DATA 0,0,0,2,6,14,30,62,126,254,0,0,0,0
 DATA 0,0,0,254,64,32,16,32,64,254,0,0,0,0
 DATA 0,0,0,132,136,158,162,70,130,14,0,0,0,0

 CLS
 DEF SEG = VARSEG(table(0))
 FOR i = 1 TO 42
    READ A%        'Place the NEW characters into
    POKE VARPTR(table(0)) + i, A%    'graphics table
 NEXT i
 DEF SEG

 RegL.AX = &H1100   ' function 11 subfunction 0
 RegL.BX = &HE00    ' There are &HE points per character
                    ' put font at table 0
 RegL.CX = &H3      ' defined three characters
 RegL.DX = 0        ' first character is chr$ (0)
 RegL.DS = -1       ' use old data seg
 RegL.ES = VARSEG(table(0))  ' address of table
 RegL.BP = VARPTR(table(0))  ' that holds the fonts
 CALL interruptX(&H10, RegL, RegL)  ' make the call

 PRINT CHR$(0) + CHR$(1) + CHR$(2) + CHR$(3)


 378. How to Define Your Own Font in Graphics Mode for EGA or VGA

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 31-OCT-1988    ArticleIdent: Q37343

 A programmer can create a specialized graphics font for use with the
 EGA or VGA graphics systems. The new font is installed by making a
 BIOS interrupt call. When you install your own font, none of the
 original graphics characters are available until they are reinstated.

 The code example below creates and installs a new user font. This font
 consists of the following four characters:

    triangle
    capital Sigma
    the fraction 1/3 (one third)
    a space

 The program displays the characters and then reinstates the original
 font and displays the original characters.

 This information applies to QuickBASIC Versions 4.00, 4.00b, 4.50 and
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
 OS/2.

 The following is a code example:

 ' $INCLUDE: 'q:qb.bi'
 DIM RegS AS regtype, RegL AS Regtypex
 DIM table(100)
 DATA 0,0,0,2,6,14,30,62,126,254,0,0,0,0
 DATA 0,0,0,254,64,32,16,32,64,254,0,0,0,0
 DATA 0,0,0,132,,136,158,162,70,130,14,0,0,0,0
 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0
 CLS
 DEF SEG = VARSEG(table(0))
 FOR i = 1 TO 56
    READ A%      'Place the created characters into the new
    POKE VARPTR(table(0)) + i, A%    'graphics table
 NEXT i
 DEF SEG

 SCREEN 9
 ' set user defined font
 RegL.AX = &H1121
 RegL.BX = &H0
 RegL.CX = &HE
 RegL.DX = 0
 RegL.DS = -1
 RegL.ES = VARSEG(table(0))
 RegL.BP = VARPTR(table(0))
 CALL InterruptX(&H10, RegL, RegL)

 LOCATE 10, 10
 FOR i = 0 TO 3
    PRINT CHR$(i) + CHR$(4); 'prints new user font
 NEXT

 '  switch back
 RegL.AX = &H1122
 RegL.BX = 0
 CALL InterruptX(&H10, RegL, RegL)

 LOCATE 12, 10
 FOR i = 0 TO 3
    PRINT CHR$(i); " "; 'prints normal characters
 NEXT


 379. How to Use Extended/Expanded Memory RAMDrive for Data Storage

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_PC
 Last Modified:  8-JAN-1990    ArticleIdent: Q37344

 Many programmers want to have speedy access to large amounts of data.
 You can store data in extended/expanded memory by using an MS-DOS
 device driver such as RAMDRIVE.SYS to make a virtual disk drive out of
 the extended/expanded memory. (You can also use a floppy or hard disk
 drive to store data, but a RAMDrive is faster.)

 This article demonstrates how to use structured data types and
 structured subprograms to quickly access information on a RAMDrive or
 disk drive. The general technique in this article applies to all
 languages that have data structures, including the following:

 1. Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 4. Microsoft C

 5. Microsoft Pascal

 The QuickBASIC Module 1 below shows how you can put any kind of data
 in a RAMDrive (or disk drive) by calling three standard subroutines,
 which are located in Module 2. The subroutines in Module 2 are named
 InitRAM, PutData, and GetData. To use these subroutines, you will need
 to change the user-defined type definition in both modules 1 and 2 to
 support your choice of data types. You may want to customize the
 routines in Module 2 to suit your own needs.

 The second module, which holds all of the subroutines, can be thought
 of as an abstract data type (ADT). Books and courses about Data
 Structures define an ADT as a set of operations (routines) that
 operate upon a given data type. You can change the ADT, Module 2, to
 save any number and type of data elements in the disk drive or
 RAMDrive. You could write each data type to a different file on the
 RAMDisk.

 Remember that each open file takes one MS-DOS file handle at run time.
 The RAMDRIVE.SYS driver also takes up one file handle.

 The following is a code example:

 Module 1
 --------

 DECLARE SUB InitRAM (j AS ANY)
 DECLARE SUB PutData (I AS INTEGER, j AS ANY)
 DECLARE SUB GetDATA (I AS INTEGER, j AS ANY)
 TYPE UserSpec
    I AS INTEGER
    L AS LONG
    S AS SINGLE
    D AS DOUBLE
    W AS STRING * 60
 END TYPE
 DIM MyData AS UserSpec
 CLS

   CALL InitRAM(MyData)

   MyData.I = 1
   MyData.L = 12345678
   MyData.S = 123.4567
   MyData.D = 17989.65492#
   MyData.W = "A way to use expanded/extended memory"
   I% = 1   ' I% will be passed as the random file record number
   CALL PutData(I%, MyData)
   MyData.W = "This gets changed back"

   CALL GetDATA(I%, MyData)
   PRINT "Integer was "; MyData.I
   PRINT "Long was    "; MyData.L
   PRINT "Single was  "; MyData.S
   PRINT "Double was  "; MyData.D
   PRINT "String was   "; MyData.W
 END

 Module 2
 --------

 ' The following routines make up the abstract data type (ADT);
 ' in other words, you can modify the data type and functionality
 ' for these routines as you wish:
 TYPE UserSpec
    I AS INTEGER
    L AS LONG
    S AS SINGLE
    D AS DOUBLE
    W AS STRING * 60
 END TYPE

 SUB GetDATA (I AS INTEGER, MyData AS UserSpec)
    GET #15, I, MyData
 END SUB

 SUB InitRAM (MyData AS UserSpec)
     OPEN "F:User.DAT" FOR RANDOM AS #15 LEN = LEN(MyData)
 END SUB

 SUB PutData (I AS INTEGER, MyData AS UserSpec)
     PUT #15, I, MyData
 END SUB


 380. BIOS Interrupt to Read Sector, Get Disk Status, Find Errors

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  9-FEB-1990    ArticleIdent: Q37345

 The BIOS interrupt call 19 decimal (13 hex), with function 2, returns
 the status of a specified disk if it is unable to read the specified
 sector. This interrupt can be used to determine if the drive door is
 open, if the disk is formatted, if the disk is write protected, and
 many other conditions. The code generated for this is smaller than a
 similar program using ON ERROR GOTO statements to trap disk errors.

 This information applies to QuickBASIC Versions 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50; to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (real mode only); and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and
 MS OS/2 (real mode only).

 Note that BIOS and MS-DOS interrupts are not allowed in MS OS/2
 protected mode.

 Interrupt 19 provides a set of functions to access the disk driver.
 Interrupt 19 with function 2 reads one or more sectors from disk into
 memory. Interrupt 19 with function 0 (reset disk system) should be
 called after a failed floppy disk Read, Write, Verify, or Format
 request before retrying the operation. For more information about this
 and other interrupts for IBM ROM BIOS and MS-DOS, see "Advanced MS-DOS
 Programming, Second Edition," by Ray Duncan (Microsoft Press, 1988).

 Unlike other DOS interrupt functions that access the disk drive using
 CALL INTERRUPT or CALL INTERRUPTX in QuickBASIC 4.00, 4.00b, or 4.50
 or BASIC compiler 6.00 or 6.00b, interrupt 19 with function 2 and 0
 does NOT cause a system hang if a critical error occurs (such as if a
 drive door is open or a disk is not formatted).

 Note: The CALL INTERRUPT or CALL INTERRUPTX statement hanging upon
 critical disk errors is a known problem with the INTERRUPT and
 INTERRUPTX routines in QuickBASIC 4.00, 4.00b, and 4.50, and Microsoft
 BASIC Compiler 6.00 and 6.00b (as reported in a separate article).
 This problem was corrected in Microsoft BASIC PDS Version 7.00.  For
 information on how to modify the INTERRUPT and INTERRUPTX routines so
 that critical errors will not hang the machine in in QuickBASIC 4.00,
 4.00b, and 4.50, and Microsoft BASIC Compiler 6.00 and 6.00b, query on
 the following keyword:

    QB4CRIT

 The following is a QuickBASIC Versions 4.00, 4.00b, and 4.50 code
 example for calling interrupt 19 decimal (13 hex) with functions 0 and
 2:

 DECLARE SUB ResetDrive (drive%)
 DECLARE SUB ReadSector (drive%, sector%)
 ' $INCLUDE: 'q:qb.bi'
 DIM regl AS RegTypeX, regS AS RegType
 DIM databuffer%(5120)          'room for 10 sectors of data
 sector% = 1                'sector number 1-9
 drive% = 0                 'drive A
 FOR i = 1 TO 3
   CALL ReadSector(drive%, sector%)
   CALL ResetDrive(drive%)
   PRINT regl.flags, (regl.flags AND 1)
   IF (regl.flags AND 1) = 1 THEN
      errornum = regl.ax AND &HFF
   ELSE
      errornum = 0
   END IF
 NEXT
 PRINT errornum
 END

 SUB ReadSector (drive%, sector%)
 SHARED databuffer%(), regl AS RegTypeX
       intnum% = 19       'interrupt number 19 decimal (13 hex)
       numsectors% = 1    '# read 1,8, or 9
       track% = 0         'track#   0-39
       head% = 0          'side 0 or 1
       regl.ds = -1
       regl.es = VARSEG(databuffer%(0))
       regl.bx = VARPTR(databuffer%(0))
       regl.cx = 256 * track% + sector%
       regl.dx = 256 * head% + drive%
       'AH loaded with function 2; AL loaded with number of sectors:
       regl.ax = 2 * 256 + numsectors%  ' AX register contains AH and AL
       CALL interruptx(intnum%, regl, regl)
 END SUB

 SUB ResetDrive (drive%)
   DIM regl AS RegTypeX
   regl.ax = 0  ' function number 0
   regl.dx = drive%
   CALL interruptx(&H13, regl, regl)
 END SUB


 381. RUN "PROG.EXE" Fails in QB.EXE Editor; Use RUN "PROG" Instead

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37346

 If you want to RUN a QuickBASIC program, such as PROG.BAS, from within
 the environment, you must type RUN "PROG" instead of RUN "PROG.EXE".
 RUN "PROG" successfully loads and executes the source file PROG.BAS.
 RUN "PROG.EXE" will fail in the editor (as designed) but will succeed
 in an .EXE running outside the editor.

 You cannot use the RUN statement to invoke a non-QuickBASIC
 application from within the QB.EXE editor environment; however, you
 can use the RUN statement from a compiled .EXE program running outside
 the editor.

 To invoke a non-QuickBASIC application from within the QB.EXE editor,
 you can SHELL to it or exit QuickBASIC before invoking it.

 The above information applies to Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 for MS-DOS, to Microsoft QuickBASIC 4.00 and 4.00b
 that come with Microsoft BASIC Compiler 6.00 and 6.00b for MS-DOS, and
 to QBX.EXE, which comes with Microsoft BASIC PDS Version 7.00 for
 MS-DOS.

 QB.EXE Version 4.50 fails to give you an immediate error message if
 you RUN an executable file from inside the editing environment. QB.EXE
 Version 4.50 attempts to load and execute the .EXE or .COM program as
 a text module, which will fail. QBX.EXE which comes with Microsoft
 BASIC PDS Version 7.00 behaves the same as QB.EXE 4.50. It loads the
 .EXE or .COM file and attempts to execute it as BASIC source code. This
 is not considered to be a problem with those products but is a result
 of incorrect use of the RUN statement in the environment.

 To illustrate the problem, execute (SHIFT+F5) the following program in
 the QB.EXE editor:

    RUN "WORD.COM"  'Any executable .EXE or .COM file will demonstrate

 QB.EXE Version 4.50 attempts to load in WORD.COM as a document; this
 produces garbage characters in the edit window. (WORD.COM is taken
 from Microsoft Word.) The environment windows are redrawn, and an
 "Expected: Statement" error box appears. At this point, you can exit
 QuickBASIC, and no harm is done.

 If this program is compiled with BC.EXE, the resultant .EXE file
 successfully transfers control to WORD.COM.

 The results of testing with QuickBASIC versions earlier than 4.50 are
 as follows:

 1. QuickBASIC Version 4.00b does not produce an error message, but
    opens a new module ("Untitled"). If compiled with BC.EXE Version
    4.00b, the .EXE file runs as expected.

 2. QuickBASIC Version 4.00 produces a "Bad File Mode" on the RUN
    "WORD.COM" statement when run inside the environment, but executes
    properly when compiled to an .EXE file.

 3. In QuickBASIC Versions 2.00, 2.01, and 3.00, the QB.EXE editor
    successfully executes RUN "WORD.COM" and removes QuickBASIC from
    memory.


 382. "Device Unavailable" on OPEN "COM1:" Compiled with BC /O/S

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 12-JAN-1990    ArticleIdent: Q37347

 A program that accesses the serial communications ports with OPEN
 "COM1:" or "COM2:" produces a "Device Unavailable" (run-time error 68)
 message if it is compiled using BC.EXE with the /O (stand-alone .EXE)
 and /S (minimize string space) options together.

 To work around this limitation, do not use the /S and /O options
 together when compiling programs that access the communications ports.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 4.00, 4.00b, and 4.50 for MS-DOS and in Microsoft BASIC Compiler 6.00
 and 6.00b (buglist6.00 buglist6.00b) for MS-DOS and MS OS/2. We are
 researching this problem and will post new information here as it
 becomes available. This problem does not occur in Microsoft BASIC PDS
 Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 The sample program below runs properly inside the environment;
 however, when compiled to an .EXE file using the BC /O and /S options,
 a "Device Unavailable" error message is produced on the OPEN "COM1:"
 statement. [The problem can also occur when you use the ON COM(n)
 GOSUB statement.]

 The following is a code example:

 OPEN "COM1:9600,N,8,1,CS,DS" FOR RANDOM AS 1
 CLOSE 1


 383. New COMMAND$ Will Not Pass with RUN from within QB Program

 Product Version(s): 3.00 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37348

 A QuickBASIC program will return the COMMAND$ as expected, but the RUN
 statement with an appended command string will not pass the COMMAND$
 to the new program. Instead, the original COMMAND$ from the first
 program is passed to the second (RUN) program. The two programs below
 demonstrate this behavior.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 If you type "PROG1 /Z" on the MS-DOS command line, "/Z" is returned
 with the COMMAND$ function in both programs, regardless of what is
 entered for X$ in Prog1. Because the RUN statement is used with a
 quoted string, the " + X$" is concatenated to the program name string.
 This means that if X$ equals "/B", then the RUN statement is actually
 RUN "PROG2.EXE/B", which is not a valid filename.

 The following is a code example:

 REM   *** Prog1 ***
 PRINT "Here is the COMMAND$: "; COMMAND$
 INPUT "Enter the new COMMAND$"; X$
 RUN "PROG2.EXE" + X$                       'Either .BAS or .EXE
 END

 REM   *** Prog2 ***
 PRINT "Here is the COMMAND$: "; COMMAND$
 END


 384. "Device I/O," Error 57, Using SCREEN 3 and Communications Port

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 10-NOV-1989    ArticleIdent: Q37405

 Programs that use both Hercules SCREEN 3 and the communication port
 ("COM1:" or "COM2:") may generate "Device I/O" errors (error 57). For
 example, one customer reported that the faster he drew to the Hercules
 graphics screen, the more frequently he got the "Device I/O" error.
 The same program will run correctly if a CGA, EGA, or VGA card is
 used. It will also work correctly if text mode is used (screen 0).

 Microsoft is researching this problem and will post new information as
 it becomes available.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 4.50 and to Microsoft BASIC Compiler 6.00 and 6.00B (buglist6.00,
 buglist6.00b) for MS-DOS.


 385. Using .. in QB.EXE Open File Dialog Doesn't Change Directory

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q37409

 Select Open Program on the QuickBASIC Version 4.00 or 4.00b File Menu
 and use .. (two periods) to go up a directory level. If your menu now
 contains only the .. entry by itself, it will be highlighted, but you
 will not be able to select it. Pressing either the direction or enter
 keys will not allow you to change the directory.

 Microsoft has confirmed this to be a problem in Versions 4.00 and
 4.00b. This problem also occurs in the QuickBASIC version included
 with Microsoft BASIC Compiler Versions 6.00 and 6.00b (buglist6.00
 buglist6.00b). This problem was corrected in QuickBASIC Version 4.50
 and in QBX.EXE of Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 The following are results of testing with previous version(s):

    In the QuickBASIC Version 3.00 editor, whenever an option from the
    File+Load menu is highlighted, it can be selected by pressing the
    ENTER key.

 You can work around this problem by doing the following:

 1. Use the TAB key to move to the File Name box.

 2. Press ENTER.

 3. Tab to the Options box.

 4. Press a direction key to highlight the .. option, then press the
    ENTER key.


 386. "Hit Any Key..." If CHAIN or RUN from Error Handler; BC /O

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q37774

 When two programs, both compiled with BC /O/X, CHAIN or RUN between
 one another, a "Hit any key to continue" error message is displayed if
 the CHAIN or RUN occurs in an error-handler routine. This problem does
 not occur if the programs are compiled to use the BASIC run-time
 module (without /O).

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00b and 4.50 (buglist4.00b, buglist4.50), and Microsoft
 BASIC Compiler Versions 6.00 and 6.00b (buglist6.00 buglist6.00b) for
 MS-DOS and OS/2. This problem was corrected in Microsoft BASIC PDS
 Version 7.00 (fixlist7.00).

 To work around this problem, use RESUME <label> to return program
 control to a label that contains the CHAIN statement.

 The following is a code example:

 '==== Prog a ====
 ON ERROR GOTO trap
 ERROR 57
 END
 trap:
    PRINT "error in a"
    'uncomment the next line to get the programs to work
    'RESUME leave
 leave:
  CHAIN "b"
  stop

 '==== Prog b ====
 ON ERROR GOTO trap
 ERROR 57
 END
 trap:
    PRINT "error in b"
    'uncomment the next line to get the programs to work
    'RESUME leave
 leave:
    CHAIN "a"
    stop


 387. MS Press "Programmer's Toolbox" Doesn't Have .OBJ for C Code

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37412

 The "Microsoft QuickBASIC Programmer's Toolbox" by John Clark Craig
 (Published by Microsoft Press, 1988), contains a useful library of
 more than 250 subprograms, functions, and utilities for supercharging
 QuickBASIC programs.

 The companion disk for "Microsoft QuickBASIC Programmer's Toolbox"
 includes the C source files CTOOLS1.C and CTOOLS2.C, but does not
 include the corresponding .OBJ files. To utilize the 22 C routines in
 those modules, the two files must first be compiled; the .C files must
 be compiled with the large memory model, in Microsoft C Compiler
 Version 5.00 or later. (QuickC compilation will work only if no
 dynamic arrays are being used in the calling QuickBASIC code.)

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 The files CTOOLS1.OBJ and CTOOLS2.OBJ are not distributed on the
 companion disks because using them also requires additional C run-time
 libraries. These, too, would have to be included to accommodate people
 without access to a C compiler.


 388. EXE2BIN Cannot Convert QuickBASIC .EXE Files to .COM Files

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37413

 With the introduction of the first MS-DOS operating system, the .EXE
 program and file structure came into existence. .EXE files allow much
 more flexibility than .COM files do. .COM files mimic the binary files
 of the earlier CP/M-80 operating system. (CP/M-80 was developed by
 Digital Research, Inc.)

 Because .COM files allow the use of only one 64K segment and no stack
 segment (the so-called "tiny" memory model), .EXE files produced in
 QuickBASIC cannot be converted to .COM files. QuickBASIC uses the
 medium-memory model, which utilizes one data segment and one or more
 code segments. QuickBASIC's far addressing capability also makes its
 .EXE files incompatible with the MS-DOS EXE2BIN.EXE program, which
 converts .EXE files to .COM files.

 This information applies to all versions of Microsoft QuickBASIC, to
 Microsoft BASIC Compiler Versions 5.35, 5.36, 6.00, and 6.00b for
 MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The EXE2BIN.EXE utility gives a "file cannot be converted" error
 message if you attempt to convert a QuickBASIC .EXE compiled program.

 Please refer to "The MS-DOS Encyclopedia," published by Microsoft
 Press, for more information on .EXE versus .COM files.

 The following is a code example:

 'Make a stand-alone .EXE named X.EXE from this program.
 'Give the MS-DOS command: EXE2BIN X.EXE X.COM
 'The "file cannot be converted" message results.
 PRINT "TEST"


 389. Cannot Nest I/O Statements or Functions in I/O Statements

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 17-JAN-1991    ArticleIdent: Q37414

 With two sequential files open, #1 for INPUT and #2 for OUTPUT, the
 following statement incorrectly sends output to the screen instead of
 to file #2:

    PRINT #2, INPUT$(10, #1)

 To work around this behavior, do the INPUT$ into a temporary string
 variable, then PRINT that temporary string into the second file.

 This behavior occurs in Microsoft QuickBASIC versions 4.00, 4.00b, and
 4.50, in Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and in Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2. This limitation
 is documented in the README.DOC file for BASIC PDS 7.00 and 7.10.

 The general rule to observe is as follows: do not nest input/output
 (i/o) statements or functions within other i/o statements or
 functions. This is a design limitation.

 The above limitation is related to the following restriction mentioned
 on Page 146 of the "Microsoft BASIC 7.0: Language Reference" (for 7.00
 and 7.10): "Avoid using I/O statements in a FUNCTION procedure called
 from an I/O statement; they can cause unpredictable results." See also
 Page 201 of "Microsoft QuickBASIC 4.0: Language Reference" for 4.00
 and 4.00b for the same caveat.

 QuickBASIC Version 3.00 successfully writes to file #2, not the
 screen. GWBASIC Version 3.22 also writes to file #2, not the screen
 (when you put line numbers in the source file below).

 The following code example shows the unexpected behavior:

 'This incorrectly writes to the screen.
 OPEN "\practice\test1.dat" FOR INPUT AS #1
 OPEN "test2.dat" FOR OUTPUT AS #2
 PRINT #2, INPUT$(10, #1)

 The input file TEST1.DAT is as follows:

 123456789012345

 The following program shows how to work around the problem by using a
 temporary string variable to accept the input before writing to file
 #2. This program correctly writes to file #2, not the screen:

 OPEN "\practice\test1.dat" FOR INPUT AS #1
 OPEN "test2.dat" FOR OUTPUT AS #2
 CopyString$ = INPUT$(10, #1)
 PRINT #2, CopyString$


 390. QuickBASIC 4.50 and Earlier May Not Work with MS-DOS 4.00

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER  |
 Last Modified:  2-NOV-1988    ArticleIdent: Q37415

 QuickBASIC Version 4.50 and earlier releases have not been tested with
 MS-DOS Version 4.00. Microsoft does not claim that QuickBASIC Version
 4.50 (and earlier versions) will work with MS-DOS Version 4.00.
 QuickBASIC Versions 4.00, 4.00b, and 4.50 require a DOS version
 between Versions 2.10 and 3.x.

 QuickBASIC may not work correctly with MS-DOS Version 4.00 because of
 memory-management issues. In particular, the SHELL feature fails, both
 from Shell in the File menu in the QB.EXE editing environment and from
 the SHELL statement in a compile program.

 The "Make .EXE" function of QuickBASIC will also not work properly in
 MS-DOS Version 4.00, because it requires a SHELL to BC.EXE and
 LINK.EXE. BC.EXE will work from the MS-DOS command line.

 CHAIN statement failures have also been reported with QuickBASIC
 operating under MS-DOS Version 4.00.


 391. QuickBASIC Hasn't Been Tested with PC-MOS or Concurrent DOS

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  4-SEP-1990    ArticleIdent: Q37416

 PC-MOS and Concurrent DOS are operating systems (not developed by
 Microsoft) that allow multitasking. QuickBASIC has not been tested
 with PC-MOS or Concurrent DOS.

 Customers running the QuickBASIC environment (QB.EXE or QBX.EXE) or
 running programs created with QuickBASIC or compiled BASIC on PC-MOS
 or Concurrent DOS have reported a variety of problems, including
 failures to recognize keyboard input. Microsoft is not responsible for
 any third-party compatibility claims regarding use of the PC-MOS or
 Concurrent DOS operating system with any version of QuickBASIC (1.00,
 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, or 4.50) or compiled BASIC
 (5.35, 5.36, 6.00, 6.00b, 7.00, or 7.10).

 For true multitasking, we recommend using the MS OS/2 operating system
 and Microsoft BASIC Compiler version 6.00 or 6.00b or Microsoft BASIC
 Professional Development System (PDS) version 7.00 or 7.10 for MS-DOS
 and MS OS/2.

 For a multiple-user system (for sharing disk and processor resources),
 you can connect multiple computers with the Microsoft OS/2 LAN Manager
 Network.


 392. SHELL Statement Loses Current Data in Serial Port Input Buffer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 21-SEP-1990    ArticleIdent: Q37417

 A SHELL statement will empty the input buffer (thus losing data) of
 the currently opened serial communications port (COM1 or COM2).

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions
 6.00 and 6.00b (buglist6.00, buglist6.00b); and in Microsoft BASIC
 Professional Development System (PDS) version 7.00 (buglist7.00).

 This problem is corrected in Microsoft BASIC PDS 7.10 (fixlist7.10) if
 you compile with BC /O or run in the QBX.EXE environment. However, if
 you compile your program in 7.10 to use the BRT71xxx.EXE run-time
 module (in other words, you don't compile with BC /O), you will still
 lose data in the communications input buffer because the support for
 communications is in the run-time module, and the run-time module is
 released from memory during a SHELL to make more room for other
 programs to load. This is not a problem; it is a design limitation.

 To work around the problem, empty the buffer (such as with the INPUT$
 statement) before invoking the SHELL statement to retain information
 that would have been lost.

 The following steps reproduce the behavior:

 1. Open a serial port (COM1 or COM2).

 2. Allow the buffer to be filled.

 2. Using the LOC function, print out the number of bytes in the
    buffer.

 3. Execute the SHELL statement with any valid parameter (such as SHELL
    "DIR").

 4. Using the LOC function again, print out the number of bytes in the
    buffer. This number will be 0 (zero).

 The following code will reproduce the above behavior. (Please note
 that the size of the buffer after the SHELL statement will be 0.)

    OPEN "com1:9600" FOR RANDOM AS #1
    ' This loop will allow data to begin flowing into COM1.
    ' The loop terminates when an ESC key is pressed.
    DO UNTIL INKEY$ = CHR$(27)
    LOOP
    PRINT "Size of buffer before SHELL statement: ", LOC(1)
    PRINT
    PRINT "press any key to shell"
    WHILE (INKEY$ = ""): WEND
    SHELL "dir"
    PRINT "Size of buffer after SHELL statement: ", LOC(1)
    CLOSE


 393. LINK "Cannot Open Response File" When Make EXE File in 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50
 Last Modified: 12-JAN-1990    ArticleIdent: Q37418

 The error "Cannot open response file" can occur if "Make EXE File..."
 in QB.EXE Version 4.50 invokes the Segmented-Executable linker (which
 does not come with QuickBASIC). QuickBASIC versions earlier than 4.50
 do not create a response file for the linker, and link successfully
 without giving this error message. (Note that QuickBASIC Versions 4.00
 and later require at least Version 3.61 of the linker to handle the
 /EX (EXEPACK) option.)

 To properly create an .EXE file from within the QuickBASIC Version
 4.50 environment, you must first make sure that the linker found by
 QuickBASIC (either in your search path, or in the executable file path
 specified in QuickBASIC) is the Overlay Linker Version 3.6x.

 If the linker found is a version earlier than 3.61, or a Segmented-
 Executable linker such as the one supplied with Microsoft BASIC
 Compiler Versions 6.00 and 6.00b or with Microsoft BASIC PDS Version
 7.00, there may be complications in using "Make EXE File..." from
 within the QuickBASIC Version 4.50 environment. BASIC PDS 7.00 comes
 with the QBX.EXE environment, which contains all of the functionality
 of the QuickBASIC 4.50 environment. Microsoft does not recommend using
 QB.EXE 4.50 or earlier with BASIC PDS 7.00.

 In QuickBASIC Version 4.50, the link step of the .EXE file creation is
 performed with the use of a response file. (A response file can be
 used to supply the input to the linker, such as object modules, output
 file name, extra libraries, etc.) QuickBASIC creates a temporary file
 (~QBLNK.TMP) that contains all of the information required by the four
 prompts of the linker (object files, .EXE file name, list file, and
 libraries), then tells the linker to use this file for a response
 file.

 This causes a problem with the Segmented-Executable linkers, because
 these linkers have a fifth input prompt (definitions file). Since the
 response file does not satisfy this prompt, the linker waits for you
 to enter a definitions file. You can press ENTER at this prompt, and
 the linker will complete its task.

 In addition to asking for a definitions file, the Segmented-Executable
 linker has another difference from the Overlay linker. If a response
 file is inadvertently supplied with a four-character extension (for
 example, RESPONSE.ABCD), the Segmented-Executable linker stops with a
 "Cannot open response file" error message. However, the Overlay linker
 truncates the filename to a three-character extension (for example,
 RESPONSE.ABCD becomes RESPONSE.ABC), and then looks for that file.

 Under some circumstances, QuickBASIC Version 4.50 generates an invalid
 file specification for the response file (specifically "~QBLNK.TMPD",
 which has an illegal fourth letter, D, on the name extension). Because
 of the differences between the two linkers, the Overlay linker ignores
 the appended "D" on the response file, and correctly produces an .EXE
 file. However, the Segmented-Executable linker gives a fatal error,
 "Cannot open response file", and aborts.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information here as it
 becomes available.

 The following is a summary of workarounds for this problem:

 1. Use the Overlay Linker Version 3.6x.

 2. If the response file is found, the .EXE file can be produced by
    pressing ENTER at the "Definitions file:" prompt. If the response
    file is NOT found, try renaming your BASIC source file, changing it
    by a factor of 1 in length (that is, if your source file is an even
    number of characters long, make it odd, and vice-versa).

 3. Compile and link your program from the DOS command line.


 394. Program to Translate QuickBASIC 4.00 to C Language

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37419

 Microsoft doesn't offer a QuickBASIC (or BASIC) to C language
 translation program, but the following information describes one such
 program:

    Software Translations has released B-Tran, a QuickBASIC-to-C source
    code translator. This product is marketed in Europe by Sector 7
    Software Ltd.

    The current version, B-Tran Version 7, supports QuickBASIC Version
    4.00. However, it does not support user-defined TYPEs or the
    following new ways to dimension arrays introduced in QuickBASIC
    Version 4.00:

       DIM varname AS type
       DIM arrayname (1 TO 5)

    Software Translations lists this program for about $495. B-Tran
    Version 7 produces C code from source code applications written in
    Microsoft QuickBASIC. B-Tran is guaranteed by Software Translations
    to have 97 percent translation. A demonstration disk is available
    from Software Translations for $25.

    Inquiries on this product should be sent to the following address:

       Software Translations, Inc.
       The Carriage House
       28 Green Street
       Newburyport, MA  01950
       (508) 462-5523

 This article may be useful to owners of Microsoft QuickBASIC Version
 1.00, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, or 4.50, Microsoft BASIC
 Compiler Version 6.00 or 6.00b, or Microsoft BASIC PDS Version 7.00
 for IBM Personal Computers and strict compatibles.


 395. Two BASIC Methods to Save & Restore Text Screens in DOS & OS/2

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37421

 This article explains two methods for saving and restoring text-mode
 screens (SCREEN 0). The first method uses BLOAD and BSAVE (supported
 under MS-DOS only, not under OS/2 protected mode). The second method
 uses the SCREEN function to save and restore the values of the screen
 characters to and from a numeric array (supported under both MS-DOS
 and OS/2 protected mode).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 (The October 27, 1987, issue of "PC Magazine" has a separate example
 of an assembly-language routine that saves and restores text screens;
 however, the code needs to be modified for QuickBASIC Versions 4.00,
 4.00b, and 4.50, for the BASIC compiler 6.00 and 6.00b, and for BASIC
 PDS 7.00.)

 First Method for Saving and Restoring Text-Mode Screens
 -------------------------------------------------------

 The following steps save the screen with BLOAD and BSAVE statements
 (under MS-DOS but not under OS/2 protected mode):

 1. Place the text on the screen using the following:

    SCREEN 0  ' This is the default SCREEN mode.
    FOR i = 1 TO 400
      PRINT i;
    NEXT i

 2. Use the following DEF SEG command to assign the current segment to
    the correct video-memory location (not supported in OS/2 protected
    mode):

    DEF SEG=&HB000   'MONOCHROME CARD
    DEF SEG=&HB800   'CGA,EGA CARD

 3. Use the BSAVE command below to save the screen (not supported in
    OS/2 protected mode). In 23-line (CGA) mode, you need 4000 bytes to
    save a complete text mode screen; (80 columns) times (25 lines)
    times (1 character byte plus 1 color attribute byte) equals 4000
    bytes. In EGA 43-line mode, you need 6880 bytes to save a complete
    text mode screen (80 times 43 times 2). The BSAVE command is as
    follows:

    BSAVE "filename",0,4000  ' For CGA 23-line mode in SCREEN 0

 Use the following steps to restore the screen:

 1. Use the following DEF SEG command to assign the current segment to
    the correct video-memory location:

    DEF SEG=&HB000   'MONOCHROME CARD
    DEF SEG=&HB800   'CGA,EGA CARD

 2. Use the following BLOAD command to reload the text:

    BLOAD "filename",0

 Second Method for Saving and Restoring Text-Only on a Screen
 ------------------------------------------------------------

 (Note: This method works both in MS-DOS and in OS/2 protected mode.)

 The second method (below) calls a BASIC routine to store the
 characters on a screen in an array, then restore them. This method
 uses the SCREEN function, which works both in MS-DOS and in OS/2
 protected mode, and in text or graphics screen modes. The SCREEN
 function returns the ASCII value of the character at a specified row
 and column (but returns the ASCII value 32, a blank, for text
 characters that are overlaid with graphics).

 Note: The following program is only a short sample. It doesn't include
 any error checking for coordinate validity. This and other possible
 enhancements are left up to you.

 DEFINT A-Z
 DECLARE SUB SaveScreen (StartCol, StartRow, ColLen, RowLen, arrar%())
 DECLARE SUB RestScreen (StartCol, StartRow, ColLen, RowLen, arrar%())
 COLOR 7, 1
 CLS
 COLOR 4
 FOR i = 1 TO 10
     PRINT "This is a test"
 NEXT i
 COLOR 7
 INPUT "Enter the Save Starting Row : ";StartRow
 INPUT "Enter the Save Starting Column : ";StartCol
 INPUT "Enter the width (the number of columns) : "; col
 INPUT "Enter the height (the number of rows) : "; row
 DIM array%(col, row, 2)
 CALL SaveScreen(StartCol,StartRow, col, row, array%())
 PRINT "Hit any Key to continue...."
 while inkey$="" : wend
 COLOR 7,3
 CLS
 INPUT "Enter the Restore Starting Row : ";StartRow
 INPUT "Enter the Restore Starting Column : ";StartCol
 CALL RestScreen(StartCol, StartRow, col, row, array%())
 COLOR 7,3
 locate 25,10 : PRINT "Hit any key to quit..."
 WHILE INKEY$ = "": WEND
 END

 '============= Restore Screen =============
 SUB RestScreen (StartCol, StartRow, ColLen, RowLen, array%()) STATIC
      FOR i = 1 TO RowLen
         LOCATE StartRow + i, StartCol
         FOR j = 1 TO ColLen
            COLOR array%(j, i, 2) MOD 16, array%(j, i, 2) \ 16
            PRINT CHR$(array%(j, i, 1));
         NEXT j
     NEXT i
 END SUB

 '============= Save Screen ===============
 SUB SaveScreen (StartCol, StartRow, ColLen, RowLen, array%()) STATIC
     FOR i = StartCol TO (StartCol + ColLen - 1)
         FOR j = StartRow TO (StartRow + RowLen - 1)
             RowIndex = i - StartRow + 1
             ColIndex = j - StartCol + 1
             array%(RowIndex, ColIndex, 1) = SCREEN(j, i)    'character
             array%(RowIndex, ColIndex, 2) = SCREEN(j, i, 1) 'color
         NEXT j
     NEXT i
 END SUB


 396. QuickBASIC Support Hours, Press Release October 1990

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 21-FEB-1991    ArticleIdent: Q37423

 The QB Advisor online Help system provided with the first packaging of
 Microsoft QuickBASIC version 4.50 incorrectly lists the telephone
 number and service hours for Microsoft Product Support Services (PSS)
 for QuickBASIC.

 Microsoft introduced a repackaged version of QuickBASIC 4.50 in
 September 1990, and the telephone number and the support hours
 changed. This is explained in a press release in a separate article,
 which can be found with the following query:

    OnCall and BASIC and expanded and support

 (On October 23, 1990, Microsoft announced OnCall(TM) for BASIC and
 expanded technical support for Microsoft QuickBASIC users.)

 Information on PSS has been deleted from the online Help system in the
 repackaged QuickBASIC 4.50. However, the Languages/Hardware support
 phone number, (206) 637-7096, is still incorrectly listed on the
 "Product Assistance Request Form" in the back of the repackaged
 QuickBASIC manual.

 Instead, QuickBASIC customers should call (206) 646-5101, from 8:00 AM
 to 5:00 PM Monday through Friday (excluding holidays), for entry-level
 assistance.

 For advanced programming questions and support of noncurrent versions,
 QuickBASIC customers may call (900) 896-9999 at a cost of $2.00 per
 minute, from 6:00 AM to 6:00 PM PST Monday through Friday (excluding
 holidays). Hold time will be minimal on the 900 phone number. If your
 phone system is blocked from calling 900 numbers, you may call our
 unblocking toll number, (206) 646-5102, for a credit card charge of
 $20.00 per call.


 397. User-Defined Character Fonts for Hercules Graphics Mode

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  5-JAN-1990    ArticleIdent: Q37475

 The method described in this article will allow you to display a
 user-defined character set of up to 256 characters in Hercules
 graphics mode. Note that this method works only in Hercules graphics
 mode (SCREEN 3) and does not work under MS OS/2.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 It is possible to modify two assembly-language programs available in
 "Programmer's Guide to PC & PS/2 Video Systems," by Richard Wilton
 (Microsoft Press), to display user-defined character fonts in the
 graphics mode.

 The first program, PixelAddrHGC, is Listing 4-3. This program computes
 the starting address of the first pixel for the data to be displayed.
 The main assembly program, DisplayCharHGC, is shown in Listing 9-4.

 As written, these programs are meant to interface with Microsoft C. To
 change them to work with BASIC, do the following:

 1. Change all near references to far (use medium memory model).

 2. Remove the underscore in the public name.

 3. Create storage space for VARmask, VARtoggle, and VAR9bits in
    DGROUP.

 4. Reverse the input order of the arguments. Instead of using
    interrupt vector 43 hex to point to the first 128 characters, and
    1F hex to point to the font table containing the rest of the
    characters, use an unused interrupt vector to point to a single
    table containing 256 characters.

 5. Set DS == ES.

 The BASIC program below calls a modified form of DisplayCharHGC to
 print a user-defined font to the screen. This program works correctly
 in the QuickBASIC environment and in stand-alone executable form.

 The following is a code example:

 ' $INCLUDE: 'q:qb.bi'
 REM for BASIC PDS 7.00 include QBX.BI instead
 DECLARE SUB DisplayCharHGC (BYVAL A%, BYVAL x%, BYVAL y%,_
              BYVAL f%, BYVAL b%)
 DEFINT A-Z
 DIM RegX AS RegtypeX

 ' set table large enough to hold the character set
 DIM table(2048) ' 256 * 8

 ' table is common to put it in the DGROUP
 COMMON table()

 DATA 2,6,14,30,62,126,254,0
 DATA 254,64,32,16,32,64,254,0
 DATA 132,136,158,162,70,130,14,0

 CLS
 SCREEN 3
 DEF SEG = VARSEG(table(0))
 FOR i = 1 TO 24
    READ A%   'Place the created characters into the new
    POKE VARPTR(table(0)) + i, A%    'graphics table
 NEXT i
 DEF SEG

  'get the initial value at interrupt 50 hex
    RegX.Ax = &H3550
    RegX.Ds = -1
    RegX.Es = -1
    CALL interruptX(&H21, RegX, RegX)
    PRINT "Vector 50H was "; RegX.Es, RegX.Bx
    oldoff& = RegX.Es
    oldPtr& = RegX.Bx

  ' reset interrupt 50 hex to point to table of characters
    RegX.Ax = &H2550
    RegX.Ds = VARSEG(table(0))
    RegX.Dx = VARPTR(table(0))
    CALL interruptX(&H21, RegX, RegX)

  ' verify the reset took
    RegX.Ax = &H3550
    RegX.Ds = -1
    RegX.Es = -1
    CALL interruptX(&H21, RegX, RegX)
    PRINT "New vector "; RegX.Es, RegX.Bx
    A% = 10

 ' print characters
 FOR i = 0 TO 2
         A% = A% + 1
         CALL DisplayCharHGC(i, 20, 20 * A%, 0, 7)
 NEXT

 'restore original vector
    RegX.Ds = oldoff&
    RegX.Dx = oldPtr&
    RegX.Ax = &H2550
    CALL interruptX(&H21, RegX, RegX)

 'verify restoration
    RegX.Ax = &H3550
    RegX.Ds = -1
    RegX.Es = -1
    CALL interruptX(&H21, RegX, RegX)
    PRINT "Vector 50H reset to "; RegX.Es, RegX.Bx

 ' pause
    SLEEP


 398. PRINT USING Statement Fails to Use Print Zones

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37481

 The PRINT USING statement is not designed to print the values of an
 expression list in the 14-character print zones. Instead, it ignores
 the comma and treats it like a semicolon. In QuickBASIC Version 4.50,
 the syntax checker correctly changes the comma to a semicolon.
 However, several manuals (listed below) and the online help system
 incorrectly state that the comma is syntactically legal.

 The incorrect syntax for the PRINT USING statement is as follows:

    PRINT USING formatstring; expressionlist [{,|;}]

 The incorrect definition for the PRINT USING statement is as follows:

    The position of each printed item is determined by the punctuation
    used to separate the items in the list. BASIC divides the line into
    print zones of 14 spaces each. In the expression list, a comma
    makes the next value print at the start of the next zone. A
    semicolon makes the next value print immediately after the last
    value.

 This incorrect syntax or definition is given in each of the following
 references:

 1. Page 275 of the "Microsoft BASIC 7.0: BASIC Language Reference" for
    Microsoft BASIC PDS Version 7.00

 2. Page 335 of the "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" for QuickBASIC 4.00 and 4.00b

 3. Page 287 of the "Microsoft QuickBASIC: BASIC Language Reference"
    for QuickBASIC 4.50

 4. Page 335 of the "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" for Microsoft BASIC Compiler Versions 6.00 and 6.00b

 5. The online help system for Microsoft QuickBASIC 4.50 under the
    entry for PRINT USING statement

 6. The online help system for BASIC PDS 7.00 under the entry for the
    PRINT USING statement

 The following is a code example that demonstrates that PRINT USING
 treats commas as if they were semicolons. When run in the environment,
 the code example will correctly substitute a semicolon between the
 variables "a" and "b" for the comma:

    a=3.45
    b=5.23
    PRINT USING "##.##";a,b

 The output is as follows:

    3.45 5.23


 399. QB.EXE 4.00b Problem LOADing Lone .BAS File from Floppy Drive

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 12-JAN-1990    ArticleIdent: Q37482

 A single .BAS file will not load from a floppy disk in QB.EXE Version
 4.00 or 4.00b under the following conditions:

 1. The disk in Drive A has only one .BAS file in it.

 2. In the QuickBASIC editor, open the File menu.

 3. Choose L for LOAD.

 4. For the "file name", enter the drive letter (that is, A:).

 5. Tab down so that the cursor is under the FIRST LETTER of the file.

 6. Press ENTER (this highlights the filename).

 7. Press ENTER again.

 Microsoft has confirmed this to be a problem in QB.EXE in QuickBASIC
 Versions 4.00 and 4.00b for MS-DOS and in QB.EXE in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for
 MS-DOS. This problem was corrected in Microsoft QuickBASIC 4.50 and in
 the QBX.EXE environment that comes with Microsoft BASIC PDS Version
 7.00 (fixlist7.00) for MS-DOS.

 If the above conditions apply, the file will not load into QuickBASIC
 as it should. To work around this problem, highlight the filename when
 the cursor is under it by using any arrow key, then press ENTER.


 400. CHAIN "RETURN Without GOSUB" When Using ON ERROR GOTO & No /O

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37483

 When chaining from a program that does not trap errors (ON ERROR GOTO)
 to a program that does, a "RETURN without GOSUB" error message can
 appear. This occurs only when the programs are compiled requiring the
 run-time library BRUN4x.EXE.

 Because the run-time system is initialized in the first program, you
 need to compile both programs with BC /E to support error trapping.

 Another way to avoid this problem is to compile both programs with BC
 /O to make them stand alone. With this process, the chaining program
 does not require compiling with /E.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2. The code below does not generate the error
 described above with Microsoft BASIC PDS Version 7.00.

 The programs below, when compiled without /O, will give the "RETURN
 without GOSUB" run-time error message in the second program.

 Code Examples
 -------------

 The first program is as follows:

 ' TEST.BAS
       CHAIN "test1"
       END

 The second program is as follows:

 ' TEST1.BAS
       ON ERROR GOTO 0
       K% = 1
       ON K% GOSUB handle
       END
 handle:
       A$ = INKEY$: IF A$ = "" THEN GOTO handler
       RETURN


 401. SCREEN Function Returns 32 for ASCII Byte 196 in SCREEN 3

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q37484

 The SCREEN function returns an ASCII value of 32 (a blank) for the
 character CHR$(196) in the Hercules graphics mode (SCREEN 3). The
 correct value (196) correctly returns in any other screen mode. The
 program below demonstrates the problem and gives a listing of other
 characters that the screen function will return 32.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS (buglist6.00, buglist6.00b); and in
 Microsoft BASIC PDS versions 7.00 and 7.10 (buglist7.00, buglist7.10)
 for MS-DOS. We are researching this problem and will post new
 information here as it becomes available.

 The following code example demonstrates the problem:

    CLS
    SCREEN 3
    OPEN "prints32.dat" FOR OUTPUT AS #1
    FOR x = 0 TO 255
    CLS
    PRINT CHR$(x)
    PRINT SCREEN(1, 1)
    WHILE INKEY$ = "": WEND
    IF SCREEN(1, 1) = 32 THEN PRINT #1, x
    NEXT x
    CLOSE

 The SCREEN function returns an ASCII value of 32 (blank) for the
 following ASCII characters:

    chr$(0)
    chr$(7)
    chr$(9)
    chr$(10)
    chr$(11)
    chr$(12)
    chr$(13)
    chr$(28)
    chr$(29)
    chr$(30)
    chr$(31)
    chr$(32)
    chr$(196)    ' <<====== Returns ASCII 32 (blank) only in SCREEN 3
    chr$(255)


 402. Call Microsoft MOUSE from QB 4.x Using Assembler, INTERRUPT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q37882

 This article demonstrates how to use CALL INTERRUPT in a BASIC program
 to make Microsoft Mouse function calls.

 The information in this article applies to Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS.

 The interrupt 51 for the Microsoft Mouse Versions 6.00 and later is
 documented in the following book:

    "Advanced MS-DOS Programming," Second Edition, by Ray Duncan
    (Microsoft Press, 1988) Pages 593-611. (The first edition published
    in 1986 did not document the mouse interrupt.)

 For more information regarding making mouse calls from BASIC, see the
 "Microsoft Mouse Programmer's Reference Guide," which can be ordered
 from Microsoft Customer Service by calling (206) 882-8088.

 Note: Throughout the rest of this article, if you are using Microsoft
 BASIC PDS 7.00, the include file QBX.BI should be substituted for
 QB.BI, the Quick library QBX.QLB should be used instead of QB.QLB, and
 the library QBX.LIB should be used in place of QB.LIB.

 To use the mouse in compiled BASIC programs, the program must be able
 to talk to the mouse driver. This is done by using the mouse interrupt
 51 (33 hex), passing up to four integer parameters in the AX, BX, CX,
 and DX registers. This can be accomplished by using either the CALL
 INTERRUPT statement in QuickBASIC, or by directly CALLing assembly
 language routines that perform the interrupt calls and return the
 information from the mouse driver.

 For more information on using CALL INTERRUPT to access the mouse,
 query on the following keywords in this database:

    call and mouse and interrupt

 For more detailed information on how to use INTERRUPT and INTERRUPTX
 query on the keyword QB4INT.

 To use an assembly language routine to make the mouse function calls,
 you can replace the MOUSE subprogram below with the assembly language
 listing, also shown below. This eliminates the need for the QB.BI
 include file, and the QB.QLB/QB.LIB libraries. However, you will have
 to place the assembly routine in another Quick library and a parallel
 conventional library.

 The mouse information is obtained by various mouse function calls.
 When using the mouse interrupt, the mouse function call number is
 passed to the mouse driver in AX, and other information that the
 driver may need is passed in BX, CX, and/or DX. The commonly used
 mouse functions are as follows:

    Function
    Number          Function
    ------          --------

    0               Mouse reset and status
    1               Show mouse cursor
    2               Hide mouse cursor
    3               Get cursor position and button status
    4               Set cursor position
    7               Set Horizontal Minimum/Maximum
    8               Set Vertical Minimum/Maximum

 Below are a series of BASIC routines that execute the function calls
 mentioned above. Each routine makes a call to a subprogram named
 MOUSE, which in turn executes an interrupt 51.

 The following are BASIC routines:

 DEFINT A-Z
 '$INCLUDE: 'qb.bi'
 ' Note: include QBX.BI for BASIC PDS 7.00
 '---------------------------------------------------------------------
 '---                                                               ---
 '--- Mouse Library Routine Declarations                            ---
 '---                                                               ---
 '---------------------------------------------------------------------

 DECLARE SUB Mouse (M0%, M1%, M2%, M3%)
 DECLARE SUB MouseOn ()
 DECLARE SUB MouseOff ()
 DECLARE SUB HideMouse ()
 DECLARE SUB ShowMouse ()
 DECLARE SUB GetMXY (mx%, my%)
 DECLARE SUB SetMXY (mx%, my%)
 DECLARE SUB MBorders (x%, y%, h%, v%)
 DECLARE FUNCTION MBtn% ()
 DECLARE FUNCTION MouseActive% ()

 '------- Get Text Mode coordinates --------
 SUB GetMXY (x, y) STATIC
   Mouse 3, 0, x, y                      'get GRAPHIC coordinates
   x = (x / 8) + 1                       'convert to TEXT coordinates
   y = (y / 8) + 1
 END SUB

 '------- Hide the Mouse Cursor -------
 SUB HideMouse STATIC
   call Mouse (2, 0, 0, 0)
 END SUB

 '------- Set Horizontal Minimum/Maximum -----
 '------- Set Vertical Minimum/Maximum -------
 SUB MBorders (x, y, h, v) STATIC
   Mouse 7, 0, (x - 1) * 8, (h - 1) * 8
   Mouse 8, 9, (y - 1) * 8, (v - 1) * 8
 END SUB

 '------- Return Button Status -------
 FUNCTION MBtn% STATIC
   Mouse 3, Buttons, 0, 0
   MBtn% = Buttons
 END FUNCTION

 '------- Mouse Interrupt ------
 SUB Mouse (M0%, M1%, M2%, M3%) STATIC
   DIM InRegs AS RegType, OutRegs AS RegType
   InRegs.ax = M0%
   InRegs.bx = M1%
   InRegs.cx = M2%
   InRegs.dx = M3%
   CALL INTERRUPT(51, InRegs, OutRegs)
   M0% = OutRegs.ax
   M1% = OutRegs.bx
   M2% = OutRegs.cx
   M3% = OutRegs.dx
 END SUB

 '------- Mouse Driver Active --------
 FUNCTION MouseActive% STATIC
   DEF SEG = 0
   mseg% = 256 * PEEK(51 * 4 + 3) + PEEK(51 * 4 + 2)
   moff% = 256 * PEEK(51 * 4 + 1) + PEEK(51 * 4)
   IF mseg% OR moff% THEN
     DEF SEG = mseg%
     IF PEEK(moff%) = 207 THEN
       MouseActive% = 0
     ELSE
       MouseActive% = -1
     END IF
   ELSE
     MouseActive% = 0
   END IF
   DEF SEG
 END FUNCTION

 '------- Turn Mouse Off -------
 SUB MouseOff STATIC
   Mouse 0,0,0,0
 END SUB

 '------- Turn Mouse On --------
 SUB MouseOn STATIC
   Mouse 0, 0, 0, 0                      'initialize mouse driver
   Mouse 1, 0, 0, 0                      'turn mouse cursor on
 END SUB

 '------- Set Mouse Coordinates --------
 SUB SetMXY (x, y) STATIC
   Mouse 4, 0, (x - 1) * 8, (y - 1) * 8
 END SUB

 '------ Draw Mouse Cursor -------
 SUB ShowMouse STATIC
   Mouse 1, 0, 0, 0
 END SUB

 The following is the assembly language counterpart to the MOUSE
 subprogram shown above. This routine can be placed in a Quick library
 and a conventional .LIB library, and your program can make calls to
 this routine, which will directly interface with the mouse driver,
 eliminating the need for the CALL INTERRUPT routine.

 This assembly listing should be compiled with Microsoft Macro
 Assembler (MASM) Version 5.00 or later.

 ;MOUSE.ASM
 .MODEL  medium
 .DATA
 bxhold    dw    ?
 .CODE

     public Mouse
 Mouse   proc    far
         push    bp
         mov     bp, sp
         mov     bx, [bp+10]        ;get BX parameter
         mov    ax, [bx]           ;in AX
         mov    bxhold, ax       ;and save
     mov    bx, [bp+6]
     mov    dx, [bx]       ;get DX parm
     mov    bx, [bp+8]
     mov    cx, [bx]       ;get CX parm
     mov    bx, [bp+12]
     mov    ax, [bx]       ;get AX parm
     mov    bx, bxhold       ;get BX back
     int    51           ;make the MOUSE call
     mov    bxhold, bx
     mov    bx, [bp+6]
     mov    [bx], dx       ;return DX
     mov    bx, [bp+8]
     mov    [bx], cx       ;return CX
     mov    bx, [bp+12]
     mov    [bx], ax       ;return AX
     mov    bx, [bp+10]
     mov    ax, bxhold
     mov    [bx], ax       ;return BX
     pop    bp
     ret    8           ;remove 4 parameters from stack
 Mouse    endp
 END


 403. QB 4.50 Help "RND(n) Function Details" Correction for n = 0

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 12-JAN-1990    ArticleIdent: Q37896

 The QuickBASIC Version 4.50 QB Advisor online Help screen under "RND
 Function Details" shows the following incorrect statement under
 Argument:

    0 or n omitted    Returns the next random number in the sequence.

 The line should be changed to read as follows:

    n > 0 or          Returns the next random number in the sequence.
    n omitted

 This information is correct in the printed manuals for Version 4.50
 and earlier versions.

 Version 4.50 is the first version of QuickBASIC that offers the QB
 Advisor, a hypertext-based, online Help system with instant cross
 referencing.

 This documentation error also occurs in the Microsoft Advisor online
 Help system in QBX.EXE, which comes with Microsoft BASIC PDS Version
 7.00.


 404. INPUT Statement Removes Unquoted Leading & Trailing Spaces

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_QuickBas B_GWBasicI B_BasicInt B_BBasic
 Last Modified: 12-JAN-1990    ArticleIdent: Q37897

 In all versions of Microsoft BASIC, the INPUT statement will remove
 leading and trailing spaces without quotation marks from an input
 string. The following two processes will help you work around this
 behavior:

 1. Put double quotation marks around the input string.

 2. Use LINE INPUT into a string variable.

 This information applies to the following products:

 1. Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 3. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 5. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 6. Microsoft BASIC Compiler and Interpreter for the XENIX Operating
    System

 7. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh

 8. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 9. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh

 The following is a code example:

 ' Run this program and input the following with leading and
 ' trailing spaces:       test
 INPUT X$
 PRINT X$,LEN(X$)
 ' You must surround leading and trailing spaces in your input with
 ' double quotation marks to make them significant: "    test    "
 ' or else use LINE INPUT:
 LINE INPUT X$


 405. Bibliography Reference for QuickBASIC: Graphics, Tutorials

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas B_BasicCom B_GWBasicI B_BasicInt
 Last Modified: 10-JAN-1991    ArticleIdent: Q37898

 This article summarizes selected textbooks from Microsoft Press and
 other sources that are useful references for BASIC programmers. This
 information applies to QuickBASIC versions 1.00, 1.01, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2; and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2. Some references also apply to
 Microsoft GW-BASIC versions 3.20, 3.22, and 3.23.

 The following book applies to general Microsoft BASIC:

    "BASIC Computer Adventures"
    by David Ahl, published by Microsoft Press (1986)

    This book contains 10 sample programs (games) to demonstrate general
    concepts of BASIC programming. All of the programs in this book are
    written in standard Microsoft BASIC for IBM PC compatibles
    (including Microsoft GW-BASIC, IBM BASICA, and COMPAQ BASICA). The
    programs also work in Microsoft BASIC for the Apple Macintosh.

 The following newsletter applies to GW-BASIC and BASICA:

    "The BASIC Teacher"
    2814 19th Street
    San Francisco, CA  94110

    This monthly newsletter discusses learning and teaching BASIC. Each
    issue contains tutorials, problems, solutions, and reviews. The
    newsletter material is written by the authors of the following
    book:

    "GW-BASIC Made Easy"
    by Bob Albrecht and Don Inman, published by Osborne McGraw-Hill
    (1989)

 The following Microsoft Press books apply specifically to QuickBASIC
 for IBM Personal Computers and compatibles:

 1. "Microsoft QuickBASIC Programmer's Toolbox"
    by John Clark Craig, published by Microsoft Press (1988)

    Contains more than 250 subprograms and functions that address common
    and unusual programming tasks, including the following:

    a. ANSI.SYS screen control.
    b. Mouse support.
    c. Pop-up windows.
    d. Graphics.
    e. String and bit manipulations.
    f. Editing routines.
    g. Engineering, mathematical, statistical, and random-number
       functions.
    h. Calendar and time routines.
    i. Demonstrations and useful routines written in Microsoft C.
       (This book shows how to write and compile C routines and how
       to create a Quick library from those routines.)

 2. "Microsoft QuickBASIC," 2nd Edition
    by Douglas Hergert, published by Microsoft Press (1988)

    This is the best resource for programming with QuickBASIC version
    4.00 for IBM PC compatibles. It provides a concise survey of the
    new features of QuickBASIC version 4.00. Special emphasis is placed
    on the editing environment, record structures, user-defined TYPEs,
    constants, additional loop and decision structures, and recursion.
    There are six programs to help illustrate QuickBASIC commands,
    functions, and techniques.

 3. "Microsoft QuickBASIC"
    by Douglas Hergert, published by Microsoft Press (1987)

    This book provides a good introduction to QuickBASIC versions 2.00,
    2.01, and 3.00 for IBM PC compatibles. It covers modular
    programming, subroutines, include files, and general programming
    practices.

 4. "Microsoft QuickBASIC: Programmer's Quick Reference"
    by Kris Jamsa, published by Microsoft Press (1989)

    For every Microsoft QuickBASIC statement and function, this quick
    reference contains a brief description, complete syntax, details on
    parameters, and usually a sample program fragment.

 5. "Learn BASIC Now"
    by Halvorson and Rygmyr, published by Microsoft Press (1990)

    This book includes the QuickBASIC interpreter (QBI.EXE) on disk,
    and provides step-by-step instructions for learning BASIC
    programming.

 6. "The Waite Group's Microsoft QuickBASIC Bible"
    by Mitchell Waite, published by Microsoft Press (1990)

    This is the definitive reference for Microsoft QuickBASIC versions
    through 4.50 (940 pages) for both novice and professional
    programmers. Since the 4.50 product's language reference is mostly
    in the online help, you may want a printed reference such as this.

 The following books are from non-Microsoft publishers:

  1. "QuickBASIC Made Easy"
     by Albrecht, Wiegand, and Brown; published by Osborne McGraw-Hill
     (1989)

     This is a programming textbook. A teacher's guide and a series of
     workbooks are also available.

  2. "Advanced QuickBASIC 4.0"
     by Murray Lesser, from Bantam Books (1988)

     This book describes building assembly-language libraries for use
     with QuickBASIC.

  3. "Using QB"
     by Inman and Albrecht, from McGraw-Hill

     This book is a good tutorial for QuickBASIC version 4.00.

  4. "Using QuickBASIC 4.0"
     by Feldman and Rugg, from Que

     This is both a tutorial and reference and is one of the most
     complete books on QuickBASIC version 4.00.

  5. "Microsoft QuickBASIC Using Modular Structure"
     by Julia Case Bradley, from William C. Brown Publishers (1989)

     This is a programming textbook. A study guide is available.

  6. "Microsoft IBM QuickBASIC: A Structured Approach"
     by Harvey and Paul Deitel, published by Prentice-Hall (1989)

     This is a programming textbook.

  7. "QuickBASIC: A Structured Programming Approach"
     by Fred Scott, published by Scott, Foresman, and Company (1988)

     This is a programming textbook.

  8. "Structured BASIC Programming" 2nd Edition
     by Harry Moriber, Merrill Publishing (1989)

     This is a programming textbook. Only the appendix discusses
     Microsoft QuickBASIC.

  9. "Advanced Structured BASIC"
     by Lloyd Onyett, published by DC Heath (1989)

     This is a programming textbook. Only the appendix discusses
     Microsoft QuickBASIC.

 10. "Microsoft QuickBASIC Programmer's Reference"
     by Douglas Hergert, published by Howard W. Sams & Company (1990)

     A comprehensive treatment of all 200 commands and functions in
     QuickBASIC version 4.50.

 The books below deal with advanced programming.

 The following books do not describe BASIC language programming; they
 describe video modes and BIOS and MS-DOS interrupt calls accessible
 from QuickBASIC versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50:

 1. "Programmer's Guide to PC & PS/2 Video Systems"
    by Richard Wilton, published by Microsoft Press (1987)

    This book gives excellent, in-depth coverage of IBM PC and PS/2
    video systems, including the following:

    a. MDA (Monochrome Display Adapter)

    b. CGA (Color Graphics Adapter)

    c. EGA (Enhanced Graphics Adapter)

    d. VGA (Video Graphics Array; the video subsystem integrated into
       the IBM PS/2 Models 50, 60, and 80)

    e. MCGA (Multi-Color Graphics Array; or Memory Controller Gate
       Array; the video subsystem integrated into the IBM PS/2 Model
       30)

    f. HGA (Hercules Graphics Adapter)

       This book also includes many invaluable C and assembler
       source-code examples. Whatever graphic output you want, (for
       example, text, circles, region fill, alphanumeric character
       sets, bit blocks, or animation), you can do it faster and more
       effectively with this book.

 2. "Advanced MS-DOS Programming," 2nd Edition
    by Ray Duncan, published by Microsoft Press (1988)

    (The 1st edition, published in 1986, was called "Advanced
    MS-DOS" and covers only MS-DOS versions 1.00 through 3.00.)

    The 2nd edition discusses MS-DOS versions 1.00 through 4.00
    in-depth. This book emphasizes the following subjects:

    a. MS-DOS disk file and record operations.
    b. MS-DOS disk directories and volume labels.
    c. MS-DOS memory management.
    d. MS-DOS EXEC functions.
    e. MS-DOS programming reference (interrupts and function calls).
    f. IBM ROM BIOS functions (up to IBM PS/2 Model 80 ROM BIOS, and
       VGA video adapter).
    g. Microsoft Mouse driver functions reference (up to Microsoft
       Mouse driver version 6.00). This was not included in the first
       edition of "Advanced MS-DOS."
    h. Lotus/Intel/Microsoft (LIM) Expanded Memory Specification (EMS)
       functions reference (up through LIM EMS version 4.00). This was
       not included in the first edition of "Advanced MS-DOS."

 3. "The New Peter Norton Programmer's Guide to the IBM PC and PS/2:
    the Ultimate Reference Guide to the Entire Family of IBM Personal
    Computers"
    by Peter Norton and Richard Wilton, published by Microsoft Press
    (1988)

 4. "The Peter Norton Programmer's Guide to the IBM PC"
    by Peter Norton, published by Microsoft Press (1985)

    This book covers the following subjects:

    a. Disk-handling information
    b. Sound generation
    c. BIOS (Basic Input Output System) information
    d. ROM BIOS video and disk services
    e. MS-DOS interrupts and function calls
    f. Installable device drivers
    g. Tips on creating interface routines for higher languages

 5. "Microsoft Mouse Programmer's Reference"
    by Microsoft Press (1989)

    This guide describes how to perform Microsoft Mouse function calls
    from Microsoft QuickBASIC, interpreted BASIC, QuickC, C, Pascal,
    Macro Assembler, and FORTRAN. Two 5.25-inch companion disks include
    sample programs.

 6. "MS-DOS Extensions: Programmer's Quick Reference"
    by Ray Duncan, published by Microsoft Press (1989)

    This is a concise reference for Lotus/Intel/Microsoft Expanded
    Memory Specification (LIM EMS) version 4.0, LIM Extended Memory
    Specification (LIM XMS) version 2.0, Microsoft CD-ROM Extensions
    version 2.10, and Microsoft mouse driver function calls.

 The following magazine is the first magazine dedicated to programming
 in BASIC. It covers programming tips, products, and articles related
 to the BASIC programming community.

    "The QuickBASIC Journal"
    Northeast Publishing
    126 Wellington Ave.
    Warwick, RI  02886
    (401) 274-5492


 406. Do Not LINK Multiple Modules with /PACKCODE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER  | B_BasicCom
 Last Modified: 16-NOV-1988    ArticleIdent: Q37900

 When developing large programs in QuickBASIC that require multiple
 modules, do not LINK with the /PACKCODE option. This can stop the
 program with the following run-time error on a RESUME NEXT statement
 (when ON ERROR GOTO is used):

    No line number in module <name> at address: <address:offset>
    Hit any key to return to system

 Linking with /PACKCODE may not produce any run-time errors in a
 single-module program.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, and the Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2.

 For more information about the /PACKCODE switch, please see the
 section on "Linking object files with LINK" in the "Microsoft CodeView
 and Utilities" manual provided with the BASIC Compiler Versions 6.00
 and 6.00b (or with the Microsoft Macro Assembler Versions 5.x).

 The following is a code example:

 '<====== Main Module ======>
 DECLARE SUB testsub ()
 CALL testsub
 END

 '<====== SUB Module, Separately compiled  ======>
 ErrTrap:
    PRINT " Error : ", ERR, " trapped in SUB module"
    PRINT
    RESUME NEXT
    END
 SUB testsub STATIC
     ON ERROR GOTO ErrTrap
     ERROR 61
     PRINT "Returned from error routine"
 END SUB


 407. ON TIMER GOSUB; ON PLAY Time Increments Smaller Than 1 Second

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 19-OCT-1990    ArticleIdent: Q37903

 The resolution of the ON TIMER (n) GOSUB statement is limited to
 increments of 1 second.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 One way to work around this limitation (to get a better timer-event
 resolution) is to use the ON PLAY statement, which can transfer
 control to a subroutine each time a musical note is played. With a
 fast tempo and very short notes, one can transfer control as much as
 30 times a second.

 The following are three separate methods to get a small time interval:

 1. Use BIOS INTERRUPT 15 Hex, with function 86 hex (or, in decimal,
    INTERRUPT 21 with function 134) for a resolution at intervals of
    976 microseconds (976 millionths or .000976 of a second).

 2. Use BIOS INTERRUPT 1A hex (26 decimal) with function 0 for a
    resolution at about 18.20648 ticks per second (or .05492549
    seconds).

 3. Use the ON PLAY statement for resolution at 30 times per second
    (or .0333333).

 This article describes method 3 above. To find the two separate
 articles that explain methods 1 and 2, search in this Knowledge Base
 for the following exact words:

    BASIC and timer and increments and smaller and second

 ON PLAY
 -------

 The MESSAGE.BAS listing shown below illustrates method 3, plus a
 method for producing smooth, pixel-based scrolling. Rather than using
 the PRINT statement, the bits for each character in the message are
 PEEKed from the ROM character table one column at a time.

 No music is actually played in this example because note zero is used,
 which means to pause with no sound.

 If 30 times per second is too fast, the speed may be varied either by
 adjusting the tempo or by using notes longer than the 64th note. Note
 that the PLAY command is again used "inside" the subroutine to prime
 the PLAY buffer and keep the process going. QuickBASIC doesn't allow
 you to use notes shorter in duration than a 32nd note. Notes shorter
 in duration than a 32nd note freeze the PC's system clock and the
 system time does not advance.

 This information is taken from Page 334 of "PC Magazine," Vol. 7,
 Number 17, October 11, 1988. The information comes from a letter sent
 to "PC Magazine" by James A. Parsly of Knoxville, Tennessee, and from
 an article written by Ethan Winer.

 The ON PLAY GOSUB statement is supported under MS-DOS, but NOT under
 MS OS/2 protected mode.

 The following is a code example:

 MESSAGE.BAS
 -----------

 DEFINT A-Z
 SCREEN 2
 'set up message and window location
 MESSAGE$ = "........The quick brown fox jumped over the lazy dog "
 LEFT = 220
 RIGHT = 420
 TOP = 8
 LETNUM = 0
 COLUMN = 8

 'draw box around window:
 LINE (LEFT - 2, TOP - 2)-(RIGHT + 2, TOP + 9), 1, B
 DIM BUFF(2 + INT((RIGHT - LEFT + 7) / 8) * 4)  'space for buffer.
 DEF SEG = &HF000   'segment of ROM characters.

 'To get a smooth crawl, we must use timed interrupts. However, ON
 'TIMER has a minimum interval of 1 second, which is not fast enough.
 'We are forced to use ON PLAY with a song consisting of a single rest.

 PLAY ON                                 'turn event ON
 PLAY "MB T130 L32 N0"                   'set up "song".
 ON PLAY(1) GOSUB MOVEIT                 'set up timed interrupt.

 'A foreground task can be executing here. In this case, the time of
 'day is printed on the screen.

 WHILE INKEY$ = ""
       LOCATE 5, 37
       PRINT TIME$
 WEND
 END

 'Interrupt handler for ON PLAY
 '
 'MOVEIT receives control at regular intervals through the ON PLAY
 'statement. It takes the current image in the window and shifts it
 'right one column. It then adds a new column at the left-hand edge.
 'This creates a message that "crawls" from left to right.

 MOVEIT:
       GET (LEFT, TOP)-(RIGHT - 1, TOP + 7), BUFF 'get current image.
       PUT (LEFT + 1, TOP), BUFF, PSET     'shift image to right.

      'A new column is added at the left. This is constructed using the
      'character pattern table located in ROM at F000:FA6E.

       COLUMN = COLUMN + 1
       IF COLUMN = 9 THEN
             COLUMN = 1
             LETNUM = LETNUM + 1     'start a new letter.
             IF LETNUM > LEN(MESSAGE$) THEN LETNUM = 1
             'wrap around if necessary.
             'compute offset into pattern table for the new letter.
             OFFSET = &HFA6E + ASC(MID$(MESSAGE$,LEN(MESSAGE$)-
             LETNUM + 1,1)) * 8
       END IF

       'copy one column of the pattern into left edge of the window:
       FOR ROW = 0 TO 7
             BYTE = OFFSET + ROW
             BIT = (PEEK(BYTE) AND 2 ^ (COLUMN - 1))
             IF BIT = 0 THEN
                   PRESET (LEFT, TOP + ROW)
             ELSE
                   PSET (LEFT, TOP + ROW)
             END IF
       NEXT

       PLAY "MB N0"       'create a new "song".
 RETURN


 408. PRINT SCREEN (Hardware Interrupt 5) Fails If Printer Is Busy

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q38068

 If the printer is busy (still working on a print job) when a hardware
 interrupt 5 (PRINT SCREEN) interrupt is issued (such as by pressing
 the SHIFT+PRINT SCREEN or PRINT SCREEN key), the interrupt will not
 dump the screen to the printer. The hardware interrupt 5 checks the
 printer status before continuing, and if the printer is busy, it
 aborts the screen dump.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC PDS 7.00 for MS-DOS. It also applies to
 any language that supports hardware interrupt 5.

 If a program sends some information to the printer and then issues an
 interrupt 5 (through CALL INTERRUPT, or an assembly-language program),
 the screen dump may be skipped. If the printer has not finished
 printing the information sent prior to the interrupt 5 call, the
 printer will return "busy" when the print screen interrupt checks the
 printer status.

 This may not be a problem running on machines with slower clock speeds
 (4.77, 6 MHz, etc.), but the same code running on a faster machine
 (clock speed 10, 12, 16, 20 MHz, etc.) may fail because the processor
 of the computer may work faster than the printer does.

 To guarantee that the printer is not busy before doing a screen dump,
 you can check the printer status yourself. The printer status can be
 obtained by invoking interrupt 17 hex, function 2. The value returned
 in the AH register by this interrupt contains the following
 information corresponding to each bit:

    Bit     Status
    ---     ------

    7       Printer NOT busy
    6       Acknowledge
    5       Out of paper
    4       Printer selected
    3       I/O error
    2       Unused
    1       Unused
    0       Timed-out

 Below are two sample program listings, one for assembly language, and
 one for BASIC using the CALL INTERRUPT method, that return the printer
 status byte. If the status byte ANDed with 128 is 128, the printer is
 not busy; if it is 0, the printer is busy, and a screen dump at that
 point would fail. Program logic should loop, constantly checking the
 printer status, until the status (AND 128) is 128, and then perform
 the interrupt 5.

 For another sample BASIC program using this interrupt, query on the
 following:

    time-out and printer and interrupt and 17 and function and 2

 Code Example
 ------------

    The assembly listing is as follows:

 ; Assembled with Microsoft Macro Assembler (MASM) Version 5.x.
 .MODEL  medium
 .CODE
         public PStat
 PStat   proc    far
         mov ah, 2
         mov     dx,0                    ;printer # 0
         int     17h
         mov al, ah
         mov     ah,0                    ;one byte return value
         ret
 PStat endp
 END

    The BASIC listing is as follows:

 REM $INCLUDE: 'QB.BI'
 REM For PDS 7.00, you must include QBX.BI
 FUNCTION PStat% STATIC
   DIM Regs AS RegType
   Regs.AX = &H200
   Regs.DX = 0                           'printer # 0
   CALL INTERRUPT(&H17, Regs, Regs)
   PStat% = Regs.AX \ 256                'status = AH
 END FUNCTION


 409. "Division By Zero" Dynamic, Fixed-Length STRING*1, 64K+ Array

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q38069

 A DIM statement gives the following error at run time when you
 dimension a dynamic, fixed-length STRING*1 array 64K or larger (which
 requires compiling with the /AH option):

    "Division by zero"

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). The
 "Division by zero" error occurs both in the QB.EXE editor and in a
 compiled .EXE program. This problem was corrected in Microsoft BASIC
 PDS Version 7.00 (fixlist7.00).

 This problem does not occur with static fixed-length STRING*1 arrays,
 or any static or dynamic array smaller than 64K.

 The following is a code example:

 ' This program must be compiled with the /AH option.
 ' A static array (limited to 64K or smaller) is ok:
 DIM darray(1 TO 4096, 1 TO 16) AS STRING * 1
 REM $DYNAMIC
 ' A dynamic, STRING*1, 64K+ array gives "DIVISION BY ZERO" at run time:
 DIM carray(1 TO 4096, 1 TO 16) AS STRING * 1


 410. "Permission Denied" If SHELLed Process Accesses Same OPEN File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 18-SEP-1990    ArticleIdent: Q38071

 "Permission Denied" normally occurs when you attempt to access a file
 that is locked by another process or attempt to write to a
 write-protected disk.

 For example, if you OPEN a file, LOCK any record, then SHELL to
 another program that attempts to access the same file, a "Permission
 Denied" error properly occurs.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The following program, which SHELLs to a copy of itself, correctly
 gives a "Permission Denied" error when run from an .EXE file or from
 within the QB.EXE or QBX.EXE editor (if you have first created
 TEST.EXE):

    TEST.BAS
    --------

    OPEN "TEST.DAT" FOR RANDOM AS #1
    LOCK #1, 3
    SHELL "TEST.EXE"
    UNLOCK #1, 3
    END

 The following program also demonstrates "Permission Denied" if you
 attempt to run TEST.EXE from within the SHELL session, before giving
 the EXIT command to end the child process (session):

    OPEN "TEST.DAT" FOR RANDOM AS #1
    LOCK #1, 3
    SHELL          ' Before saying EXIT, run TEST.EXE to show the
    UNLOCK #1, 3   ' "Permission Denied" message.
    END


 411. PAINT Must Not Use Fixed-Length String Patterns

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q38273

 The following command can be used to fill in an enclosed polygon:

    PAINT (x,y), pat, border

 In this case, x and y represent screen coordinates inside the polygon;
 the figure is drawn in a color specified by "border" and the variable
 "pat" may be either an integer or a character string. If "pat" is an
 integer, the fill is done with a solid color. But if "pat" is a string
 value, it represents a fill pattern.

 A string value for "pat" works correctly in the QB.EXE environment
 whether the string value is a fixed-length string or a variable-length
 string. However, the compiled .EXE version of such a program produces
 an "Illegal function call" error when "pat" is a fixed-length string.

 This design limitation applies to QuickBASIC Versions 4.00, 4.00b, and
 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS
 OS/2.

 Note: Fixed-length strings are not implemented in earlier versions of
 these products.

 The following is a code example:

 DIM SHARED pat AS STRING * 16

 pat = "cc3c0c00"
 SCREEN 9
 WINDOW (0, 0)-(1250, 1000)
 COLOR 1, 0
 CIRCLE (600, 200), 150
 COLOR 3, 0
 PAINT (600, 200), pat, 1
 INPUT a$


 412. Single Precision "Overflow" when Nearing Divide By Zero;10E-38

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  9-DEC-1988    ArticleIdent: Q38274

 The code example below produces an "OVERFLOW" error at n = 38 for
 QuickBASIC Versions 3.00, 4.00, and 4.00b, and BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and OS/2. The overflow occurs as you divide
 by ever larger numbers and approach the limits of the negative
 exponent for single precision. The program may overflow at different
 places in other versions of BASIC. To work around the "Overflow"
 error, use at least one double precision variable or constant in the
 expression before assigning to the variable.

 The following code example gives an "Overflow" error at n = 38:

 FOR n = 1 TO 100
  x# = 1 / 10 ^ n
  PRINT n, x#
 NEXT

 In the above program, the expression 1/10^n is optimized to use single
 precision, since the most precise argument in the expression is n,
 which defaults to single precision.

 To avoid the overflow of the negative single precision exponent,
 change n to double precision (n#). This forces the expression 1/10^n#
 to be stored in a double precision temporary storage area before being
 assigned to x#:

 FOR n# = 1 TO 100  ' This program runs fine from n#=1 through 100.
  x# = 1 / 10 ^ n#
  PRINT n#, x#
 NEXT


 413. "Out Of Memory" During CHAIN Using Large COMMON Block

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 29-NOV-1988    ArticleIdent: Q38276

 The two programs shown below demonstrate that a program can run out of
 memory when CHAINing to another program if there is insufficient
 memory to copy the COMMON data. If run from within the QB.EXE
 environment, the error is simply "Out of memory," while the error
 message "Out of memory during chain" is produced when the programs are
 run as .EXE programs. To solve the error, you must use a smaller
 COMMON block.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 and Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2.

 The following are code examples:

 'chain1.bas
 DIM a#(5000)
 COMMON a#(), b#(), c#()
  x = FRE(-1) - 1000
  PRINT FRE(-1)
 DIM b#(x / 16), c#(x / 16)
 PRINT FRE(-1)
 CHAIN "chain2"

 'chain2.bas
 DIM a#(5000)
 COMMON a#(), b#(), c#()
 PRINT FRE(-1)
 PRINT "Chain complete"



 414. LOCATE Must Place Cursor in VIEW PRINT Window or Line 25

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q38277

 Page 445 of the "Microsoft QuickBASIC 4.00: BASIC Language Reference"
 manual specifies that the LOCATE statement must operate within the
 screen limited by the VIEW PRINT statement. This is true for all lines
 except line number 25. Line 25 is unique; the following explanation
 appears on Page 256 of the same manual:

    The last line on the screen is reserved for the softkey display
    and is not accessible to the cursor unless the softkey display is
    off (KEY OFF) and LOCATE is used with PRINT to write on the line.

 KEY OFF (softkey display off) is the default. Therefore, even with a
 screen limited from line 4 to line 12, if the command KEY ON has not
 been issued, you may use the LOCATE command to print on line 25.

 This information applies to QuickBASIC Versions 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The following is a code example:

    VIEW PRINT 4 TO 12
    LOCATE 25, 1     ' This LOCATE is OK
    LOCATE 13, 1     ' This LOCATE is an "Illegal Function Call"


 415. User-Defined TYPE vs. FIELD & MKS in Random-Access File PUT#

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  2-MAR-1990    ArticleIdent: Q38278

 When a numeric data type (INTEGER, LONG, SINGLE, DOUBLE, or CURRENCY)
 stored in a user-defined TYPE is PUT directly to a random-access file
 as the third argument of the PUT statement, the values stored in the
 file are stored the same as those written with PUT using variables
 defined in a FIELD statement and initialized with LSET A$ = MKI$(i).

 This is true for all TYPEs, except if you compile with the /MBF
 option. When you compile with /MBF, SINGLE or DOUBLE user-defined
 TYPEs still store on disk in IEEE format instead of in MBF format,
 which is not what you desire when you compile /MBF.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2.

 When you compile with the /MBF compiler option, you cannot use a
 SINGLE or DOUBLE declaration in user-defined variables that are used
 as the third argument of a random-access PUT. When compiling /MBF, you
 must use STRING*4 and STRING*8 to PUT single- and double-precision
 numbers that are in a user-defined TYPE; this requires using MKS, MKD,
 CVS, and CVD for conversion of those numbers between string and
 numeric TYPEs.

 More information on this subject can be found under "Using
 Random-Access Files" on Pages 126-134 in the "Microsoft QuickBASIC
 4.0: Programming in BASIC: Selected Topics" manual supplied with
 QuickBASIC Version 4.00 or 4.00b and in the "Microsoft BASIC Compiler
 6.0: Programming in BASIC: Selected Topics" manual supplied with
 Microsoft BASIC Compiler Version 6.00 or 6.00b, or starting on Page
 102 in the "Microsoft BASIC 7.0: Programmer's Guide" for Microsoft
 BASIC PDS 7.00.

 User-defined TYPEs are not available in earlier versions.

 If you define an integer, such as in a user-defined TYPE, it is stored
 as 2 bytes. A long integer is stored as 4 bytes. A single-precision
 variable is stored as 4 bytes. A double-precision variable is stored
 as 8 bytes. Fixed-length strings are stored with 1 byte per character.

 Variable-length-string variables (such as x$ AS STRING) cannot be
 placed in a user-defined TYPE record. For information about the
 special way variable-length strings are stored on disk when written
 directly as the third argument of the PUT# statement, search for a
 separate article with the following words:

    PUT and THIRD and "BAD RECORD LENGTH" and VARIABLE and STRING

 Code Example
 ------------

 The code example below shows two equivalent methods of reading and
 writing to random files when you compile without the /MBF option. One
 method uses user-defined-TYPE records, and the other (older) method
 uses variable-length strings in a FIELD statement to define the file
 record. Note how much simpler your code is when you use user-defined
 TYPE records instead of records defined by a FIELD statement.

    ' Note: This program is NOT compatible with the /MBF compiler
    ' option because of the single- and double-precision TYPEs in the
    ' user-defined TYPE. When compiling /MBF, you must use STRING*4
    ' and STRING*8 to PUT single- and double-precision numbers that
    ' are in a user-defined TYPE, which requires rewriting this program
    ' to use MKS, MKD, CVS, and CVD for conversion of those numbers.
    ' INTEGER, LONG, and STRING TYPEs are independent of the /MBF option.
    TYPE Users
        i AS INTEGER
        l AS LONG
        s AS SINGLE
        d AS DOUBLE
        a AS STRING * 15
    END TYPE
    DIM dat AS Users
    dat.i = 32000
    dat.l = 21345678
    dat.s = 1234.567
    dat.d = 98765.54321#
    dat.a = "first data set"
    CLS

    ' The following outputs a user-defined-TYPE record to the file all
    ' at once:

    OPEN "test.dat" FOR RANDOM AS #1 LEN = LEN(dat)
    PUT #1, 1, dat
    CLOSE

    ' The following inputs from the file into FIELDed variables:

    OPEN "test.dat" FOR RANDOM AS #1 LEN = 33
    FIELD #1, 2 AS a$, 4 AS B$, 4 AS C$, 8 AS d$, 15 AS e$
    GET #1, 1
    i1% = CVI(a$)
    l1& = CVL(B$)
    s1! = CVS(C$)
    d1# = CVD(d$)
    PRINT i1%, l1&, s1!, d1#, e$

    ' The following outputs a new record using the FIELDed variables:

    LSET e$ = "New data "
    PUT #1, 2
    CLOSE

    ' The following inputs from the file into a user-defined variable:

    OPEN "test.dat" FOR RANDOM AS #1 LEN = 33
    GET #1, 2, dat
    PRINT dat.i, dat.l, dat.s, dat.d, dat.a
    CLOSE


 416. Long-Integer Array May Give Zero Unless Compiled /d (Debug)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b fixlist4.50
 Last Modified: 13-MAR-1990    ArticleIdent: Q38279

 Code Example 1 below shows a case where you must compile a QuickBASIC
 Version 4.00 or 4.00b program that uses LONG-integer arrays with the
 /d (debug) option, or else restructure the program as shown in Example
 2. Otherwise, the result of a division with a LONG-integer array may
 incorrectly result in zero.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem
 was corrected in QuickBASIC Version 4.50 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 When Code Example 1 below is compiled with BC.EXE in QuickBASIC
 Version 4.00 or 4.00b, (in Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2, the debug (/d) option is required). If you
 compile without using the /d option, the code produces the following
 printout:

    20000  0  0  0
    20000  0  0  0
    20000  0  0  0

 Code Example 1 displays the following correct results when executed
 within the QB.EXE editor:

    20000  20000  0  0
    20000  20000  20000  0
    20000  20000  20000  20000

 If you use a temporary variable to hold the value of Ddiv(ival) and
 then divide by the temporary variable, the correct results are
 generated (see Example 2).

 [Note that QuickBASIC versions earlier than 4.00 and BASIC compiler
 versions earlier than 6.00 do not support long integers.]

 The following are code examples:

 Example 1
 ---------

 ' Requires BC.EXE debug (/d) option in Versions 4.00 and 4.00b.
 ' OK in BC.EXE Version 4.50 with or without /d (debug) option.
 DEFINT I, L: DEFLNG N: DEFDBL D
 DIM NVal(3), NNum(3), Ddiv(5)
 Ddiv(2) = 5
 Ival = 2
 FOR i = 0 TO 2
   NNum(i) = 100000
   NVal(i) = NNum(i) / Ddiv(Ival)
   PRINT NVal(i); NVal(0); NVal(1); NVal(2)
 NEXT

 Example 2
 ---------

 ' This works with or without /d (debug) option in Versions 4.00,
 ' 4.00b, and 4.50.
 DEFINT I, L: DEFLNG N: DEFDBL D
 DIM NVal(3), NNum(3), Ddiv(5)
 Ddiv(2) = 5
 Ival = 2
 FOR i = 0 TO 2
   NNum(i) = 100000
   DTemp = Ddiv(Ival)
   NVal(i) = NNum(i) / DTemp
   PRINT NVal(i); NVal(0); NVal(1); NVal(2)
 NEXT


 417. Change for SELECT CASE Example 2 in QB.EXE 4.50 On-Line Help

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q38475

 In the second SELECT CASE example available through QuickBASIC Version
 4.50 Advisor on-line Help, there is an error in a CASE statement.

 The following correction applies to "HELP: SELECT Statement
 Programming Examples." To check for digit entry, the CASE statement
 should read as follows

    CASE 48 TO 57

 instead of the following:

    CASE 30 TO 29

 The correct ASCII decimal values for digit entries 0 through 9 are 48
 to 57.

 Version 4.50 is the first version of QuickBASIC that offers the QB
 Advisor, a hypertext-based, on-line help system with instant cross
 referencing. This error was corrected in the QBX.EXE Microsoft Advisor
 that is included with Microsoft BASIC PDS Version 7.00.


 418. Cannot Make EXE... with BRUN45.EXE if Full Menus Turned Off

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-NOV-1988    ArticleIdent: Q38488

 The QuickBASIC Version 4.50 environment lets you toggle the Full Menus
 item under the Options menu. When QB.EXE is run for the first time,
 the Full Menus item is off by default.

 For QuickBASIC veterans, selecting the Make Exe... item from the Run
 menu presents an unfamiliar pop-up dialog box when Full Menus are
 "off."  This dialog box does not have any way of selecting between
 compiling with BRUN45.LIB or BCOM45.LIB. The compiler forces you to
 use BCOM45.LIB (which makes a stand-alone program) when Full Menus are
 "off."

 You can work around this limitation by turning on the Full Menus item.


 419. FILEATTR Gets MS-DOS File Handle to Get File Date/Time Stamp

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-MAR-1990    ArticleIdent: Q38492

 When you open a file with the OPEN statement in a compiled BASIC
 program, the file number that you give is not the MS-DOS file handle.
 Instead, the file number acts as a pointer into an internal table that
 BASIC uses to hold the file handles. You can use the FILEATTR function
 to obtain the actual MS-DOS file handle.

 The syntax for getting the file handle is as follows:

    FILEATTR(filenumber, 2)

 The program example below shows how to obtain the MS-DOS file handle
 of a file using the FILEATTR function. The program then uses the file
 handle in an MS-DOS INTERRUPT call to return the file's date and time
 stamp.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 The FILEATTR function is not available with QuickBASIC versions
 earlier than Version 4.00.

 This code example invokes MS-DOS interrupt 21 hex (33 decimal) with
 function 57 hex (87 decimal) to get a file's date and time stamp from
 the file's directory entry. This interrupt requires an MS-DOS file
 handle as an argument. BASIC's FILEATTR function is used to retrieve
 the file handle before invoking the interrupt.

 Code Example
 ------------

 DEFINT A-Z
 REM $INCLUDE: 'qb.bi'
 REM  In BASIC PDS 7.00 you must instead include 'qbx.bi'
 REM  In QB.EXE, use QB /L QB.QLB. In QBX.EXE, use QB /L QBX.QLB.
 REM  In BC.EXE for QuickBASIC 4.00, 4.00b, 4.50, or BASIC Compiler
 REM  6.00, 6.00B, link with QB.LIB. In BC.EXE for BASIC PDS 7.00,
 REM  link with QBX.LIB. (To support the CALL INTERRUPT statement.)

 DIM inregs AS RegType, outregs AS RegType
 ON ERROR GOTO ErrorHandler
 CLS
 INPUT "Enter filename:", filename$

 OPEN filename$ FOR INPUT AS #1
 filename$ = filename$ + CHR$(0)  ' ASCIIZ (Null on end)
 inregs.ax = &H5700
 inregs.bx = FILEATTR(1, 2)       ' Get DOS File Handle
 CALL INTERRUPT(&H21, inregs, outregs)

 REM Date is returned in outregs.dx.
 REM   Day   : Bits 0-4
 REM   Month : Bits 5-8
 REM   Year  : Bits 9-15 (from 1980)
 Day = outregs.dx AND 31                ' Mask the upper bits
 Month = (outregs.dx \ 2 ^ 5) AND 15    ' Shift L 5 & mask upper bits
 Year = 1980 + (outregs.dx \ 2 ^ 9)     ' Shift left 9 & add 1980
 PRINT "Month ="; Month; "  Day ="; Day; "  Year ="; Year

 REM Time is returned in outregs.cx
 REM   Seconds : Bits 0-4 (2 second increments)
 REM   Minutes : Bits 5-10
 REM   Hours   : Bits 11-15
 seconds = 2 * (outregs.cx AND 31) '  Mask the upper bits & mult. by 2
 minutes = (outregs.cx \ 2 ^ 5) AND 63  ' Shift L 5 & mask upper bits
 hours = outregs.cx     ' Shift left 11 - Be sure to shift in zeros!
 hours = hours \ 2
 hours = hours AND 32767
 hours = hours \ 2 ^ 10
 PRINT "Sec ="; seconds; "  Min ="; minutes; "  Hours ="; hours
 SHELL "dir " + filename$
 CLOSE #1
 END

 ErrorHandler:
         IF ERR = 53 THEN    ' File Not Found
           PRINT "Incorrect path or File does not exist"
         ELSE
           PRINT ERR
         END IF
         END


 420. CodeView Problem Stepping into BASIC GOSUB Compiled /X or /D

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | S_CodeView B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q38493

 If you compile the program below with BC /X or /D in addition to the
 /Zi option (and then LINK with /CO) for Microsoft CodeView
 compatibility, the GOSUB subroutine cannot be "stepped into" in
 CodeView (using the F8 key in CV.EXE). The CodeView stepping-in
 process works correctly if the program is compiled without /X and
 without /D. The compiler switch /X is needed to do error trapping
 using ON ERROR with RESUME statements.

 To work around this limitation, do the following:

 1. When the GOSUB is encountered, switch the View option to "Mixed"
    mode and step through lines in "Mixed" mode until the subroutine
    is reached, then switch back to "BASIC" mode.

 2. When the RETURN statement is reached, go back into "Mixed" mode
    until you are back to the line after the GOSUB.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b); and
 in Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 Code Example
 ------------

    CLS
    PRINT "Point 1"
    GOSUB 100
    PRINT "Point 3"
    END

    REM * Subroutine *
    100 PRINT "Point 2"
    200 RETURN


 421. Beep or Hang Using RETURN without GOSUB with No BC /D Debug

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 30-NOV-1988    ArticleIdent: Q38494

 Using a RETURN statement within a subprogram without an accompanying
 GOSUB statement is a programming error.

 A program with this syntax error will actually compile (in BC.EXE) and
 link without error. However, the resulting executable program will
 hang in various ways, ranging from a continuous beep from the speaker
 to the printing of random ASCII characters on the screen. The bad
 symptoms will only occur if you compile without the /D (debug) option.
 The error is successfully trapped at run time if you compile with the
 /D (debug) option.

 The syntax error also is caught in the QB.EXE environment at run time,
 because the editor is always in debug mode.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2. We are researching this problem and
 will post new information as it becomes available.

 The problem symptoms occur whether the program is compiled with or
 without the BC /O (stand-alone) option. You will need to run in QB.EXE
 or compile with the /D (debug) option to uncover programming errors
 such as these.

 The following is a code example:

 DECLARE SUB foo ()
 PRINT "In Main Program"
 CALL foo
 PRINT "After SUB"
 END

 SUB foo
   PRINT "In Sub"
   RETURN  ' Program will hang on this statement.
           ' This RETURN should be deleted; it is a programming error.
 END SUB


 422. "Subscript Out of Range" Using Complex Expression with BC /D

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q38495

 The program below returns a "Subscript Out Of Range" error message at
 run time when compiled with the BC /D (debug) option. The program
 works correctly inside the QB.EXE editor.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in QuickBASIC Version 4.50 and in Microsoft
 BASIC PDS Version 7.00 (fixlist7.00).

 To work around the problem, you can break up the complex expression.
 For example, replace the following line:

         r = SGN(t(b%)) * SQR(ABS(t(b%)))

 with the following:

         r1 = t(b%)
         r2 = ABS(r1)
         r = SGN(r1) * SQR(r2)

 The following is a code example:

 DIM t(12)
 FOR i = -6 TO 6
   t(i + 6) = i
 NEXT i
 FOR b% = 1 TO 12
   r = SGN(t(b%)) * SQR(ABS(t(b%)))
   PRINT r
 NEXT b%


 423. Cursor May Disappear in EGA 43-Line Mode Using Logitech Mouse

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-DEC-1988    ArticleIdent: Q38497

 It has been reported that when using a LogiTech mouse and QB.EXE in
 EGA 43-line mode, the mouse cursor disappears below the 25th line. The
 mouse is active even though invisible, i.e., it can place the cursor
 at any location on the screen, or make selections in dialog boxes.

 When using the Microsoft Mouse and the mouse driver that is included
 with QuickBASIC Version 4.50, the mouse operates properly in 25-line,
 43-line, and 50-line modes.

 Microsoft does not claim compatibility of QuickBASIC with the LogiTech
 mouse, or any mouse other than the Microsoft Mouse. QuickBASIC
 requires you to use the Microsoft Mouse with the mouse driver that
 comes on the QuickBASIC disk (or a later version of the Microsoft
 Mouse driver).

 Although Microsoft does not claim compatibility, QuickBASIC should
 work correctly with the latest Logitech mouse drivers (such as
 Versions 3.42 and 3.43). Earlier versions such as LogiMouse driver
 Version 3.2 will not work correctly with QuickBASIC. If QuickBASIC
 does not work with your version of the LogiMouse driver, you should
 contact Logitech to determine if an upgrade driver is available.
 Logitech's phone numbers are as follows:

    LogiMouse (415) 795-8500
    LogiTech, Inc. (415) 795-0427 Technical Support Line


 424. "Expression Too Complex" Error when Compiling with BC.EXE

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50
 Last Modified: 29-NOV-1988    ArticleIdent: Q38498

 The program below, which runs properly inside the QuickBASIC Version
 4.50 environment, will generate an "Expression too complex" error
 message when compiled with BC.EXE.

 Microsoft has confirmed this to be a problem in BC.EXE in QuickBASIC
 Version 4.50. We are researching this problem and will post new
 information as it becomes available.

 The program compiles and executes properly in Microsoft QuickBASIC
 Versions 4.00 and 4.00b.

 When the program listed below is compiled using BC.EXE, either from
 the DOS command line, or from the QuickBASIC environment with "Make
 .EXE File..." option, an "Expression too complex" error message is
 generated on the END SUB statement. The problem does not occur if the
 expression in the subprogram is simplified in any way (such as
 breaking the expression into two parts, using temporary variables,
 etc.), or if the array values in the subprogram are SHARED rather than
 passed as parameters.

 To avoid the problem, you can either break the expression in the
 subprogram down, using multiple expressions and temporary variables,
 or make the arrays SHARED rather than passed to the subprogram as
 parameters.

 The following is a code example:

 DEFINT A-Z
 DECLARE SUB cd (cur(), c(), b(), sn, l())
 DIM b(10), c(1, 10), cur(10, 2, 1, 6)
 DIM l(10)
 PRINT "This is a test."
 END
 'Note that the subprogram does NOT have to be CALLED
 'to reproduce the problem
 SUB cd (cur(), c(), b(), sn, l())
   mp = cur(l(sn), 0, 1, c(0, sn)) - 1
 END SUB


 425. BC.EXE "Internal Error Near x" Using Static Long Integer Array

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900305-180 B_BasicCom buglist4.00 buglist4.00b buglist4
 Last Modified: 20-SEP-1990    ArticleIdent: Q59427

 Indexing a static long-integer array with an expression containing
 subtraction or division can cause the error, "Internal Error Near
 xxxx," at compile time with BC.EXE. Addition and multiplication work
 correctly; only division and subtraction cause the error.

 To work around the problem, change the expression to use addition or
 multiplication, or use a variable instead of an expression to
 subscript the static long-integer array.

 Microsoft has confirmed this to be a problem in the BC.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 for MS-DOS; in
 the BC.EXE environment of Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b); and in the
 BC.EXE environment of Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2 (buglist7.00,
 buglist7.10). We are researching this problem and will post new
 information here as it becomes available.

 This problem does not occur in the QB.EXE or QBX.EXE environment.

 Code Example
 ------------

 The following code example produces the "Internal Error Near xxxx"
 error when compiled with BC.EXE. An example of the workaround
 suggested above is listed in a comment after the offending statement.

 Compile the program below as follows:

    BC INTERNAL.BAS;

 (Note that the BC /D and /O compiler options do not eliminate the
 problem.)

 ' INTERNAL.BAS
 DIM A&(10, 10)
 'Subtraction and division cause error, not addition or multiplication:
 B& = A&(i%, 1 - i%) + A&(i%, i%)   'Remove this line to prevent error
 'B& = A&(i%, 0 + 1 - i%) + A&(i%, i%) 'Equivalent line works correctly


 426. Calling a BIOS Interrupt to Determine the Scan Code of a Key

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 28-FEB-1990    ArticleIdent: Q38878

 This article gives an example of a CALL INTERRUPT to determine the
 scan code of a key. This program only reports the scan codes for keys
 that are supported in the BIOS of the machine. Keys such as F11 and
 F12 do not return scan codes using this interrupt. There are other
 interrupts that can be used to get the scan codes of extended keys,
 but they are only supported on machines with extended BIOS. This
 example program is generic and runs on any PC compatible.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 The interrupt called is "READ STATUS." This is BIOS interrupt 16 Hex,
 Function 1 Hex.

 The following is a code example:

 'The following example requires the Quick library, QB.QLB and the
 'include file, QB.BI. When starting the QuickBASIC environment,
 'one must type: QB /L QB.QLB.

 ' $INCLUDE: 'QB.BI'
 ' Note: You will have to include 'qbx.bi' for BASIC PDS 7.0
 DIM inregs AS regtype
 DIM outregs AS regtype
 inregs.ax = &H1         ' Function 1
 DO
   CALL INTERRUPT(&H16, inregs, outregs)     ' Call INT 16H
   PRINT "Scan Code is "; outregs.ax \ 256,  ' AH
   PRINT "ASCII is "; outregs.ax AND 255     ' AL
 LOOP
 END


 427. License Agreement: Copyright Notice for Sign-On and Disks

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q38883

 This article summarizes the copyright messages that must be included
 in a program developed for distribution.

 If you do not include any run-time modules separate from your
 executable (.EXE) program, then you do not have to include any notice
 of copyright. (In Microsoft BASIC Compilers, you can compile with the
 /O option to make a stand-alone program that does not require a
 separate run-time module.)

 You may distribute, free of any royalty fee, the following files only
 if they are a necessary and integrated component of your software
 product.

 1. For all Microsoft BASIC Compilers, QuickBASIC, or Microsoft BASIC
    Professional Development System (PDS), you may distribute the
    run-time module or run-time DLL, MSHERC.COM (from QuickBASIC 4.50
    or BASIC PDS 7.00), QBHERC.COM (from QuickBASIC 4.00 or 4.00b),
    MOUSE.COM, FIXSHIFT.COM, or PATCH87.COM.

 2. For Microsoft BASIC PDS, you may also distribute any xxxx.FON
    file, PROISAM.EXE, PROISAMD.EXE, ISAMIO.EXE, ISAMCVT.EXE,
    ISAMPACK.EXE, and ISAMREPR.EXE.

 If you include any of the above supporting files from a Microsoft
 BASIC product, you must have a copyright notice in both your software
 sign-on message and on your disk labels. It is not necessary to
 include this message in your manuals. The copyright notice should
 appear as follows:

                         Portions (c) Copyright
                          Microsoft Corporation
       (Insert the copyright years listed for the language here)
                           All Rights Reserved.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 There are no royalty fees for distribution of the supporting files
 listed above.

 This information comes from the documents ZRUN1 and ZRUN2, which are
 distributed by Microsoft Customer Service when a customer is concerned
 about copyrights and license agreements for Microsoft Business
 Language products.


 428. Leading Edge Display Problems with QuickBASIC Version 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-APR-1990    ArticleIdent: Q38886

 Microsoft has not tested QuickBASIC Version 4.50 with Leading Edge
 computers; therefore, we do not claim any compatibility between
 QuickBASIC Version 4.50 and Leading Edge. Running QuickBASIC Version
 4.50 on a Leading Edge computer might give you some display or editor
 problems.

 It has been reported that QuickBASIC works correctly with Leading Edge
 Model D with ROM BIOS Versions 3.00 or later (running MS-DOS 3.30),
 but may fail with earlier versions. Microsoft has not confirmed this
 information. Other unconfirmed reports are listed below.

 It has also been reported that when using a Leading Edge Model M, you
 are unable to get QuickBASIC Version 4.50 to appear on the screen
 successfully. The problem occurs with either a Leading Edge Hercules
 video card or a Leading Edge CGA video card. According to the report,
 earlier versions of QuickBASIC work correctly. According to one
 customer, the Leading Edge Model M (and Model MT) has a Switch 3 for
 Advanced Features (for color support and RS-232 enhancements). If
 Switch 3 is ON, the picture is bad using a CGA card and monochrome
 monitor, but with Switch 3 off, the screen looks fine.

 It has been reported that a Leading Edge Model D does not work
 correctly when used with either the Microsoft Mouse or the shortcut
 editing keys when cutting and pasting text in QuickBASIC Version 4.50.
 The first time an attempt is made to cut and paste text, the operation
 is successful. However, when a second attempt is made to cut and paste
 text, the operation is unsuccessful.

 It also has been reported that when TRACE is on in the QuickBASIC
 environment, the lines of text are not highlighted; only a cursor
 appears, moving from line to line. The Leading Edge's video card may
 be causing the problem.

 Two customers reported that SETUP.EXE would not work on the Leading
 Edge Model D, but they could run QuickBASIC and QB Express from the
 floppy disks.

 A customer with a Leading Edge Model D2 found a solution to his video
 problems using QuickBASIC. He said an ATI video file came with his
 computer, and he ran the program VCONFIG, which contains a menu that
 let him set video options. His computer was set to VGA, but he
 actually had an EGA, so he set it to EGA, and then QB.EXE worked
 correctly with no video problems.

 As stated above, this information has not been confirmed by Microsoft.


 429. &H8000 to &HFFFF Hex = -32,768 to -1, Affects LONG Bit Masking

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 10-JAN-1991    ArticleIdent: Q38888

 This article concerns assigning a LONG integer to a hexadecimal
 constant in the range &H8000 through &HFFFF hex. This information is
 especially important if you intend to do any bit manipulation with the
 logical operators (AND, OR, NOT, XOR, EQV, or IMP) with any LONG
 integer larger than &HFFFF& hex (or 65,535 decimal) that has at least
 one bit from 16 through 32 on.

 Many programmers may not realize that the constants &H8000 through
 &HFFFF default to a type of short integer, representing decimal values
 -32,768% through -1% respectively. Also note that the LONG-integer
 constants &H8000& through &HFFFF& represent decimal values +32,768 to
 +65,535. BASIC must follow these integer-type notation standards and
 behaviors since it doesn't have an unsigned data type.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 Assigning a LONG integer variable to a short integer hexadecimal
 constant in the range &H8000 through &HFFFF adds &HFFFF0000 to the
 number, resulting in the LONG integer being stored as &HFFFF8000 to
 &HFFFFFFFF (that is, -32,768& to -1& decimal).

 This behavior occurs because constants &H8000 through &HFFFF default
 to a type of short integer (%). In short integer notation, constants
 &H8000 through &HFFFF have decimal values -32,768% through -1%,
 respectively. For example:

    PRINT VAL("&HFFFF"); &HFFFF   ' Prints:  -1 -1
    PRINT VAL("&H8000"); &H8000   ' Prints:  -32768 -32768

 To assign hex constants &H8000 through &HFFFF to a LONG integer
 without turning on bits 16 through 32 (&HFFFF0000), you must change
 them to a type of LONG by appending an ampersand (&) character as
 follows:

    LongInt& = &H8000&  ' Use &H8000& (or +32768) instead of &H8000
    LongInt& = &H8001&  ' Use &H8001& (or +32769) instead of &H8001
       . . .                . . .
    LongInt& = &HFFFF&  ' Use &HFFFF& (or +65535) instead of &HFFFF

 Appending "&" to the constant is not necessary for hex constants
 outside the range &H8000& through &HFFFF&.

 The LONG integer &HFFFF& hex is equal to 65,535 decimal. The short
 integer &HFFFF hex is equal to -1 decimal (according to the signed,
 two's complement, integer format standard). A -1 in decimal notation
 is &HFFFFFFFF in hex LONG-integer notation.

 The hexadecimal constants &H8000 through &HFFFF default to short
 integers &H8000% through &HFFFF%, which represent the decimal numbers
 -32,768% to -1% in the two's complement, signed binary integer format.
 You must append an ampersand (&) character to the end of the constant
 to make it a LONG integer, as follows: &H8000& through &HFFFF& (which
 represent the decimal numbers 32,768 through 65,535).

 The hexadecimal constants &HFFFF8000 to &HFFFFFFFF are LONG integers
 that represent the decimal numbers -32,768& to -1& in the two's
 complement, signed binary integer format.

 Note: Bit masking (manipulation) is normally NOT done with
 floating-point numbers, because of the nature of the floating-point
 format. Bit masking normally is useful only with integers.

 Code Example 1
 --------------

 'a& is a variable, and b& will serve as a bit mask:
 a& = &HFFFF0000 ' &HFFFF0000 is a constant of type LONG
 b& = &HFFFF&  ' ATTENTION: Assign &HFFFF& instead of &HFFFF
 'This masks out bits 16 through 32, and keeps bits 1 through 15:
 a& = a& AND b&
 PRINT "a& AND b& = "; a&, HEX$(a&); " prints zero (all bits off)"

 ' Assigning b& to &HFFFF instead of &HFFFF& changes the result:
 b& = &HFFFF
 ' Now, b& contains &HFFFFFFFF, or -1 (all bits on). ANDing with b&
 ' does not change a&:
 a& = a& AND b&
 PRINT "a& AND b& = "; a&, HEX$(a&); " prints -65536, hex FFFF0000"

 Code Example 2
 --------------

 ' The following assigns short constant &HFFFF (-1) to a LONG
 ' integer. &HFFFF is converted to &HFFFFFFFF; the decimal
 ' value (-1) stays the same:
 longint& = &HFFFF
 shortint% = &HFFFF
 PRINT "longint& =", longint&, HEX$(longint&)
 PRINT "shortint% =", shortint%, HEX$(shortint%)

 ' The following assigns short constant &H8000 (-32,768) to a LONG
 ' integer. &H8000 is converted to &HFFFF8000; the decimal
 ' value (-32,768) stays the same:
 longint& = &H8000
 shortint% = &H8000
 PRINT "longint& =", longint&, HEX$(longint&)
 PRINT "shortint% =", shortint%, HEX$(shortint%)


 430. LINKer Error with /Q and /E; Can't EXEPACK Quick Library File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified:  5-SEP-1990    ArticleIdent: Q38889

 The LINK /Q option (for making a Quick library) is not compatible with
 the /E (for EXEPACK) option. The following LINKer error (L1003) will
 occur if these options are used together:

    LINK : fatal error L1003: /QUICKLIB, /EXEPACK incompatible

 This information is not documented in the "Microsoft QuickBASIC 4.0:
 BASIC Language Reference" manual, but it is covered on Page 421 of the
 "Microsoft QuickBASIC 4.5: Programming in BASIC" manual, shipped with
 QuickBASIC version 4.50.


 431. How to Get 3.5-Inch Disks for QuickBASIC for MS-DOS

 Product Version(s): 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881130-20
 Last Modified:  9-JUN-1989    ArticleIdent: Q38957

 If you already have 5.25-inch disks for a given version of QuickBASIC
 but wish to obtain the 3.5-inch disks for that version, you need to
 contact the Microsoft Information Service at (800) 426-9400 or
 Microsoft Customer Service at (206) 882-8088 between 6 AM and 5:30 PM
 Pacific time.

 The 3.5-inch disks were produced for the following QuickBASIC
 versions:

    2.01
    3.00
    4.00
    4.00b
    4.50

 When you contact Microsoft Customer Service or the Microsoft
 Information Center, you need one of the following:

    Registration Card (if you haven't sent it in)
    Product Number on the disk
    Document Number inside the QuickBASIC manuals

 If you already have 5.25-inch disks for a given version of QuickBASIC
 from Version 2.01 through Version 4.50, Microsoft can send you the
 3.5-inch disks if available for that same version number. As of
 December 1988, there is no charge for this, but you must confirm the
 charges and conditions with Microsoft Customer Service.


 432. QuickBASIC 4.50 Editor Aborts Exit if Key Pressed During Save

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S881121-15
 Last Modified: 26-FEB-1990    ArticleIdent: Q38960

 If a key is pressed while the QuickBASIC Version 4.50 editor is saving
 before an Exit, when the file is completely saved, QuickBASIC will run
 the program rather than exit to DOS.

 This information applies to Microsoft QuickBASIC Version 4.50 for
 MS-DOS. This problem does not occur in QuickBASIC Extended (QBX)
 shipped with Microsoft BASIC Profession Development System (PDS)
 Version 7.00 (fixlist7.00).

 If any file is in memory and has not been saved since last edit, and
 you select "Exit" from the File menu, QuickBASIC will ask if you
 wish to save the file before exiting. If you choose Yes, the file
 will be saved before QuickBASIC returns to DOS. However, if you
 choose to save the file, and then press any key before the save is
 finished, QuickBASIC will finish saving the file, but rather than
 exit to DOS, it will alter the program according to the key pressed,
 and attempt to RUN the program. If the key pressed makes a change
 to the source such that the program will not compile, an appropriate
 error message displays.

 You can work around this problem by allowing QuickBASIC to complete
 the process of saving the file before pressing a key.


 433. "Input Run-Time Module Path:" on DOS 2.10; QuickBASIC 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-DEC-1988    ArticleIdent: Q38961

 If BRUN45.EXE is not in the current directory or MS-DOS path, then any
 program compiled with QuickBASIC Version 4.50 requiring the BRUN45.EXE
 run-time module and running under DOS Version 2.10 will get the
 following message:

    "Input run-time module path :"

 If you respond to this prompt and input the complete drive and
 subdirectory name to locate BRUN45.EXE, then the prompt will still
 occur, and the run-time module will not be found. (This problem does
 not occur with versions of QuickBASIC earlier than Version 4.50.)

 This problem only occurs under DOS Version 2.10. On versions of DOS
 later than Version 2.10, typing in the path correctly satisfies the
 above prompt.

 To work around the problem and avoid the "Input run-time module path"
 prompt, set a PATH environment variable in MS-DOS that includes the
 run-time module in the path, as in the following example:

    SET PATH=c:\subdir


 434. Can't Highlight on PS/2 Model 60 If Sidekick Is Resident

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 B_BasicCom
 Last Modified: 19-APR-1990    ArticleIdent: Q38962

 The shortcut editing keys in QuickBASIC Version 4.50 do not work
 correctly when run on an IBM PS/2 model 60 with Borland's SideKick
 resident in memory.

 To use the shortcut editing keys, select text with the SHIFT+ARROW
 keys. Press SHIFT+DEL to cut the selected text, and move it to the
 appropriate line in the code. Press SHIFT+INS to paste the contents of
 the Clipboard into the code. If SideKick is taken out of memory, the
 shortcut editing keys work correctly.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Version 4.50. We are researching this problem and will post new
 information here as it becomes available.

 The shortcut editing keys on the IBM PS/2 model 80 work correctly with
 SideKick in memory.

 Microsoft QuickBASIC Version 4.50 is supposed to be compatible with
 SideKick; however, the above test proves otherwise.

 The QB.EXE editor in Microsoft QuickBASIC Versions 3.00, 4.00, and
 4.00b, and the QBX.EXE editor in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 work without problems when
 SideKick is in memory.


 435. MouseTrak Mouse Reportedly Does Not Work with QuickBASIC 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-DEC-1988    ArticleIdent: Q38963

 It has been reported that the MouseTrak mouse will not work correctly
 with QuickBASIC Version 4.50. The MouseTrak mouse was reportedly able
 to work correctly with QuickBASIC Versions 4.00 and 4.00b.

 Note: Microsoft has only designed and tested QuickBASIC for use with a
 Microsoft Mouse. Microsoft makes no guarantees about using QuickBASIC
 with other brands of mice.

 Microsoft recommends checking with your respective mouse manufacturer
 to see if a more up-to-date mouse driver is available that will allow
 your mouse to work with QuickBASIC Version 4.50.


 436. QuickBASIC 4.50 Incompatible with Sperry 8086 PC with IBM CGA

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881128-21
 Last Modified: 12-JAN-1990    ArticleIdent: Q38964

 It has been reported that a Sperry 8086 or 8088 PC upgraded with an
 IBM CGA card is incompatible with QuickBASIC Version 4.50. The same
 configuration reportedly works with QuickBASIC Versions 4.00 and
 4.00b.

 To correct this problem, turn the "Advanced Features" switch (switch
 number 3) on the back of the machine into the off (down) position.
 QuickBASIC 4.50 should then work correctly.

 Note: Turning off the "Advanced Features" switch may not correct the
 problem if you have a Hercules card on the Sperry PC. QuickBASIC 4.50
 has not been tested on a Sperry PC with an installed Hercules card,
 and therefore, you may experience QuickBASIC 4.50 compatibility
 problems.


 437. How to Emulate INKEY$ Function by CALLing MS-DOS INTERRUPT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900803-74 B_BasicCom
 Last Modified: 16-AUG-1990    ArticleIdent: Q64933

 The INKEY$ function in QuickBASIC can be replaced by the following
 code example that uses two MS-DOS interrupt service routines. These
 interrupt routines allow NEWINKEY$ to function the same way that
 INKEY$ works and return the same results for any given keystroke.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and 4.50
 for MS-DOS; to Microsoft BASIC Compiler 6.00 and 6.00b for MS-DOS; and
 to Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 The following code contains the NEWINKEY$ function, which must be
 called from BASIC in the same manner that INKEY$ is called.

 '********************************************************************
 '
 '   Written for Microsoft QuickBASIC 4.00, 4.00b, and 4.50; Microsoft
 '   BASIC Compiler 6.00 and 6.00b; and Microsoft BASIC PDS 7.00 and
 '   7.10 for MS-DOS.
 '
 '   This code contains a function (NEWINKEY$) that can be used instead
 '   of the built-in INKEY$ function.
 '
 '   NEWINKEY$ uses two interrupt calls to retrieve information from
 '   the keyboard buffer.
 '
 '   The interrupt (INT) service routines are :
 '   Hexadecimal: INT 16 with Function 11 and INT 16 with Function 10
 '   (Decimal   : INT 22 with Function 17 and INT 22 with Function 16)
 '
 '   For more information regarding the functionality of these and
 '   other interrupts, see "Advanced MS-DOS Programming," second edition,
 '   by Ray Duncan (Microsoft Press, 1988).
 ' *********************************************************************

 DECLARE FUNCTION NewInkey$ ()

 ' Use (uncomment) one of the following two INCLUDE statements:
 '
 ' The following is the include statement for Microsoft QuickBASIC
 ' 4.00, 4.00b, 4.50 or for Microsoft BASIC Compiler 6.00 or 6.00b:
 '
 ' REM $INCLUDE: 'QB.BI'
 '
 ' The following is the include statement for Microsoft BASIC PDS 7.00
 ' or 7.10:
 '
 ' REM $INCLUDE: 'QBX.BI'

 FUNCTION NewInkey$

    ' RegType is defined in the QB.BI (or QBX.BI) include file

    DIM Regs AS RegType

    ' Register AX will contain 1100 Hexadecimal to specify
    ' the interrupt function to execute.
    '
    ' Function 11 Hexadecimal will get the enhanced keyboard status.

    Regs.ax = &H1100
    CALL Interrupt(&H16, Regs, Regs)

    KeyCode$ = ""

    ' If the zero flag is clear, then a key was pressed (Bit 6).

    IF (Regs.flags AND 2 ^ 6) = 0 THEN

       ' Call Function 10 Hexadecimal to remove the key from the
       ' keyboard buffer.

       Regs.ax = &H1000
       CALL Interrupt(&H16, Regs, Regs)

       Scan% = (Regs.ax AND &HFF00) \ 256 AND &HFF
       Char% = Regs.ax AND &HFF

       ' Character code of zero is for the special keys (such as
       ' function keys F1 through F12.
       ' Character code of 224 is for the Enhanced Keyboard keys (such
       ' as HOME and END keys)

       IF Char% = 0 OR Char% = 224 THEN
            KeyCode$ = CHR$(0) + CHR$(Scan%)
       ELSE
            KeyCode$ = CHR$(Char%)
       END IF
    END IF
    NewInkey$ = KeyCode$
 END FUNCTION


 438. BC.EXE "Variable Name Not Unique" Using Period in Identifier

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 SR# S881130-29 ptm214
 Last Modified: 26-FEB-1990    ArticleIdent: Q39185

 The following program gives a "Variable Name Not Unique" error when
 you attempt to compile with BC.EXE or the Make .EXE File... option in
 QuickBASIC Versions 4.00, 4.00b, and 4.50:

    DIM cur.pos AS INTEGER
    DIM cur(1,1) AS INTEGER

 Microsoft has confirmed this to be a problem with Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS, and Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2 (buglist6.00,
 buglist6.00b).  The problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00.

 The same program runs correctly within the QB.EXE editor environment.

 To work around the problem, do not use a period (.) in a variable name
 except for an element in a user-defined type (defined with TYPE...END
 TYPE). Another workaround is to use DIM CUR%(1,1) (using the % type
 suffix) instead of DIM CUR(1,1) AS INTEGER.

 The error appears in the BC.EXE compiler output listing as follows:

    DIM cur.pos AS INTEGER
    DIM cur(1,1) AS INTEGER
                    ^Variable Name Not Unique


 439. "Bad File Name" OPENing "COM1:" with 1.5 Stop Bits

 Product Version(s): 1.00 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881207-9
 Last Modified:  5-SEP-1990    ArticleIdent: Q39187

 The option for 1.5 stop bits is not supported in any version of
 QuickBASIC (1.00, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, or 4.50) or in
 Microsoft BASIC Compiler version 6.00 or 6.00b for MS-DOS and MS OS/2.
 However, 1.5 stop bits is supported in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10.

 In QuickBASIC, if you try to open the serial communications port using
 1.5 Stop Bits, you will get a "Bad file name" error when you run the
 program in the QB.EXE editor. This error will not occur with 1.5 stop
 bits in BASIC PDS 7.00 and 7.10.

 The following similar error message is returned when you run an .EXE
 file compiled with the BC.EXE environment that comes with QuickBASIC:

    BAD FILE NAME in module $$$ at address xxx:xx

 The communications option for 1.5 stop bits is supported by GW-BASIC
 versions 3.20, 3.22, and 3.23.

 The following is a code example:

    OPEN "COM1:1200,N,8,1.5" FOR RANDOM AS #1


 440. Cannot CHAIN to Earlier QuickBASIC Version Unless Stand Alone

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q39191

 CHAINing between QuickBASIC version 4.50 programs and programs
 compiled in earlier versions of QuickBASIC can hang the computer
 unless you CHAIN to a stand-alone program (compiled with the /O
 option). The problem occurs when CHAINing in either direction (version
 4.50 to earlier version, or earlier version to version 4.50).

 The problem is caused by a run-time systems conflict. We recommend
 that you only CHAIN between .EXE programs that are all compiled with
 the same version of QuickBASIC. To avoid compatibility problems, you
 should avoid mixing programs compiled in different versions.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 441. Tandy 3000, EGA Card, RGB CM11 Monitor, incompatible w/ 4.50

 Product Version(s): 4.00 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881205-37
 Last Modified: 12-DEC-1988    ArticleIdent: Q39193

 It has been reported that several QuickBASIC Version 4.50 programs
 (including DEMO1.EXE) fail to run on a Tandy 3000. One customer has a
 built-in EGA card connected to a RGB CM11 monitor. This customer has
 tried this program on several other 3000s, all with EGA monitors. The
 same program works on the customer's 3000 if it is compiled with
 QuickBASIC Version 4.00. There were no TSR's running on the customer's
 system, and the mode co80 and co40 DOS commands had already been
 tried.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and wil post new information as it becomes
 available.


 442. "File AB45ADVR.HLP Not Found" QB Advisor 4.50, ERASE Example

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q39238

 The QB Advisor on-line help in QuickBASIC Version 4.50 fails to find
 the example for the ERASE statement when the <example> hyperlink
 button is chosen for that statement. QB Advisor displays "File
 AB45ADVR.HLP not found" in a dialog box and prompts you to reset the
 environment path or insert the disk with that file.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Version 4.50. The problem does not occur in the QuickBASIC Extended
 (QBX) enviroment which comes with Microsoft BASIC Professional
 Development System (PDS) Version 7.00 (fixlist7.00).

 To work around this problem, first select ERASE <detail> information
 and then choose ERASE <example>.

 Note: There is no file in QuickBASIC Version 4.50 called AB45ADVR.HLP,
 but there is one called QB45ADVR.HLP. QB45ADVR is misspelled as
 AB45ADVR in the error message.

 A test of the other keywords in QB Advisor showed no other words give
 the message "File AB45ADVR.HLP not found".

 The following is a more roundabout workaround:

 1. After entering the QB Advisor, choose the help INDEX.

 2. Choose the EOF Function (two before ERASE on the list).

 3. Choose the EOF Function example, then press CTRL+F1 (or select
    <Next>). This will put you in the window for the ERASE statement.

 4. Choose the ERASE <example> and it will come up on the screen.


 443. "Expression Too Complex", "Stack Overflow", Adding Strings

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q39239

 When the program below concatenates more than 19 string variables
 together in one equation, the BC.EXE compiler can give a misleading
 error message at compile time.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS; in Microsoft BASIC Compiler
 versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS
 OS/2; and in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 (buglist7.00, buglist7.10) for MS-DOS and MS
 OS/2. We are researching this problem and will post new information
 here as it becomes available.

 To work around this problem, split up the concatenation line so that
 the program does two concatenations on separate lines.

 In QuickBASIC versions 4.00 and 4.50 and BASIC PDS 7.00, BC.EXE gives
 the following correct error message, but the message misleadingly
 points to the bottom of the next structure (IF..ENDIF, WHILE..WEND,
 or SELECT CASE) in the source file after the concatenation:

    Expression Too Complex

 BC.EXE should point to the concatenation instead of to the end of the
 structure.

 In QuickBASIC version 4.00b and Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS and OS/2, BC.EXE displays the following error
 message in a continuous stream; you must press CTRL+C or CTRL+BREAK to
 stop the compiler:

    run-time error R6000 - stack overflow

 The following program will cause problems:

    REM The line continuation character (_) is for display purposes
    REM only and should be removed when typing in the program.
    WHILE a$ = ""
    b$ = INKEY$
    a$ = b$ + c$ + d$ + e$ + f$ + g$ + h$ + i$ + j$ + k$ + l$ _
            + m$ + n$ + o$ + p$ + q$ + r$ + s$ + t$ + u$
    WEND

 The program can be changed as follows to correct the problem:

    WHILE a$ = ""
    b$ = INKEY$
    a$ = b$ + c$ + d$ + e$ + f$ + g$ + h$ + i$ + j$ + k$ + l$
    a$ = a$ + m$ + n$ + o$ + p$ + q$ + r$ + s$ + t$ + u$
    WEND


 444. Incorrect Result Using SGN in a Mathematical Expression

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified:  2-MAR-1990    ArticleIdent: Q39244

 This article describes a problem with compiling and running a program
 that uses the SGN function in an arithmetic expression. Some examples
 fail only on machines with a coprocessor, but the code listed below
 fails using the emulator or a coprocessor. The sample code works when
 compiled with Microsoft BASIC Compiler Versions 6.00 and 6.00b with
 the /FPa switch.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00 and 4.00b, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This
 problem was corrected in the BC.EXE provided with Microsoft QuickBASIC
 Version 4.50 and Microsoft BASIC Professional Development System (PDS)
 Version 7.00 (fixlist7.00).

 This problem is caused by an error in code optimization. When the
 assembly code is examined in CodeView (or in the .LST file after
 compiling with BC /a), the reason for the addition error becomes
 clear. The result of the first half of the equation is moved from AX
 to BX after the SGN is called. This can change the value of AX and
 thus cause an incorrect result for the addition.

 In QuickBASIC 4.50 and BASIC PDS 7.00, the MOV BX,AX instruction is
 correctly placed before the call to compute the SGN.

 Code Example
 ------------

 The following code example displays incorrect results for the third
 value in an EXE compiled with QuickBASIC 4.00 or 4.00b, or BASIC
 compiler 6.00 or 6.00b. When compiled with QuickBASIC 4.50 or BASIC
 PDS 7.00, the code works correctly.

    CLS
    PRINT LEN(STR$(FIX(S!))                   'Works ->  2
    PRINT (SGN(S!) = 0)                       'Works -> -1
    PRINT LEN(STR$(FIX(S!))) + (SGN(S!) = 0)  'Fails -> 16385
    END                                       'Should be (2 + -1) = 1


 445. BC.EXE "Internal Error" Using Passed Integers in Expression

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 27-FEB-1990    ArticleIdent: Q39245

 An "internal error" is produced when compiling the sample code
 fragment (below) with BC.EXE. The problem relates to a compiler
 code-optimization problem in a particular case of passing integer
 variables as parameters to a subprogram and using them in certain
 expressions.

 Microsoft has confirmed this to be a problem in BC.EXE in Microsoft
 QuickBASIC Versions 4.00, 4.00b, and 4.50, and in the BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00)

 To work around this problem, assign a temporary value to one of the
 integer parameters before doing arithmetic (see below).

 The following code example causes an "internal error":

 DECLARE SUB XSCROLL (BarLen%, LCol%, BRow%, Rcol%)
 SUB XSCROLL (BarLen%, LCol%, BRow%, Rcol%)
    LCol% = LCol% + 3
    NumCol# = ((Rcol% - LCol%) + 1) \ BarLen%
 END SUB

 The following code example works around the problem:

 DECLARE SUB XSCROLL (BarLen%, LCol%, BRow%, Rcol%)
 SUB XSCROLL (BarLen%, LCol%, BRow%, Rcol%)
    temp1% = LCol%
    temp1% = temp1% + 3
    LCol% = temp1%
    NumCol# = ((Rcol% - LCol%) + 1) \ BarLen%
 END SUB


 446. No QB Support for Mixed Languages Compiled with /FPc or /FPa

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER  | SR# S881129-40  B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q39246

 QuickBASIC versions 4.00, 4.00b, and 4.50 do not support the use of
 the Alternate IEEE Math Library (/FPa) or code that generates
 floating-point calls (/FPc). QuickBASIC generates in-line math
 coprocessor instructions and uses the emulator library. If a math
 coprocessor is present, it will be used.

 Mixed-language routines linked to a QuickBASIC routine must be
 compiled so they generate in-line math coprocessor instructions and
 use the emulator library. This is the default option for Microsoft C
 version 5.10 and most other Microsoft languages.

 The following is an example of compiling and LINKing a mixed-language
 application:

    BC bmain.bas;
    CL /c /AM csub;
    LINK bmain + csub /noe;

 Note: If the /FPa or /FPc switch was used on the CL command line, the
 linker may produce "duplicate definition" errors. If you get
 "duplicate definition" errors at link time, the resulting executable
 file may or may not run correctly.

 Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2 and Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 each support the /FPa option for the BC.EXE
 compiler. However, neither the QuickBASIC environment (QB.EXE) that
 comes with the BASIC compiler nor the QuickBASIC Extended environment
 (QBX.EXE) that comes with BASIC PDS support /FPa. Therefore,
 mixed-language programming using alternate math (/FPa) could be
 accomplished with compiled programs with these products.


 447. QB.EXE 4.x Doesn't Save Screen Settings on Hercules Adapter

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom SR# S881129-
 Last Modified:  9-MAR-1990    ArticleIdent: Q39248

 Changes made to the QB.EXE Versions 4.00, 4.00b, or 4.50 environment
 are not saved if a Hercules or compatible adapter is used. After
 changing the editor color options and exiting the environment,
 QuickBASIC always restarts with the default-color attributes. The
 QB.INI file is not correctly updated. Display attributes must be
 reselected every time QuickBASIC is started.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and in the QB.EXE environment that
 comes with Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 (buglist6.00, buglist6.00b). This problem was corrected in the QBX.EXE
 (QuickBASIC Extended) environment that comes with Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).


 448. ON KEY Trapping CTRL, SHIFT, CAPS LOCK, NUM LOCK Combinations

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q39252

 Pressing any key in combination with CTRL, SHIFT, ALT, CAPS LOCK, or
 NUM LOCK changes the keyboard scan code. To trap combinations of keys,
 the KEY statement requires adding together the values of the keyboard
 flags as shown in the code example below.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The following is a code example:

    CONST alt = &H8
    CONST noflag = &H0
    CONST leftshift = &H1
    CONST rightshift = &H2
    CONST ctrl = &H4
    CONST numlock = &H20
    CONST capslock = &H40
    CONST extendedkeyboard = &H80
    CONST left = &H4B
    CONST right = &H4D
    CONST up = &H48
    CONST down = &H50
    CONST C = &H2E
    CONST scrolllock = &H46

    KEY 15, CHR$(extendedkeyboard + numlock) + CHR$(left)
    KEY 16, CHR$(extendedkeyboard + numlock) + CHR$(right)
    KEY 17, CHR$(extendedkeyboard + numlock) + CHR$(up)
    KEY 18, CHR$(extendedkeyboard + numlock) + CHR$(down)
    KEY 19, CHR$(ctrl + capslock) + CHR$(C)
    KEY 20, CHR$(extendedkeyboard + ctrl + numlock) + CHR$(scrolllock)

    ON KEY(15) GOSUB left
    ON KEY(16) GOSUB right
    ON KEY(17) GOSUB up
    ON KEY(18) GOSUB down
    ON KEY(19) GOSUB break
    ON KEY(20) GOSUB break

    KEY(15) ON
    KEY(16) ON
    KEY(17) ON
    KEY(18) ON
    KEY(19) ON
    KEY(20) ON

    WHILE UCASE$(INKEY$) <> UCASE$("q")
    WEND
    END

    left:
     PRINT "left"
    RETURN

    right:
     PRINT "right"
    RETURN

    up:
     PRINT "up"
    RETURN

    down:
     PRINT "down"
    RETURN

    break:
     PRINT "break"
    RETURN


 449. QB 4.50 Debugger Reference Bar Displays until STOP or END

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881208-23
 Last Modified: 14-DEC-1988    ArticleIdent: Q39253

 In the QB.EXE Version 4.50 environment, when a program is run using
 any of the debug features, the reference bar is replaced by a debug
 reference bar listing the debugging keys and their actions. The normal
 reference bar is as follows:

    <SHIFT+F1=Help> <F6= > <F2=Subs> <F5=Run> <F8=Step>

 The debug mode reference bar is as follows:

    <SHIFT+F1=Help> <F5=Continue> <F9=Toggle Bkpt> <F8=Step>

 The normal reference bar is not replaced until the program ends by
 reaching an END or STOP statement.

 To restore the normal reference bar, go to the immediate window and
 type STOP and press ENTER. This will terminate the program and restore
 the reference bar.


 450. QuickBASIC May Not Function with 25-MHz 80387 Coprocessor

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881212-11
 Last Modified:  4-SEP-1990    ArticleIdent: Q39256

 Customers have reported that QuickBASIC version 4.50 does not function
 correctly with a 25-MHz 80387 math-coprocessor chip. The reported
 problems include the following:

 1. Incorrect floating-point numeric results

 2. Coprocessor not detected

 The problem does not occur on 80387 chips slower than 25 MHz.

 Microsoft has not tested QuickBASIC version 4.50 with 25-MHz 80387
 chips.

 To test potential problems, you can compare numeric results with and
 without the coprocessor by turning the coprocessor on or off. The
 following command in MS-DOS turns off access to the coprocessor in the
 current boot session (where any message with one or more characters
 must follow the "="):

    SET NO87=Coprocessor is currently disabled.

 The following command makes the coprocessor accessible again (where no
 characters follow the "="):

    SET NO87=


 451. Hardware Compatibilities with QuickBASIC Version 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881212-9
 Last Modified: 14-FEB-1991    ArticleIdent: Q39257

 QuickBASIC version 4.50 is more selective of the video hardware on
 which it will operate than QuickBASIC versions 4.00 and 4.00b.
 QuickBASIC requires a video card that is 100-percent compatible with
 an IBM CGA, EGA, VGA, or Hercules monochrome card.

 If QB.EXE version 4.50 does not operate with your video system, try
 invoking QuickBASIC with each of the video-specific options, such as
 the /b (black and white) option, the /nohi (no high intensity) option,
 the /g (update screen as fast as possible) option, and the /h (high
 resolution) option. Also, try setting the video mode from MS-DOS using
 the Mode command before starting QuickBASIC (for example, Mode CO80
 and Mode BW80).

 If a ghost image appears after running QuickBASIC on your video
 system, use the MS-DOS Mode command to clear the screen if CLS doesn't
 clear it.

 Below are computers and video adapters listed as compatible and
 incompatible with QuickBASIC version 4.50.

 The following video cards were successfully tested with QuickBASIC
 version 4.50:

    (Note: If the card is a VGA but not an IBM PS/2 VGA, there will be
    problems swapping on screen 10.)

    AST EGA (256K)
    COMPAQ PORTABLE (monochrome)
    COMPAQ VGC (Compaq's name for VGA)
    Daewoo (Leading Edge/AT) EGA (256K) monochrome
    Genoa EGA (256K)
    Genoa EGA (256K) monochrome
    Hercules monochrome
    IBM EGA 256K
    IBM EGA 64K
    IBM PC Convertible
    IBM VGA (Non-PS/2)
    IBM PS/2 VGA
    IBM MCGA
    IBM EGA (64K) with monochrome
    IBM CGA
    IBM MDPA
    NCR EGA
    Olivetti monochrome
    Olivetti EGA (256K)
    Olivetti VGA
    Paradise Autoswitch EGA (256K)
    PC Limited VGA
    Tandy EGA (256K)
    Vega Video Seven (7) Deluxe EGA (256K)
    Zenith EGA monochrome

 If the QB.EXE environment looks fine before running a program but is
 not visible after running the program, try invoking SCREEN 0,0 at the
 end of the program, or in QB.EXE's immediate window (F6 key). One
 customer reported this solution on a Compaq 2e mono VGA, where the VGA
 video card is built-in.

 The following is a list of known compatibility problems:

 1. According to Microsoft's testing, the following cards loaded
    QB.EXE, but had numerous problems with screen swapping:

       Tecmar VGA
       Quadram VGA
       Vega Video Seven (7) FastWrite VGA
       Vega VGA (a customer suggested QB /H for better Vega VGA
                 behavior)

 2. According to Microsoft's testing, the following cards will not
    load QB.EXE:

       COMPAQ Laptop (BIOS problem - no correction)
       COMPAQ SLT/286 (okay with AC power, fails with battery, unless
                      you disable the power-conservation utility
                      PWRCON.EXE or PWRCON.COM)
       Genoa SuperVGA HiRes
       ATI VIP VGA
       Sigma EGA!

 In addition, the cards below have been reported by customers as
 potential problem cards. The problems range from hanging the machine
 to causing an unreadable display. Microsoft has not tested QuickBASIC
 version 4.50 on the hardware listed below; therefore, we do not
 guarantee compatibility. The potential problem cards are as follows
 (this information may be inaccurate because it is reported secondhand
 and is unconfirmed by Microsoft):

 1. Computers with the following video cards installed (potential
    QuickBASIC compatibility problems):

       ATI VIP card
       Vega VGA from Video Seven (7) (although one customer said
          QB /H corrected QB.EXE problems with Vega VGA)
       Sigma VGA
       Everex EGA
       Older Quadram CGA cards
       Unisys CGA
       NEC EGA
       AST Turbo Scan EGA -- A customer reported he couldn't invoke
          QB.EXE 4.50 in 80- or 43-line mode on a PC clone with this
          card.
       Tecmar VGA -- In 43-line mode, the last seven lines on the screen
          are truncated. This was found to be a problem with the Tecmar
          VGA ROM versions 1.08 and 1.09.
       Packard Bell EGA -- A customer reported that the QB Express
          tutorial failed on this card, but Setup and the QB.EXE editor
          ran correctly.
       Paradise Auto-Switching VGA -- Two customers reported that this
          card caused QB.EXE 4.50 to hang when run on an IBM XT.

 2. Computers, as follows (potential problems):

       Sperry PCs and XTs with Hercules and CGA cards
       Tandy 1000s with Tandy Enhanced CGA cards
       Leading Edge Model M (which comes with CGA or Hercules)
       Leading Edge Model D (but according to one customer, it might
          work on BIOS version 3.00 or later)
       IBM PCjr
       Zenith 151, an XT compatible, with EGA Boca, and up-to-date BIOS
       DEL 310 models that come with Vega Video Seven (7), VGA 16-bit
          graphics (try QB /H for better results)
       DEL AT-compatible with VGA monochrome system, Vega Video Seven (7)
          16-bit graphics card. Visibility problems reported in QB.EXE.
          The following reportedly do not help: QB /NOHI, /B, /H, and
          /G, and the Mode CO80 and Mode BW80 commands in DOS.
       Hyundai XT (Other non-XT Hyundai models may be OK, according to
          one customer.)
       Austin 286/12-5 computer -- a customer reported that QuickBASIC
          generated an "illegal function call" error when he tried to
          use SCREEN 9. This computer comes standard with a WDM-20 EGA
          card integrated into the motherboard and it seems that
          QuickBASIC will not recognize this card because SCREEN modes
          other than 0 give "Illegal function call."

 A customer using the Zenith 151 reported an "Internal Stack Failure"
 when holding down an arrow key for scrolling in the QB.EXE version
 4.50 editor.

 A customer reported that several QuickBASIC version 4.50 programs
 (including DEMO1.EXE) fail to run on several Tandy 3000 computers with
 a built-in EGA card connected to a RGB CM11 monitor. (The same program
 works on the customer's Tandy 3000 if it is compiled with QuickBASIC
 version 4.00.) There were no TSRs running on the customer's system,
 and the Mode CO80 and CO40 DOS commands did not help.

 For the ATI VGA Wonder card, some customers have reported "Illegal
 Function Call" errors when using SCREEN 9 in QuickBASIC programs.
 However, another customer reported that the ATI VGA Wonder card works
 properly if you run the setup correctly for the monitor type connected
 (monochrome, multisync, color, etc.). For example, if a monochrome
 monitor is connected to the card but the setup is not set correctly,
 SCREEN 9 fails, but SCREEN 10 may work. Setting the ATI VGA Wonder
 card for the monochrome monitor makes SCREEN 9 work successfully.


 452. "Symbol Defined More Than Once"; Linking BASIC and FORTRAN

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50 B_BasicCom H_Fortran
 Last Modified: 20-SEP-1990    ArticleIdent: Q39260

 Mixed-language programming with BASIC and FORTRAN may produce an
 "L2025: Symbol defined more than once" linker error. The error occurs
 even if the /NOE linker switch is used. Possible reasons for this
 problem are version-dependent, as described below.

 The following are three known problems that make LINK.EXE give an
 "L2025: Symbol defined more than once" error when linking compiled
 BASIC and FORTRAN. Problem 1 is a software limitation (not a bug), but
 Problems 2 and 3 are software problems (bugs) that Microsoft is
 researching:

 1. LINKing compiled BASIC with the incorrect version of Microsoft
    FORTRAN can cause the L2025 error.

    Microsoft BASIC Professional Development System (PDS) version 7.10
    currently cannot link with any version of FORTRAN (5.00 or earlier),
    but Microsoft is working on a workaround for this limitation.
    BASIC PDS version 7.00 requires Microsoft FORTRAN version 5.00.
    QuickBASIC versions 4.00b and 4.50 and Microsoft BASIC Compiler
    versions 6.00 and 6.00b require Microsoft FORTRAN version 4.10.
    QuickBASIC version 4.00 requires Microsoft FORTRAN version 4.00.

    The following error displays if you LINK the incorrect version of
    Microsoft FORTRAN with compiled BASIC:

       The symbol __FF_MSGBANNER is defined more than once.

    The solution to this problem is to link only the correct versions
    of FORTRAN and compiled BASIC, as listed above.

 2. Using math functions such as SIN, COS, and SQRT in the FORTRAN
    subroutine can cause the L2025 linker error. The following linker
    error occurs if a BASIC program compiled with /O is linked with a
    FORTRAN routine that was compiled with the correct version of
    Microsoft FORTRAN compiler:

       __ctrand1 [and __ctrand2]: Symbol defined more that once.

    Compile and LINK the code example farther below as follows to
    duplicate problem #2:

       BC BASIC.BAS, BASIC.OBJ /x/o;
       FL /c FORTRAN.FOR
       LINK BASIC.OBJ+FORTRAN.OBJ, BFTEST.EXE /NOE;

    Microsoft has confirmed this to be a problem in QuickBASIC versions
    4.00b and 4.50 and in Microsoft BASIC Compiler versions 6.00 and
    6.00b (buglist6.00, buglist6.00b). This problem was corrected in
    Microsoft BASIC Professional Development System (PDS) version 7.00
    (fixlist7.00).

 3. Using math functions such as SIN, COS, and SQRT in a FORTRAN 5.00
    subroutine linked into a Quick library can cause the L2025 linker
    error in BASIC PDS 7.00 (buglist7.00). This problem does not occur
    when linking into an .EXE program (instead of into a Quick library),
    or when not using FORTRAN math functions in the Quick library.

    Compile and LINK the code example further below as follows to
    duplicate Problem 3 in BASIC PDS 7.00 and FORTRAN 5.00:

       FL /c FORTRAN.FOR
       LINK /Q /NOE /NOD FORTRAN.OBJ+QBX.LIB,,,QBXQLB.LIB LLIBFORE.LIB

     This LINK gives about 28 L2025 errors, such as the following:

        llibfore.lib(dos\crt0dat.asm) : error L2025:: __osversion :
        symbol defined more than once

 Code Example for Problems 2 and 3 (Above)
 -----------------------------------------

 The following is a set of routines that demonstrate Problems 2 and 3
 above. Note: If the BASIC program is compiled with QuickBASIC version
  4.50 and the BC /O option is not used, Problem 2 does not occur.

 === BASIC.BAS ===:

    CALL ftest
    END

 === FORTRAN.FOR ===:

         subroutine ftest
         real a,b,c,d,e,p,q,r,s,t
         c = sin(d)
         p = p/e**5
         q = sqrt(r * r + s * s + t * t)
         return
         end


 453. Don't Mix .OBJ or .EXE Modules Compiled in Different Versions

 Product Version(s): 1.00 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G881202-7335 B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q39261

 When you are compiling a series of BASIC programs, Microsoft
 recommends compiling all associated routines with the same version
 number of the compiler. When the compiler is updated (such as from
 version 4.00 to version 4.00b, or version 4.00b to version 4.50), it
 is best to re-compile each routine with the new compiler and link with
 the new run-time module libraries. Both code generated by the compiler
 and the BASIC run-time modules may change between versions.

 This information applies to QuickBASIC versions 1.00, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50; Microsoft BASIC Compiler versions
 5.35 and 5.36 for MS-DOS; Microsoft BASIC Compiler 6.00 and 6.00b for
 MS-DOS and MS OS/2; and Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.


 454. How to Print Images on SCREENs 7 Through 12 to Epson Printer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom appnote BQ0085
 Last Modified: 18-OCT-1990    ArticleIdent: Q51859

 The program listing below demonstrates one method of printing an EGA
 or VGA SCREEN 7, 8, 9, 10, 11, or 12 image to an Epson printer (or
 compatible) with graphics capability.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC PDS (Professional Development
 System) versions 7.00 and 7.10 for MS-DOS. (Earlier versions do not
 support VGA SCREEN 12.)

 This article is one part of the application note titled "How to Print
 BASIC Video Screens to Epson Printers." A printed copy of this
 application note can be obtained by calling Microsoft Product Support
 Services at (206) 637-7096. This application note can also be obtained
 in separate parts in this Knowledge Base by searching for the
 following words:

    Epson and print and screen and QuickBASIC

 If you have a printer other than an Epson, you must change the printer
 control codes used in the following program for setting line spacing
 and graphics mode. Control codes can be found in your printer's
 manual.

 The routine below for printing EGA and VGA SCREEN modes 7 through 12
 is required only if you aren't running under MS-DOS version 4.00 or
 later. In MS-DOS 4.00 and later, the program GRAPHICS.COM supports all
 standard EGA and VGA SCREEN modes. Thus, the routine given in a
 separate article (part of the same application note) for printing CGA
 SCREEN modes can be used to print EGA and VGA SCREENs in MS-DOS 4.00
 and later.

 If you want further information about graphics memory and the various
 graphics modes, please refer to the following book, which is available
 in bookstores or by calling Microsoft Press at (800) 888-3303 or (206)
 882-8661:

     "Programmer's Guide to PC and PS/2 Video Systems," by Richard
     Wilton (published by Microsoft Press, 1987)

 Printing EGA or VGA Screen Modes 7 Through 12
 ---------------------------------------------

 Because EGA and VGA memory are stored in contiguous blocks per
 "plane," printing the screen to a printer can be a fairly simple
 operation. The method used in the program below prints the image
 sideways, which avoids the need to do any bit-shifting and uses a
 simple two-dots-per-pixel shading pattern to represent different
 colors.

 To produce different patterns for different colors, each color plane
 must be analyzed. In SCREEN modes with four video planes (7, 8, 9, and
 12), each of the four different base EGA/VGA colors --  blue, green,
 red, and intensity -- is represented in a separate memory bank or
 plane of EGA/VGA memory. Each bit in a color plane represents a pixel
 on the screen; thus, each pixel on the screen has a color attribute
 depicted by four bits, one in each color plane.

 Each plane is addressed for reading/writing by selecting the bank of
 memory to access with an OUT instruction. This program logically OR's
 the blue and red planes together and does the same with the green and
 intensity planes. This effectively reduces the number of pattern
 (color) combinations from 16 to 4. Therefore, some colors that appear
 to be different on the screen have the same appearance on paper.

 SCREEN modes 10 and 11 are almost identical, except that there are
 only two color planes; thus, each pixel on the screen has a color
 attribute depicted by two bits, one in each of the two color planes.
 Because there are only two bits per pixel and two pins are being
 fired, no OR'ing of the color planes needs to be done.

 The Epson printer can fire up to eight pins per graphics byte sent.
 Thus, moving from left to right, a loop that reads screen data from
 the bottom of the screen upward can access eight vertical columns at a
 time. This behavior coincides with the printer firing eight pins at a
 time and creates eight horizontal columns on the page, turning the
 printout sideways.

    DECLARE SUB ScreenParams (scrn%, ScreenWidth%, ScreenLength%, NP%)
    DECLARE SUB DRAWPIC (scrn%)
    DECLARE SUB VGAtoEpson (scrn%, f$, flip%, border%)
    ' Demonstrates the use of VGAtoEpson, a subprogram that dumps
    ' a SCREEN 7, 8, 9, 10, 11 or 12 image to an Epson printer.

    CLS : scrn% = 0
    WHILE (scrn% < 7) OR (scrn% > 12)
       INPUT "Enter Screen Mode: (7, 8, 9, 10, 11 or 12)"; scrn%
    WEND

    SCREEN scrn% : CALL DRAWPIC(scrn%)      ' Draw the picture
    CALL VGAtoEpson(scrn%, "LPT1", 0, 255)  ' Do the VGA screen print
    END

    SUB DRAWPIC (scrn%)                     ' Draw picture on screen
      CALL ScreenParams(scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)
      IF NumPlanes% = 2 THEN ci% = 0 ELSE ci% = 1  ' Color increment
      xmax% = ScreenWidth% : ymax% = ScreenLength%
      halfx% = xmax% / 2 : halfy% = ymax% / 2
      x% = halfx% : c% = 1
       FOR y% = ymax% TO halfy% STEP -5
          deltax% = xmax% - x% : deltay% = ymax% - y%
          LINE (halfx%, y%)-(x%, halfy%), c%
          LINE (x%, ymax%)-(xmax%, y%), c% + ci%
          LINE (halfx%, deltay%)-(x%, halfy%), c% + 2 * ci%
          LINE (x%, 0)-(xmax%, deltay%), c% + 3 * ci%
          LINE (halfx% + 1, y%)-(deltax%, halfy%), c% + 4 * ci%
          LINE (deltax%, ymax%)-(0, y%), c% + 5 * ci%
          LINE (halfx%, deltay%)-(deltax%, halfy% + 1), c% + 6 * ci%
          LINE (deltax%, 0)-(0, deltay%), c% + 7 * ci%
          x% = x% + (((xmax% + 1) / (ymax% + 1)) * 5)
       NEXT y%
    END SUB

    SUB ScreenParams (scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)
      ' Return the screen dimensions in pixels
      ' and the number of planes.
      NumPlanes% = 4          ' Set default values for SCREEN 12
      ScreenWidth% = 640 : ScreenLength% = 480
      SELECT CASE scrn%       ' Change values for other SCREEN modes
         CASE 7
            ScreenWidth% = 320 : ScreenLength% = 200
         CASE 8
            ScreenLength% = 200
         CASE 9
            ScreenLength% = 350
         CASE 10
            NumPlanes% = 2 : ScreenLength% = 350
         CASE 11
            NumPlanes% = 2
      END SELECT
    END SUB

    SUB VGAtoEpson (scrn%, fileN$, flip%, border%) STATIC
    ' Sends the image on SCREEN 7, 8, 9, 10, 11 or 12
    ' to an Epson printer.
    ' Parameters:
    '    scrn%   - SCREEN video mode of screen to print (7 through 12)
    '    fileN$  - Name of file or device to send image to
    '    flip%   - Invert flag (0 = normal, not 0 = invert)
    '    border% - Character to use for border drawing on screens
    '              9 and 10 (0 = none, 255 = solid, etc.)
      OPEN fileN$ FOR BINARY AS 1            'Open the output file
      WIDTH #1, 255
      esc$ = CHR$(27) : crlf$ = CHR$(13) + CHR$(10)
      line$ = esc$ + "A" + CHR$(8)           'Set printer to 8/72 lpi"
      PUT #1, , line$
      CALL ScreenParams(scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)

      IF ScreenLength% < 480 THEN       ' Figure how many bytes to send
         numbyte% = ScreenLength% * 2 + 16   ' to printer for one
         maxy% = ScreenLength% - 1           '  line of graphics.
      ELSE
         numbyte% = 960 : maxy% = 479
      END IF

      DEF SEG = &HA000               'Start of EGA/VGA screen memory
      BorderOffset% = (960 - numbyte%) / (2 * 8)
      IF ScreenLength% < 480 THEN
         ' Print top line for border on screens where border will fit
         line$ = SPACE$(BorderOffset%)           '(for margin)
         PUT #1, , line$
         line$ = esc$ + "L" + MKI$(numbyte%)
         line$ = line$ + STRING$(numbyte%, border%) + crlf$
         PUT #1, , line$
      END IF

      ' This loop is the horizontal byte location
      colend% = (ScreenWidth% / 8) - 1
      FOR col% = 0 TO colend%
        ' Set the printer up to receive 716 or 960 bytes
        ' of graphics data
        IF ScreenLength% < 480 THEN
           line$ = SPACE$(BorderOffset%)
           PUT #1, , line$  '(for border)
        END IF

        line$ = esc$ + "L" + MKI$(numbyte%)  '(for init)
        PUT #1, , line$
        IF ScreenLength% < 480 THEN
           line$ = STRING$(8, border%)
           PUT #1, , line$    '(for border)
        END IF

        '--- This loop is the vertical byte position
        FOR row% = maxy% TO 0 STEP -1
          ' For 4 plane screens (7, 8, 9 and 12) logically OR the blue
          ' plane with the red plane, send that byte, then OR the green
          ' plane with the intensity plane and send that byte.

          ' For screens 10 and 11, the video planes are sent directly
          ' to the printer.
          FOR plane% = 0 TO 1                'Plane (* 2) set
            OUT &H3CE, 4 : OUT &H3CF, plane%
            place& = row%                   'Figure out screen memory
            place& = place& * (colend% + 1) ' location to read - use
            place& = place& + col%          ' a long to avoid overflow.
            mem% = PEEK(place&)

            IF NumPlanes% = 4 THEN ' OR color planes together
               OUT &H3CE, 4 : OUT &H3CF, plane% + 2
               mem% = mem% OR PEEK(place&)
            END IF

            '--- Flip the byte if need be (inverses printed picture)
            IF flip% <> 0 THEN mem% = 255 - mem%
            line$ = CHR$(mem%) : PUT #1, , line$
          NEXT plane%
        NEXT row%

        line$ = crlf$    ' Default for no border
        IF ScreenLength% < 480 THEN
           line$ = STRING$(8, border%) + crlf$   ' Righthand border
        END IF
        PUT #1, , line$
      NEXT col%

      IF ScreenLength% < 480 THEN     '--- Print bottom line for border
         line$ = SPACE$(BorderOffset%)       '(for margin)
         PUT #1, , line$
         line$ = esc$ + "L" + MKI$(numbyte%)
         line$ = line$ + STRING$(numbyte%, border%) + crlf$
         PUT #1, , line$
      END IF
      ResetPrn$ = esc$ + "@"
      PUT #1, , ResetPrn$                 ' Reset printer
      line$ = CHR$(12) : PUT #1, , line$  ' Send formfeed (page eject)
      CLOSE 1                             ' All done
    END SUB


 455. How to Solve Common QuickBASIC Communications Port Problems

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  9-AUG-1990    ArticleIdent: Q39342

 This article outlines troubleshooting advice for using serial
 communications in QuickBASIC versions 4.00, 4.00b, and 4.50, in
 Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10.

 This article gives a sample OPEN COM statement that should work
 correctly. Additional communications troubleshooting hints are also
 given. For a related article, query in this Knowledge Base on the
 following words:

    "COM1:" and "COM2:" and error and message and explanations

 If you have problems using "COM1:" or "COM2:", try the following OPEN
 statement, which makes BASIC as tolerant as possible of
 hardware-related problems:

    OPEN "COM1:300,N,8,1,BIN,CD0,CS0,DS0,OP0,RS,TB2048,RB2048" AS #1

 (This OPEN is FOR RANDOM access.) The following is an explanation of
 each recommended parameter used in this OPEN statement:

 1. The higher the baud rate, the greater the chances for problems;
    thus, 300 baud is unlikely to give you problems. 2400 baud is
    the highest speed possible over most telephone lines, due to
    their limited high-frequency capability. 19,200 baud, which
    requires a direct wire connection, is most likely to cause
    problems. (Possible baud rates for QuickBASIC are 75, 110, 150,
    300, 600, 1200, 1800, 2400, 4800, 9600, and 19,200.)

 2. Parity usually does not help you significantly; because of this,
    you should try No parity (N).

    For those devices that require parity, you should use the PE option
    (Parity Enable) in the OPEN COM statement, which is required to
    turn on parity checking. When the PE option turns on parity
    checking, a "Device I/O error" occurs if the two communicating
    programs have two different parities. (Parity can be Even, Odd,
    None, Space, or Mark). For example, a "Device I/O error" occurs
    when two programs try to talk to each other across a serial line
    using the following two different OPEN COM statements:

       OPEN "COM1:1200,O,7,2,PE" FOR RANDOM AS #1

    and

       OPEN "COM2:1200,E,7,2,PE" FOR RANDOM AS #2

    If the PE option is removed from the OPEN COM statements above, no
    error message displays.

 3. The above example uses 8 data bits and 1 stop bit. Eight data bits
    requires No parity (N), because of the size limit for BASIC's
    communications data frame (10 bits).

 4. The BIN (binary mode) is the default. Note: The ASC option does NOT
    support XON/XOFF protocol, and the XON and XOFF characters are
    passed without special handling.

 5. Ignoring hardware handshaking often corrects many problems. Thus,
    if your application does not require handshaking, you should try
    turning off the following hardware line-checking:

       CD0 = Turns off time-out for Data Carrier Detect (DCD) line
       CS0 = Turns off time-out for Clear To Send (CTS) line
       DS0 = Turns off time-out for Data Set Ready (DSR) line
       OP0 = Turns off time-out for a successful OPEN

 6. RS suppresses detection of Request To Send (RTS).

 7. For buffer-related problems, try increasing the transmit and
    receive buffer sizes above the 512-byte default:

       TB2048 = Increases the transmit buffer size to 2048 bytes
       RB2048 = Increases the receive buffer size to 2048 bytes

    A larger receive buffer can help you work around BASIC delays
    caused by statements like PAINT, which use the processor
    intensively.

 The following are additional important hints for troubleshooting
 communications problems:

 1. You should use the INPUT$(x) function in conjunction with the
    LOC(n) function to receive all input from the communications
    device (where "x" is the number of characters returned by LOC(n),
    which is the number of characters in the input queue waiting to be
    read. "n" is the file number that you OPENed for "COM1:" or
    "COM2:").

    Avoid using the INPUT#n statement to input from the communications
    port because INPUT#n waits for a carriage return (ASCII 13)
    character.

    Avoid using the GET#n statement for communications because GET#n
    waits for the buffer to fill (and buffer overrun could then occur).

    Also, avoid using the PUT#n statement for communications, and use
    the PRINT#n statement instead. For example, in QuickBASIC 4.00b and
    4.50, in BASIC Compiler 6.00 and 6.00b, and in BASIC PDS 7.00 and
    7.10, using the PUT#n,,x$ syntax for sending a variable-length
    string variable as the third argument of the PUT#n statement sends
    an extra 2 bytes containing the string length before the actual
    string. These 2 length bytes sent to the communications port may
    confuse your receiving program if it is not designed to handle
    them. No length bytes are sent with PUT#n,,x$ in QuickBASIC 4.00.
    (QuickBASIC versions earlier than 4.00 don't offer the feature to
    use a variable as the third argument of the PUT#n statement.)

 2. For an example of data communications, please refer to the
    TERMINAL.BAS sample program that comes on the release disk for
    QuickBASIC versions 4.00, 4.00b, and 4.50, for Microsoft BASIC
    Compiler versions 6.00 and 6.00b, and for Microsoft BASIC
    Professional Development System (PDS) versions 7.00 and 7.10.
    Many communications problems may actually be due to inappropriate
    source code design and flow of control.

 3. Many communications problems can only be shown on certain hardware
    configurations and are difficult to resolve or duplicate on other
    computers. We recommend experimenting with a direct connection
    (with a short null-modem cable) instead of with a phone/modem link
    between sender and receiver to isolate problems on a given
    configuration.

 4. The wiring schemes for cables vary widely. Check the pin wiring on
    your cable. For direct cable connections, a long or high-resistance
    cable is more likely to give problems than a short, low-resistance
    cable.

 5. If both "COM1:" and "COM2:" are open, "COM2:" will be serviced
    first. At high baud rates, "COM1:" can lose characters when
    competing for processor time with "COM2:".

 6. Using the ON COM GOSUB statement instead of polling the LOC(n)
    function to detect communications input can sometimes work around
    timing or buffering problems caused by delays in BASIC. Delays in
    BASIC can be caused by string-space garbage collection, PAINT
    statements, or other operations that heavily use the processor.

 Many commercial communications programs use sophisticated techniques
 not found in Microsoft BASIC and may give better performance.

 If you need better communications performance than you are getting
 through BASIC, you may want to try Microsoft C. (You can call
 Microsoft C routines from Microsoft QuickBASIC 4.00, 4.00b, and 4.50,
 from Microsoft BASIC Compiler 6.00 and 6.00b, and from Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10.) The
 following is an excellent reference:

    "C Programmer's Guide to Serial Communications"
    by Joe Campbell, published by Howard W. Sams & Company.

 QuickBASIC 3.00, 4.00, 4.00b, and 4.50 implement communications by
 direct interrupts to the IRQ3 and IRQ4 input lines on the 8259
 controller chip (instead of invoking BIOS interrupts).

 The following book gives an excellent technical, hardware-level
 description of serial communications for the IBM PC:

    "8088 Assembler Language Programming: The IBM PC" Second Edition by
    Willen & Krantz, published by Howard W. Sams & Co. (1983, 1984).
    Pages 92-93, and Chapter 7 (Pages 166 to 188).


 456. QuickBASIC Compile Errors Not Given in M.EXE Editor; No BC /Z

 Product Version(s): 1.00 1.01 1.02 2.00 2.10 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881213-16 B_BasicCom S_Editor
 Last Modified:  4-SEP-1990    ArticleIdent: Q39362

 QuickBASIC versions 1.x, 2.x, 3.00, 4.00, 4.00b, and 4.50 do not
 generate the error message format necessary for the Microsoft Editor
 (M.EXE). You can compile programs from within the M.EXE Editor, but
 return code 4 (which is an ARG COMPILE return code stating an error
 occurred) will not give the error message inside the M.EXE Editor
 program.

 Note: The Microsoft M.EXE Editor is not provided with the QuickBASIC
 package. The Microsoft Editor is provided with Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2, with
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS and MS OS/2, and with some Microsoft system languages.

 The BC.EXE environment that comes with QuickBASIC versions 4.50 and
 earlier does not allow the /Z option, which produces the proper error
 message format for the M.EXE Editor. However, the /Z option is
 supported by the BC.EXE environment provided with Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS and OS/2. Adding the
 following line to the TOOLS.INI file under section [M] will allow the
 BC.EXE version 6.00 or 6.00b environment to be used from within the
 M.EXE Editor:

    EXTMAKE:BAS BC /Z %|F;

 If this EXTMAKE line is in the TOOLS.INI and ARGCOMPILE is set to F5
 (ARGCOMPILE:F5) in the TOOLS.INI file, pressing F5 while editing BASIC
 source code in the M.EXE Editor causes BC.EXE to be invoked. If BC.EXE
 finds errors, they are returned correctly to the M.EXE Editor and the
 cursor is placed on the first error.


 457. QCARDS Code Entry 19 Correction; Press SHIFT+F6 Once

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 21-DEC-1988    ArticleIdent: Q39367

 The correction below applies to Page 120 of the "Learning to Use
 Microsoft QuickBASIC Version 4.50" manual.

 Under QCARDS Code Entry 19 (Page 120), Step 1 incorrectly states the
 following:

    Press SHIFT+F6 twice.

 It should say the following:

    Press SHIFT+F6 once.


 458. QuickBASIC Program to Rotate Characters and Graphic Images

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881213-23
 Last Modified:  4-SEP-1990    ArticleIdent: Q39368

 The subprogram below rotates two-dimensional graphic images. It takes
 as parameters the upper-left and lower-right corners of the region to
 rotate, and the number of degrees to rotate the picture.

 It also includes a subprogram that returns the upper-left corner of an
 ASCII-printed character for those who wish to rotate individual
 characters on the screen.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS; and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The character rotation will perform correctly only if the coordinate
 system is not altered (such as with the WINDOW statement).

 To rotate larger areas, compile with /ah.

 The program works correctly on screen modes 1, 2, 3 (Hercules), 7, 8,
 and 9. It can be expanded to support modes 10, 11, and 12 by changing
 the FindCharPos routine to include those screens.

 The more complex the image, the slower the program will run.

 The following is a code example:

 ' This program is provided as is. No guarantees about performance
 ' or support are implied.
 DECLARE SUB FindCharPos (row%, col%, gx%, gy%, screenmode%)
 DECLARE SUB RotatePic (ulx%, uly%, lrx%, lry%, deg!)
 DECLARE SUB RotatePoint (p!(), deg!)
 DECLARE SUB TranslatePoint (p!(), xdist!, ydist!)
 DECLARE SUB MatrixMult (p!(), t!())

 CLS
 INPUT "Enter Screen Mode (1, 2, 3, 7, 8, or 9) : ", screenmode%
 INPUT "Enter a Rotation (in Degrees) : ", r

 SCREEN screenmode%

 '** Rotating a Portion of a Picture **
 FOR row = 10 TO 150 STEP 10
   LINE (10, row)-(150, row)
 NEXT row
 CALL RotatePic(55, 55, 100, 100, r)
 LOCATE 20
 INPUT "Press Enter to Continue", k$

 '** Rotating a Character **
 CLS
 textRow% = 10
 textCol% = 5
 LOCATE textRow%, textCol%
 PRINT "H"
 CALL FindCharPos(textRow%, textCol%, gx%, gy%, screenmode%)

 IF screenmode% = 3 OR screenmode% = 9 THEN  'Characters are 8x14
   CALL RotatePic(gx%, gy%, gx% + 8, gy% + 14, r)
 ELSE                                        'Characters are 8x8
   CALL RotatePic(gx%, gy%, gx% + 8, gy% + 8, r)
 END IF

 LOCATE 20
 INPUT "Press Enter ", k$

 SCREEN 0    '* Restore Screen *

 ' * ----------------------------------------------------------- *

 SUB FindCharPos (row%, col%, gx%, gy%, screenmode%)
 '* Translates character coordinates to graphics coordinates. *
 '* Returns the upper left corner of the character box.       *

   SELECT CASE screenmode%
     CASE 1 TO 2
       gx% = col% * 8 - 9
       gy% = row% * 8 - 9
     CASE 3             ' * Hercules *
       gx% = col% * 8 + 1
       gy% = row% * 14 - 14
     CASE 7 TO 8
       gx% = col% * 8 - 9
       gy% = row% * 8 - 9
     CASE 9
       gx% = col% * 8 - 8
       gy% = row% * 14 - 14
     CASE ELSE
       PRINT "Error in Screen Mode Setting - FindCharPos"
   END SELECT
 END SUB

 SUB MatrixMult (p!(), t!())
 '* Multiply 1x4 array with a 4x4 array *

   DIM r(1 TO 3) AS SINGLE

   FOR i = 1 TO 3
     r(i) = (p!(1) * t!(1,i)) + (p!(2) * t!(2,i)) + (p!(3) * t!(3,i))
   NEXT i
   FOR i = 1 TO 3
     p!(i) = r(i)
   NEXT i
 END SUB

 SUB RotatePic (ulx%, uly%, lrx%, lry%, deg!)
 ' * This Program will scan any picture and replace it    *
 ' * with a rotated version in the current foreground and *
 ' * background colors.                                   *
 ' * To rotate larger pictures, compile with /ah.         *

   REM $DYNAMIC
   DIM p(1 TO 3) AS SINGLE

   xspan = lrx% - ulx%
   yspan = lry% - uly%
   IF FRE(-1) < (xspan * yspan * 2 * 2) THEN  '* Enough memory? *
     PRINT "Area too large to rotate"
     EXIT SUB
   ELSE
     DIM rotArea(1 TO xspan, 1 TO yspan, 1 TO 2) AS INTEGER
   END IF

   FOR i = 0 TO xspan - 1
     FOR j = 0 TO yspan - 1
       IF POINT(i + ulx%, j + uly%) <> 0 THEN
         PSET (i + ulx%, j + uly%), 0
         p(1) = i + ulx%
         p(2) = j + uly%
         p(3) = 1
         CALL TranslatePoint(p(), CSNG(-ulx%) - (xspan / 2),_
                                  CSNG(-uly%) - (yspan / 2))
         CALL RotatePoint(p(), deg!)
         CALL TranslatePoint(p(), CSNG(ulx%) + (xspan / 2),_
                                  CSNG(uly%) + (yspan / 2))
         rotArea(i + 1, j + 1, 1) = p(1)
         rotArea(i + 1, j + 1, 2) = p(2)
       END IF
     NEXT j
   NEXT i

   FOR i = 1 TO xspan
     FOR j = 1 TO yspan
       PSET (rotArea(i, j, 1), rotArea(i, j, 2))
     NEXT j
   NEXT i
 END SUB

 REM $STATIC
 SUB RotatePoint (p!(), deg!)
 '* Set up the rotation matrix and multiply with the point. *

   CONST PI = 3.14159

   DIM RotMatrix(1 TO 3, 1 TO 3) AS SINGLE

   radians! = deg! * PI / 180

   RotMatrix(1, 1) = COS(radians!)
   RotMatrix(1, 2) = SIN(radians!)
   RotMatrix(2, 1) = -SIN(radians!)
   RotMatrix(2, 2) = COS(radians!)
   RotMatrix(3, 3) = 1

   CALL MatrixMult(p!(), RotMatrix())
 END SUB

 SUB TranslatePoint (p!(), xdist!, ydist!)
 '* Set up the translation matrix and multiply with the point. *

   DIM t(1 TO 3, 1 TO 3) AS SINGLE

   t(1, 1) = 1
   t(2, 2) = 1
   t(3, 3) = 1
   t(3, 1) = xdist!
   t(3, 2) = ydist!

   CALL MatrixMult(p!(), t())
 END SUB


 459. Amount of RAM Required by QUICKBASIC Applications

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881208-10 B_BasicCom
 Last Modified: 21-DEC-1988    ArticleIdent: Q39377

 The amount of RAM required by a QuickBASIC program varies depending on
 how the program is compiled. As a rule, the MINIMUM load size of a
 program is approximately the size of the .EXE file. If the program
 requires the run-time module (BRUNXX.EXE), an additional 76K or so is
 taken by the run-time module.

 Once the program is loaded, additional RAM may be required for dynamic
 allocation. This includes file buffers, dynamic arrays, and
 variable-length strings.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00B and 4.50, and the BASIC Compiler Versions 6.00 and
 6.00B.

 The EXEMOD.EXE utility shipped with the BASIC Compiler Versions 6.00
 and 6.00B can be used to determine the minimum load size of an .EXE
 file. The utility is also shipped with Microsoft C, Microsoft Fortran,
 Microsoft Pascal and Microsoft Macro Assembler.


 460. "Formal Parameter Specification Illegal" for DECLARE Variable

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881208-34
 Last Modified: 21-DEC-1988    ArticleIdent: Q39378

 The BC.EXE compiler generates a "Formal parameter specification
 illegal" error when a DECLARE statement uses a variable that is the
 same name as a FUNCTION or SUB previously declared in the program.
 The QB.EXE editor will not generate an error for the same DECLARE
 statement.

 In general, you should never have any variables with the same name as
 any other identifier in your programs. You should also avoid having
 any two variables or identifiers that only differ by the data type
 specifier. For example A$ and A% are poor choices for variable names
 in the same program.

 This information applies to Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50, and to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2.

 The DECLARE statement is only used as a prototype for checking the
 number and types of the arguments used to invoke the procedures, and
 it affects the entire module. The type of the variables can be
 INTEGER, LONG, SINGLE, DOUBLE, STRING, or a user-defined type.
 Fixed-length strings (STRING*n) cannot be used in a DECLARE statement,
 because only variable-length strings can be passed to SUB and FUNCTION
 procedures.

 More information about the DECLARE statement can be found in the
 "Microsoft QuickBASIC: BASIC Language Reference" manual (on pages
 139-146 for QuickBASIC Versions 4.00 and 4.00b; pages 55-56, 271, 299,
 and 332- 333 for QuickBASIC Version 4.50; and pages 139-146 for BASIC
 Compiler Versions 6.00, and 6.00b).

 The following is a code example:

 DECLARE FUNCTION test% (Num%)
 DECLARE SUB ShowTest (test%)   ' This will generate an error
 A = test%(10)
 ShowTest (A)
 END

 SUB ShowTest (Var%)
     PRINT Var%
 END SUB

 FUNCTION test% (Num%)
     test% = Num%
 END FUNCTION

 The following error is generated for the above program:

 Microsoft (R) QuickBASIC Compiler Version 4.50
 (C) Copyright Microsoft Corporation 1982-1988.
 All rights reserved.
 Simultaneously published in the U.S. and Canada.
  0030   0006    DECLARE SUB ShowTest (test%)
                                       ^ Formal parameter
                                         specification illegal

 43869 Bytes Available
 43355 Bytes Free

     0 Warning Error(s)
     1 Severe  Error(s)


 461. QB.EXE 4.50 "Binding..." then Hang If SWAP User-TYPE Strings

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S881206-72
 Last Modified: 24-MAR-1989    ArticleIdent: Q39379

 SWAPping two string variables that are fields of a user-defined type
 can display the "Binding..." message and then hang the QuickBASIC
 QB.EXE Version 4.50 editor. Hanging does not happen SWAPping
 non-user-defined type strings or other types of variables. The hanging
 does not occur in programs compiled with BC.EXE Version 4.50, it is
 just a QB.EXE editor problem.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available.

 QB.EXE Versions 4.00 and 4.00b do not have this problem.

 Putting the TYPE variables in either $DYNAMIC or $STATIC arrays still
 hangs. If an INTEGER or DOUBLE appears in the record before the string
 field that is being swapped, then you can usually warm reboot,
 otherwise it usually requires a cold reboot. Other variables such as
 floating point or other TYPES do not prevent the cold reboot. Which
 String is swapped (1-5) in the following record makes no difference.

 Swapping any non-string type of field in a user-defined record does
 not hang the computer. Swapping both variable- and fixed-length
 strings as single variables (not in record) also does not hang the
 computer.

 The following code demonstrates the problem:

    TYPE rectype
       num1 AS INTEGER
       string1 AS STRING * 16
       string2 AS STRING * 16
       string3 AS STRING * 16
       string4 AS STRING * 16
       string5 AS STRING * 16
    END TYPE
    DIM var1  AS rectype, var2 AS rectype
    var1.string1 = "String1"
    var2.string1 = "String2"
    SWAP var1.string1, var2.string1
    ' The QB.EXE environment will freeze up at this SWAP statement.

 To work around the problem, use a standard swapping technique with two
 variables and a temporary variable:

    DIM var1 as rectype, var2 as rectype, temp as rectype
    temp.string1 = var1.string1      ' 1. a -> temp
    var1.string1 = var2.string1      ' 2. b -> a
    var2.string1 = temp.string1      ' 3. temp -> b


 462. GET with BINARY File Fills String with NULL Bytes at EOF

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881214-12
 Last Modified: 21-DEC-1988    ArticleIdent: Q39380

 Using the GET #n statement with a file that has been opened for BINARY
 will fill the last bytes of an existing input string (which is the
 third parameter of GET) with NULLs. This only occurs if the length of
 the existing string exceeds the number of bytes between the file
 pointer (before the GET) and the end of file. This behavior applies to
 both fixed-length and variable-length string variables.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, and to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2. (Earlier versions do not have a third parameter for
 the GET#n statement, and are not affected.)

 The example program below demonstrates how this occurs. If TestString$
 = "123456789012345" and TEST.DAT is a text file OPENed in BINARY
 containing only the string "TEST", the following GET statement will
 alter TestString$ such that it contains the string "TEST" and 11 NULL
 bytes.

 The following is a code example:

 CLS
 OPEN "TEST.DAT" FOR BINARY AS #1
 TestString$ = "123456789012345"
 PRINT "ASCII dump of string BEFORE GET from small file"
 FOR i = 1 TO 15: PRINT ASC(MID$(TestString$, i, 1)); : NEXT i
 GET #1, 1, TestString$   ' This GET requires QuickBASIC 4.x
 PRINT "ASCII dump of string AFTER GET from small file"
 FOR i = 1 TO 15: PRINT ASC(MID$(TestString$, i, 1)); : NEXT i
 END

 The output is as follows:

 ASCII dump of string BEFORE GET from small file
 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53
 ASCII dump of string AFTER GET from small file
 84 69 83 84 0 0 0 0 0 0 0 0 0 0 0


 463. BASIC Supports MASM 5.10 Update .MODEL and PROC Extensions

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881213-30
 Last Modified: 21-DEC-1988    ArticleIdent: Q39381

 The Microsoft Macro Assembler Version 5.10 includes several new
 features (not found in MASM Version 5.00 or earlier) that simplify
 assembly-language routines linked with high-level language programs
 Two of these features are as follows:

 1. An extension to the .MODEL directive that automatically sets up
    naming, calling, and return conventions for a given high-level
    language; for example, .MODEL MEDIUM,BASIC

 2. A modification of the PROC directive that handles most of the
    procedure entry automatically. The PROC directive saves specified
    registers, defines text macros for passed arguments, and generates
    stack setup code on entry and stack tear-down code on exit.

 These new features are supported by QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and the Microsoft BASIC Compiler Versions 6.00 and 6.00b.

 Section 5 of the "Microsoft Macro Assembler 5.1: 5.1 Update" manual
 discusses the new features.

 Page 332 of the "Microsoft QuickBASIC Version 4.00: Learning and Using
 QuickBASIC" manual provides an example of an assembly-language
 function called by BASIC. The example from Page 332 is modified below
 to demonstrate the new features in the Microsoft Macro Assembler
 Version 5.10.

 Compile and Link Instructions are as follows:

    BC power.bas;
    MASM power.asm,powera;
    LINK power + powera;

 The following is the BASIC Program, POWER.BAS, which invokes the
 assembly language function POWER2:

    DEFINT A-Z
    DECLARE FUNCTION power2 (x%, y%)
    PRINT power2(3, 5)
    END

 The following is POWER2.ASM, an example of using the extended .MODEL
 and .PROC directives in MASM 5.10:

 .model medium,BASIC  ;Adds the language option ",BASIC"
 .code
                      ;PUBLIC directive was removed. The label on
                      ;the PROC directive is now the function name.
 Power2 PROC arg1:word, arg2:word  ;parameters added to PROC

    ;Note: PUSH BP and MOV BP,SP are no longer needed.
    ;The arguments are refered to by the names supplied on the
    ;PROC list instead of their offset from BP (Base Pointer):
        mov   bx,arg1
        mov   ax,[bx]
        mov   bx,arg2
        mov   cx,[bx]
        shl   ax,cl
    ;Note, POP BP is no longer needed.
        ret      ;RET is used now, instead of RET n, (where n is
                 ;two times the number of passed arguments.)
 Power2 endp
        end

 For comparison, the following is the equivalent, earlier (MASM Version
 5.00) form for POWER2.ASM, taken from Page 332 of "Learning and Using
 QuickBASIC" (for Versions 4.00 and 4.00b, and BASIC Compiler Versions
 6.00 and 6.00b):

 .model medium
 .code
        PUBLIC Power2
 Power2 PROC
        PUSH  BP
        MOV   BP,SP        ; Set stack framepointer
        mov   bx,[bp+8]    ; Load Arg1 into
        mov   ax,[bx]      ;   AX
        mov   bx,[bp+6]    ; Load Arg2 into
        mov   cx,[bx]      ;   CX
        shl   ax,cl        ; AX = AX * (2 to power of CX)
                           ; Leave return value in AX
        POP   BP           ; Exit sequence -- restore old BP
        ret   4            ; Return and restore 4 bytes.
 Power2 endp
        end


 464. QuickBASIC 4.50 QB.EXE Does Not Allow CTRL+P, ESC Sequence

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881209-34 buglist4.50
 Last Modified: 21-DEC-1988    ArticleIdent: Q39382

 The QuickBASIC Version 4.50 editor will not allow you to insert the
 escape key code (ASCII 27) into a BASIC program by pressing CTRL+P
 followed by either ESC or CTRL+[.

 Note: QB.EXE Versions 4.00 and 4.00b do allow you to type a CTRL+P
 followed by either ESC or CTRL+[ and thereby insert a CHR$(27) byte
 into either a REMark or a quoted string.


 465. INPUT to Out of Range Array Element Can Hang; or Bad Value

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 B_BasicCom
 Last Modified: 21-DEC-1988    ArticleIdent: Q39384

 When an array element in an INPUT statement is out of range, the
 QuickBASIC editor may hang, instead of producing a "Subscript out of
 range" error message. (The problem occurs when the program explicitly
 dimensions the array or uses the default values.)

 The program also fails if compiled to an executable file. If compiled
 with the DEBUG option /d, the program will hang, similar to the
 QuickBASIC editor. Without the /d option, the results will vary from
 incorrect values being displayed to the machine hanging.

 This information applies to QuickBASIC Version 4.00 and 4.00b, and the
 BASIC Compiler Version 6.00 and 6.00b (buglist6.00, buglist6.00B). This
 problem was corrected in QuickBASIC Version 4.50.

 To work around the problem you should avoid assigning array elements
 that are outside of the allowed range.

 The following two code examples demonstrate the problem:

 REM *** EXAMPLE 1: Using the DEFAULT array size limits, 0 to 10
 FOR a = 1 TO 20
     INPUT "ENTER NUMBER "; b(a)
 NEXT a

 REM *** EXAMPLE 2: Using DIM statement to explicitly set limits
 DIM b(10)
 FOR a = 1 TO 20
     INPUT "ENTER NUMBER "; b(a)
 NEXT a


 466. Error Message Explanations When Using "COM1:" and "COM2:"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 10-AUG-1990    ArticleIdent: Q39386

 The following error messages can appear when using the "COM1:" or
 "COM2:" device:

    Error Message                     Number
    -------------                     ------

    File Already OPEN                 (Error 55)
    Bad File Name or Number           (Error 52)
    Out of Memory                     (Error 7)
    Device Unavailable                (Error 68)
    Device I/O Error                  (Error 57)
    Communications Buffer Overflow    (Error 69)
    Device Timeout                    (Error 24)

 This article gives the logic used to determine when to display these
 errors during OPEN, INPUT, OUTPUT, and other statements when using the
 "COM1:" or "COM2:" device. This information applies to Microsoft
 QuickBASIC versions 4.00, 4.00b, and 4.50 and to Microsoft BASIC
 Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2. For a related
 article concerning how to solve common communications port problems,
 search for the following words in this Knowledge Base:

    solve and "com1:" and port and problems

 The OPEN "COM1:" or OPEN "COM2:" statement uses the following logic,
 in order of execution, to check for errors:

 1. Check if <device number> was OPEN previously in the program. "File
    Already OPEN" displays if <file number> is already open.

 2. Parse the options used in the OPEN "COM1:" or OPEN "COM2:"
    statement. "Bad File Name or Number" displays if any of the
    following are true:

    a. Baud rate is not numeric or over 65,535

    b. Parity is not N, O, E, M, or S

    c. Data bits are not 5, 6, 7, 8

    d. Data bits are 8 and parity is O, E, M, or S

    e. Stop bits are not 1 or 2 (1.5 is not supported)

    f. One of the following arguments is misspelled (order is not
       significant for these; "m" can be null or a number from 0 to
       65,535 milliseconds; buffersize "x" can be up to 32,767 bytes):

             OPm, DSm, CSm, CDm, RBx, TBx, RS, LF, BIN, ASC

 3. Allocate transmit and receive buffers. "Out of Memory" displays if
    no room is left for buffers in the default data segment.

 4. Initialize device interface.

    a. "Bad File Name" displays when using anything other than "COM1:"
       or "COM2:" or when using a baud rate not equal to 75, 110, 150,
       300, 600, 1200, 1800, 2400, 4800, 9600, or 19,200.

    b. "Device Unavailable" displays if the communications interface is
       already in use or does not exist (according to the 4 bytes at
       400 hex in low PC memory).

       If no errors have occurred at this point in the OPEN, the baud
       rate, data size, parity, and stop bits are now set. DTR is set.
       RTS is set if the RS option is not specified. If you use the OPn
       (OPEN time-out) option, Item 4c (below) applies.

    c. "Device I/O Error" displays if an OPn OPEN time-out occurs after
       waiting for DSR (Data Set Ready) or DCD (Data Carrier Detect).

       (Note: QuickBASIC versions 2.00, 2.01, and 3.00 use the DSn and
       CDn options for DSR and DCD time-out instead of the later
       versions 4.00, 4.00b, and 4.50 OPn option.)

 Compiled BASIC uses the following logic during INPUT from "COM1:" or
 "COM2:":

 1. Check for errors.

    a. "Communications Buffer Overflow" displays for receive (or
       transmit) buffer overflow.

    b. "Device I/O Error" displays for any of the following conditions:

          Condition       Description
          ---------       -----------

          break           A special line condition where line voltage
                          is held "on" (sending 1 bit, which is
                          between -25 and -3 volts) over more than 10
                          bit-times. (Note that "off" means a 0 bit,
                          which is between +3 and +25 volts).

          parity error    Can occur if line is noisy, or the wrong baud
                          or parity is being used.

          overrun error   The character (a 10-bit data frame) was not
                          read from the interface hardware in time
                          before it was overwritten by the next
                          received character.

          framing error   The bit to be interpreted as the stop bit was
                          not 0. A framing error can occur if the line
                          is noisy, if the wrong baud rate is used, or
                          if the clock speeds on the communicating PCs
                          are mismatched.

    c. "Device Timeout Error" displays if a CTS, DSR, or DCD time-out
       occurs.

 2. If no errors occurred, get next character from receive buffer. If
    none, then loop.

 Compiled BASIC uses the following logic during OUTPUT to "COM1:" or
 "COM2:":

 1. Check for errors. (Same as for INPUT above.)

 2. Test if transmit buffer is full. If full, loop back to 1.

 3. Put character into buffer.

 The LOC(n) function does the following when used with "COM1:" or
 "COM2:":

 1. Check for errors. (Same as for INPUT above.)

 2. LOC(n) returns the number of characters currently in the receive
    buffer.

 The LOF(n) function does the following when used with "COM1:" or
 "COM2:":

 1. Check for errors. (Same as for INPUT above.)

 2. LOF(n) returns the room left in the TRANSMIT buffer in QuickBASIC
    versions 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler
    versions 6.00 and 6.00b for MS-DOS and MS OS/2.

    LOF(n) returns the room left in the RECEIVE buffer in QuickBASIC
    versions 1.00, 1.02, 2.00, 2.01, and 3.00.

 BASIC uses the following logic when you CLOSE the "COM1:" or "COM2:"
 device:

 1. Transmit output. If using the ASC option (and not the BIN option),
    transmit an end-of-file (EOF) character (CTRL+Z).

 2. Wait for pending output to finish or time-out.

 3. Restore interrupt vectors.

 4. Deallocate transmit and receive buffers from BASIC's default data
    segment.

 5. Report any pending errors.


 467. DRAW "Illegal Function Call" In .EXE Compiled with BC /D

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom ptm226
 Last Modified: 10-APR-1989    ArticleIdent: Q39577

 The program example below will draw a large number 1 on the screen.
 This program works correctly under QB.EXE and as a .EXE program when
 compiled WITHOUT the debug option.

 The program causes an "Illegal function call" at run time if compiled
 using the debug option (BC /D). The program can be modified to work
 correctly by using a single variable-length string instead of an
 element of a variable-length string array, i.e., B$ instead of A$(x)
 and by not using the VARPTR$ FUNCTION.  The following two statements
 will execute identically:

                           DRAW "X" + VARPTR$(A$(1))
                           DRAW A$(1)

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in the BASIC Compiler Versions 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and OS/2. The program
 works correctly in QuickBASIC Version 3.00. We are researching this
 problem and will post new information as it becomes available.

 The following is a code example:

 DIM a$(65)
 a$(17) = "BU6BR2NG1D6L1R2BR4"
 SCREEN 1
 DRAW "BM52,52;s24;c1"
 DRAW "x" + VARPTR$(a$(17))
 INPUT x$
 END


 468. CHR$(0) PRINTs As Space to Screen; LPRINTs Nothing to Printer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881212-23
 Last Modified: 21-DEC-1988    ArticleIdent: Q39578

 CHR$(0) (a null byte) is a non-printable character in MS-DOS. However,
 the PRINT and PRINT USING statements in BASIC print this character as
 a space.

 Sending CHR$(0) to the following MS-DOS logical device names will
 print nothing:

   "CONS:"
   "LPTn:"
   "COMn:"
   "SCRN:"

 Likewise, printing CHR$(0) with the LPRINT or LPRINT USING statements
 sends nothing.

 Fixed-length strings are initialized to null bytes. Printing these
 fixed-length strings to the screen and to the printer will give
 different column alignment. This difference can be circumvented by
 using the STRING$() function to initialize the fixed length string
 with spaces.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, and to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2.

 The following is a code example:

 'The following piece of code will print an uninitialized fixed-length
 'string to the screen and printer using the PRINT and LPRINT
 'statements. Unless the STRING$() function is used to fill the
 'fixed-length string with spaces, the hard copy and screen will show
 'different column alignment.
 TYPE aType
   Field1 AS STRING * 32    ' a fixed length string
 END TYPE
 DIM aVariable AS aType
 CLS
 ' Comment out the following line to cause different column alignment
 ' between LPRINT and PRINT; otherwise columns will line up the same:
 aVariable.Field1 = STRING$(32, " ")

 ' Use LPRINT:
 FOR i = 1 TO 10: LPRINT : NEXT i
 LPRINT "printing aVariable.Field1 to printer with 'xxxx' following"
 LPRINT "1234567890123456789012345678901234567890"
 LPRINT aVariable.Field1; "xxxx"
 LPRINT "printing aVariable.Field1 with LPRINT USING '\     \xxxx'"
 LPRINT USING "\     \xxxx"; aVariable.Field1
 FOR i = 1 TO 10: LPRINT : NEXT i

 ' Use PRINT:
 PRINT "printing aVariable.Field1 to screen with 'xxxx' following"
 PRINT "1234567890123456789012345678901234567890"
 PRINT aVariable.Field1; "xxxx"
 PRINT "printing aVariable.Field1 with PRINT USING '\     \xxxx'"
 PRINT USING "\     \xxxx"; aVariable.Field1


 469. How to Get an Earlier Version of QuickBASIC for MS-DOS

 Product Version(s): 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881202-8
 Last Modified: 19-JUN-1989    ArticleIdent: Q39579

 If you need an earlier version of Microsoft QuickBASIC because the
 latest version does not help you and a previous version is known to
 solve the problem(s), you can obtain one by calling Microsoft Customer
 Service at (206) 882-8088 between 6 AM and 5:30 PM Pacific time.

 Microsoft normally only sells the most current version of QuickBASIC,
 but Microsoft Customer Service may have earlier versions available. As
 of December 1988, the following QuickBASIC versions are available from
 the Microsoft Customer Service Department:

    Version 2.01
    Version 3.00
    Version 4.00
    Version 4.00b
    Version 4.50

 You may be asked to return your current version for a "down grade," or
 if you can't return your current version, you may have to purchase the
 earlier version.

 Please confirm availability, charges, and conditions by calling the
 Microsoft Customer Service Department.

 You can also check your local dealer or software discount companies to
 see if they have any earlier versions.


 470. QuickBASIC SETUP Only Works from Logical Disk Drive A or B

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881201-15
 Last Modified: 21-DEC-1988    ArticleIdent: Q39580

 The SETUP program (SETUP.EXE) is designed to help you copy the
 QuickBASIC files from floppy disks to your hard drive.

 The SETUP program (SETUP.EXE) from QuickBASIC Version 4.50 only works
 correctly from logical disk Drive A or B of your computer. SETUP.EXE
 does not work correctly when run from any logical disk Drive C, D, E,
 or higher. If you run SETUP on a logical drive other than Drive A or
 B, it is assumed to be a hard disk, and SETUP.EXE will fail.

 As an alternative for installing QuickBASIC, you can use the MS-DOS
 COPY command to copy each floppy to the hard disk with the following
 command:

    COPY *.* c:

 For QuickBASIC Version 4.00 or 4.00b, the SETUP program (SETUP.EXE)
 only works from Drive A. SETUP will not work on Drive B or higher for
 Version 4.00 or 4.00b.

 Versions of QuickBASIC earlier than Version 4.00 do not have a SETUP
 program.


 471. Forcing FIXSHIFT.COM to Install Using the /I Switch

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S881213-39
 Last Modified:  8-JUN-1989    ArticleIdent: Q39586

 Because of errors in their ROM BIOS, some machines have
 keyboard-editing problems in QuickBASIC Versions 4.00, 4.00b, and
 4.50. The utility FIXSHIFT.COM corrects many of these problems. If one
 encounters keyboard-editing problems, FIXSHIFT.COM should be
 installed.

 If FIXSHIFT.COM is invoked and it displays the message "FIXSHIFT Not
 Required," you can force it to install. You can force FIXSHIFT to
 install using the /I switch. The following can be typed on the DOS
 command line:

    DOS-PROMPT>   FIXSHIFT /I

 FIXSHIFT should then display a banner message and a "FIXSHIFT
 Installed" message.

 One customer with a PC Craft Turbo computer reported that he had to
 run FIXSHIFT/I to successfully use SHIFT+INSERT to copy text in the
 QB.EXE editor. Microsoft has not tested or confirmed this information
 for the PC Craft Turbo computer -- the information is provided as is.


 472. QB Advisor 4.50 "Help: ON ERROR Statement Details" Correction

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S881206-71
 Last Modified: 19-JAN-1989    ArticleIdent: Q39587

 The paragraph in the QuickBASIC Version 4.50 QB Advisor (on-line help
 facility) that describes how to perform error trapping in a SUB or
 FUNCTION procedure or DEF FN function is incorrect, and an incorrect
 example is shown.

 The paragraph incorrectly states that a SUB, FUNCTION, or DEF FN block
 can contain an error-handling routine. The error handler-label and
 RESUME must be at the main-program level or module level.

 The "Help: ON ERROR Statement Details" should instead say the
 following:

    To have an error-handling routine trap errors occurring within a
    SUB, FUNCTION, or DEF FN block, you need to place the error-
    handling routine at the module-level code (before the SUB or
    FUNCTION procedure definition). A label (such as Labelx) marks the
    start of the error-handler routine. The ON ERROR GOTO Labelx
    statement must be an executable statement within the same module as
    Labelx, but Labelx is put OUTSIDE the SUB...END SUB or
    FUNCTION...END FUNCTION procedure block, and the
    ON ERROR GOTO Labelx statement can be put INSIDE the
    procedure block or main program.

 Note: QuickBASIC Version 4.50 uses global-error handling. For more
 information about global-error handling, please search for "GLOBAL",
 "ERROR", "HANDLING", and "4.50" in this KnowledgeBase.

 The following program correctly demonstrates the flow of control when
 an error occurs in a SUB procedure:

 DECLARE SUB dork ()
   CALL dork
   PRINT "This is the last statement in main module"
 END

 handler:
   PRINT "error 50 has occurred"
   RESUME NEXT

 SUB dork()
   ON ERROR GOTO handler
   ERROR 50              'This forces an error to occur
   PRINT "In the subroutine"
 END SUB

 You can find the incorrect paragraph in the QB Advisor "Help: ON ERROR
 Statement Details," as follows:

 1. Run QB.EXE Version 4.50.

 2. Press SHIFT+F1 to invoke the QB Advisor Help menu.

 3. Select Index.

 4. Press PAGE DOWN key, or press "O" to jump directly to the Keywords
    beginning with the letter "O", then cursor to the ON ERROR statement
    and select it.

 5. Select Details. The following window title appears:

       "Help: ON ERROR Statement Details"

 6. Scroll down to the seventh paragraph. This paragraph and the
    example program below contain errors.

 The following is the INCORRECT paragraph and example that can be found
 in the HELP facility:

    " [ The following information is in error: ]
    SUB and FUNCTION procedures and DEF FN functions can contain their
    own error handlers. The error handler must be located after the
    last executable statement but before the END SUB, END FUNCTION, or
    END DEF statement. To keep the error handler from executing when
    there is no error, the procedure or function must terminate with an
    EXIT SUB, EXIT FUNCTION, or EXIT DEF statement immediately ahead of
    the error handler, as in the following example:

 SUB InitializeMatrix (var1, var2, var3, var4)
       .
       .
    ON ERR GOTO ErrorHandler    ' [ Should be ON ERROR, not ON ERR! ]
       .
       .
    EXIT SUB         ' [ EXIT SUB is optional (not required). ]

    ErrorHandler:    ' [ Must move this after END SUB !]
       .
       .
    RETURN           ' [ Use RESUME, not RETURN!  Must move
                     '   ErrorHandler...RESUME to after END SUB ]

 END SUB
 [ end of incorrect HELP example. ] "


 473. In QB.EXE 4.50, No Editor Color on TANDY 1000 with CGA

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881215-3
 Last Modified:  5-JAN-1989    ArticleIdent: Q39592

 Running QB.EXE Version 4.50 on an "older" TANDY 1000 with CGA graphics
 circuitry built-in to the mother board (CGA, 640 x 200 pixels) brings
 up the QuickBASIC environment in black and white (monochrome).

 Invoking QuickBASIC with the /b, /nohi, or /h option or any
 combination of these options does not correct the problem. The MS-DOS
 command MODE CO80 also does not help.

 It has been reported that QuickBASIC Version 4.00b and earlier
 versions supported color under the QB.EXE environment on this system.

 Another customer using a TANDY 1000 SX reported a similar problem. The
 customer worked around the problem by doing the following:

 1. Issue the following MODE command in MS-DOS:

       MODE CO80

 2. Now, when you invoke QB.EXE Version 4.50, you still get black and
    white, but if you select the Options... menu, you can see and
    select the desired colors.

 3. When you exit QuickBASIC, the QB.INI file will contain the new
    settings. The next time you invoke QB.EXE, it will come up in
    color.


 474. Version History of Microsoft QuickBASIC for MS-DOS

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881219-27
 Last Modified:  9-MAY-1989    ArticleIdent: Q39730

 Listed below is the product history for the United States version of
 QuickBASIC for the IBM PC.

 The differences among the versions should be consistent with the
 differences among the versions released in France; however, the dates
 may vary. To receive information about international releases, please
 contact Microsoft International Customer Support at (206) 882-8661.

    Version Number      5.25-Inch Release      3.5-Inch Release

    1.00                08/18/85               none

       First release.

    1.01                January 1986           none

       Corrects problems known in Version 1.00. No major enhancements.
       Few copies of Version 1.01 were shipped due to a problem
       discovered with compiling medium-sized programs.

    1.02                02/06/86               05/07/86

       Corrects problems known in Version 1.01. No major enhancements.

    2.00                09/29/86               08/15/86

       Major release. The following new features are added:

          Built-in editor environment
          Support for dynamic numeric arrays using far heap (up to 64K
          each)
          Multiline block IF..THEN..ELSE..ENDIF statements
          EGA graphics card support
          BLOAD/BSAVE statements

    2.01                01/20/87               02/02/87

       Corrects problems discovered in Version 2.00. Addition of
       keyboard driver for Tandy 1000 and IBM EXTENDED keyboard.

    3.00                04/13/87               04/13/87

       Major release. Comes with QB.EXE and QB87.EXE. The QB87.EXE
       program supports the math coprocessor. The following additional
       new language statements are added:

          SELECT CASE
          DO LOOP
          CONST

       The editor includes insert/overtype mode command. You can use
       the editor with SuperKey, Prokey, or Sidekick. Other features
       include a simple debugger to set breakpoints and watch
       variables. The editor can take advantage of 43-line mode on the
       Enhanced Graphics Adapter (EGA) card.

    4.00                10/10/87               10/10/87

       Major release. Introduction of threaded p-code technology, which
       error-checks lines when typed and runs programs almost instantly
       in the editor environment. You can load multiple modules within
       the editing environment.

       The following new features are added:

          Hercules graphics support
          Recursive SUBprogram procedures
          User-defined TYPE variables (TYPE...END TYPE)
          Huge dynamic arrays (larger than 64K)
          Fixed-length strings
          CALLs to high-level languages (Microsoft C, FORTRAN, Pascal)

       Enhanced debugger in editor allows setting breakpoints, watch
       points, and watch variables, plus MS CodeView compatibility. New
       on-line help for BASIC syntax.

    4.00a               02/20/88               02/20/88

       QuickBASIC Version 4.00a was released with the Microsoft BASIC
       Compiler Version 6.00. Version 4.00a provided corrections to
       problems discovered in Version 4.00. QuickBASIC Version 4.00a
       was never sold as a product separate from the Microsoft BASIC
       Compiler 6.00.

    4.00b               05-05-88               06/01/88

       Version 4.00b is almost the same as Version 4.00a, except some
       memory-management and data-communications problems in Version
       4.00a (and Version 4.00) are corrected. Version 4.00b is
       enhanced to support the AT&T and Olivetti high-resolution
       screens. (A copy of QuickBASIC Version 4.00b is also distributed
       with the Microsoft BASIC Compiler Version 6.00b package.)

    4.50                10/21/88               10/21/88

       New user interface with complete context-sensitive help that
       contains the entire language reference manual. On-line help
       system also contains examples that can be cut and pasted
       directly into programs. 4.50 provides corrections for some
       problems discovered in Version 4.00b.


 475. In QB.EXE 4.50 on Tandy 1000 SX, "\" Key Acts Like HOME Key

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881130-17
 Last Modified: 14-DEC-1989    ArticleIdent: Q39732

 It has been reported that the Tandy 1000 SX with a standard keyboard
 does not work correctly with the QuickBASIC Version 4.50 editor or the
 QBX.EXE environment provided with Microsoft BASIC PDS Version 7.00.
 The BACKSLASH (\) key, which is needed to specify a directory path,
 does not function correctly. Instead, the BACKSLASH key acts the same
 as a HOME key.

 According to reports, the BACKSLASH key works correctly in QuickBASIC
 Versions 4.00 and 4.00b on the Tandy 1000 SX.

 It has also been reported that the pipe character (|), which is the
 same as SHIFT+BACKSLASH, does not work correctly in the QB.EXE
 environment of QuickBASIC 4.50 or in the QBX.EXE environment of BASIC
 PDS Version 7.00.

 Tandy has supplied a keyboard driver with Tandy DOS Version 3.20 that
 corrects this problem. It converts the scan code of the key pressed to
 the IBM standard scan code. The driver can be installed by placing the
 following line in your CONFIG.SYS file if the file KEYCNVRT.SYS is in
 the root directory:

    device=KEYCNVRT.SYS

 If it is in a subdirectory, you must supply a full pathname, or move
 the file to the root directory. After the CONFIG.SYS file is modified,
 reboot the computer.

 Note: This KEYCNVRT.SYS is applicable only to Tandy DOS.

 To work around this problem, if you have a Tandy 1000 with PC-DOS or
 MS-DOS, press ALT+92 (where NUM LOCK must be active, and 9 and 2 must
 be typed on the numeric keypad while holding down the ALT key) to type
 a backslash character in the QB.EXE editor. (The ASCII value for a
 backslash is 92. You can create an ASCII character by pressing up to
 three digits on the numeric keypad while holding down the ALT key.)

 To get a pipe character (|), press ALT+124 (where NUM LOCK must be
 active, and 1, 2, and 4 must be typed sequentially on the numeric
 keypad while holding down the ALT key).


 476. Networks Supported by QuickBASIC, BASIC Compiler & BASIC PDS

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881220-65
 Last Modified: 31-JAN-1990    ArticleIdent: Q39853

 Microsoft QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50
 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and OS/2 support only the IBM
 PC-NET and MS-NET compatible networks.

 The above versions of QuickBASIC, BASIC compiler, and BASIC PDS have
 NOT been tested by Microsoft on the following networks:

    Token Ring
    Novell
  * LAN Manager
    3COM Net
    Alloy

 * Note: This is not Microsoft LAN Manager, but is a product of another
         company.

 Even though varying degrees of success have been reported using some
 of these non-Microsoft networks, problems may occur, such as the
 inability to lock individual records, or permission-denied errors when
 an application attempts to open an unlocked file.

 To troubleshoot problems with non-Microsoft networks, you must  find
 out the version number of the network software, the version of the
 network card, the exact circumstances and programs necessary to
 reproduce the problem, and whether the problem occurs on a server or
 workstation. It may help to call the company that sells the network to
 help determine known problems and troubleshooting techniques.
 Unrelated TSR (terminate and stay resident) programs should be removed
 from memory to help isolate the problem.


 477. CALL INTERRUPT 25H Doesn't Return Error Flags in the AX Reg

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881216-23
 Last Modified: 14-DEC-1989    ArticleIdent: Q39859

 Microsoft QuickBASIC supports the CALL INTERRUPT and CALL INTERRUPTX
 statements for calling MS-DOS and ROM BIOS functions/interrupts. The
 Interrupt Hex 25 is used to perform an absolute read from disk to a
 memory location. If there are any errors during this operation, the
 interrupt will return them in the AH register.

 If the CALL INTERRUPT or CALL INTERRUPTX are used to execute Interrupt
 25 Hex, the correct error code is not returned. This problem occurs
 because Interrupt 25H does not POP the CPU flags from the stack after
 its operation; these are flags the INT 25 Hex function originally
 PUSHed onto the stack. Therefore, when INTERRUPTX returns to
 QuickBASIC, it returns the "old" flags. These do not reflect the
 Interrupt 25 Hex function-flag return. Most MS-DOS and ROM BIOS
 interrupts do POP the CPU flags from the stack upon completion and
 this problem does not exist. INTERRUPTX does not compensate for the
 extra set of flags on the stack.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and Microsoft BASIC PDS 7.00 for MS-DOS and OS/2.

 The two workarounds for this problems are as follows:

 1. Call an assembly-language subroutine that performs the Interrupt 25
    Hex. The correct flags will be directly accessible by the
    subroutine and can then be cleared with a POPF or ADD SP,2
    instruction. More information on this can be found on Pages 388-389
    of "Advanced MS-DOS" by Ray Duncan (published by Microsoft Press,
    1986).

 OR

 2. Call a different but very similar interrupt as follows:

       Interrupt 13 Hex  Function 02 Hex

    This is not an MS-DOS function, but rather a ROM BIOS interrupt,
    which (unlike Interrupt 25 Hex) does its own stack clearing. This
    is described below.

 In the following programs, Prog1 demonstrates the problem. No matter
 what Interrupt 25 Hex error occurs, the AX flags are always returned
 the same. Prog2 follows the second workaround described above and uses
 the Interrupt 13 Hex, which will return the proper error flags.

 Prog1 is as follows:

 'The include file below needs to be 'QBX.BI' when using
 'BASIC PDS 7.00 and the Quick library is QBX.QLB.

 '$INCLUDE: 'QB.BI'
 DEFINT A-Z
 DIM InRegs AS RegTypeX, OutRegs AS RegTypeX
 DIM buffit(1 TO 8000)  AS INTEGER
 CLS
 InRegs.ax = &H0
 InRegs.cx = &H0
 InRegs.dx = &H0
 InRegs.ds = VARSEG(buffit(1))
 InRegs.bx = VARPTR(buffit(1))
 CALL INTERRUPTX(&H25, InRegs, OutRegs)
 PRINT OutRegs.ax
 END

 Prog2 is as follows:

 'The include file below needs to be 'QBX.BI' when using
 'BASIC PDS 7.00

 '$INCLUDE: 'QB.BI'
 DEFINT A-Z
 DIM InRegs AS RegTypeX, OutRegs AS RegTypeX
 DIM buffit(1 TO 8000)  AS INTEGER
 CLS
 InRegs.ax = &H201
 InRegs.cx = &H1
 InRegs.dx = &H0
 InRegs.es = VARSEG(buffit(1))
 InRegs.bx = VARPTR(buffit(1))
 CALL INTERRUPTX(&H13, InRegs, OutRegs)
 PRINT OutRegs.ax
 END


 478. Cannot Nest ON ERROR GOTO Error-Trapping Routines in BASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom  SR# G881215-8171
 Last Modified: 14-DEC-1989    ArticleIdent: Q39860

 After control is passed to an error handler in a Microsoft QuickBASIC
 program, additional errors cannot be trapped until a RESUME, RESUME
 label, or RESUME NEXT occurs. This behavior is by design and applies
 to Microsoft QuickBASIC Versions 2.00 2.01 3.00 4.00 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2.

 This also applies to Microsoft BASIC PDS for MS-DOS and MS OS/2 when
 using global or "module level" error trapping. However, error trapping
 is possible inside a local error handler invoked with an ON LOCAL
 ERROR statement available in Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 Error-trapping routines perform best when they help notify you or the
 program of an error condition, allow for the error to be corrected,
 and then RESUME back into the program.

 For example, the following error-trapping structure could be used when
 attempting to open a user-supplied filename. If more coding was used
 and an error occurred while in the TRAP routine, the error would not
 be trapped by the program.

 The following is a code example:

 ON ERROR GOTO TRAP
 10  INPUT "Enter a FileName: ";a$
 20  OPEN a$ for input as #1
 END
 TRAP:
    IF ERL = 20 THEN
       RESUME 10
    ELSE
       Print "The error Number is: ";err
       RESUME NEXT
    END IF


 479. Quick Library Routines Must Be Compiled in Same Version as QB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G881214-8094 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q39866

 Compiled BASIC modules that are placed into a Quick library must be
 compiled with the same version of BC.EXE that was shipped with the
 QB.EXE in use.

 For example, BASIC code placed into a Quick library that will be used
 with QuickBASIC Version 4.50 must be compiled with the BC.EXE shipped
 with Version 4.50. Prior versions of BC.EXE, such as the version
 shipped with Microsoft BASIC Compiler Versions 6.00 or 6.00b, are not
 necessarily compatible with QuickBASIC Version 4.50.

 This information applies to the QB.EXE environment of QuickBASIC
 Versions 4.00, 4.00b, and 4.50, to the QB.EXE environment of
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to the QBX.EXE
 environment of the Microsoft BASIC PDS Version 7.00.


 480. NORTON Programming Guide for BASICS (TSR) Fails with QB 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881227-28
 Last Modified: 12-JAN-1989    ArticleIdent: Q40139

 It has been reported that the NORTON Programming Guide for BASICS,
 which is a Terminate-and-Stay-Resident (TSR) program, does not work
 correctly with QuickBASIC Version 4.50, but works properly with
 QuickBASIC Versions 4.00 and 4.00b.

 Microsoft has not officially tested this product with QuickBASIC and
 makes no guarantees of compatibility. As always, you should be careful
 using any memory-resident (TSR) program with QuickBASIC.


 481. How to Incorporate Paintbrush (PCX) EGA File into QB SCREEN 9

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881229-80
 Last Modified: 12-DEC-1989    ArticleIdent: Q40152

 Microsoft QuickBASIC can incorporate PCX files created with the
 Microsoft Mouse Paintbrush package through the use of the FRIEZE
 terminate-and-stay-resident (TSR) program. The FRIEZE TSR is included
 in the Microsoft Mouse Paintbrush package and can be loaded up into
 memory by running the PAINT.BAT file located on the Microsoft Mouse
 Utilities distribution disk. The steps you should first take are as
 follows:

 1. Load the FRIEZE TSR into memory from within a batch file.

 2. Load your QuickBASIC program, which will issue an interrupt 5. This
    makes the TSR active, allowing you to load a PCX file from disk
    into the video-card memory.

 Your QuickBASIC program then can BSAVE the four EGA planes--red,
 green, blue, and intensity--out to disk. This makes it possible to
 include high quality, color pictures in QuickBASIC programs.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS and Microsoft BASIC Compiler Versions 6.00 and
 6.00b and Microsoft BASIC PDS 7.00 for MS-DOS and MS OS/2.

 The following is a code example:

 +++++++++++++++++++++++++++++++++++
 EGAPBSAV.BAS
 +++++++++++++++++++++++++++++++++++

 REM If you are using BASIC PDS 7.00, change the include file
 REM below to 'QBX.BI'.

 REM $INCLUDE: 'QB.BI'
 DIM REGS AS RegType
 DIM SHARED TOTALVIDEOMEM AS INTEGER
 DIM SHARED FILNAME$

 TOTALVIDEOMEM=28000
 SCREEN 9
 COLOR 5,0
 CLS
 PRINT "MAKE SURE THAT YOU HAVE LOADED THE FRIEZE TSR INTO MEMORY BEFORE"
 PRINT "RUNNING THIS PROGRAM."
 PRINT
 CALL SAVEPCXFILE
 END

 SUB SAVEPCXFILE STATIC
   DIM REGS AS REGTYPE
   PRINT : PRINT
   PRINT "WHAT BASE NAME WOULD YOU LIKE TO GIVE THE BINARY IMAGE FILE?"
   PRINT "PLEASE DO NOT PROVIDE AN EXTENSION (e.g. .BAS OR .BIN)"
   PRINT
   INPUT "FILENAME: ",FILENAME$
   PRINT "PRESS ANY KEY TO BRING UP THE FRIEZE TSR...."
   SLEEP
   CALL INTERRUPT(&H5,REGS,REGS)
   DEF SEG=&HA000
   FOR I=0 TO 3
         'SET EGA REGISTER FOR A READ FROM EACH PLANE
         OUT &H3CE,4
         OUT &H3CF,I
         TEMP$=RTRIM$(FILENAME$)+LTRIM$(STR$(I))+".EGA"
         BSAVE TEMP$,0,TOTALVIDEOMEM
   NEXT I
   DEF SEG
 END SUB


 482. QB.EXE "OUT OF MEMORY" after SHELL to DOS PRINT, MODE, ASSIGN

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881220-74 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q40154

 The MS-DOS PRINT, MODE, and ASSIGN commands should not be run from the
 QuickBASIC environment during a SHELL or from a SHELL statement in an
 executable program. The MS-DOS PRINT, MODE, and ASSIGN commands remain
 resident in memory after being invoked. Subsequent attempts to LOAD
 another QuickBASIC program that is larger or adds more code to an
 existing program result in the error message "OUT OF MEMORY." You must
 exit QuickBASIC and reboot to eliminate this memory-fragmentation
 problem.

 When the MS-DOS PRINT, MODE, and ASSIGN commands are invoked, they are
 loaded into memory above QuickBASIC and the program loaded in the
 environment. This causes memory to become fragmented. Although there
 may be more memory above the resident commands, QuickBASIC will not
 recognize this memory.

 A QuickBASIC program that SHELLs to an MS-DOS batch file containing
 the PRINT, MODE, or ASSIGN command usually executes correctly.
 However, if an attempt is made to unload the current program and load
 in a program that is larger than the first, the "OUT OF MEMORY" error
 message displays. If you exit QuickBASIC and then bring QuickBASIC up
 again, any attempt to load a program into the environment also
 generates the error message.

 If any application invoked after this is larger than QuickBASIC, the
 following error displays: "PROGRAM TOO LARGE TO FIT IN MEMORY." The
 only way to alleviate this situation is to reboot the machine. Exiting
 QuickBASIC and then running QB.EXE again does not eliminate the
 problem.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS and to the QBX.EXE environment
 of Microsoft BASIC PDS Version 7.00.

 To work around this problem, invoke the MS-DOS PRINT, MODE, or ASSIGN
 command before running QB.EXE. You should never SHELL to any
 terminate-and-stay-resident (TSR) program (such as the MS-DOS PRINT,
 MODE, or ASSIGN command).

 The following code example demonstrates the memory-fragmentation
 problem:

    cls
    print "start"
    shell "test.bat"
    print "done"
    end

 The following is the batch file TEST.BAT:

    mode com1:300,N,8,1,bin
    mode lpt1:=com1:


 483. QB.EXE 4.50 Bad Alert Box if User TYPE "Element Not Defined"

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S890104-76 ptm234
 Last Modified:  8-MAR-1989    ArticleIdent: Q40155

 In QuickBASIC Version 4.50, if you attempt to run a program that
 contains erroneous use of user-defined typed variables (specifically,
 an "element not defined" error), QuickBASIC may bring up an alert box
 that contains irrelevant information, and possibly garbage.

 This problem occurs only in Microsoft QuickBASIC Version 4.50 for
 MS-DOS. Microsoft is researching this problem and will post new
 information as it becomes available.

 This problem is not an issue if you always make sure to define all
 elements of a user-defined TYPE before using them.

 Consider the following program:

 TYPE Test
   x AS INTEGER
   y AS DOUBLE
 END TYPE
 DIM Var AS Test
 PRINT Var

 To reproduce the problem, do the following:

 1. Run this program as is. You should get a "Type mismatch" error
    message on the PRINT statement.

 2. Change the PRINT statement line to print out an element of Var that
    does not exist (for example, PRINT Var.z).

 Attempting to run the modified version of the program will produce an
 alert box that contains completely random, irrelevant information,
 often incomplete sentences, sometimes single words or characters, and,
 occasionally, incomprehensible garbage.

 If the program is run again without changing it, the same information
 will appear in the alert box. However, if the PRINT statement is
 changed again (i.e., to another element that does not exist), a new
 alert box is produced, with different, meaningless information. If
 this is repeated several times (making a change, running the program,
 making a change, running the program, etc., about 30 times), the alert
 box itself may be garbled or incomplete and the machine eventually
 will hang.

 However, if a change is made to the DIM statement line (even a
 noncritical edit, such as inserting a line before the DIM statement),
 you will get the correct "Element not defined" error when you run the
 program. The problem will not recur from this point on, until you
 change the PRINT statement back to just PRINT Var, and run to get the
 "Type Mismatch" error message.


 484. FRE(-2) Returns Fixed Lowest Value Even After Stack Shrinks

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q40188

 The FRE(-2) function returns in bytes the amount of unused stack space
 available for the program.

 However, when the stack-space allocation decreases, the value returned
 by FRE(-2) stays fixed at the smallest size that was unused by the
 stack up to that point of program execution. In other words, the
 values successively returned by FRE(-2) never increase -- they either
 decrease or stay the same.

 Microsoft has confirmed this to be a problem in QuickBASIC in versions
 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2 (buglist6.00, buglist6.00b); and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 The sample program below demonstrates this behavior. The example given
 is a recursive subprogram that reports the value of FRE(-2) on the way
 down and back up through 10 levels of subprogram recursion. As the
 stack space increases with the level of recursion, the value of
 FRE(-2) decreases as expected. However, as the stack space decreases
 with lower levels of recursion, the value reported by FRE(-2) stays
 "bottomed out" at the lowest value reached during recursion.

 The only way to reset the "bottomed-out" value returned by FRE(-2) is
 to end the program or execute a CLEAR statement. Note: CLEAR erases
 all variables and closes all files. In some cases, as shown in Example
 2, adding an INPUT statement before the FRE(-2) allows FRE(-2) to go
 back up. Adding INPUT does not help Example 1.

 Example 1
 ---------

 The following code example demonstrates a case in which FRE(-2) goes
 down and stays down:

    DECLARE SUB test (num)
    CLS
    PRINT "Before any calls, FRE(-2):"; FRE(-2)
    CALL test(0)
    END
    SUB test (num)
      PRINT "Call number"; num; "on the way DOWN, FRE(-2):"; FRE(-2)
      IF num < 9 THEN
        CALL test(num + 1)
      ELSE
        PRINT "Bottom of recursion reached."
      END IF
      PRINT "Call number"; num; "on the way UP, FRE(-2):"; FRE(-2)
    END SUB

 Example 2
 ---------

 The following example demonstrates a case in which adding an INPUT
 statement lets the value returned by FRE(-2) go back up:

    DECLARE SUB foo ()
    DEFINT A-Z
    CLS
    'INPUT k   ' Adding this INPUT statement makes FRE(-2) go back up.
    PRINT FRE(-2)
    a$ = "Test string"
    CALL foo
    PRINT FRE(-2)
    END

    SUB foo
    SHARED a$
    PRINT "hello "; a$
    END SUB


 485. SADD Function Will Not Accept Concatenated or Quoted Strings

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890103-51
 Last Modified: 14-DEC-1989    ArticleIdent: Q40189

 The SADD (String ADDress) function will not accept a concatenation of
 strings or a quoted literal string as a parameter. The only valid
 argument for the SADD function is a single, variable-length string
 variable.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Under versions of QuickBASIC earlier than Version 4.00, the SADD
 function accepts an argument that is a quoted literal string or a
 concatenation of strings. This behavior returns the address of the
 temporary storage location for the string. This is no longer allowed
 in QuickBASIC Version 4.00 or later.

 The following is a code example:

 c$ = "This program compiles and runs"
 b$ = " under Microsoft QuickBASIC 3.00"
 PRINT c$ + b$
 PRINT SADD(c$ + b$)


 486. Same Access Speed for Static, Dynamic Arrays If Debug Is On

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q40190

 The code shown below demonstrates that the access time for an array is
 not dependent upon whether the /AH option is used. Furthermore, a
 static array requires the same amount of access time as a dynamic
 array when executed from within QB.EXE or when compiled with the debug
 (BC /d) option. Static-array access is faster than dynamic-array
 access when compiled without the debug (BC /d) compiler switch.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2.

 The following times were required for the sample program below when
 executed under QuickBASIC Version 4.50 using the indicated options on
 an AT compatible running at 10 megahertz with a 6-megahertz 80287
 chip:

    Array Type       QB.EXE      BC.EXE /d      BC.EXE No Debug
    ----------       ------      ---------      ---------------
                     With an 80287 coprocessor:

    Huge             23.22       38.05           30.02
    Static           23.17       38.10           17.96
    Dynamic          23.24       38.07           30.32

                     Without an 80287 coprocessor:

    Huge             88.65       105.39          97.5
    Static           88.64       105.40          82.6
    Dynamic          88.64       105.45          97.49

 Earlier versions do not allow huge (larger than 64K) arrays.

 The following is sample code:

 ' $DYNAMIC
 DIM ar0(20000)

 ' $STATIC
 DIM ar1(2000)
 ' $DYNAMIC
 DIM ar2(2000)

 s# = TIMER
 FOR j = 1 TO 100000
    ar0(1) = ar0(1) + ar0(0)
 NEXT
 PRINT TIMER - s#; " seconds elapsed  FOR HUGE"

 s# = TIMER
 FOR j = 1 TO 100000
    ar1(1) = ar1(1) + ar1(0)
 NEXT
 PRINT TIMER - s#; " seconds elapsed FOR STATIC"

 s# = TIMER
 FOR j = 1 TO 100000
    ar2(1) = ar2(1) + ar2(0)
 NEXT
 PRINT TIMER - s#; " seconds elapsed FOR DYNAMIC"


 487. QuickBASIC Cursor Position Incorrect after Interlanguage Write

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890104-135 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q40361

 If a Microsoft QuickBASIC program calls a subroutine or function
 written in another language (Microsoft C, Pascal, Assembly, or
 FORTRAN) that writes information to the screen, the QuickBASIC cursor
 position is not updated.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2.

 The sample program below calls a FORTRAN subroutine. The FORTRAN
 subroutine starts writing to the screen at the point where QuickBASIC
 finishes.

 This program example's printout is readable. The FORTRAN information
 is printed on line 10 and the BASIC information is printed on lines 1
 and 2. However, if you remove the second LOCATE statement, both
 FORTRAN and BASIC print on line 10.

 The following is a code example:

 DECLARE SUB forsub (BYVAL addr%, BYVAL addr2%, x&, y&)
 DIM b%(3000)                'Needed if any string is changed
 COMMON /nmalloc/ b%()

 B$ = "there     "     'FORTRAN expects these to be 10 long
 a$ = "hello     "     'Allocate space for the string 10.
 x&= 1
 y&= 2
 CLS
 LOCATE 10, 1
 CALL forsub(SADD(a$),SADD(b$), x&, y&)
 LOCATE 1, 1
 PRINT a$;" "; b$, x&, y&

 The following is the FORTRAN subroutine:

        SUBROUTINE FORSUB(A, B, C, D)
        CHARACTER*10 A [NEAR]
        CHARACTER*10 B [NEAR]
        INTEGER*4 C [NEAR]
        INTEGER*4 D [NEAR]
        WRITE(*,*) A, B, C, D
        A = 'hi there '
        B = 'lets talk'
        C = 3
        D = 4
        END


 488. Programs LINKed with Incorrect Version of LINK.EXE May Hang

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890106-58 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q40362

 Programs developed in a particular version of Microsoft QuickBASIC or
 Microsoft BASIC Compiler may yield unpredictable results during run
 time if they are LINKed with a version of LINK.EXE other than the
 version that was shipped with the product. The behavior where a
 program runs correctly in the QB.EXE environment but performs
 incorrectly or hangs in the .EXE executable version may be the result
 of using an older or NEWER version of LINK.EXE.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2.


 489. QuickBASIC 4.50 Does Not Return to 25-Line Mode after Make EXE

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890110-36 buglist4.50 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q40368

 When you invoke Microsoft QuickBASIC Version 4.50 with the
 high-resolution (QB /H) option and you compile a program using the
 Make EXE And Exit option, the screen remains in high-resolution mode
 when QuickBASIC exits back to MS-DOS. The resolution can be returned
 to 25-line mode by typing the following:

    MODE CO80

 The commands to enter QuickBASIC using the high-resolution mode and
 the command to reset the resolution upon exit can be included in a
 batch file for convenience.

 The batch file might look like the following:

   REM  *** Here is the STARTQB.BAT file ***
   QB /H
   MODE CO80

 Versions 4.00 and 4.00b of Microsoft QuickBASIC and the QBX.EXE
 environment provided with Microsoft BASIC PDS Version 7.00 all return
 to 25-line mode upon exiting (fixlist7.00).


 490. NUM LOCK On; ALT+BACKSPACE Fails on IBM PS/2 Model 50 and 60

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S890103-87 ptm235
 Last Modified:  8-MAR-1989    ArticleIdent: Q40369

 When Microsoft QuickBASIC Version 4.50 is running on an IBM PS/2 Model
 50 or 60, the following key sequences fail if the NUM LOCK key is on:

 1. ALT+BACKSPACE fails to UNDO editing (i.e., pressing the BACKSPACE
    key while holding down the ALT key).

 2. ALT+[-] or ALT+[+] fails to size the window (i.e., pressing "+" or
    "-" while holding down the ALT key).

 If the NUM LOCK key is off, the above key strokes perform as
 documented.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available.


 491. Using Medium and Large Memory FORTRAN Models with BASIC

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | H_Fortran B_BasicCom SR# S890110-32
 Last Modified: 21-DEC-1989    ArticleIdent: Q40371

 The information below applies to QuickBASIC Versions 4.00, 4.00b, and
 4.50, and Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and OS/2.

 This information also applies to Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2, but only when using near strings. (For more
 information on using far strings in mixed-language programs, please
 refer to Chapter 13, "Mixed Language Programming with Far Strings," in
 the "Microsoft BASIC 7.0: Programmer's Guide." Note that far strings
 are only available with BASIC PDS 7.00.)

 Variables in a FORTRAN subroutine may be specified as being [NEAR] or
 [FAR]. Likewise, QuickBASIC can pass parameters to a subroutine by
 near or far reference. When parameters are passed as near and the
 FORTRAN subroutine is compiled under the medium memory model or the
 parameters are passed as far and the subroutine is compiled with the
 large memory model option, the variables are passed correctly.

 The run-time error message "F2729 I/O item illegal in namelist I/O" is
 reported if you try to use far pointers while compiling in the
 medium memory model.

 Example 1 below demonstrates a program that performs correctly when
 near parameters are used and the FORTRAN subroutine is compiled using
 the medium model (FL /AM) option. The parameters are passed
 incorrectly when the FORTRAN subroutine in Example 1 is compiled with
 the large model (FL /AL) option.

 Example 2 is the equivalent program using the far option. Example 2
 performs correctly when the FORTRAN subroutine is compiled with the
 large model option.

 The following is Example 1, which uses the medium memory model:

    Compile in BASIC as follows:     BC basprog/o;
    Compile in FORTRAN as follows:   fl /AM /APi /c forsub.for
    Link as follows:                 LINK basprog forsub/noe;

 The following BASIC program is BASPROG.BAS:

 DECLARE FUNCTION MAKEIT$(S$,SIZE%)
 DECLARE SUB DUM1(BYVAL S1%, BYVAL S2%, BYVAL S3%, BYVAL S4%)
 DIM NAM%(3000)
 COMMON /NMALLOC/ NAM%()
 STR1$ = MAKEIT ("TEST OF PARAMETER VALUE PASSING" ,44)
 STR2$ = MAKEIT ( "STRING 2" ,43)
 STR3$ = MAKEIT ("STRING 3", 14)
 STR4$ = MAKEIT ("STRING 4" ,14)
 CALL DUM1(SADD(STR1$), SADD(STR2$), SADD(STR3$), SADD(STR4$))
 END
 FUNCTION MAKEIT$ (S$,SIZE%)
    MAKEIT$ = LEFT$(S$+STRING$(80, 32),SIZE%)
 END FUNCTION

 The following FORTRAN program is FORSUB.FOR:

       SUBROUTINE DUM1(STR1, STR2, STR3, STR4)
       CHARACTER*14 STR3, STR4 [NEAR]
       CHARACTER*43 STR1 [NEAR]
       CHARACTER*44 STR2 [NEAR]
       WRITE (*,*) STR1, STR2, STR3, STR4
       END

 The following is Example 2, which uses the large memory model:

 Compile in BASIC as follows:    BC basprog/o;
 Compile in FORTRAN as follows:  fl /AL /FPi /c forsub.for
 Link as follows:                LINK basprog forsub/noe;

 The following BASIC program is BASPROG.BAS:

 DECLARE FUNCTION MAKEIT$(S$,SIZE%)
 DECLARE SUB DUM1(BYVAL S1%, BYVAL S2%, BYVAL S3%, BYVAL S4%,_
                  BYVAL S5%, BYVAL S6%, BYVAL S7%, BYVAL S8%)
 DIM NAM%(3000)
 COMMON /NMALLOC/ NAM%()
 STR1$ = MAKEIT ("TEST OF PARAMETER VALUE PASSING" ,44)
 STR2$ = MAKEIT ( "STRING 2" ,43)
 STR3$ = MAKEIT ("STRING 3", 14)
 STR4$ = MAKEIT ("STRING 4", 14)
 CLS
 LOCATE 10,1
 CALL DUM1(VARSEG(STR1$),SADD(STR1$), VARSEG(STR2$),SADD(STR2$),_
           VARSEG(STR3$), SADD(STR3$), VARSEG(STR4$), SADD(STR4$) )
 LOCATE 24,1
 END
 FUNCTION MAKEIT$ (S$,SIZE%)
    MAKEIT$ = LEFT$(S$+STRING$(80, 32),SIZE%)
 END FUNCTION

 The following FORTRAN program is FORSUB.FOR:

       SUBROUTINE DUM1(STR1, STR2, STR3, STR4)
       CHARACTER*14 STR3, STR4 [FAR]
       CHARACTER*43 STR1 [FAR]
       CHARACTER*44 STR2  [FAR]
       WRITE (*,*) STR1, STR2, STR3, STR4
       END


 492. Recursive FUNCTION Procedure Shouldn't Be STATIC in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S890111-178 B_BasicCom
 Last Modified:  8-DEC-1989    ArticleIdent: Q40413

 Further below is a correction that applies to the factorial example
 program (in the Recursive Procedures section) in the following
 manuals:

 1. Page 82 of "Microsoft QuickBASIC 4.0: Programming in BASIC:
    Selected Topics" (for QuickBASIC 4.00 and 4.00b)

 2. Page 82 of "Microsoft BASIC Compiler 6.0 for MS OS/2 and MS-DOS:
    Programming in BASIC: Selected Topics" (for 6.00 and 6.00b)

 3. Page 72 of "Microsoft QuickBASIC 4.50: Programming in BASIC"

 4. Page 68 of "Microsoft BASIC Version 7.0: Programmer's Guide"

 In the factorial function, the STATIC clause should be removed from
 the FUNCTION line so that it reads as follows:

    FUNCTION Factorial# (N%)

 The example on this page incorrectly defines the recursive function to
 be STATIC when it should actually be non-STATIC. Recursive functions
 should be defined as non-STATIC because the usefulness of a recursive
 function relies on automatic variables saved temporarily on the stack,
 instead of variables that retain their values between invocations.

 The function Factorial# depends on the value for N% to be correct in
 each level of the recursive iteration. The value for N% cannot be
 correct if the number is not stored on the stack with each recursive
 call.


 493. ALT+PLUS/EQUALS Doesn't Size QB.EXE 4.50 Window; Must SHIFT

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890111-168
 Last Modified: 12-DEC-1989    ArticleIdent: Q40545

 To make the current window larger using the keyboard when inside the
 Microsoft QuickBASIC 4.50 environment, you must press either ALT+PLUS
 (pressing the PLUS key on the numeric keypad while holding down ALT)
 or SHIFT+ALT+EQUAL, where EQUAL is the EQUAL/PLUS key on the normal
 keyboard. If you press ALT in conjunction with the EQUAL/PLUS key
 without holding down the SHIFT key, the computer will simply beep
 because this is the same as ALT+EQUAL. This limitation applies only to
 Microsoft QuickBASIC 4.50 for MS-DOS.

 QB.EXE Versions 4.00 and 4.00b did not require holding down the SHIFT
 key in conjunction with the EQUAL/PLUS key on the regular keyboard.

 In the QBX.EXE environment provided with the Microsoft BASIC PDS
 Version 7.00, the PLUS key must be the key on the numeric keypad.
 Using ALT+PLUS or ALT+SHIFT+PLUS where PLUS is the EQUAL/PLUS has no
 effect.

 Inside the QuickBASIC editing environment, pressing the PLUS and MINUS
 keys in conjunction with the ALT key will enlarge or reduce the size
 of the active window. In QB.EXE Versions 4.00 and 4.00b, you can size
 the active window by pressing ALT+PLUS or ALT+MINUS using either the
 PLUS and MINUS keys on the numeric keypad or the regular keyboard.

 However, with QuickBASIC Version 4.50, the ALT+PLUS using the
 EQUAL/PLUS key on the regular keyboard will not work unless you use
 SHIFT+ALT+PLUS because you have to press SHIFT to get the PLUS sign on
 the regular keyboard.

 In the QBX.EXE environment of the BASIC PDS Version 7.00 the
 ALT+MINUS will work with either the MINUS on the regular keyboard or
 the numeric keypad. ALT+PLUS will work only when PLUS is the PLUS key
 on the numeric keypad.


 494. BC.EXE Will Not Compile Files Named USER.*

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881221-29
 Last Modified: 12-DEC-1989    ArticleIdent: Q40547

 The BASIC compiler (BC.EXE) will not compile any source file with a
 name of USER.* (e.g. USER.BAS, USER.TXT, etc.). Instead, it will take
 input from the console and report any errors on each line as they are
 entered. BC.EXE will create an object file only if a name other than
 USER.OBJ is specified.

 The filename USER is a special filename reserved for compiling files
 that are entered directly from the console instead of from a file.
 Thus, if you have a file that is named USER.BAS, BC.EXE will not
 compile it.

 To work around this limitation, rename your BASIC file to something
 other than USER.BAS.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 4.50, and Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS
 and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and MS
 OS/2.


 495. Using CALL INTERRUPT to Determine Current Video Mode

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S881221-34
 Last Modified: 15-JAN-1991    ArticleIdent: Q40548

 Microsoft QuickBASIC cannot determine which kind of video card is
 installed on your machine. However, you can use the CALL INTERRUPT
 statement to invoke ROM BIOS video interrupt 10 Hex, function 0F Hex
 (Get Video Mode), to find out which video mode the machine is
 currently using. From the information returned by this interrupt, you
 can determine whether the video card installed is a monochrome card,
 such as a Hercules or compatible card, or if it is a color card, such
 as an IBM CGA, EGA, VGA, or compatible card.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS. It also applies to Microsoft BASIC Compiler
 versions 6.00 and 6.00b and Microsoft BASIC PDS versions 7.00 and 7.10
 running under MS-DOS or in MS OS/2 real mode in the DOS compatibility
 box.

 In QuickBASIC versions 2.00, 2.01, and 3.00, you can use the CALL
 INT86 routine instead of CALL INTERRUPT to invoke the video interrupt.

 A BASIC application may need to determine whether or not the video
 system in the machine it is running on is monochrome or color (that
 is, to decide which colors to use for its output, etc.).

 The ROM BIOS interrupt 10 Hex, function 0F Hex, will return the
 current video mode. If this interrupt returns a 7 in the AL register,
 the video card is a monochrome card and cannot support color. If it
 returns something other than 7, the video card can support color;
 however, this does NOT determine whether or not a color monitor is
 connected to the computer.

 Also, this function can determine where video memory for text mode
 begins. If the function returns 7, video memory begins at the segment
 paragraph address of B000 hex; otherwise, it begins at segment B800
 hex.

 For more information, see Page 415 of "Advanced MS-DOS" by Ray Duncan
 (Microsoft Press, 1986) and Page 45 of "Microsoft QuickBASIC
 Programmer's Toolbox" by John Clark Craig (Microsoft Press, 1988).

 The following sample listing demonstrates the use of CALL INTERRUPT to
 obtain the current video mode. This program can be compiled in
 QuickBASIC 4.00, 4.00b, or 4.50 with QB /L QB.QLB or linked with
 QB.LIB, which contains the INTERRUPT routine:

 ' Note: The QB.BI file includes the TYPE definition of RegType.
 ' If you are using BASIC PDS version 7.00/7.10, the include file
 ' name should be 'QBX.BI' and the Quick library should be QBX.QLB.

 REM $INCLUDE: 'QB.BI'
 FUNCTION GetVMode% STATIC
 '--------------------------------------------------------------------
 'Function to return the current video mode. The mode value returned is
 'the same value returned from INT 10H, function 0FH -- Get Video Mode
 '(7 = Monochrome card, other = color graphics card)
 '--------------------------------------------------------------------
   DIM InRegs AS RegType, OutRegs AS RegType
   InRegs.ax = &HF00                    'INT 10H, fn. 0FH (get vmode)
   CALL INTERRUPT(&H10, InRegs, OutRegs)
   GetVMode% = OutRegs.ax AND 255       'AL returns the Video Mode
 END FUNCTION


 496. QB.EXE May Overwrite File Allocation Table If Floppy Switched

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 b_basiccom
 Last Modified: 23-JAN-1989    ArticleIdent: Q40549

 Microsoft has duplicated the following problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and to the QB.EXE program that is shipped with
 the Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2.

 QB.EXE can damage a floppy disk's File Allocation Table (FAT) if the
 following steps occur:

 1. A program OPENs a disk file.

 2. The disk file is aborted with CTRL+BREAK before the file is ever
    closed.

 3. The floppy running QB.EXE is replaced with a different floppy disk.

 4. You exit QB.EXE.

 The program example shown below will cause QB.EXE to overwrite the
 File Allocation Table after the following steps are executed:

 1. QB.EXE is executed from a floppy disk.

 2. The program is started and then interrupted with a CTRL+BREAK.

 3. A different disk is put into the drive from which QB.EXE was
    executed.

 4. The QuickBASIC QB.EXE editor is exited (such as with ALT+F+X).

 The overwrite may occur whether the file is opened with RANDOM access
 or SEQUENTIAL access.

 Microsoft is currently researching this problem and will post more
 information as it becomes available.

 To work around the problem, do one of the following after breaking out
 of the program:

 1. Go to the immediate window and issue the command CLOSE.

 2. Exit QuickBASIC before switching disks.

 This program does not cause any problem with versions of Microsoft
 QuickBASIC earlier than Version 4.00.

 The following is a code example:

 OPEN "test.dat" FOR OUTPUT AS #1
 FOR i = 1 TO 10000
     PRINT #1, i
 NEXT


 497. Bad Results with Recursion of STATIC Procedure in QB.EXE

 Product Version(s): 4.00 4.00B 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 SR# S890113-13
 Last Modified: 23-JAN-1989    ArticleIdent: Q40553

 The use of the STATIC clause in recursive functions or SUBprograms
 should be avoided. Using STATIC may cause you to overwrite values from
 a previous CALL. For example, recursively CALLing a STATIC SUBroutine
 and decrementing the passed parameter actually will change the value
 of the parameter when the procedure returns at the END SUB statement.
 However, the QuickBASIC editor incorrectly allows the recursive use of
 a STATIC subroutine or function without any side effects of changing
 the passed parameters. This problem can lead to subtle programming
 errors because the incorrect results don't become apparent until
 compile time.

 More information on recursion in Version 4.00 or 4.00b can be found
 on Pages 81-82 of "Microsoft QuickBASIC 4.0: Programming in BASIC:
 Selected Topics." For QuickBASIC Version 4.50, recursion is documented
 on Pages 71-72 of "Microsoft QuickBASIC: Programming in BASIC."

 The following is a code example:

 DECLARE SUB anysub (Param#)
 CLS
  Param# = 10#
  CALL anysub(Param#)
 END

 SUB anysub (Param#) STATIC
   IF Param# > 1 THEN
      CALL anysub(Param# - 1)
   END IF
   PRINT Param#;
 END SUB

 You will get the following results when this code sample is run in the
 QB.EXE editor:

 1  2  3  4  5  5  6  7  8  9  10

 You will get the following results when it is run as an executable
 .EXE program:

 1  1  1  1  1  1  1  1  1  1  10


 498. SHELL Redirected to NUL Device Suppresses MS-DOS Message

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 14-DEC-1989    ArticleIdent: Q40592

 From a BASIC program, you can invoke the SHELL statement to execute an
 MS-DOS command. Normally, many MS-DOS commands give you a confirmation
 message. If you want to suppress the message (thus making the SHELL
 operation less visible), you can redirect the standard MS-DOS output
 to the NUL device.

 The following is an example:

    SHELL "copy file1 file2 > NUL"

 The above statement copies file1 to file2 and redirects the success
 report "1 file(s) copied" to the NUL device, which is never displayed.

 This information applies to the following products:

 1. Microsoft QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, 4.00b,
    and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2
    and MS-DOS

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 4. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23
    for MS-DOS

 In MS-DOS, the greater-than sign, ">", redirects standard output to
 standard input. The less-than sign, "<", redirects standard input to
 standard output.


 499. QB.EXE 4.x Won't Trace or Single Step through KEY Routine

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 SR# S881220-50 ptm240
 Last Modified:  8-MAR-1989    ArticleIdent: Q40631

 When single stepping or tracing through a program, the QB.EXE Version
 4.00, 4.00b, or 4.50 editor executes key-trapping or event-trapping
 routines correctly, but fails to display the tracing through the
 routine unless you place a breakpoint there.

 Microsoft has confirmed this to be a problem in Versions 4.00 and
 4.00b. We are researching this problem and will post new information
 as it becomes available.

 QuickBASIC Version 3.00 successfully displays the single stepping or
 tracing through key-trapping or event-trapping routines.

 This article applies to all forms of ON Event GOSUB, where the
 Event can be COM(n), KEY(n), PEN, PLAY(q), STRIG(n), and TIMER(n).

 To trace through a program in QuickBASIC Versions 4.x, choose the
 Debug menu, toggle the Trace On option, and run the program. (In
 QuickBASIC Version 3.00, insert the statement TRON as the first
 statement of the program and run it.)

 To Single Step through a program in QuickBASIC Versions 4.x, press F8
 repeatedly. (In QuickBASIC Version 3.00, you need to choose DEBUG from
 the Run menu, then press F8 repeatedly.)

 When you single step or trace the program below in the QuickBASIC
 Versions 4.00, 4.00b, and 4.50 editors, press F1 or F2 while the
 program is waiting for INPUT activates the key-trapping routine. After
 you press ENTER to terminate the INPUT, the editor executes the
 key-trapping routine but does not display the single stepping or
 tracing.

 To work around this behavior, set a breakpoint at the label of the
 key-handling routine to stop execution at the label. Then, the QB.EXE
 editor correctly single steps or traces through the key routine. You
 can press F5 to continue tracing or press F8 for single stepping.

 The following is a code example:

 ON KEY(1) GOSUB KeyRoutine1
 ON KEY(2) GOSUB KeyRoutine2
 KEY(1) ON
 KEY(2) ON
 WHILE 1
 INPUT "Press F1 or F2 and then hit ENTER key", X$
 WEND
 END
 KeyRoutine1: 'Must set a breakpoint here to single step
                    'or trace through this routine.
    PRINT "inside key routine 1"
    RETURN
 KeyRoutine2: 'Must set a breakpoint here to single step
                    'or trace through this routine.
    PRINT "inside key routine 2"
    RETURN


 500. If PRINT Fails on Non-Standard System, PRINT#n to "CONS:"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890112-74
 Last Modified: 12-DEC-1989    ArticleIdent: Q40632

 The PRINT and WRITE statements write directly to video memory; they do
 not write to the screen through function calls to MS-DOS or the ROM
 BIOS. This information applies to Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 By circumventing MS-DOS and the ROM BIOS, the PRINT and WRITE
 statements may not work correctly with certain non-standard or
 unsupported operating-system configurations (such as PC-MOS,
 Multi-DOS, or multitasking packages added to MS-DOS).

 To be more compatible with non-standard systems, you can send output
 to a logical device name that routes the characters through an
 MS-DOS character device driver.

 For example, output through the "CONS:" (CONSole) or "CON" device name
 forces all output through the MS-DOS console device driver. The MS-DOS
 console device driver makes ROM BIOS calls to perform the output.

 You can OPEN "CONS:" FOR OUTPUT AS #n and send output with the PRINT#n
 or WRITE#n statement.

 Similarly, if you have trouble printing with LPRINT to a network
 printer, OPEN "LPT1:" FOR OUTPUT AS #n and send output with the
 PRINT#n or WRITE#n statement.

 Some computer manufacturers provide an ANSI.SYS device driver on their
 DOS disk. Limited graphics control may be performed through ANSI
 control codes. For more information about ANSI codes, query on the
 following words:

    PRINT# MS-DOS "CON" Device ANSI Escape Codes

 The following device names supported by the OPEN statement are
 discussed on Pages 293 and 294 of the "Microsoft QuickBASIC Version
 4.0: BASIC Language Reference" manual for Versions 4.00 and 4.00b:

    "CONS:"
    "KYBD:"
    "SCRN:"
    "COM1:", "COM2:"
    "LPT1:", "LPT2:"

 The following is a code example:

 CLS
 OPEN "CONS:" FOR OUTPUT AS #1
 PRINT #1, "Howdy pahd-nuh..."
 CLOSE #1
 END


 501. SCREEN 4 Fails on Compaq Portable III

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890116-25
 Last Modified: 12-DEC-1989    ArticleIdent: Q40633

 BASIC's SCREEN 4 is designed for the Olivetti/AT&T high-resolution
 screen mode (640 x 400). This screen mode allows you to run programs
 that utilize the special screen mode available on the Olivetti PC,
 models M24, M28, M240, M280, and M380, and the AT&T PC 6300 Personal
 Computer series.

 This information applies to Microsoft QuickBASIC Versions 4.00b and
 4.50, Microsoft BASIC Compiler Version 6.00b for MS-DOS and MS OS/2,
 and Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2.

 If you have one of the computers mentioned above, you can utilize the
 640 x 400 resolution screen mode by using SCREEN 4. The computers
 listed above are the only computers with which this mode was tested;
 therefore, Microsoft cannot guarantee that the mode works correctly on
 any other hardware configuration.

 SCREEN 4 fails on the following hardware:

    Compaq III


 502. "Permission Denied" Is Only Error for BASIC Record/File LOCK

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom SR# S881221-115
 Last Modified: 12-JAN-1990    ArticleIdent: Q40635

 The only error message that you will get for locked files or records
 is "Permission denied," error number 70.

 Normally, you only get a "Bad record number" error message when
 attempting to access record number zero. However, the message "Bad
 record number" has nothing to do with the LOCK statement, contrary to
 a statement in the documentation (listed below).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 This documentation error occurs in the following places. Each of these
 references is in the language reference manual for that product and is
 under the entry describing the LOCK... UNLOCK statement.

 1. Page 259 of the "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" manual for QuickBASIC Versions 4.00 and 4.00b

 2. Page 259 of the "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" manual for Microsoft BASIC Compiler Versions 6.00 and
    6.00b

 3. Page 220 of the "Microsoft QuickBASIC 4.5: BASIC Language
    Reference" manual for QuickBASIC Version 4.50

 4. Page 200 of the "Microsoft BASIC 7.0: Language Reference" manual
    for Microsoft BASIC PDS Version 7.00

 Each of the references above makes the following misleading statement:

    If you attempt to access a file that is locked, the following
    error messages may appear:

       Bad record number
       Permission denied

 This same incorrect information appears in the QB Advisor online Help
 system for QuickBASIC Version 4.50 and in the Microsoft Advisor online
 Help system for QBX.EXE, which comes with Microsoft BASIC PDS Version
 7.00. The error occurs under the entry for the "LOCK... UNLOCK
 Statement Details" in both Help systems.

 The program example below demonstrates that a "Permission Denied"
 error occurs if a program does any of the following:

 1. LOCKs a file that is already LOCKed.

 2. Reads any record from a random access file where the whole file is
    LOCKed.

 3. Reads any part of a sequential file where any part of that file is
    LOCKed.

 4. Reads the portion of a BINARY access file that was LOCKed.

 The following is sample code:

 OPEN "test5" FOR BINARY AS #1   'Open the same file as #1 and #2.
 OPEN "test5" FOR BINARY AS #2

 OPEN "test4" FOR RANDOM AS #3 LEN = 11   'Open as #3 and #4.
 OPEN "test4" FOR RANDOM AS #4 LEN = 11

 OPEN "test3" FOR INPUT AS #5   'Open as #5 and #6.
 OPEN "test3" FOR INPUT AS #6

 OPEN "test3" FOR INPUT AS #7   'Open the same file as #5 and #6.

 FIELD #3, 11 AS f3$
 FIELD #4, 11 AS f4$

 LOCK #1, 30 TO 32       'Lock some bytes in #1.
 LOCK #3                 'lock entire file #3
 LOCK #5, 1              'Lock first record in #5.
 CLS
 n = 10
 LOCK #7          'Permission denied attempt to lock a locked file
 a$ = INPUT$(34, #2) 'Permission denied if any part is locked.
 GET #4, n           'Permission denied for any n except n=0
                     'n=0 gives a bad file number
 INPUT #6, a$        'Permission denied for record 1
 UNLOCK #1, 30 TO 32
 UNLOCK #3
 UNLOCK #5, 1
 CLOSE


 503. Why QuickBASIC Might Hang; Hardware or Software Conflicts

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890111-129
 Last Modified: 14-DEC-1989    ArticleIdent: Q40636

 This article provides a list of possible software and hardware
 conflicts that may cause a program to hang (in the QB.EXE editor or in
 an executable .EXE program). To determine why a program might hang,
 the possibilities below should be checked.

 If the steps below are followed and the program still hangs, the
 problem may be related to a coding error or a problem associated with
 QuickBASIC itself.

 The information in this article applies to the following products:

 1. Microsoft QuickBASIC Versions 1.00, 1.02, 2.00, 2.01, 3.00, 4.00,
    4.00b, and 4.50 for IBM PC and compatibles

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
    MS OS/2

 3. The QBX.EXE environment of Microsoft BASIC PDS Version 7.00 for
    MS-DOS and MS OS/2.

 The following are potential software conflicts:

 1. Terminate-and-stay-resident (TSR) programs. QuickBASIC is not
    designed for use with most TSRs and does not support them.
    Remove these programs and reboot the computer without loading
    the TSRs.

 2. Networks. Unsupported networks fall into the same category as TSRs,
    and they should be removed. (However, there should be no problem
    with the IBM PC Network or MS Network, both of which are
    supported.)

 3. Operating systems. Always use the standard operating system
    provided by the manufacturer of the computer. QuickBASIC is not
    supported under multiuser or multitasking operating systems.
    Try using the standard PC-DOS or MS-DOS with the computer.

 4. Extended/expanded memory. QuickBASIC does not use either
    extended or expanded memory, and the drivers that provide this
    support should also be removed from the system.

 Note: To ensure that there are no programs loaded in memory in all the
 cases above, use the original DOS disk provided for the computer by
 the manufacturer. There should be no special DEVICE=xxx.SYS statements
 in your CONFIG.SYS file and no special programs installed by your
 AUTOEXEC.BAT file.

 The following are potential hardware conflicts:

 1. Incorrect math-coprocessor settings. If the math-coprocessor switch
    settings are incorrect, QuickBASIC may hang. By using the command
    "SET NO87=xxxx" at the DOS prompt, you inform QuickBASIC not to use
    or check for the math coprocessor. If QuickBASIC then works
    correctly, the switch settings may be incorrectly set. For more
    information on the correct switch settings, query on "NO87" in this
    Knowledge Base.

    Also, the speed of the coprocessor must be equal to or less than
    the speed of the computer's CPU (central processing unit);
    otherwise, a numeric exception error can hang the machine.

 2. Video systems. The computer's video system should be a standard
    video system (CGA, EGA, VGA, or MONO-TEXT). There are several
    options available for checking the video system. Proper
    configuration of the video hardware can be performed by issuing
    three MS-DOS MODE commands, as follows:

       MODE MONO -- MONOCHROME SYSTEM
       MODE BW80 -- MONOCHROME MONITOR with COLOR GRAPHICS ADAPTER
       MODE CO80 -- COLOR SYSTEM, both ADAPTER and MONITOR

    If QB.EXE Version 4.50 does not operate with your video system, try
    invoking QuickBASIC with each of the video-specific options, such
    as the /b (black and white) option, the /nohi (no high-intensity)
    option, the /g (update screen as fast as possible) option, and the
    /h (high-resolution) option. For more information, query on the
    words "compatibilities and QuickBASIC" in the Microsoft Knowledge
    Base.


 504. BASIC TYPE...END TYPE Must Be Physically at Top of Program

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890117-64 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q40718

 The QuickBASIC TYPE...END TYPE statement must be physically at the top
 of the program. If it isn't, the program may not compile correctly.
 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The code example shown below does not compile correctly. In the QB.EXE
 editor, an error "Identifier cannot include a period" is reported on
 Line 2. In BC.EXE, two errors are reported, as follows:

    Variable name not unique

    Type Mismatch

 To correct the program, move the TYPE ... END TYPE block and the DIM
 statement before the use of the variable. It is best to place these
 types of statements at the beginning of the program.

 The following is sample code:

 GOSUB initvar
   PRINT x.str
 END

 initvar:
         TYPE user
             str AS STRING * 10
         END TYPE
         DIM x AS user
         x.str = "hello"
 RETURN


 505. Cannot Use FN at Beginning of SUB or Variable Names

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890124-96 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q40859

 In Microsoft QuickBASIC, the FN character combination is reserved for
 user-defined functions created with the DEF FN statement. Variable
 names, SUBprogram procedure names, and function procedure names
 defined with the FUNCTION statement may NOT use FN as the first
 characters in the name.

 Depending on usage, QuickBASIC can give you errors such as the
 following when you incorrectly use FN in a name:

    Duplicate definition
    Invalid identifier
    Cannot start with FN
    Function not defined

 The variable, SUBprogram, or FUNCTION should be renamed so that it
 does not start with the FN character combination.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 More information on the DEF FN statement can be found in the Microsoft
 BASIC language reference manual for your version of BASIC or
 QuickBASIC.


 506. With QB /L, "Far Heap Corrupt" After Deleting Module

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | BUGLIST4.50 SR# S881220-39
 Last Modified:  7-FEB-1989    ArticleIdent: Q40877

 The following key sequence causes a "Far Heap Corrupt" error, aborting
 the QB.EXE Version 4.50 editor and returning you back to DOS:

 1. Start QB with /L, loading any quick library.

 2. Load a program that uses graphics and has a subprogram.

 3. Press CTRL+F10 to enable the full screen.

 4. Run the program (SHIFT+F5, or Start Program from the Run menu).

 5. Press CTRL+BREAK to stop execution of the program.

 6. Press F2 (View Subs) and select a subprogram.

 7. Choose the Delete option.

 8. A window opens asking if you want to delete the indicated
    subprogram; select OK.

 9. A window opens telling you that the program has to
    be restarted after the indicated edit; select OK.

 The screen will then go blank with the message "Far Heap Corrupt"
 at the top.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available.


 507. Passing a LONG INTEGER Array to FORTRAN 4.10 From QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890123-197 B_BasicCom
 Last Modified:  7-FEB-1989    ArticleIdent: Q40884

 This article contains a sample BASIC program that calls a Microsoft
 FORTRAN Version 4.10 subroutine, which passes a long-integer array.
 The array is passed to FORTRAN by FAR reference, allowing you to
 compile the FORTRAN subroutines with both medium- and large-memory
 models.

 When passing an array to FORTRAN by FAR reference, the BASIC program
 must use the VARSEG and VARPTR commands. The FAR keyword in FORTRAN
 requires that the variable segment (VARSEG) is passed as the first two
 bytes, and the offset (VARPTR) as the next two bytes.

 The following BASIC program and FORTRAN Version 4.10 subroutine has
 been tested with Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50
 and the BASIC Compiler Versions 6.00 and 6.00b. The BASIC compiler
 Versions 6.00 and 6.00b supports the alternate math (/FPa) in addition
 to the emulation math (/FPi), both of which have been successfully
 tested.

 Both QuickBASIC and the BASIC compiler can produce stand-alone
 programs (compiled with the /o option) and programs that require a
 run-time library (compiled without the /o option). The following table
 has been produced to show the results of execution with these options.

 Note: An "X" means the product worked correctly, and an "O" means
 the program failed to work correctly, possibly hanging the computer.

 QuickBASIC           4.00      4.00b     4.50

 Stand-Alone            X         X         X
 Run-Time Library       X         X         X

 NOTE: When using QuickBASIC, FORTRAN must be compiled with the /FPi
 math option because this is the only math option available to
 QuickBASIC.

 BASIC Compiler       6.00      6.00b

 /FPa Stand-Alone       X         X
 /FPa Run-Time          X         X

 /FPi Stand-Alone       X         X
 /FPi Run-Time          X         X

 As the above information shows, it is possible to pass a LONG INTEGER
 array by FAR reference to a FORTRAN subroutine.

 When using a mixed-language program, you should not mix the math
 options between the different languages and between the subroutines of
 the same language.

 The following are the compiling instructions:

    BC file1;
    FL /FPi /c /AL file2.for
    LINK file1 file2 /NOE;

 The above compiling instructions assume that FILE1.BAS is the BASIC
 source file, and FILE2.FOR is the FORTRAN source filename. When
 invoking the FORTRAN compiler in the second step above, the filename
 and extension is used.

 The FORTRAN subroutine can be compiled with the /AM (medium-model)
 compiler directive.

 The following is the BASIC source code:

 DECLARE SUB forsub (BYVAL segvar%, BYVAL valvar%)
 REM ** Passing the elements BYVAL is required.  The first
 REM ** element is the segment and the second element is the
 REM ** offset.  Using the INTEGER sign "%" after the variable
 REM ** names ensures that two-bytes of information is being
 REM ** passed, since the FAR keyword is being used in the FORTRAN
 REM ** subroutine.

 DIM heap%(2048)
 COMMON SHARED /nmalloc/ heap%()
 REM ** This is used to increase the amount of heap available to
 REM ** the FORTRAN subroutine.

 DIM PassInt&(10)
 REM ** Array actual contains elements 0 through 10 which
 REM ** make 11 values being passed in this example.

 RANDOMIZE 32767
 PRINT "BASIC Language"
 PRINT "=============="
 FOR a& = 0 TO 10
   PassInt&(a&) = INT(RND * 50000&)
   PRINT PassInt&(a&),
 NEXT a&
 REM ** Load the array elements with random LONG INTEGER numbers
 REM ** and print these numbers to the screen.

 PRINT

 CALL forsub(VARSEG(PassInt&(0)), VARPTR(PassInt&(0)))
 REM ** Call the FORTRAN subroutine passing the segment (VARSEG)
 REM ** and offset (VARPTR) of the first element of the array.
 END

 The following is the FORTRAN source code:

       subroutine forsub(PassInt)
       integer*4 PassInt [far] (11)
 C     ** Receive the array into a four-byte LONG INTEGER array of
 C     ** 11 elements, since the BASIC array was from 0 through 10
 C     ** which makes 11 elements.
       write (*,*) ' '
       write (*,*) 'FORTRAN Language'
       write (*,*) '================'
       write (*,*) PassInt(1), PassInt(2), PassInt(3)
       write (*,*) PassInt(4), PassInt(5), PassInt(6)
       write (*,*) PassInt(7), PassInt(8), PassInt(9)
       write (*,*) PassInt(9), PassInt(10), PassInt(11)
 C     ** Display the 11 elements to the screen to compare with
 C     ** what was displayed by the BASIC program.
       RETURN
       END

 The following is the output from the program:

    BASIC Language

     37940         33524         13884         43346         27709
     3244          147           10789         9183          19917
     29339

     FORTRAN Language

     37940       33524       13884       43346
     27709        3244         147       10789
     9183       19917       29339


 508. Passing a Single-Precision Array to FORTRAN from BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890120-112 B_BasicCom H_Fortran
 Last Modified: 31-AUG-1989    ArticleIdent: Q40885

 This article contains a sample BASIC program that calls a Microsoft
 FORTRAN Version 4.10 subroutine, passing a single-precision array. The
 array is passed to FORTRAN by FAR reference. This allows you to
 compile the FORTRAN subroutines with both medium- and large-memory
 models.

 When passing an array to FORTRAN by FAR reference, the BASIC program
 must use the VARSEG and VARPTR functions. The FAR keyword in FORTRAN
 requires that the variable segment (VARSEG) be passed as the first two
 bytes and the offset (VARPTR) as the next two bytes.

 The following BASIC program and Microsoft FORTRAN Version 4.10
 subroutine has been tested with QuickBASIC Versions 4.00, 4.00b, and
 4.50 and the BASIC Compiler Versions 6.00 and 6.00b. The BASIC
 compiler Versions 6.00 and 6.00b supports the alternate math (/FPa) in
 addition to the emulation math (/FPi), both of which have been
 successfully tested.

 Both QuickBASIC and the BASIC compiler can produce stand-alone
 programs (compiled with the /o option) and programs that require a
 run-time library (compiled without the /o option). The table below has
 been produced to show the results of execution with these options.

 Note: An "X" means the product worked correctly, and a "O" means the
 program performed incorrectly, possibly hanging the computer.

    QuickBASIC           4.00      4.00b     4.50
    ----------           ----      -----     ----
    Stand-Alone          X         X         X
    Run-Time Library     O         X         X

    BASIC Compiler       6.00      6.00b
    --------------       ----      -----
    /FPa Stand-Alone     X         X
    /FPa Run-Time        X         X
    /FPi Stand-Alone     X         X
    /FPi Run-Time        O         O

 The following is a code example:

 ====== BASIC SOURCE CODE =====

 DECLARE SUB forsub (BYVAL segvar%, BYVAL valvar%)
 REM ****
 REM ** Passing the elements BYVAL is required. The first
 REM ** element is the segment and the second element is the
 REM ** offset. Using the integer sign "%" after the variable
 REM ** names ensures that two-bytes of information is being
 REM ** passed, since the FAR keyword is being used in the FORTRAN
 REM ** subroutine.
 REM ****

 DIM heap%(2048)
 COMMON SHARED /nmalloc/ heap%()
 REM   ** This is used to increase the amount of heap available to
 REM   ** the FORTRAN subroutine.

 DIM PassReal!(10)
 REM   ** Array actually contains elements 0 through 10 which
 REM   ** make 11 values being passed in this example.

 RANDOMIZE 32767
 PRINT "BASIC Language"
 PRINT "=============="
 FOR a! = 0 TO 10
   PassReal!(a!) = RND * 10
   PRINT PassReal!(a!),
 NEXT a!
 REM   ** Load the array elements with random single-precision numbers
 REM   ** and print these numbers to the screen.
 PRINT
 CALL forsub(VARSEG(PassReal!(0)), VARPTR(PassReal!(0)))
 REM   ** Call the FORTRAN subroutine passing the segment (VARSEG)
 REM   ** and offset (VARPTR) of the first element of the array.
 END

 ===== FORTRAN SOURCE CODE =====

       subroutine forsub(PassReal)
       real*4 PassReal [far] (11)
 C     ** Receive the array into a four-byte real array of
 C     ** 11 elements, since the BASIC array was from 0 through 10
 C     ** which makes 11 elements.
       write (*,*) ' '
       write (*,*) 'FORTRAN Language'
       write (*,*) '================'
       write (*,*) PassReal(1), PassReal(2), PassReal(3)
       write (*,*) PassReal(4), PassReal(5), PassReal(6)
       write (*,*) PassReal(7), PassReal(8), PassReal(9)
       write (*,*) PassReal(10), PassReal(11)
 C     ** Display the 11 elements to the screen to compare with
 C     ** what was displayed by the BASIC program.
       RETURN
       END

 ===== OUTPUT FROM THE PROGRAM =====

 BASIC Language
 ==============
  7.58816       6.704937      2.776845      8.669397      5.541911
  .6488597      2.955019E-02                2.157865      1.836764
  3.983537      5.867804

 FORTRAN Language
 ================
        7.588160        6.704937        2.776845
        8.669397        5.541911    6.488597E-01
    2.955019E-02        2.157865        1.836764
        3.983537        5.867804

 ===== COMPILING INSTRUCTIONS =====

    BC file1;
    FL /FPi /c /AL file2.for
    LINK file1 file2 /NOE;

 The above compiling instructions assume that FILE1.BAS is the BASIC
 source file, and the FILE2.FOR is the FORTRAN source filename. When
 invoking the FORTRAN compiler in the second step above, the filename
 and extension are used. The FORTRAN subroutine can be compiled with
 the /AM (medium-model) compiler directive.


 509. PUT Statement Correction, Page 342 QB Language Reference

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr
 Last Modified: 15-DEC-1989    ArticleIdent: Q40886

 Page 342 of the "Microsoft QuickBASIC: BASIC Language Reference"
 manual for Versions 4.00 and 4.00b and the "Microsoft BASIC 6.0
 Compiler: BASIC Language Reference" manual for Versions 6.00 and
 6.00b, ("PUT Statement - File I/O") incorrectly states the following:

    ...characters in the string's value. For example,
     the following two statements write 15 bytes to file
     number 1:

     VarString$=STRING$ (15, "X")
     GET #1,,VarString$

 The GET should be changed to PUT as follows:

     VarString$=STRING$ (15, "X")
     PUT #1,,VarString$

 This documentation error was corrected in the QuickBASIC Version 4.50
 QB Advisor on-line Help system and in the "Microsoft QuickBASIC 4.5:
 BASIC Language Reference" manual for Version 4.50 and in the
 "Microsoft BASIC 7.0: Language Reference" manual for Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.


 510. RUN and execlp Between QB 4.00 and C Can Dump to DOS

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890124-94 buglist4.00 fixlist4.00b fixlist4.50
 Last Modified: 17-FEB-1989    ArticleIdent: Q40888

 When transferring control back and forth between a Microsoft
 QuickBASIC Version 4.00 compiled program (using the RUN statement) and
 a Microsoft C program (using the execlp routine), the C program can
 dump itself to MS-DOS. The following are the conditions necessary for
 this behavior to occur:

 1. The QuickBASIC program RUNs a C program with the RUN statement.

 2. The Microsoft C program invokes the execlp routine to transfer
    control back to the QuickBASIC program.

 3. The QuickBASIC program RUNs the C program again. At this point,
    the Microsoft C program aborts to MS-DOS.

 The error only occurs when QuickBASIC is the starting program. If C
 started the process, the transfer of control continues correctly back
 and forth without aborting.

 Microsoft has confirmed this to be a problem in Version 4.00. This
 problem was corrected in Version 4.00b (and 4.50).

 Below is the QuickBASIC example code, BEXAMPLE.BAS:

 ' Compile and LINK as follows:  BC /O BEXAMPLE;
 '                               LINK BEXAMPLE;
 CLS
 PRINT "Inside the BASIC Program."
 FOR i = 1 TO 1000: NEXT i          ' Do nothing loop to take up time
 PRINT "Calling C."
 FOR i = 1 TO 1000: NEXT i          ' Do nothing loop to take up time
 RUN "CEXAMPLE"                     ' Calls the C Program
 END

 Below is the C example code, CEXAMPLE.C:

 /*
    Compile and LINK as follows:  CL /lib/graphics CEXAMPLE.C
 */
 #include <stdio.h>
 #include <graph.h>
 #include <process.h>
 main()
 {
 _clearscreen(_GCLEARSCREEN);
 printf("In The C Program.....Hit RETURN To Continue");
 getchar();
 _clearscreen(_GCLEARSCREEN);
 execlp("BEXAMPLE.EXE",NULL);             /* Calls the QB Program */
 }


 511. BC "Variable Name Not Unique" on SUB with Period in Name

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890123-207 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q40890

 If a BASIC SUBprogram name contains a period (that is, a dot), then
 any variables that have the same name as the portion of the SUBprogram
 name that is left of the period produce a "Variable name not unique"
 error message from BC.EXE at compile time. The program does not
 produce the error inside the QB.EXE editor environment.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2.

 This behavior does not occur in Microsoft BASIC PDS Version 7.00.
 BASIC PDS Version 7.00 will successfully compile a program under the
 above conditions.

 The sample program below runs inside the QuickBASIC environment.
 However, when compiled using BC.EXE, a "Variable name not unique"
 error message is produced.

 It is recommended that variable and subprogram/function names contain
 no periods. Periods are now used by BASIC in specifying individual
 elements of a user-defined type variable. To eliminate the problem in
 the program below, remove the period from the SUBprogram name.

 The following is a code example:

 DECLARE SUB Test.one ()
 COMMON SHARED Test AS SINGLE
 Test = 4
 CALL Test.one
 END

 SUB Test.one
   PRINT "in Test.one"
 END SUB


 512. No Variable Name Cross-reference for QuickBASIC for MS-DOS

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q40952

 There is no variable-name cross-reference facility provided with
 QuickBASIC Versions 4.00, 4.00b, 4.50, Microsoft BASIC Compiler
 Version 6.00 or 6.00b, or Microsoft BASIC PDS Version 7.00. Variables
 in BASIC are not public symbols, so they do not show up in the
 linker's .MAP file.

 You can write or obtain a utility that analyzes the source file and
 displays a cross-reference listing.

 According to the "Language Support Directory for Microsoft QuickBASIC
 and Microsoft BASIC Compiler" (a pamphlet that comes with QuickBASIC
 Version 4.50 and Microsoft BASIC Compiler Versions 6.00 and 6.00b),
 the following company offers a product called Source Print, which
 gives a cross-reference list showing where variables are used and
 where functions, procedures, and routines are called:

    Aldebaran Laboratories, Inc.
    3339 Vincent Road
    Pleasant Hill, CA  94523
    (415) 930-8966

    Product: Source Print
    Price: $97

 Other companies may also offer a cross-reference program for the BASIC
 language.


 513. Missing Options in QuickBASIC 4.50 Editor without Full Menus

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890131-108
 Last Modified: 17-FEB-1989    ArticleIdent: Q41003

 In the QB.EXE editor in QuickBASIC Version 4.50, the following items
 are not available when Full Menus are not selected:

 1. Under the File menu:

    Merge...
    Save
    SaVe All
    Create File...
    Load File...
    Unload File...
    DOS Shell

 2. Under the Edit menu:

    Undo
    Clear
    New SUB...
    New FUNCTION...

 3. Under the View menu:

    Next SUB
    Split
    Next Statement
    Output Screen
    Included File

 4. Under the Search menu:

    Selected Text
    Repeat Last Find
    Label...

 5. Under the Run menu:

    Modify COMMAND$...
    Make Library...
    Set Main Module...

 6. Under the Debug menu:

    Watchpoint...
    Delete All Watch
    Trace On
    History On
    Break on Errors
    Set Next Statement

 7. The entire Calls menu

 8. Under the Options menu:

    Right Mouse...
    Syntax Checking

 In addition to the above items, the following options do not appear on
 certain menu items:

 1. Under (File) Print:

    All Modules

 2. Under (View) Subs:

    Edit in Split
    Move

 3. Under (Search) Find and (Search) Change:

    Active Window
    Current Module
    All Module

 4. Under (Run) Make EXE File...:

    EXE requiring BRUN45
    Stand-Alone EXE


 514. "UNRESOLVED EXTERNAL"; Can't Call External from Quick Library

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890202-70
 Last Modified: 20-DEC-1989    ArticleIdent: Q41004

 Routines in a Quick library are not allowed to call procedures that
 are external to that Quick library. If you manually execute LINK with
 the /QU option to make a Quick library and you get an "Unresolved
 External" error, then the CALL statement in the Quick library that
 calls that routine is skipped at run time.

 This information applies to the QB.EXE editor supplied with QuickBASIC
 Versions 4.00, 4.00b, 4.50, Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2, and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 A Quick library (which has the filename extension .QLB) is essentially
 an executable file, but it cannot be invoked directly from DOS or from
 an .EXE program compiled in BASIC. A Quick library can only be used
 within the QuickBASIC QB.EXE or BASIC PDS 7.00 QBX.EXE environments.

 When you manually execute LINK with the /QU option to attempt to make
 a Quick library that tries to CALL a routine that is not in the .OBJ
 list or .LIB library list, then the error message "UNRESOLVED
 EXTERNAL" is properly displayed at LINK time. Despite the "UNRESOLVED
 EXTERNAL" message, the linker still creates a Quick library (.QLB
 file). This Quick library runs properly in the QB.EXE or QBX.EXE
 environment without giving any error messages. However, the CALL
 statement in the Quick library that calls the routine that was
 reported as an "UNRESOLVED EXTERNAL" is skipped at run time.

 If you attempt to make a Quick library from inside QB.EXE or QBX.EXE
 (by using the Make Library command on the Run menu), the error message
 "Subprogram not defined" prevents the creation of the Quick library
 that has an "UNRESOLVED EXTERNAL."

 The following steps illustrate this limitation:

 1. Compile the subprogram TEMP5.BAS as follows:

       BC TEMP5.BAS;

    (Compile with the /Fs (far strings) option if you are using BASIC
    PDS 7.00, since the QBX.EXE environment always uses far strings).

 2. Make the Quick library TEMP5.QLB as follows in QuickBASIC Version
    4.50:

       LINK TEMP5.OBJ,,,BQLB45.LIB/QU

    (Link with BQLB40.LIB in QuickBASIC Version 4.00; BQLB41.LIB in
    QuickBASIC Version 4.00b; or QBXQLB.LIB in BASIC PDS 7.00).

 3. Invoke the QB.EXE or QBX.EXE editor with the TEMP5.QLB Quick
    library as follows:

       QB MAIN/L TEMP5

    (Or QBX MAIN /L TEMP5 if using BASIC PDS Version 7.00)

 4. When you run the MAIN.BAS program in QB.EXE, the Quick library
    subroutine TEMP5 attempts to call INMAIN (which is a subprogram
    in the main program), but the CALL INMAIN statement is skipped. The
    program successfully continues.

 The CALL INMAIN statement runs successfully if you LINK
 MAIN.OBJ+TEMP5.OBJ outside of the editor and run MAIN.EXE from DOS.
 (You can create MAIN.OBJ as follows: BC MAIN.BAS;).

 The following is MAIN.BAS:

 DECLARE SUB temp4 ()
 PRINT "main"
 CALL temp5
 END
 SUB inmain STATIC
 PRINT "Inside inmain subprogram."
 END SUB

 The following is TEMP5.BAS, which is made into a Quick library:

 SUB temp5 STATIC
 PRINT "Inside temp5 subprogram"
 CALL inmain  ' This CALL is skipped when run within a Quick Library,
              ' but works fine if you link the .OBJ file into a .EXE.
 PRINT "End of temp5 subprogram"
 END SUB


 515. QuickBASIC WIDTH Command Resets Default Values for PALETTE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 SR# S890206-73
 Last Modified: 17-FEB-1989    ArticleIdent: Q41040

 Any switch of WIDTH causes the PALETTE values to be reset to their
 default values. In the example code below, the circle is always drawn
 in the color of the default value for PALETTEs 1 to 15. It should
 always be drawn in the color corresponding to 15948 (63 * 256). This
 is true of all SCREENs that allow multiple page lengths.

 Microsoft has confirmed this to be a problem in Version 4.00, 4.00b,
 4.50 and in Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and OS/2 (buglist6.00, buglist6.00b). We are researching this
 problem and will post new information as it becomes available.

 The following code will reproduce the problem:

 CLS
 SCREEN 12
 i=0
 FOR k = 1 TO 15
    PALETTE k, 63 * 256
    i = 30-i
    WIDTH 80, 30 + i
    CIRCLE (100, 100), 80, 5
    PAINT (100, 100), k, 5
    LOCATE 20, 1: PRINT i, k; : INPUT a$
 NEXT


 516. QB.EXE 4.50 Instant Watch... "STRING SPACE CORRUPT" or Hang

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S890120-38 SR# S890120-39
 Last Modified: 17-FEB-1989    ArticleIdent: Q41041

 The QuickBASIC Version 4.50 editor can hang or give a "String Space
 Corrupt" error if you add an Instant Watch... (from the Debug menu)
 for a long variable-length string while single stepping or during a
 program BREAK.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available.

 The problem only occurs if you set the Instant Watch... after you
 single-step (F8) or press CTRL+BREAK or STOP the program in the
 middle.

 To work around the problem, choose the Restart option from the Run
 menu before adding an Instant Watch... for a variable-length string,
 or add all needed Instant Watch... variables before running the
 program.

 Below are two examples displaying the problem.

 The following steps duplicate the problem (Example 1):

 1. Type the following program in the QB.EXE Version 4.50 editor:

    a$=STRING$(800,65)
    STOP

 2. Run the program. (Or press F8 twice to single-step to the STOP
    statement.)

 3. Move the cursor to the a$ variable.

 4. Select Instant Watch... from the Debug menu (or press SHIFT+F9).

 5. A dialog box appears but the computer is now hung. (The dialog
    box displays the string's name, its contents, a CANCEL button,
    and a HELP button.) You must reboot the computer.

 The following steps duplicate the problem (Example 2):

 1. Type the following program in the QB.EXE Version 4.50 editor:

    A$=STRING$(190,"X")
    PRINT A$
    DO : LOOP

 2. Run the program.

 3. Press CTRL+BREAK to abort the program.

 4. Move the cursor to the A$ variable.

 5. Select Instant Watch... from the Debug menu (or press SHIFT+F9).

 6. Select the Add Watch button.

 7. Now attempts to Start, Continue, or add another Watch variable
    can hang the computer, or fail with a "String Space Corrupt"
    error, which often dumps control out of the editor back to DOS.

 The problem does not occur in the above examples if you set the
 Instant Watch... variable BEFORE running the program or BEFORE
 pressing CTRL+BREAK or AFTER choosing the Restart option.


 517. No Warning If GET or SEEK Past End of Random File; Use EOF(n)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890203-60
 Last Modified: 14-DEC-1989    ArticleIdent: Q41043

 When reading a random access file with the GET statement, if you GET
 or SEEK beyond the number of existing records, then no "END OF FILE"
 error occurs. The records that GET reads after the end of a random
 file are simply blank or set to zero. To avoid this behavior, you must
 do either of the following:

 1. Test the value (true or false) of the EOF(n) function after every
    GET or SEEK statement to determine if you have reached the end of
    the random access file.

 OR

 2. Calculate the number of records in the random access file by
    dividing the number of bytes returned from the LOF(n) function by
    the length (in bytes) of each record. You can then design your
    program to GET or SEEK up to, but not greater than, the number
    of records in the file.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 Microsoft BASIC PDS Version 7.00.

 When working with files OPENed in RANDOM mode, you can use the
 following steps together to avoid running past the end of the file:

 1. Check the value of the EOF(n) function after every SEEK or GET
    for file number n. If EOF(n) returns -1 (a logical value of true)
    for a random access file, then the last executed GET statement
    was unable to read an entire record (which happens when reading
    past the end of the file).

 2. The LOF(n) function returns the length of file number n.

 3. The LEN= clause of the OPEN statement specifies the record length
    for input from a random file.

 4. The SEEK and GET statements set the next location to read in the
    file.

 5. The SEEK(n) and LOC(n) functions return your current location
    in file number n.

 6. The GET statement accepts input into a FIELDed buffer or directly
    into a variable specified as the third argument of the GET.

 The following is a code example:

 (This example demonstrates how to check the value of the EOF function
 after every GET.)

 ' Create a file with RANDOM access as follows:
 CLS
 OPEN "junk2" FOR RANDOM AS #1 LEN = 10
 FIELD #1, 10 AS x$
 LSET x$ = "1234567890"
 FOR i = 1 TO 5
    PUT #1, i
 NEXT
 CLOSE

 ' Input from the existing RANDOM file as follows:
 OPEN "junk2" FOR RANDOM AS #1 LEN = 10
 FIELD #1, 10 AS x$
 i=0
 DO
    i=i+1
    GET #1, i
    IF EOF(1) THEN EXIT DO  ' Exit GET loop when end of file.
    PRINT i, x$
 LOOP
 CLOSE


 518. IEEE Number Range Correction for QB 4.0 "Learning and Using"

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | DOCERR B_BasicCom
 Last Modified: 17-FEB-1989    ArticleIdent: Q41086

 The range for IEEE single and double precision numbers is correct in
 the "QuickBASIC 4.0: BASIC Language Reference" manual (Page 16), but
 is incorrect in the "QuickBASIC 4.0: Learning and Using QuickBASIC"
 manual (Page 248).

 The IEEE floating-point ranges on Page 248 of the following manuals
 are incorrect:

 1. "Microsoft QuickBASIC: Learning and Using" for QuickBASIC
    Versions 4.00 and 4.00b.

 2. "Microsoft BASIC Compiler: Learning and Using QuickBASIC" for
    BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2.

 The IEEE number range limits on Page 16 of the "BASIC Language
 Reference" for QuickBASIC Versions 4.00 and 4.00b and BASIC compiler
 Versions 6.00 and 6.00b are correct (and agree with Page 337 of the
 "Programming in BASIC" manual for QuickBASIC Version 4.50).

 The following is a sample test program:

 ' This program shows that the single precision limit as k goes to
 ' zero is k=1.40E-45. Change j# to j! to show the 3.40E+38 limit
 ' for single precision j!.
 DEFSNG A-Z
 j# = 1E+36
 t:
 j# = j# * 1.1
 k = 1 / j#
 PRINT j#, k
 IF k = 0 THEN STOP
 GOTO t


 519. QB 4.50 SHELL Forces Linefeed If Cursor Is on Line 25

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890203-69 buglist4.50
 Last Modified: 15-MAY-1989    ArticleIdent: Q41146

 The first program below demonstrates that a SHELL statement in
 QuickBASIC Version 4.50 programs causes the screen to scroll up
 (linefeed) one line if the cursor is LOCATEd on line 25. (The problem
 occurs in programs run in both the QB.EXE editor and .EXE programs.)

 If the cursor is not LOCATEd on line 25 at the time SHELL executes,
 then SHELL does not cause a linefeed.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available. This problem does not occur in earlier versions.

 The following program redirects output of a directory to a file and
 scrolls the screen up one line after the SHELL statement:

 CLS
 WIDTH 80,25  ' Must use WIDTH or VIEW PRINT 1 to 25 to use line 25.
 LOCATE 1,1
 PRINT "LINE 1. This scrolls off the screen after SHELL."
 LOCATE 2,1
 PRINT "LINE 2. This line scrolls up one line."
 LOCATE 25,1
 PRINT "LINE 25: NOW DOING A SHELL";
 SHELL " DIR c:\ > TEST.TXT"

 The following program can be used as a workaround to prevent the
 linefeed caused by SHELL:

 CLS
 WIDTH 80, 25
 LOCATE 1, 1
 PRINT "LINE 1 now stays on the screen without scrolling."
 LOCATE 2, 1
 PRINT "LINE 2 remains as the second line."
 LOCATE 25, 1
 PRINT "LINE 25 : DOING A SHELL AFTER CURSOR IS MOVED TO LINE 23";
 xpos% = POS(0)       ' Saves the cursor position, which is
 ypos% = CSRLIN       ' currently on line 25.
 LOCATE 23, 1
 SHELL "DIR c:\ > TEST.TXT"
 LOCATE ypos%, xpos%  'returns cursor to line 25 in remembered column.


 520. Getting Help on NULL CONST String Hangs QB 4.50 Editor

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890206-5 buglist4.50
 Last Modified: 17-FEB-1989    ArticleIdent: Q41147

 In the QuickBASIC Version 4.50 QB.EXE editor, getting Help on a CONST
 string, which is assigned to a NULL string, hangs the computer.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available.

 To demonstrate the problem, run QB.EXE Version 4.50 and type in the
 following:

    CONST A$ = ""

 Position the cursor on anything in the line except CONST and press the
 F1 key to invoke the QB Advisor Help. The computer now hangs and must
 be restarted with CTRL+ALT+DELETE.


 521. CTRL+Q+X Moves Cursor to Bottom of Window in QB 4.50 Editor

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified:  8-MAR-1989    ArticleIdent: Q41148

 Table 12.2 on Page 204 of the QuickBASIC Version 4.50 "Learning to Use
 Microsoft QuickBASIC" manual lists a "top of window" function followed
 by its corresponding function "bottom of file."  This corresponding
 function goes to the bottom of the window, not the bottom of the file.
 It should state "bottom of window."

 The "QuickHelp" within the QB.EXE editor properly states "bottom of
 window."


 522. Single Precision Numbers Have 1 to 7 Digits; Double Have 8+

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom  SR# S890208-209
 Last Modified: 12-DEC-1989    ArticleIdent: Q41149

 The documentation below should be changed to say that a constant is
 single precision if it has fewer than eight digits and is double
 precision if it has eight or more digits.

 This correction applies to the following documentation:

 1. Page 24 of "Microsoft QuickBASIC: BASIC Language Reference" manual
    for Versions 4.00 and 4.00b for MS-DOS.

 2. Page 24 of "Microsoft BASIC Compiler: BASIC Language Reference" for
    Versions 6.00 and 6.00b for MS OS/2 and MS-DOS. (Note: This is the
    same as QuickBASIC's language reference manual.)

 3. Page 18 of the "Microsoft QuickBASIC: BASIC Language Reference"
    manual for QuickBASIC Version 4.50. This manual must be ordered
    separately from the Version 4.50 package.

 4. The QuickBASIC Version 4.50 QB Advisor on-line help system, when
    you select "Help - Contents - Data Types - Constants".

 The above pages INCORRECTLY state that a number is single precision if
 it has fewer than 15 digits and is double precision if it has more than
 15 digits.

 This documentation error was corrected in the "Microsoft BASIC 7.0:
 Language Reference" manual of Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 The above products follow the IEEE standard format for storage of
 floating-point numbers.


 523. SEEK Function Not Hyperlinked to SEEK Statement in QB Help

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S890115-3
 Last Modified: 17-FEB-1989    ArticleIdent: Q41150

 In the QuickBASIC on-line help system, the help screen for the SEEK
 function contains a hyperlink to the SEEK statement, but the SEEK
 statement is missing the hyperlink to the SEEK function.

 This information applies only to Microsoft QuickBASIC Version 4.50 for
 MS-DOS.

 The only way to bring up the help screen for the SEEK function is to
 select it from the index. If you click the right mouse button on
 either the SEEK statement or the SEEK function, the help screen for
 the SEEK statement comes up, and there is no hyperlink to the SEEK
 function.


 524. Function KEY Strings Retained After CHAIN in QuickBASIC 4.x

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890120-97
 Last Modified: 14-DEC-1989    ArticleIdent: Q41151

 If you define strings to be returned by function keys F1 through F10
 (using KEY n,"<string>"), and then CHAIN to another program, these
 function key strings are retained unless the programs are compiled as
 stand alone. This behavior applies to Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and Microsoft BASIC PDS Version 7.00.

 In QuickBASIC Versions 3.00 and earlier, the function key strings are
 not retained after CHAINing.

 When CHAINing between programs, unnamed COMMON blocks and open files
 are preserved from the CHAINing program to the CHAINed-to program only
 if the programs are compiled without the /O (stand-alone EXE) option.

 If the two programs below are compiled with QuickBASIC Version 3.00
 using no options, the KEY list is destroyed after the CHAIN. However,
 if the same programs are compiled using no /O option under a later
 version of QuickBASIC or Microsoft BASIC Compiler Version 6.00 or
 6.00b, or BASIC PDS 7.00, the KEY list is retained in the second
 program.

 The following is a code example:

 '** KEY1.BAS
 FOR t=1 TO 10
   KEY t,"*****"
 NEXT t
 KEY LIST
 INPUT "Press any function key F1 - F10 and hit RETURN",X$
 CHAIN "key2"

 '** KEY2.BAS
 CLEAR
 KEY LIST
 INPUT "Press any function key F1 - F10 and hit RETURN",X$
 PRINT "End of programs."
 END


 525. Same Random File Opened with Multiple Handles Loses Records

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50 b_basiccom
 Last Modified: 17-FEB-1989    ArticleIdent: Q41152

 Records written to disk may be lost when the same random file is
 opened with more than one file handle at once.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 3.00, 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). We are
 researching this problem and will post new information as it becomes
 available.

 There are four possible workarounds for this problem, as follows:

 1. Install the MS-DOS SHARE.EXE utility prior to running the BASIC
    program.

 2. Use a user-defined TYPE variable to define the buffer for writing
    instead of using a FIELD statement. The user-defined TYPE variable
    must be written to the file as the third argument of the PUT
    statement.

 3. QuickBASIC Version 3.00 (or earlier) does not have the user-defined
    TYPE option or the third argument of the PUT statement; therefore,
    it cannot use workaround 2 above. An alternative is to OPEN the
    file under just one file number, write the LAST record, CLOSE the
    file, and then reOPEN it with the multiple handles.

 4. Open a given file under only one file number at once. Few, if any,
    programs actually need different file numbers opened at once for
    the same file. Note that you can use multiple FIELD statements for
    the same file number as long as the FIELDed variable names are
    distinct. The following is an example:

       FIELD#1, 5 AS X$, 5 AS Y$
       FIELD#1, 10 AS Z$

 The problem occurs when you have the same random file open several
 times at once under different file numbers and you use the FIELD
 statement to define the file buffers.

 Some or all of the records written to all but the last file handle may
 be lost, depending on the following criteria (where the "last" file
 handle is defined as being the file handle that is opened last in
 the program and is used to write a record):

 1. If the file does not exist when it is opened, only records written
    using the last file handle are saved.

 2. If the file already has records when it is opened, records written
    using all but the last file handle will be lost if they are written
    beyond the existing records. However, any records written over
    existing records will be saved.

 3. If the file already has records when it is opened, and a record is
    written beyond the last existing record using the last file handle,
    this record becomes the effective end of file. Any records written
    up to this effective end of file will be saved. The effective end
    of file can be created at any point during program execution and
    any records written to the file previously in the program or after
    will be saved.

 For example, a program opens the file "test.dat" as file handles #1,
 #2, and #3 in that order. There is only one record in the file when it
 initially opened. Records 1-40 are written using file handle #2, then
 records 41-75 are written using file handle #1. If record number 76 is
 then written out using file handle #3, all the records written (1-76)
 will be saved. If record number 20 is written out by file handle #3,
 only records 1-20 will be saved. Because file handle #3 was the last
 one opened, it controls the effective end of file.

 The following is an example program that opens the file "test.dat"
 using four different file handles. It writes out 150 records using
 file handle 1, and the next 150 records using file handle 2. It then
 writes out record number 7 using file handle 3 and closes the file. It
 then reopens the file, reads a record, then uses the DOS TYPE command
 to print the contents of the file. It only prints out seven records.
 Although file handle 4 is opened last, it has no effect on which
 records are saved to disk because no record is written using this
 handle.

 The following is a source code:

 CLS
 SHELL "del test2.dat"
 OPEN "test2.dat" FOR RANDOM AS #1 LEN = 52
 FIELD #1, 25 AS lastname1$
 LSET lastname1$ = "test record"
 PUT #1, 1
 CLOSE

 OPEN "test2.dat" FOR RANDOM AS #1 LEN = 52
 OPEN "test2.dat" FOR RANDOM AS #2 LEN = 52
 OPEN "test2.dat" FOR RANDOM AS #3 LEN = 52
 OPEN "test2.dat" FOR RANDOM AS #4 LEN = 52

 FIELD #1, 25 AS lastname1$, 15 AS firstname1$, 12 AS ssn1$
 FIELD #2, 25 AS lastname2$, 15 AS firstname2$, 12 AS ssn2$
 FIELD #3, 25 AS lastname3$, 15 AS firstname3$, 12 AS ssn3$
 FIELD #4, 25 AS lastname4$, 15 AS firstname4$, 12 AS ssn4$

 LSET lastname1$ = "Doe1"
 LSET firstname1$ = "John"
 LSET ssn1$ = "111-22-3333"
 LSET lastname2$ = "Doe2"
 LSET firstname2$ = "John"
 LSET ssn2$ = "111-22-3333"
 LSET lastname3$ = "Doe3"
 LSET firstname3$ = "John"
 LSET ssn3$ = "111-22-3333"

 FOR i = 1 TO 150
   PUT #1, i
 NEXT i
 FOR i = 151 TO 300
   PUT #2, i
 NEXT i

 PUT #3, 7

 CLOSE
 OPEN "test2.dat" FOR RANDOM AS #1 LEN = 52
 FIELD #1, 25 AS lastname$
 GET #1, 30
 PRINT lastname$
 CLOSE
 SHELL "type test2.dat"

 In the program example shown below, the correct information is written
 to records 2 and 4, but not to records 1 and 3. The results are as if
 the FIELD #1 statement had no effect.

 The following is the source code:

 CLS
 KILL "test.dat"
 OPEN "test.dat" FOR RANDOM AS #1 LEN = 10
 ' Add following code as work around (such as for QuickBASIC 3.00),
 ' where you would set n equal to the largest file to be written:
 '   FIELD #1, 10 as a$
 '   LSET a$=""
 '   n=10
 '   PUT #1,n
 CLOSE #1

 OPEN "test.dat" FOR RANDOM AS #1 LEN = 10
 OPEN "test.dat" FOR RANDOM AS #2 LEN = 10
 FIELD #1, 10 AS a$
 FIELD #2, 10 AS b$

 LSET a$ = "firstpart"
 PUT #1, 1
 LSET b$ = "second"
 PUT #2, 2
 LSET a$ = "third"
 PUT #1, 3
 LSET b$ = "fourth"
 PUT #2, 4
 CLOSE

 OPEN "test.dat" FOR RANDOM AS #1 LEN = 10
 FIELD #1, 10 AS a$
 GET #1, 1
 PRINT a$
 GET #1, 2
 PRINT a$
 GET #1, 3
 PRINT a$
 GET #1, 4
 PRINT a$

 Additional Reference Words: SR# S890111-116 SR# S881228-141


 526. "AS Clause Required" Error for REDIM Not Detected in QB 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S890115-2
 Last Modified: 17-FEB-1989    ArticleIdent: Q41153

 In the QB.EXE environment, if you REDIM an array of any type (which
 had been previously DIMensioned using an AS clause) without
 re-specifying the type with the AS clause, the error is not reported.
 The error is correctly reported when the program is compiled using
 BC.EXE.

 Microsoft has confirmed this to be a problem in Version 4.50. We are
 researching this problem and will post new information as it becomes
 available.

 The program example below demonstrates the problem. When run as shown
 below inside the QuickBASIC environment, the program executes
 without error. However, if it is compiled using BC.EXE, the error
 message "AS clause required" is generated. This error message
 also properly displays if the program is run inside the QuickBASIC
 Version 4.00 or 4.00b environment.

 The following is a code example:

 TYPE Test
   a AS STRING * 40
   b AS STRING * 40
 END TYPE

 REDIM a(1 TO 100) AS Test
 PRINT LBOUND(a), UBOUND(a), LEN(a(LBOUND(a)))

 REDIM a(20 TO 50)                     'This line contains the error
 PRINT LBOUND(a), UBOUND(a), LEN(a(LBOUND(a)))



 527. Towers of Hanoi: QuickBASIC 4.50 Recursive SUBprogram Example

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890210-54
 Last Modified: 14-DEC-1989    ArticleIdent: Q41154

 The Towers of Hanoi is a classic computer problem that has been used
 to demonstrate the usefulness and ease of use of recursion. The
 following example program shows how this problem can be solved with
 recursion in QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS,
 Microsoft BASIC Compiler Versions 6.00 or 6.00b for MS-DOS and MS
 OS/2, or  Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.
 QuickBASIC versions earlier than Version 4.00 do not support
 recursion.

 The information below demonstrates the Towers of Hanoi problem.

 If you have three towers (labeled A, B, and C, respectively) of equal
 height, and you have "n" number of disks on Tower A, move the "n"
 disks from Tower A to Tower C in the shortest number of moves.

 Additional rules are as follows:

 1. A larger disk cannot be placed on top of a smaller disk.

 2. Only one disk can be moved at a time.

 3. For each move, a disk must have one of the towers as a destination.

 You will find through inductive proof that the shortest number of
 moves required will be 2 raised to the n-1 power. The order of this
 algorithm (best case) is O(2^n).

 You will also notice that the only thing being kept track of on the
 three towers is what is on top of each tower. The recursion of the
 program handles the pushing and popping of the stack. Some
 implementations of the Towers of Hanoi use a stack to keep track of
 what is on each tower.

 The following is a code example:

 DEFINT A-Z
 DECLARE SUB HANOI(DISKS,TOWERA(),TOWERB(),TOWERC())
 CLEAR ,, 4096
 DIM TOWERA(2)
 DIM TOWERB(2)
 DIM TOWERC(2)
 PRINT
 PRINT"                   RECURSIVE TOWERS OF HANOI"
 DO
 INPUT "NUMBER OF DISKS? ", DISKS
 PRINT
         IF DISKS<>0 THEN
                 TOWERA(0)=1
                 TOWERB(0)=2
                 TOWERC(0)=3
                 PRINT
                 CALL HANOI(DISKS,TOWERA(),TOWERB(),TOWERC())
         END IF
 LOOP UNTIL DISKS=0
 END

 FUNCTION WHICHTOWER$(TOWER%)
   SELECT CASE TOWER%
         CASE 1: WHICHTOWER$=" A "
         CASE 2: WHICHTOWER$=" B "
         CASE 3: WHICHTOWER$=" C "
   END SELECT
 END FUNCTION

 SUB HANOI (DISKS,TOWERA(),TOWERB(),TOWERC())
         IF DISKS=1 THEN
                 DESTINATION$=WHICHTOWER$(BYVAL TOWERC(0))
                 SOURCE$=WHICHTOWER$(BYVAL TOWERA(0))
                 PRINT "MOVED DISK FROM"; SOURCE$;"TO";DESTINATION$
         ELSE
                 CALL HANOI(DISKS-1,TOWERA(),TOWERC(),TOWERB())
                 DESTINATION$=WHICHTOWER$(BYVAL TOWERC(0))
                 SOURCE$=WHICHTOWER$(BYVAL TOWERA(0))
                 PRINT "MOVED DISK FROM"; SOURCE$;"TO";DESTINATION$
                 CALL HANOI(DISKS-1,TOWERB(),TOWERA(),TOWERC())
         END IF
 END SUB


 528. .EXE Compiled BC /S May Not Print String in PRINT TAB(n),A$

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S881230-49 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q41388

 Creating an executable .EXE program with QuickBASIC Version 4.50 with
 the BC /S compiler option may cause the following statement to print a
 blank line:

    PRINT TAB(n); A$

 The program works correctly from inside the QuickBASIC editor, or when
 compiled without the /S option.

 The /S option is used to minimize string data at compile time by
 writing quoted strings to the object file instead of the symbol table.
 The only use for the /S option is to help the compiler handle large
 programs at compile time. Normally, /S does not affect the size or
 behavior of the object code.

 This problem can be corrected by doing the following:

 1. Not using the /S compiler option.

 2. Replacing the PRINT TAB(nn) with a PRINT SPACE$(nn) statement.

 3. Compiling with the /X switch, which is normally used to indicate
    the presence of ON ERROR with RESUME, RESUME NEXT, or RESUME 0.

 This problem occurs only in QuickBASIC Version 4.50; it does not occur
 in earlier versions of QuickBASIC, Microsoft BASIC Compiler 6.00 or
 6.00b, or Microsoft BASIC PDS Version 7.00.

 Code Examples
 -------------

 REM  ** SAMPLE PROGRAM 1 ** DOES NOT WORK CORRECTLY **

 A$ = "THIS SHOULD BE PRINTED"
 PRINT TAB(40 - LEN(A$) / 2); A$
 END

 REM  ** SAMPLE PROGRAM 2 ** WORKS FINE **

 A$ = "THIS SHOULD BE PRINTED"
 PRINT SPACE$(39 - LEN(A$) / 2); A$
 END


 529. SIGNAL Is BASIC Reserved Word; SIGNAL ON Usable Only in OS/2

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890125-25
 Last Modified: 15-DEC-1989    ArticleIdent: Q41389

 The ON SIGNAL(n) GOSUB and SIGNAL ON statements are implemented only
 in OS/2 protected mode for programs compiled with BC.EXE in Microsoft
 BASIC Compiler Versions 6.00 and 6.00b or Microsoft BASIC PDS Version
 7.00.

 SIGNAL is a reserved word in QuickBASIC Versions 4.00, 4.00b, and
 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and Microsoft
 BASIC PDS Version 7.00. However, the SIGNAL statements will be
 accepted only by BASIC compiler 6.00 and 6.00b and BASIC PDS 7.00 when
 compiling in protected mode under OS/2. In all other situations, a
 SIGNAL statement results in an "Advanced feature unavailable" error
 message.

 The BC.EXE compiler that comes with BASIC compiler 6.00 and 6.00b and
 BASIC PDS 7.00 supports the ON SIGNAL(n) GOSUB and SIGNAL ON
 statements, as documented in Section 5 (Pages 27-29) of "Microsoft
 BASIC Compiler 6.0: User's Guide" for Versions 6.00 and 6.00b for MS
 OS/2 and MS-DOS and the "Microsoft BASIC 7.0: Language Reference"
 manual on Pages 341-342.

 Below is an example of the correct use of the ON SIGNAL(n) GOSUB and
 SIGNAL ON statements. This program is supported only if you compile in
 OS/2 protected mode with BC.EXE from Microsoft BASIC Compiler Version
 6.00 or 6.00b, or Microsoft BASIC PDS Version 7.00, and run the
 resulting executable in protected mode:

    PRINT "This program traps CTRL+BREAK in OS/2. Try it."
    ON SIGNAL(4) GOSUB trap
    SIGNAL(4) ON
    10 a$ = INKEY$
    IF a$ = "" THEN GOTO 10
    END
    trap:
      PRINT "CTRL+BREAK trapped. Press any key to quit"
      RETURN

 The above program always reports "Advanced feature unavailable" when
 run in real mode (DOS) as a compiled executable or when run inside the
 QuickBASIC QB.EXE or the BASIC PDS 7.00 QBX.EXE environments.


 530. Handling Events and ERRORs When BASIC Calls Non-BASIC Routines

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom SR# S890202-69
 Last Modified: 22-DEC-1989    ArticleIdent: Q41390

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2,
 and Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The following corrections for documentation errors apply to Page 296
 of the learning and using Microsoft QuickBASIC manual for QuickBASIC
 4.00 and 4.00b and BASIC compiler 6.00 and 6.00b, and to Page 442-443
 of the "Microsoft BASIC Version 7.0: Programmer's Guide" for BASIC PDS
 7.00:

 1. The section "Events and Errors" incorrectly implies that BASIC
    can call a subroutine written in a different language, have that
    language sense an EVENT or ERROR, and then jump to the error
    handling routine in BASIC. BASIC is not designed to do this. What
    happens is that the first event (but not subsequent events) that
    occurs during the other language procedure is stored on the stack
    until control returns to BASIC. If the other language procedure
    calls a BASIC procedure in which the ERROR statement forces an
    error (or a natural error occurs), then the error handler (if any)
    in the BASIC program handles the error and RESUMEs as described
    below.

 2. The last sentence is incorrect ("The BASIC statement containing...
    is the statement that RESUME would reexecute"). This sentence should
    be changed to say the following:

    "The BASIC statement containing the error (ERROR x%) is the
    statement that RESUME would reexecute. RESUME NEXT would reexecute
    at the following statement."

 The program shown below is an example of a BASIC program calling a C
 function that calls a BASIC procedure. The program, as written, will
 loop indefinitely between the error-handling routine and the BASIC
 subprogram that generates the error. If the RESUME statement is
 changed to RESUME NEXT, the program executes the next statement in the
 subprogram: PRINT "Return from ERROR".

 (The documentation incorrectly states that "The BASIC statement
 containing the call to the non-BASIC code is the statement that RESUME
 would reexecute." According to this statement, the CALL CSUB statement
 would be executed; however, execution actually returns to the BASIC
 subprogram where the error occurred, as described above.)

 The following is a code example:

 REM ** Here is the BASIC program
 DECLARE SUB jump ()
 DECLARE SUB csub CDECL ()
 CLS
 ON ERROR GOTO errhand
 FOR i = 1 TO 5
   PRINT " Before call to c ", FRE(-2)
   CALL csub
   PRINT " out if c:", FRE(-2)
 NEXT
 PRINT "At end ", FRE(-2)
 END
 errhand:
    PRINT " error handle => ", FRE(-2)
    RESUME
 SUB jump
   print " Generate and Error"
   ERROR 9
   print "Return from ERROR "
 END SUB

 extern void fortran jump(void);
 void csub(void)
  {
    jump();
  }


 531. Saving Source with Error in SUB Statement Reloads Incorrectly

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q41394

 In the QB.EXE environment of QuickBASIC Version 4.00, 4.00b, or 4.50,
 Microsoft BASIC Compiler Version 6.00 or 6.00b, or in the QBX.EXE
 environment of Microsoft BASIC PDS Version 7.00, saving a module in
 which a SUB or FUNCTION statement contains a syntactically incorrect
 parameter list may cause QuickBASIC to fail to reload the same program
 into separate windows. A SUBprogram or FUNCTION that was initially
 displayed in its own window is now displayed (incorrectly) in the
 window containing the module-level code.

 If the error in the SUB or FUNCTION parameter list is now corrected,
 and the cursor is moved to another line of code (using an ARROW key,
 the ENTER key, or a mouse), the SUB or FUNCTION statement is correctly
 displayed in its own window. However, any code that was contained
 within the SUBprogram or FUNCTION remains with the module-level code,
 including a copy of the END SUB or END FUNCTION statement. That code
 must be manually moved (using Cut and Paste) from the module-level
 code to the SUBprogram or FUNCTION.

 To prevent this problem, always correct any problems that have been
 noted by the QB.EXE or QBX.EXE environment BEFORE saving the file to
 disk.

 This information applies to the QB.EXE environment that comes with
 QuickBASIC Versions 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS, and to the QBX.EXE environment
 that comes with Microsoft BASIC PDS Version 7.00 for MS-DOS. This
 behavior is a design limitation of these environments.


 532. COLOR "Illegal Function Call" in SCREEN 2; Use PALETTE on EGA

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 14-DEC-1989    ArticleIdent: Q41395

 If you invoke the COLOR statement while under SCREEN 2, you will
 always get an "Illegal Function Call" error message at run time.
 SCREEN 2 does not support the COLOR statement in any version of
 Microsoft QuickBASIC, GW-BASIC, or Microsoft BASIC Compiler Versions
 6.00 or 6.00b, or Microsoft BASIC PDS Version 7.00.

 On a CGA card, you can get only black and white in SCREEN 2.

 To get color in SCREEN 2, you must have an EGA or VGA card and you
 must invoke the PALETTE statement to change colors. You can have only
 two colors on the screen at once in SCREEN 2. You can choose from
 sixteen different colors (0 through 15).

 The PALETTE statement can be invoked with the following syntax on a
 computer with an EGA or VGA card:

    PALETTE attribute,colornumber

 In the above syntax, attribute=0 assigns the background color and
 attribute=1 assigns the foreground color in SCREEN 2. You may specify
 colornumber to be a color number from 0 through 15.

 You can only use attribute numbers 0 and 1 with the PALETTE statement
 in SCREEN 2; any other number will give you an "Illegal Function Call"
 error at run time.

 The following is a code example:

 ' This must be run on a computer that has an EGA or VGA card.
 SCREEN 2
 PALETTE 0, 5  ' Background set to Magenta (color number=5)
 PALETTE 1, 2  ' Foreground set to Green (color number=2)
 PRINT "This prints in the foreground color"


 533. In QB, "Blank lines Not Allowed before SUB/FUNCTION" Misleads

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50
 Last Modified: 17-FEB-1989    ArticleIdent: Q41396

 In the QB.EXE editor in QuickBASIC Versions 4.00, 4.00b, and 4.50, if
 the syntax of the parameter list in a SUB or FUNCTION statement is
 incorrect and the ENTER key is used to move to the next line, the
 following misleading error message is displayed:

    "Blank lines not allowed before SUB/FUNCTION line. Is Remark OK?"

 If you select the "OK" option, a remark (') line is inserted AFTER the
 SUB or FUNCTION line, and the correct error message is then displayed.
 The message may differ based on what the actual error is.

 If you use the Mouse or ARROW keys (instead of the ENTER key) to move
 to the next line, the correct error message will then display. (You
 will not receive the incorrect error message, and a remark line will
 not be inserted after the SUB or FUNCTION line.)

 Microsoft is researching the initially misleading error message and
 will post new information as it becomes available.

 When using the ENTER key to move to the next line, the QuickBASIC
 Environment will not allow you to leave the SUB/FUNCTION line until
 the syntax error has been corrected. However, you can move to another
 line using the Mouse or ARROW keys without correcting the error.

 Moving to another line without correcting the error in a SUB or
 FUNCTION line is not a good idea. Various editing steps within the
 same window following this can cause unexpected results. The following
 example will hang the machine:

 1. Type in the following program:

         CALL test(X)
         SUB test(X)
           PRINT
         END SUB

    (The Subprogram is displayed in its own window.)

 2. Edit the SUB statement so that it is incorrect (e.g. by deleting
    the right parenthesis):

         SUB test(X

 3. Press the ENTER key to produce the events described above.

 4. Attempt to enter another SUB or FUNCTION statement following
    the END SUB statement.

 5. You will receive one or two incorrect error messages as described
    previously.

 6. You will then receive one or two correct messages:

      "END SUB or END FUNCTION must be last statement in window"

 7. If you ignore the messages and enter the SUB or FUNCTION statement,
    the machine will hang, possibly requiring a cold boot.


 534. Garbage with PRINT TAB, Array Element in .EXE Compiled in 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S881221-120
 Last Modified: 12-NOV-1990    ArticleIdent: Q41398

 A QuickBASIC version 4.50 program compiled with BC.EXE displays
 garbage (a memory dump) on the screen (plus random beeps) when all of
 the following conditions occur simultaneously:

 1. Two consecutive PRINT, PRINT#, or LPRINT statements occur, the
    second of which uses the TAB function.

 2. The variable being printed is an element of an array.

 3. The program is compiled with BC without the /D option.

 4. The program is compiled without the /O option.

 Microsoft has confirmed this to be a problem in QuickBASIC version
 4.50. This problem is corrected in Microsoft BASIC Professional
 Development System (PDS) version 7.00 (fixlist7.00).

 This problem does not occur in QuickBASIC version 4.00 or 4.00b.

 There are several workarounds for this problem:

 1. Use the /D (debug) switch when compiling.

 2. Replace the TAB function with an equivalent number of spaces.

 3. Put an IF statement between the PRINT, PRINT#, or LPRINT statements
    (as shown in comment in program below).

 4. Use local variables for the subscripts.

 5. Use the /X switch when compiling, which is normally used to
    indicate the presence of ON ERROR with RESUME, RESUME NEXT, or
    RESUME 0.

 6. Use the /AH switch when compiling. (Invoking QB /AH will ensure
    that the Make EXE File command compiles with  /AH).

 Code Example
 ------------

 DIM lbc%(8), wmsg$(8)
 COMMON SHARED lbc%(), wmsg$()
 ' OPEN "CON" FOR OUTPUT AS #1    ' This lets you use PRINT#1 below.
 CLS
 FOR i% = 1 TO 8
   lbc%(i%) = i%
   wmsg$(i%) = STRING$(17, 48 + i%)
 NEXT
 j% = 58
 FOR i% = 1 TO 4
 LOCATE 2 + i%, 3
     PRINT wmsg$(lbc%(i%));   ' Also, PRINT#1, and LPRINT give problem
   ' IF i%=4 THEN j%= 58 ' INSERT THIS STATEMENT TO CORRECT PROBLEM
   ' A simple assignment will not correct the problem.
   ' The following statement fails:
     PRINT TAB(j%); wmsg$(lbc%(i% + 4));  ' Also PRINT#1, or LPRINT
   ' The following statement also fails:
   '  PRINT wmsg$(lbc%(i%)); TAB(j%); wmsg$(lbc%(i% + 4));
 NEXT i%


 535. QB 2.x/3.00 Example to Load DOS Directory Listing into Array

 Product Version(s): 2.00 2.01 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-MAR-1989    ArticleIdent: Q41446

 This article discusses methods to put a disk directory listing into a
 string array in QuickBASIC Version 2.00, 2.01, or 3.00. (This
 information was prepared because the FILES statement in QuickBASIC
 only outputs to the screen, and not to a file or variables.)

 Example 1 shows a simple method to SHELL to the DIR command, redirect
 the output to a file, and input from the file into string variables.

 Example 2 shows how to invoke MS-DOS operating-system functions to
 retrieve a disk directory into string variables. This example uses the
 CALL INT86 statement to invoke MS-DOS interrupt hex 21 with the
 following functions:

    hex 1A (SetDTA)

    hex 4E (FindFirst)

    hex 4F (FindNext)

 This example of using CALL INT86 applies to Microsoft QuickBASIC
 Versions 2.00, 2.01, and 3.00. For instructions for later versions of
 QuickBASIC, please refer to a separate article in this KnowledgeBase
 by querying for the following keywords:

    INTERRUPT and FINDFIRST and FINDNEXT

 Example 1 (the simplest technique) is as follows:

 ' Works in QuickBASIC 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50, and
 ' BASIC Compiler 6.00 and 6.00b. Add line numbers to work in
 ' GW-BASIC 3.20, 3.22, or 3.23.
 nf = 200   ' Handles directory listing up to 200 lines.
 DIM buffer$(nf)
 INPUT "Enter Search Path: ", path$   ' Enter path such as c:
 SHELLSTRING$ = "dir " + path$ + " >dirfile.dat"
 SHELL SHELLSTRING$   ' SHELL to the MS-DOS DIRectory command.
 OPEN "dirfile.dat" FOR INPUT AS #1
 pntr% = 0
 WHILE NOT EOF(1) AND pntr% < nf
   pntr% = pntr% + 1
   INPUT #1, buffer$(pntr%)  ' Inputs one directory line at a time.
   PRINT buffer$(pntr%)
 WEND
 CLOSE #1
 KILL "dirfile.dat"   ' Deletes the temporary file.
 END

 Example 2 is as follows:

 To use the DIRLIST.BAS program below in QuickBASIC Version 3.00, you
 must first make a User Library that contains INT86.OBJ, or else you
 can link DIRLIST.OBJ directly to INT86.OBJ. In QuickBASIC Versions
 2.00 and 2.01, you would use USERLIB.OBJ instead of INT86.OBJ in the
 two alternatives below. The following are the two choices:

 1. The following command makes USERLIB.EXE:

       BUILDLIB INT86;

    You can then invoke the QB.EXE editor with the /L option to
    access the User Library that contains the INT86 routine:

       QB DIRLIST.BAS /L USERLIB.EXE

    When you choose the EXE output option in the Compile... window, the
    resulting .EXE program requires the presence of USERLIB.EXE.

 2. You can compile and link as follows:

       QB DIRLIST.BAS;
       LINK DIRLIST.OBJ+INT86.OBJ;

 The following is the Source Code for DIRLIST.BAS:

 DIM InArray%(9), OutArray%(9)
 AX% = 0: DX% = 3: DS% = 8: CX% = 2  ' -- Register locations
 DTA$ = SPACE$(43)                   ' -- DTA Buffer size
 Path$ = "*.*" + CHR$(0)             ' -- Search path, plus null byte

 REM -- Find Segment and Offset for the DTA (Disk Transfer Area)
 CALL PTR86(Seg1%, Off1%, VARPTR(DTA$))

 REM -- The real Offset for the string DTA$ is found by using the
 REM    SADD function.
 Off1% = SADD(DTA$)

 REM -- Set the DTA with Interrupt Hex 21, and Function Hex 1A
 InArray%(AX%) = &H1A00
 InArray%(DX%) = Off1%
 InArray%(DS%) = Seg1%
 CALL INT86(&H21, VARPTR(InArray%(0)), VARPTR(OutArray%(0)))

 REM -- Find the Segment and Offset for the Search Path
 CALL PTR86(Seg1%, Off1%, VARPTR(Path$))

 REM -- Real Offset is found by using the SADD function
 Off1% = SADD(Path$)

 REM -- Find the first file with Interrupt Hex 21, Function Hex 4E
 InArray%(AX%) = &H4E00
 InArray%(CX%) = 22
 InArray%(DX%) = Off1%
 InArray%(DS%) = Seg1%
 CALL INT86(&H21, VARPTR(InArray%(0)), VARPTR(OutArray%(0)))

 REM -- Stay in while loop until
 REM    18 = No more files
 REM     3 = Invalid search path -OR- no files found
 WHILE (OutArray%(AX%) <> 18) AND (OutArray%(AX%) <> 3)
    a% = CVI(MID$(DTA$, 27, 2))  ' -- Low word of file size
    b% = CVI(MID$(DTA$, 29, 2))  ' -- High word of file size
    IF a% < 0 THEN               ' -- Calculate size relative to
       d! = 65536 + a%           '    Low word
    ELSE
       d! = a%
    END IF
    IF b% < 0 THEN               ' -- Calculate size with High word
       d! = d! + (65536 * (65536 + b%))
    ELSE
       d! = d! + (65536 * b%)
    END IF
    PRINT RIGHT$(DTA$, 13);      ' -- Print file name
    PRINT "  ";
    PRINT d!                     '    and file size
    MID$(DTA$, 31, 13) = SPACE$(13) ' -- Blank out current name
    InArray%(AX%) = &H4F00       ' Function Hex 4F - Find Next File
    CALL INT86(&H21, VARPTR(InArray%(0)), VARPTR(OutArray%(0)))
 WEND
 END


 536. QB 4.x Example to Load MS-DOS Directory Listing into an Array

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q41447

 This article discusses three methods to put an MS-DOS disk directory
 listing into a string array. This article applies to Microsoft
 QuickBASIC versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS, and to Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 Example 1 shows a simple method to SHELL to the MS-DOS DIR command,
 redirect the output to a file, and input from the file into string
 variables.

 Example 2 shows how to use the CALL INTERRUPT routine to invoke MS-DOS
 function calls (SetDTA, FindFirst, and FindNext) to retrieve a disk
 directory into string variables in a compiled BASIC program.

 A third method is to use the DIR$ function introduced in Microsoft
 BASIC PDS version 7.00/7.10 for MS-DOS and MS OS/2. For an example of
 using the DIR$ function (which works both in MS-DOS and MS OS/2),
 search for a separate article by querying on the following words:

    7.00 and "DIR$" and DIRECTORY and LISTING

 For an example of calling the MS-DOS interrupt functions to obtain
 disk directory information in QuickBASIC Version 2.00, 2.01, or 3.00,
 query on the following words:

    INT86.OBJ and FINDFIRST

 For a Microsoft BASIC PDS 7.00 or 7.10 or BASIC compiler version 6.00
 or 6.00b example that displays directory information in MS OS/2
 protected mode, query on the following words:

    DosFindFirst or DosFindNext

 Example 1 (a technique simpler than the next example)
 ---------

 ' Works in QuickBASIC 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50, and
 ' Microsoft BASIC Compiler 6.00 and 6.00b, and BASIC PDS 7.00, 7.10
 nf = 200   ' Handles directory listing up to 200 lines.
 DIM buffer$(nf)
 INPUT "Enter Search Path: ", path$   ' Enter path such as c:
 SHELLSTRING$ = "dir " + path$ + " >dirfile.dat"
 SHELL SHELLSTRING$   ' SHELL to the MS-DOS DIRectory command.
 OPEN "dirfile.dat" FOR INPUT AS #1
 pntr% = 0
 WHILE NOT EOF(1) AND pntr% < nf
   pntr% = pntr% + 1
   INPUT #1, buffer$(pntr%)  ' Inputs one directory line at a time.
   PRINT buffer$(pntr%)
 WEND
 CLOSE #1
 KILL "dirfile.dat"
 END

 Example 2
 ---------

 Example 2 below shows how to load an MS-DOS disk directory listing
 into a string array, using the CALL INTERRUPT statement to invoke the
 MS-DOS operating-system interrupt 21 hex, with functions 1A hex
 (SetDTA), 4E hex (FindFirst), and 4F hex (FindNext). Example 2 below
 applies to QuickBASIC versions 4.00, 4.00b, and 4.50 and Microsoft
 BASIC Compiler versions 6.00 and 6.00b running under MS-DOS (or OS/2
 real mode, which emulates DOS versions 3.x).

 To make this example work in BASIC PDS 7.00, modify the Firstfm
 FUNCTION in the example further below as follows:

 1. DIM inreg AS RegTypex and outreg AS RegTypex
 2. Change CALL INTERRUPT to CALL INTERRUPTX
 3. Add the following line in between the assignment for inreg.dx and
    the CALL INTERRUPTX:    inreg.ds = SSEG(FileName$)

 REM  DIR.BAS
 '$INCLUDE: 'QB.BI'      '<-- look at what is in this file
 '  QB.BI contains the TYPE definitions for "Outreg" and "Inreg"
 '  and the declarations for both INTERRUPT and INTERRUPTX.
 TYPE FileFindBuf
       dos            AS STRING * 21
       Attributes     AS STRING * 1
       CreateTime     AS INTEGER
       AccessDate     AS INTEGER
       FileSize       AS LONG
       FileName       AS STRING * 13
 END TYPE
 TYPE FileInfo
       FileName       AS STRING * 13
       Size           AS STRING * 8
       Seconds        AS STRING * 4
       Minutes        AS STRING * 4
       Hours          AS STRING * 4
       Day            AS STRING * 4
       Month          AS STRING * 4
       Year           AS STRING * 5
 END TYPE
 DIM BUFFER AS FileFindBuf
 DIM FileInfoBlock(100) AS FileInfo
 DECLARE SUB intbuf (BUFFER AS FileFindBuf)
 DECLARE SUB setdta (BUFFER AS FileFindBuf)
 DECLARE FUNCTION firstfm! (path$, fa%)
 DECLARE FUNCTION nextfm ()
 DECLARE SUB CalculateAssign (FileInfoBlock() AS ANY, BUFFER AS ANY,_
                              counter!)
 DECLARE SUB PrintDirList (FileInfoBlock() AS ANY, i!)
 CLS : CALL setdta(BUFFER)
 INPUT "Enter the files spec: "; path$
 fa% = 0  ' A value of 16 includes directory names.
 counter = 0
 IF (firstfm(path$, fa%) = 0) THEN
   DO
    counter = counter + 1
    CalculateAssign FileInfoBlock(), BUFFER, counter
    CALL setdta(BUFFER)
   LOOP WHILE (nextfm = 0)
 END IF
 CLS
 FOR i = 1 TO counter
    PrintDirList FileInfoBlock(), i
 NEXT i
 END

 SUB CalculateAssign (FileInfoBlock() AS FileInfo, _
                      BUFFER AS FileFindBuf, counter)
    FileInfoBlock(counter).FileName = BUFFER.FileName
    FileInfoBlock(counter).Size = STR$(BUFFER.FileSize)
    FileInfoBlock(counter).Seconds = STR$(BUFFER.CreateTime AND &H1F)
    FileInfoBlock(counter).Minutes = _
               STR$((BUFFER.CreateTime AND &H7E0) \ 32)
    'If BUFFER.CreateTime is negative add 64K to make unsigned integer:
    IF BUFFER.CreateTime < 0 THEN
      FileInfoBlock(counter).Hours = _
               STR$(((BUFFER.CreateTime + 2 ^ 16) AND &HF800) \ 2048)
    ELSE
      FileInfoBlock(counter).Hours = _
               STR$((BUFFER.CreateTime AND &HF800) \ 2048)
    END IF
    FileInfoBlock(counter).Day = STR$(BUFFER.AccessDate AND &H1F)
    FileInfoBlock(counter).Month = _
               STR$((BUFFER.AccessDate \ 32) AND &HF)
    FileInfoBlock(counter).Year = _
               STR$((BUFFER.AccessDate \ 512) + 1980)
 END SUB

 FUNCTION firstfm (path$, fa%)
   DIM inreg AS regtype, outreg AS regtype '1. Use regtypex for BASIC 7.00
   inreg.ax = &H4E00
   inreg.cx = fa%
   FileName$ = path$ + CHR$(0)
   inreg.dx = SADD(FileName$)
 ' 2. Add this here for BASIC 7.00:  inreg.ds=SSEG(FileName$)
   CALL INTERRUPT (&H21, inreg, outreg) '3. Use INTERRUPTX in BASIC 7.00
   firstfm = (outreg.ax AND &HF)
 END FUNCTION

 SUB intbuf (BUFFER AS FileFindBuf) STATIC
 ' The first 20 bytes are reserved for DOS and are unchanged
     BUFFER.CreateTime = 0
     BUFFER.Attributes = " "
     BUFFER.AccessDate = 0
     BUFFER.FileSize = 0
     BUFFER.FileName = STRING$(13, 32)
 END SUB

 FUNCTION nextfm
   DIM inreg AS regtype, outreg AS regtype
   inreg.ax = &H4F00
   CALL interrupt(&H21, inreg, outreg)
   nextfm = outreg.ax AND &HF
 END FUNCTION

 SUB PrintDirList (FileInfoBlock() AS FileInfo, i)
   PRINT FileInfoBlock(i).FileName;
   PRINT TAB(15); FileInfoBlock(i).Size;
   PRINT TAB(25); RTRIM$(LTRIM$(FileInfoBlock(i).Month)) + "-";
   IF LEN(RTRIM$(LTRIM$(FileInfoBlock(i).Day))) = 1 THEN
     FileInfoBlock(i).Day = "0" + LTRIM$(FileInfoBlock(i).Day)
   END IF
   PRINT RTRIM$(LTRIM$(FileInfoBlock(i).Day)) + "-";
   PRINT RTRIM$(LTRIM$(FileInfoBlock(i).Year));
   IF VAL(FileInfoBlock(i).Hours) = 0 THEN
     FileInfoBlock(i).Hours = STR$(12) 'Change midnight from 0 to 12.
   END IF
   IF VAL(FileInfoBlock(i).Hours) > 12 THEN
     x% = VAL(FileInfoBlock(i).Hours) - 12
     FileInfoBlock(i).Hours = STR$(x%)
     suffix$ = "p"
   ELSE
     suffix$ = "a"
   END IF
   IF VAL(FileInfoBlock(i).Hours) = 12 AND _
              VAL(FileInfoBlock(i).Minutes) > 0 THEN suffix$ = "p"
   IF LEN(RTRIM$(LTRIM$(FileInfoBlock(i).Hours))) = 1 THEN
     t% = 39
   ELSE
     t% = 38
   END IF
   PRINT TAB(t%); RTRIM$(LTRIM$(FileInfoBlock(i).Hours)) + ":";
   IF LEN(RTRIM$(LTRIM$(FileInfoBlock(i).Minutes))) = 1 THEN
     FileInfoBlock(i).Minutes = "0" + LTRIM$(FileInfoBlock(i).Minutes)
   END IF
   PRINT RTRIM$(LTRIM$(FileInfoBlock(i).Minutes));
   PRINT suffix$
 END SUB

 SUB setdta (BUFFER AS FileFindBuf) STATIC
   DIM inreg AS regtypex, outreg AS regtypex
   CALL intbuf(BUFFER)
   inreg.ax = &H1A00
   inreg.ds = VARSEG(BUFFER)
   inreg.dx = VARPTR(BUFFER)
   CALL interruptx(&H21, inreg, outreg)
 END SUB


 537. BC Command-Line Options in QuickBASIC Version 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890216-64
 Last Modified:  8-MAR-1989    ArticleIdent: Q41525

 The BC.EXE command-line options are not included in the QB Advisor
 on-line help that comes with Version 4.50. They are discussed in the
 following manuals:

 1. Pages 353 and 354 of the "Microsoft QuickBASIC: Programming in
    BASIC" manual for Version 4.50

 2. Pages 210 and 211 of the "Microsoft QuickBASIC 4.0: Learning and
    Using Microsoft QuickBASIC" manual for Versions 4.00 and 4.00b

 The command-line options for BC are identical in QuickBASIC Versions
 4.00, 4.00b, and 4.50. When you update to Version 4.50 from 4.00 or
 4.00b, you can refer to the Version 4.00 or 4.00b manual for the BC
 options list.

 The BC /T (Terse) option is used in both Version 4.00b and 4.50. More
 information on this switch can be found in this database by querying
 for the following keywords:

    TERSE and BC and OPTION


 538. How to Calculate Absolute Address; DEF SEG and PEEK Example

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM  SR# S890216-196
 Last Modified: 18-APR-1989    ArticleIdent: Q41531

 The DEF SEG statement in BASIC sets the current segment address for a
 subsequent PEEK function, or a subsequent POKE, BLOAD, BSAVE, or CALL
 ABSOLUTE statement. PEEK, POKE, BLOAD, BSAVE, and CALL ABSOLUTE can
 all specify an offset (from the current segment) as an argument.

 You can calculate the absolute address (the n'th byte) in memory from
 the segment and offset as follows:

 1. Multiply the segment address by 16 (or shift the hexadecimal
    representation 1 to the left, adding zero to the right-most
    digit; for example, &H40 times 16 equals &H400).

 2. Add this value to the offset.

 In the 8086 chip architecture, the addressable memory space is divided
 into segments, each of which can contain up to 64K of memory. Segments
 can only start on a paragraph address. A paragraph address is a byte
 location that is evenly divisible by 16 bytes. Every 16th byte in
 memory contains segment number n. To access specific bytes or words in
 memory, you must use an offset relative to the beginning of a
 specified segment.

 Together, a segment and an offset provide a segmented address that can
 locate any byte in the 1 megabyte of address space in the 8086
 processor.

 The following PEEK function returns 1 byte located at an
 offset from the paragraph address of the current segment:

    DEF SEG=paddress   ' Sets paragraph address of "current" segment
    x% = PEEK(offset)  ' A byte is returned in integer variable x%

 The following book contains more information about 8086-segmented
 architecture and memory addressing:

    "The New Peter Norton Programmer's Guide to the IBM PC & PS/2," by
    Peter Norton and Richard Wilton (published by Microsoft Press,
    1988).

 Example 1

 The following two PEEK functions access the same location in memory
 starting from two different segments (using decimal notation):

    DEF SEG = 0
    x% = PEEK(256)      'PEEKs at address 0000:0256 decimal
    print x%

    DEF SEG = 1         'The next segment is 16 bytes higher.
    y% = PEEK(240)      'PEEKs at address 0001:0240 decimal
    print y%

 The previous lines of code print the same PEEKed value because
 (0 * 16) + 256 equals (1 * 16) + 240.

 Example 2

 The following is another example of two PEEK functions accessing the
 same location in memory starting from two different segments, this
 time using hexadecimal notation:

    DEF SEG = 0
    x% = PEEK(&H417)     'PEEKs at address 0000:0417 Hexadecimal
    print x%

    DEF SEG = &H40
    y% = PEEK(&H17)     'PEEKs at address 0040:0017 Hexadecimal
    print x%

 The previous lines of code accesses the same values and prints them
 because they have the same absolute address: (0 hex + 417 hex) equals
 (400 hex + 17 hex).

 Remember, when you calculate the absolute address, you shift the
 segment address 1 digit to the left in hexadecimal notation (i.e.,
 multiply by 16 decimal, or 10 hex) and then add to the offset: 40 hex
 times 10 hex equals 400 hex, which is added to 17 Hex.


 539. FRE(-1), FRE(") Both Reduced by Run-Time String Allocation

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890210-64
 Last Modified: 29-JAN-1991    ArticleIdent: Q41532

 Any allocation of variable-length strings (or data in the default data
 segment, DGROUP) that is done at run time reduces the values returned
 by both the FRE("") and FRE(-1) functions by an equal amount.

 This behavior occurs because the area that is unused by the default
 data segment (64K maximum) can potentially be consumed by the far heap
 and vice versa. In other words, the following is true:

 1. Run-time allocation of data in the default data segment (64K
    maximum) always reduces the space free for the far heap by an
    equal amount.

 2. Allocation of far heap (which is always done at run time with
    non-variable-length-string arrays only) reduces the memory
    available for the default data segment if all other memory has
    already been consumed.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, and to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2.

 This information also applies to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2
 when using near strings. The meaning of the information returned by
 the FRE function when using far strings in BASIC PDS 7.00/7.10 is
 slightly different, and is documented in the "Microsoft BASIC 7.0:
 Language Reference" manual on pages 140-141. Note that the QBX.EXE
 environment of BASIC PDS 7.00/7.10 always uses and requires far
 strings. You can print the value of the STACK function to find
 available DGROUP space when using far strings.

 Unused memory can be consumed at run time by either the default data
 segment (DGROUP) (64K maximum), or by the far heap (640K maximum minus
 DOS, minus code, minus previously allocated data), as shown in the
 three examples below. The boundary between the default data segment
 and the far heap is dynamically variable at run time.

 Example 1
 ---------

 In the following program, an array in the far heap consumes all except
 2K or less of available memory, leaving less than 2K free for the
 default data segment:

    ' Compile this with QB or BC with the /AH option
    ' for supporting huge (larger than 64K) arrays:
    OPTION BASE 1
    x = FRE(-1)
    PRINT FRE("")  ' Default data space free starts around 48K.
    DIM y(1023, x / (4 * 1024))  ' Dynamically allocate all but < 2K.
    PRINT FRE("")  ' Default data space free ends at less than 2K.

 FRE("") reports the size, in bytes, of the memory available for the
 storage of variable-length (dynamic) strings at run time. FRE(-1)
 reports the size, in bytes, of the memory available for the largest
 dynamic non-variable-length-string array that can be dimensioned.

 Example 2
 ---------

 The following is another example showing that any variable-length
 string allocated at run time reduces both FRE("") and FRE(-1) by an
 equal amount:

 CLS
 far = FRE(-1)
 near = FRE("")
 a$ = STRING$(1000, 34)   ' Initializes a 1000-byte string.
 PRINT "far heap difference=",far - FRE(-1)
 PRINT "default data difference=",near - FRE("")
 PRINT : PRINT "Now allocate some more default data space..."
 far = FRE(-1)
 near = FRE("")
 REM $DYNAMIC
 DIM b$(250)   ' Dynamically allocates variable-length string array.
 PRINT "far heap difference=",far - FRE(-1)
 PRINT "default data difference=",near - FRE("")

 Example 3
 ---------

 The following code produces a $STATIC array of variable-length
 strings, which allocates memory for the string descriptors in the
 default data segment at compile time (NOT at run time):

    PRINT FRE(-1)
    PRINT FRE("")
    DIM a$(200)
    PRINT FRE(-1)  ' Unchanged free far heap.
    PRINT FRE("")  ' Unchanged free default data space.

 Each array element has a string descriptor that takes 4 bytes (2 bytes
 for length plus 2 bytes for string pointer). In a $STATIC array, these
 descriptors are allocated at compile time.

 (Note: Assigning variable-length string array elements to string
 values is done only at run time for both $STATIC and $DYNAMIC arrays,
 which consumes default data space at run time. The FRE function
 displays the changing free memory values at run time.)

 If a $DYNAMIC metacommand is placed before this block of code, the
 array of string descriptors is allocated at run time, which reduces
 the space available in the data segment and the far heap at run time.
 The values returned by FRE(-1) and FRE("") are reduced by an equal
 amount. Results from running the above code with and without a
 $DYNAMIC declaration are listed below for both the QuickBASIC
 environment and compiled EXEs:

    In QB.EXE with $DYNAMIC        In QB.EXE Without $DYNAMIC
    -----------------------        --------------------------

    Prior:         Heap = 245070   Prior:         Heap = 244246
    Prior: String space = 47694    Prior: String space = 46870
    After:         Heap = 244258   After:         Heap = 244246
    After: String space = 46882    After: String space = 46870

    Compiled EXE with $DYNAMIC     Compiled EXE Without $DYNAMIC
    --------------------------     -----------------------------

    Prior:         Heap = 444120   Prior:         Heap = 443368
    Prior: String space = 59144    Prior: String space = 58360
    After:         Heap = 443308   After:         Heap = 443368
    After: String space = 58332    After: String space = 58360


 540. BASIC 7.00 Can Return Exit Code (Error Level) to Batch File

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI SR# S890216-141
 Last Modified:  4-SEP-1990    ArticleIdent: Q41533

 MS-DOS batch processing (.BAT) files can use an "IF ERRORLEVEL n"
 statement to detect exit code levels returned by some programs.

 However, the only versions of Microsoft BASIC that allow a program to
 return an error level code to MS-DOS are Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10. The END n or STOP n
 statement returns error level n to the batch file that invoked the
 BASIC 7.00 or 7.10 .EXE program. The IF ERRORLEVEL n statement in the
 batch file can detect if the returned exit code is equal to or greater
 than n.

 In all other versions of Microsoft BASIC, the error level (exit) code
 returned by a BASIC program is controlled by the BASIC run-time
 module, not by your program. As an alternative, you can create a file
 in the BASIC program to serve as a flag when a certain condition
 occurs. The batch file that called your program can then check for the
 existence of the flag file in place of checking for an error level. In
 batch files, the "IF EXIST filename" command can be used.

 The following products do not allow your program to return an error
 level to MS-DOS batch files:

 1. QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00,
    4.00b, and 4.50 for MS-DOS

 2. Microsoft GW-BASIC versions 3.20, 3.22, and 3.23 for MS-DOS

 3. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS and
    versions 6.00 and 6.00b for MS-DOS and MS OS/2

 Your BASIC program must not attempt to invoke any MS-DOS interrupts
 (CALL INTERRUPT) to terminate the program with an error level;
 otherwise, strange results may occur and the machine may hang. BASIC
 must handle program termination by itself.

 BASIC 7.00 or 7.10 Can Return Exit Code (ERRORLEVEL) to Batch File
 ------------------------------------------------------------------

 An .EXE program compiled in BASIC 7.00 or 7.10 can use the STOP n% or
 END n% statement to return an exit code (n%) to MS-DOS, as follows:

    ' TEST.BAS
    PRINT "This is a BASIC program that returns an exit code of 5."
    n% = 5
    END n%

 The exit code can be trapped in a MS-DOS batch file with the IF
 ERRORLEVEL n GOTO statement, as follows:

    TEST
    ECHO OFF
    IF NOT ERRORLEVEL 1 GOTO DONE
       ECHO  An error occurred with exit code 1 or higher.
    :DONE
    ECHO End of batch file.

 Using a File as a Flag for a Batch File
 ---------------------------------------

 The following technique lets any BASIC version give a simple yes or no
 message to a batch file.

 The following batch file, ERRT.BAT, calls the BASIC program ERRTST,
 which drops back to the batch file. It then checks for the existence
 of the file ERRFIL (which is an arbitrary name) to see if an error
 occurred while running the BASIC program:

    echo off
    del errfil
    errtst
    if not exist errfil goto end
    echo An error occurred during program running
    :end
    echo End of batch file

 The following file is ERRTST.BAS; it creates the error file if it
 cannot open the file GARBAGE.DAT:

 ' set up to error out if "GARBAGE.DAT" does not exist
 ON ERROR GOTO errorlevel
 OPEN "garbage.dat" FOR INPUT AS #1
 CLOSE #1
 END
 errorlevel:
    CLOSE #1
    OPEN "errfil" FOR OUTPUT AS #1   'Create file that acts as a flag
    CLOSE #1
    SYSTEM   ' Returns to DOS.

 To demonstrate this procedure, compile and link ERRTST.BAS as follows:

    BC ERRTST.BAS;
    LINK ERRTST.OBJ;

 Now run the batch file ERRT.BAT. If the BASIC program cannot find
 GARBAGE.DAT, ERRT.BAT shows "An error occurred during program
 running."


 541. ON KEY (n) GOSUB Cannot Trap for SCROLL LOCK Status; Ignored

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI SR# S890216-167
 Last Modified: 14-DEC-1989    ArticleIdent: Q41534

 It is not possible to use the keyboard flag of the KEY statement to
 check the status of the SCROLL LOCK key in conjunction with
 user-defined keys. The status of the SCROLL LOCK key (on or off) is
 ignored and does not affect trapping of any other keys (with ON KEY
 (n) GOSUB).

 This information applies to the following products:

 1. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2
    and MS-DOS

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 4. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23


 542. Syntax Differs When Calling a SUB without the CALL Keyword

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q41535

 When calling a SUBprogram in QuickBASIC without the keyword "CALL" (by
 specifying just the SUB name and arguments), you must omit the
 parentheses around the parameter list. This is known as an "implied
 CALL" statement. You must also declare that procedure in a DECLARE
 statement.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 Microsoft BASIC PDS Version 7.00. Earlier versions of these products
 do not support the implied CALL syntax.

 The normal form of the CALL statement is as follows:

    CALL foo (arg1,arg2)

 In the above example, arg1 and arg2 are passed "by reference." Passing
 "by reference" means that if the subprogram changes the values of the
 passed parameters, they are passed back changed.

 If an individual parameter is placed inside parentheses, the parameter
 is passed "by value":

    CALL foo ((arg1),(arg2))

 Passing a variable "by value" means that only its value is passed, and
 the value of the variable in the calling program is not changed by
 assignments in the SUBprogram.

 If the CALL statement is omitted from the line (i.e., only the SUB
 name is given to indicate the CALL), then the outermost parentheses
 must be omitted.

 The proper syntax for a call by reference without the CALL keyword is
 as follows:

    foo arg1,arg2

 The proper syntax for a call by value without the CALL keyword is as
 follows:

    foo (arg1),(arg2)

 The following is an example of the difference between calling by
 reference and by value:

   DECLARE SUB foo (arg1, arg2)
   arg1 = 5
   arg2 = 6
   foo arg1, arg2                        ;call by reference
   PRINT arg1, arg2                      ;results in 1 and 2
   arg1 = 5
   foo (arg1), (arg2)          ;call by value
   PRINT arg1, arg2                      ;results in 5 and 6
   END

   SUB foo (arg1, arg2)
     arg1 = 1
     arg2 = 2
   END SUB


 543. PRINT TAB Can Change Value of Parameter in Subprogram

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S890216-214
 Last Modified: 14-FEB-1991    ArticleIdent: Q41536

 The code below demonstrates that a variable that has been passed to a
 subprogram procedure may incorrectly be changed by a PRINT TAB(n)
 statement. However, the same statement in the main module does not
 cause the error.

 The problem can be avoided by not using the PRINT TAB(n) statement, or
 by assigning a local variable to the passed parameter in the SUB and
 using the local variable in the PRINT TAB(n) statement, or by
 compiling with the BC /X option. (The /X compiler switch is normally
 used only to flag an ON ERROR statement with RESUME, RESUME NEXT, or
 RESUME 0.)

 Microsoft has confirmed this to be a problem in an .EXE program
 compiled with BC.EXE in QuickBASIC version 4.50. No problem occurs in
 the QB.EXE environment. We are researching this problem and will post
 new information here as it becomes available.

 The program example below works correctly with all versions of
 QuickBASIC earlier than version 4.50.

 Code Example
 ------------

 DECLARE SUB testsub (row%)
 row% = 9
 ' this line is ok -- it is in the main module
 LOCATE row%, 1: PRINT "main line row%= "; row%; TAB(38); row%;
 row% = 10
 CALL testsub(row%)
 END

 SUB testsub (row%)
   LOCATE row%, 1: PRINT "Sub row%= "; row%;
   ' The value of row% prints incorrectly:
   PRINT TAB(38); "row now = "; row%
 END SUB

 To work around the problem in QuickBASIC 4.50, print a local variable
 instead of the passed parameter, for example:

 SUB testsub (row%)
   x%=row%
   LOCATE row%, 1: PRINT "Sub row%= "; row%;
   PRINT TAB(38); "row now = "; x%      ' x% prints ok.
 END SUB


 544. QB Editor Causes Fourth Line to Be Overwritten by Third Line

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50  SR# S890216-212
 Last Modified:  8-MAR-1989    ArticleIdent: Q41537

 When the following sequence of events occurs, the QB.EXE editor causes
 the fourth line to be overwritten by the third line; therefore, the
 information on the third line is duplicated:

 1. Run QB.EXE and type the program example shown below.

 2. Type an additional word on line three following BULL.

 3. Try to move the cursor down one line with the DOWN ARROW key.

 4. Clear the error message; press ENTER.

 5. Use SHIFT+UP ARROW to highlight all lines.

 6. Press the TAB key.

 This problem appears only when an error occurs prior to performing the
 text selection step.

 Microsoft has confirmed this to be a problem in the QB.EXE program
 provided in QuickBASIC Versions 4.00, 4.00b, and 4.50 and to the
 QB.EXE program supplied with Microsoft BASIC Compiler Version 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and OS/2. We are
 researching this problem and will post new information as it becomes
 available.

 The following is an example code:

 'create a program with several lines
 'make one of the lines call a subprogram
 'cause an error by adding an extra word on the call line
 'just press return
 'start from line 1, use shift+down arrow to highlight all lines
 'press the TAB key
 'Line three replaces line four
     REM line one
     REM line two
     CALL bull
     REM line four


 545. More Information about BASIC's DRAW Statement Macro Language

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI SR# S890217-132
 Last Modified: 12-DEC-1989    ArticleIdent: Q41581

 This information illustrates the DRAW statement, which is supported in
 the following products:

 1. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2
    and MS-DOS

 3. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 4. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 The DRAW statement is only valid in a graphics mode (i.e., SCREEN 1,
 2, and higher). The DRAW statement is not supported in SCREEN 0.

 DRAW allows you to draw lines, shapes, change colors, fill in areas,
 and also perform powerful graphic functions. The DRAW statement
 combines most of the capabilities of the other graphics statements
 found in BASIC into an object-definition language called the Graphics
 Macro Language (GML).

 The syntax for the DRAW statement is as follows:

    DRAW string-expression

 This syntax is documented under the BASIC statement DRAW in the
 "Microsoft GW-BASIC Interpreter: User's Reference" and the BASIC
 language reference manuals for QuickBASIC and the BASIC compiler. The
 valid options for string expressions are also documented with the DRAW
 command.

 The DRAW command expects a string expression that is composed of the
 following, where "x" is a reserved letter (command) and "n" is a
 numerical value, interpreted as a string:

    xn

 You can have one or more combinations of xn's separated by a space or
 a comma. The following are examples:

    DRAW "U5"         'Moves the pointer Up 5
    DRAW "U5 L7"      'Moves the pointer Up 5 and Left 7
    DRAW "U5,L7"      'Moves the pointer Up 5 and Left 7
    DRAW "G5"         'Moves the pointer diagonally down and left 5

 The integer value of "n" can also be assigned to a string variable and
 then used as in the following example. You will have to concatenate
 the strings to build the command. The following is an example:

    A$ = "200" : B$ = "120" : DRAW "M" + A$ + "," + B$

 The value for "n" can also be stored in an integer variable, and then
 converted to a string using the VARPTR$() or STR$() functions. If
 using VARPTR$(), you must include the extra "=" signs or else an
 "Illegal function call" error is generated. The syntax is as follows:

    A% = 200 : B% = 120 : DRAW "M=" + VARPTR$(A%) + ",=" + VARPTR$(B%)
                          DRAW "M" + STR$(A%) + "," + STR$(B%)

 This command moves the pointer to pixel location (200,120) on the
 screen.

 DRAW "X" is another powerful command. This command allows you to
 execute a substring of commands. The BASIC reference describes this as
 being a powerful tool to execute second, third, etc. strings, but does
 not give any examples.

 The DRAW "X" command allows you to embed draw commands within a string
 variable and then execute that string at any point. This is a nice
 concept but can be accomplished with simpler means. The following is
 an example of DRAW "X":

    D$ = "F60 L120 E60 BD30 P1,2 BU30 E60 L120 F60 BU30 P1,2"
    DRAW "X" + VARPTR$(D$)

 The above command draws two triangles, sitting one on top of the
 other, and fills them both in. The following two commands do the same
 thing:

    DRAW "F60 L120 E60 BD30 P1,2 BU30 E60 L120 F60 BU30 P1,2"
 or
    D$ = "F60 L120 E60 BD30 P1,2 BU30 E60 L120 F60 BU30 P1,2"
    DRAW D$

 You can use whichever DRAW syntax is easiest for you.

 Note: Remember the following when using DRAW:

 1. If your "n" value is an INTEGER, use string concatenation with
    VARPTR$() and EQUAL signs, or use STR$().

 2. If your "n" value is assigned as a STRING variable, use string
    concatenation.

 This Graphics Macro Language (GML) is a very powerful addition to the
 BASIC language, but there are limitations. The DRAW statement just
 draws graphics, it does not have any conditional or looping
 statements. Therefore, the DRAW "X" command is not recursive.

 Please refer to the BASIC language reference for further details about
 the DRAW statement.


 546. Amdek Has CLREPC.EXE to Help with Keyboard Incompatibilities

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890217-27 B_BasicCom
 Last Modified: 12-NOV-1990    ArticleIdent: Q41582

 Amdek has a keyboard driver called CLREPC.EXE to help with keyboard
 incompatibilities with QuickBASIC. To obtain this file, you can call
 Amdek Product Support at (408) 435-2832. This program is not
 guaranteed by Microsoft to work properly and is only mentioned for
 your information.

 This information applies to QB.EXE from Microsoft QuickBASIC versions
 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50, to QB.EXE from Microsoft BASIC
 Compiler versions 6.00 and 6.00b, and to QBX.EXE from Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS.

 It is best to create a batch file that loads the CLREPC.EXE driver and
 then invokes QuickBASIC. The following is a sample batch file:

    clrepc
    C:\<PATH NAME>\QB
    set epc

 This loads the driver, runs QuickBASIC, and then resets the keyboard
 after you exit QuickBASIC.

 This keyboard correction does not let you highlight text with the
 extended-keyboard cursor keys; instead, you must use the numeric
 keypad with the SHIFT key.


 547. LINK Options Can Be Specified in AUTOEXEC.BAT with SET LINK=

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890213-93
 Last Modified: 14-DEC-1989    ArticleIdent: Q41583

 LINK options can be set in your AUTOEXEC.BAT file (or in the MS-DOS
 command line) as an environment variable with the statement "SET
 LINK=options". The following is an example

    SET LINK=/NOE /NOI /E

 where /NOE is NOEXTDICTIONARY, /NOI is NOIGNORECASE, /E is EXEPACK.

 This behavior can cause some unexpected errors to occur because you
 might forget what LINK switches are SET in your AUTOEXEC.BAT file.

 If the /E [XEPACK] switch is SET within your AUTOEXEC.BAT FILE and you
 attempt to create a Quick library with the /Q [UICKLIB] switch, the
 following linker error is generated:

    L1003    /QUICKLIB, /EXEPACK incompatible

 To make Quick libraries with /E [XEPACK] set as a LINK option, use
 /NOP [ACKCODE] to turn /E [XEPACK] off.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00
 and 6.00b, and Microsoft BASIC PDS Version 7.00.


 548. CodeView Does Not Watch Local Variables in Subprogram

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 fixlist4.00b fixlist4.50 B_BasicCom
 Last Modified: 19-APR-1990    ArticleIdent: Q60857

 CodeView does not display correct values for local variables in
 SUBprograms in QuickBASIC Version 4.00. With local individual
 (nonarray) variables, the watch always displays 0 (or "" for strings).
 Adding a watch on a local array element causes CodeView to display the
 message "Too many array bounds given." This is a problem with the
 BC.EXE 4.00 compiler, not with CodeView.

 Microsoft has confirmed this to be problem in Microsoft QuickBASIC
 Version 4.00 for MS-DOS. This problem was corrected in Microsoft
 QuickBASIC Versions 4.00b and 4.50 for MS-DOS, Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2 (fixlist6.00,
 fixlist6.00b), and Microsoft BASIC Professional Development System
 (PDS) Version 7.00 (fixlist7.00).

 Code Example
 ------------

 The following code example demonstrates the problems with watching a
 local variable in a SUB in CodeView with QuickBASIC 4.00. Use the
 following steps to reproduce this problem:

 1. Compile the program with /Zi, and link with /CO with the BC.EXE
    4.00 compiler. You cannot do this from within the QuickBASIC
    environment.

 2. Start CodeView as follows:

       CV localv.exe

 3. Step through the program using the F8 key until you are inside the
    SUBprogram.

 4. Choose Add Watch from the Watch menu (or press CTRL+W). Type the
    name of the variable to be watched in the dialog box.

 5. Continue to step through the subprogram with the F8 key. The
    variables being watched will not change in the watch window.

 Code Example
 ------------

    'Compile and link lines:
    '
    ' BC /Zi localcv;
    ' LINK /CO localcv;
    CALL test(1)
    END

    SUB test (param%)                 'Watch param% displays correctly
    DIM array%(10)                    'Watch array%(10) -> Too many
                                      'bounds
    locali% = 10                      'Watch locali% displays 0
    PRINT param%, locali%, array%(10) 'These print correctly
    END SUB


 549. Wrong Colors Displayed If Map Mask Register Set Incorrectly

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900306-100 B_BasicCom
 Last Modified: 14-MAY-1990    ArticleIdent: Q60963

 If the color of a CIRCLE, DRAW, LINE, PCOPY, PSET, or PRESET statement
 does not turn out correctly in an EGA or VGA screen mode (except
 SCREEN 13), make sure that the lower 4 bits (bits 0 through 3) of the
 Mask Map register (&H3C5) are set. If any of these bits are cleared
 (not set), an attribute whose number requires those bits set will not
 be displayed properly.

 To set the lower 4 bits (also called the "low nibble") of the Mask Map
 register, execute the following statement:

    OUT &H3C5, INP(&H3C5) OR 15

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS, and Microsoft BASIC Professional
 Development System (PDS) version 7.00 for MS-DOS.

 Some graphics programming tasks require the manipulation of the mask
 map register, the most common of these being the use of BLOAD in an
 EGA or VGA screen mode (except SCREEN 13). The lower 4 bits of the
 register determine which attributes are used when color is displayed
 on the screen. If any of these bits are cleared and the attribute
 being used requires that they be set, the color that the attribute
 represents will not be displayed. Since the possible attributes for
 the affected screen modes range from 0 to 15, only 4 bits are needed
 for this purpose.

 For example, if all 4 bits are set, the low nibble of the map mask
 register has this internal representation:

      3   2   1   0
    +---+---+---+---+
    | 1 | 1 | 1 | 1 |
    +---+---+---+---+

    2^0 + 2^1 + 2^2 + 2^3 = 1 + 2 + 4 + 8 = 15

 The nibble equals 15, allowing all attributes to be displayed.

 If the nibble is set to 13, it will look like the following:

      3   2   1   0
    +---+---+---+---+
    | 1 | 1 | 0 | 1 |
    +---+---+---+---+

    2^0 + 2^2 + 2^3 = 1 + 4 + 8 = 13

 Since bit 1 is cleared in this case, any attribute that requires bit 1
 set will not be displayed.

 Let's look at how this will affect the display of attribute 14, which
 has this internal representation:

      3   2   1   0
    +---+---+---+---+
    | 1 | 1 | 1 | 0 |
    +---+---+---+---+

    2^1 + 2^2 + 2^3 = 2 + 4 + 8 = 14

 Attribute 14 requires that bit 1 be set. Since bit 1 is cleared in the
 map mask register, attribute 14 cannot actually be displayed. Any
 reference to it in a graphics statement actually yields attribute 12,
 (which is just attribute 14 without bit 1 set) as in the following
 example:

      3   2   1   0
    +---+---+---+---+
    | 1 | 1 | 0 | 0 |
    +---+---+---+---+

    2^2 + 2^3 = 4 + 8 = 12

 As mentioned above, the low nibble of the map mask register affects
 the color of the CIRCLE, DRAW, LINE, PCOPY, PSET, or PRESET
 statements. However, CIRCLE, DRAW, and LINE reset the nibble to 15
 upon their completion, so the color of the next graphics statement
 executed will turn out properly. Also any PRINT or CLS statement will
 reset the nibble. PCOPY, PSET, and PRESET have no effect on the map
 mask register.

 The following sample program demonstrates the effects of changing the
 low nibble of the map mask register. Each of the affected graphics
 statements is used to draw an object with 14 (yellow) as the
 attribute. Then the low nibble of the map mask register is set to 13,
 which clears bit 1. The graphics statement is again executed using
 attribute 14, but the attribute actually used to draw the color will
 be 12 (light red). The third time the graphics statement is executed,
 the attribute used will be 14 for CIRCLE, DRAW, or LINE, and 12 again
 for PCOPY, PSET, and PRESET.

 The statements DRAW and LINE become special cases if they are used to
 draw multiline objects. In this situation, only the first line of the
 object will have the wrong color because after it is drawn, the low
 nibble of the map mask register will be reset to 15. For example, if
 the LINE statement is used to draw a box (using the B parameter), the
 bottom line of the box will have the wrong color because it is drawn
 first, but the rest of the lines will use the correct attribute. This
 is also true with the DRAW statement -- each line drawn within the
 string macro constitutes a separate call to the LINE statement.

 The following program example contains SLEEP statements in certain
 places so you can view the results:

 'This program will work in SCREEN modes 7, 8, 9, 10, 11, and 12.

 SCREEN 9

 LINE (100, 0)-(100, 349), 14 'attribute 14 will be used.
 OUT &H3C5, 13                'clear bit 1 of map mask register.
 LINE (300, 0)-(300, 349), 14 'attribute 12 will be used instead of
                              '14.
 LINE (500, 0)-(500, 349), 14 'attribute 14 can be used again.
 SLEEP

 CLS                   'bits 0-3 of map mask register will be set.
 PSET (100, 150), 14   'attribute 14 will be used.
 OUT &H3C5, 13         'clear bit 1 of map mask register.
 PSET (300, 150), 14   'attribute 12 will be used instead of 14.
 PSET (500, 150), 14   'attribute 12 will still be used.
 SLEEP

 CLS                        'bits 0-3 of map mask register will be
                            'set.
 CIRCLE (100, 150), 20, 14  'attribute 14 will be used.
 OUT &H3C5, 13              'clear bit 1 of map mask register.
 CIRCLE (300, 150), 20, 14  'attribute 12 will be used instead of 14
 CIRCLE (500, 150), 20, 14  'attribute 14 can be used again.
 SLEEP

 CLS                     'bits 0-3 of map mask register will be set.
 PRESET (100, 150), 14   'attribute 14 will be used.
 OUT &H3C5, 13           'clear bit 1 of map mask register.
 PRESET (300, 150), 14   'attribute 12 will be used instead of 14.
 PRESET (500, 150), 14   'attribute 12 will still be used.
 SLEEP

 CLS                     'bits 0-3 of map mask register will be set.
 DRAW "C14BM100,0D349"   'attribute 14 will be used.
 OUT &H3C5, 13           'clear bit 1 of map mask register.
 DRAW "C14BM300,0D349"   'attribute 12 will be used instead of 14.
 DRAW "C14BM500,0D349"   'attribute 14 can be used again.
 SLEEP

 CLS                        'bits 0-3 of map mask register will be
                            'set.
 DRAW "C14BM100,0D349R100"  'attribute 14 will be used for both
                            'lines.
 OUT &H3C5, 13              'clear bit 1 of map mask register.
 DRAW "C14BM300,0D349R100"  'attribute 12 will be used for the 1st
                            'line
                            'drawn but 14 can be used for the 2nd
                            'line.
 DRAW "C14BM500,0D349R100"  'attribute 14 will be used for both
                            'lines.
 SLEEP

 CLS                               'bits 0-3 of map mask register
                                   'will be set.
 LINE (100, 0)-(150, 349), 14, B   'attribute 14 will be used for all
                                   'sides of the box.
 OUT &H3C5, 13                     'clear bit 1 of map mask register.
 LINE (300, 0)-(350, 349), 14, B   'attribute 12 will be used for the
                                   'bottom side of the box (the 1st
                                   'line drawn) but the other sides
                                   'can
                                   'use attribute 14.
 LINE (500, 0)-(550, 349), 14, B   'attribute 14 will be used for all
                                   'sides of the box.
 SLEEP

 CLS                            'bits 0-3 of map mask register will
                                'be set.
 LINE (300, 0)-(300, 349), 14   'attribute 14 will be used.
 SLEEP
 SCREEN 9, , 1, 1               'switch from page 0 to page 1.
 OUT &H3C5, 13                  'clear bit 1 of map mask register.
 PCOPY 0, 1                     'the copied line will use attribute
                                '12
                                'instead of 14.
 PCOPY 0, 1                     'the copied line will still use
                                'attribute 12.


 550. Syntax Error, Duplicate Definition, Expected:Variable=Express

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890209-84 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q42321

 The sample code below shows three very closely related pairs of BASIC
 code. Each example produces a different error, as shown.

 This information applies to the QB.EXE environment supplied with
 QuickBASIC Versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS, and the QBX.EXE environment
 supplied with Microsoft BASIC PDS Version 7.00 for MS-DOS.

 Under QuickBASIC Version 3.00, all three code segments produce the
 error message "MISSING =".

 The following are code examples:

 ' PROG #1
      bd% = 6
      bd% - 13 = c   ' "Expected: variable= expression"

 ' PROG #2
      bd% = 6        ' "Duplicate Definition"
      bd - 13 = c

 ' PROG #3
      x% = 6
      bd - 13 = c    ' "Syntax error"


 551. "Symbol Defined More Than Once" Linking to QuickC 2.00 Routine

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_QuickC S_C
 Last Modified: 19-OCT-1990    ArticleIdent: Q42323

 Calling C routines compiled with Microsoft QuickC Compiler version
 2.00 works correctly only from BASIC routines compiled with Microsoft
 QuickBASIC version 4.50 or Microsoft BASIC PDS version 7.00. Using
 versions of QuickBASIC earlier than 4.50 or using BASIC compiler 6.00
 or 6.00b results in numerous LINK errors of "Symbol Defined More Than
 Once" (L2025).

 If the QuickC library includes the C Graphics or Pgchart library
 routines, then QuickBASIC version 4.50 calling programs must be
 compiled without the /O option (using the BRUN45 library instead of
 BCOM45); otherwise, you will get many "Symbol Defined More Than Once"
 errors at link time.

 The presence of the Graphics or Pgchart libraries does not affect
 LINKing with Microsoft BASIC PDS 7.00.

 QuickBASIC versions 4.00 and 4.00b and Microsoft BASIC Compiler
 versions 6.00 and 6.00b require QuickC version 1.00 or 1.10.

 QuickBASIC version 4.50 requires QuickC version 2.00.

 For more information about linked Microsoft QuickBASIC or compiled
 BASIC with Microsoft C, search in this Knowledge Base using the
 following word:

    BAS2C


 552. Period in Name of NAMED COMMON Can Erase BLANK COMMON Values

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q42324

 The following information applies to the QB.EXE editor in Microsoft
 QuickBASIC Versions 4.00, 4.00b, and 4.50 and to QB.EXE in Microsoft
 BASIC Compiler Versions 6.00 and 6.00b.

 When CHAINing between two programs that contain COMMON blocks, the
 values are not passed under the following conditions:

 1. Both programs contain at least one blank and one named COMMON
    block.

 2. The program being CHAINed to contains an additional COMMON block
    with variables declared as a user-defined TYPE.

 3. The "Names" of the named COMMON blocks contain periods.

 The COMMON values are passed correctly if the periods are removed from
 the names in the COMMON blocks, or if the additional COMMON block with
 a user-defined TYPE is removed.

 This problem occurs only when running the programs from within the
 QB.EXE environment. It does not occur when the programs are run as
 compiled programs.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in QB.EXE in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b (buglist6.00, buglist6.00b). The problem was
 corrected in QBX.EXE in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 (fixlist7.00).

 Code Example
 ------------

 If the following program is run inside the QuickBASIC environment,
 the values in the blank COMMON block are not passed to PROGRAM #2.
 If the COMMON block name /named.block1/ is changed to /namedblock1/
 or the COMMON block following the user-defined TYPE in PROGRAM #2 is
 removed, then the values are passed correctly, as follows:

 'PROGRAM #1
 '
 COMMON SHARED a1%, a2&, a3!, a4#
 COMMON SHARED /named.block1/ b1%, b2&, b3!, b4#

 CLS
 a1% = 1: a2& = 64000: a3! = 1.5: a4# = 64000.5
 CHAIN "prog2.bas"
 END

 'PROGRAM #2
 '
 TYPE UserDefinedType
   c1 AS INTEGER
   c2 AS INTEGER
 END TYPE
 COMMON SHARED a1%, a2&, a3!, a4#
 COMMON SHARED /named.block1/ b1%, b2&, b3!, b#
 COMMON SHARED /namedblock2/ var1 AS UserDefinedType

 PRINT a1%, a2&, a3!, a4#
 END

 To prevent this problem, and to follow a good general rule, use only a
 period in a name when accessing a field of a variable that is
 DIMensioned as a user-defined TYPE.


 553. 4.50 Language Manual Error Page 33 "while program is running"

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890306-90 docerr
 Last Modified: 15-MAR-1989    ArticleIdent: Q42325

 In the first paragraph on Page 33 of the "Microsoft QuickBASIC 4.50:
 BASIC Language Reference," the sentence should read "The storage taken
 by dynamic arrays can be eliminated while the program is running ..."
 instead of "The storage ... while the program is NOT running."


 554. Wrong Example in QB Advisor for CALL INTERRUPT

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890220-8 docerr
 Last Modified: 12-NOV-1990    ArticleIdent: Q42326

 The code example for CALL INTERRUPT in the QuickBASIC version 4.50 QB
 Advisor hypertext online Help system is the wrong example because it
 is actually a code example for CALL INT86OLD, and the CALL INTERRUPT
 example is missing. In addition, two errors need correcting in this
 CALL INT86OLD example. Working examples of CALL INT86OLD (corrected)
 and CALL INTERRUPT are shown below.

 The following two errors need to be corrected in the CALL INT86OLD
 example that comes up on the QuickBASIC 4.50 QB Advisor "Help: Call
 Interrupt Statement Programming Example":

 1. The following incorrect line

       $INCLUDE: 'QB.BI'    [Gives "Expected: Statement" error in QB.EXE.]

    should be corrected to read as follows:

       REM $INCLUDE: 'QB.BI'

 2. The following incorrect line

       INARY%(DX) = SADD("FOO.TXT" + CHR$(0))  ["Expected: Variable" error.]

    should be changed into the following two lines:

       a$ = "FOO.TXT" + CHR$(0)
       INARY%(DX) = SADD(a$)

 The corrected CALL INT86OLD example is shown in Example 1 below.

 The CALL INTERRUPT statement is shown in Example 2 below. A code
 example for CALL INTERRUPT can also be found on Pages 74-76 of
 "Microsoft QuickBASIC 4.5: BASIC Language Reference," which is sold
 separately (see the order card in the 4.50 package).

 In the QBX.EXE Microsoft Advisor online Help system (for Microsoft
 BASIC PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2), the CALL
 INTERRUPT code example correctly displays on the "Help: Interrupt,
 Interruptx Routines Programming Example" screen (and the example works
 correctly).

 Note that the INT86OLD and INT86XOLD routines are not documented in
 any printed or online documentation in BASIC PDS 7.00 and 7.10, as
 explained in a separate article found by querying with the following
 words:

    INT86OLD and help and docerr

 Example 1: CALL INT86OLD Example (Corrected)
 --------------------------------------------

 ' Note:  To use CALL INTERRUPT, you must load the Quick library QB.LIB
 '        with QuickBASIC. The program also uses the QB.BI header file.

 ' Include header file for INT86OLD, etc.
 REM $INCLUDE: 'QB.BI'  ' Added REM to correct "Expected: Statement" error

 DIM INARY%(7), OUTARY%(7)         'Define input and output
                   'arrays for INT86.
 '
 ' Define register-array indices to
 ' make program easier to understand.
 CONST AX = 0, BX = 1, CX = 2, DX = 3, bp = 4, si = 5, di = 6, FL = 7
 '
 INARY%(AX) = &H3C00               'DOS function to create a file.
 INARY%(CX) = 0                    'DOS attribute for created file.
 a$ = "FOO.TXT" + CHR$(0)   ' Added this line and modified next line to
 INARY%(DX) = SADD(a$)      ' correct "Expected: Variable" error.
                   'Pointer to file-name string
                   'with zero byte termination.

 CALL INT86OLD(&H21, INARY%(), OUTARY%())
                   'Perform the creation.
 '
 INARY%(BX) = OUTARY%(AX)          'Move created file handle for write.
 INARY%(AX) = &H4000               'DOS function to write to file.
 TEXT$ = "hello, world" + CHR$(13) + CHR$(10)
                   'Define text to write to file.
 INARY%(CX) = LEN(TEXT$)           'Get length of text string.
 INARY%(DX) = SADD(TEXT$)          'Get address of text string.
 CALL INT86OLD(&H21, INARY%(), OUTARY%())
                   'Perform the write.
 '
 INARY%(AX) = &H3E00               'DOS function to close a file.
 CALL INT86OLD(&H21, INARY%(), OUTARY%())
                   'Perform the close.

 Example 2: CALL INTERRUPT Example (not found in QB Advisor 4.50 Help)
 ---------------------------------------------------------------------

 'This example uses the Interrupt routine to determine the current
 'drive and the amount of free space remaining on the drive.

 'Note: To use the Interrupt routine, you must load the Quick library
 'QB.QLB using the /L switch when you begin QB. The following include
 'file must also be present.

 '$INCLUDE: 'QB.BI'

 'Define registers.
 DIM regs AS RegType

 'Get current drive info; set up input and do system call.
 regs.ax = &H1900
 CALL INTERRUPT(&H21, regs, regs)

 'Convert drive info to readable form.
 Drive$ = CHR$((regs.ax AND &HFF) + 65) + ":"

 'Get disk free space; set up input values and do system call.
 regs.ax = &H3600
 regs.dx = ASC(UCASE$(Drive$)) - 64
 CALL INTERRUPT(&H21, regs, regs)

 'Decipher the results.
 SectorsInCluster = regs.ax
 BytesInSector = regs.cx
 IF regs.dx >= 0 THEN
     ClustersInDrive = regs.dx
 ELSE
     ClustersInDrive = regs.dx + 65536
 END IF
 IF regs.bx >= 0 THEN
     ClustersAvailable = regs.bx
 ELSE
     ClustersAvailable = regx.bx + 65536
 END IF
 Freespace = ClustersAvailable * SectorsInCluster * BytesInSector

 'Report results.
 CLS
 PRINT "Drive "; Drive$; " has a total of";
 PRINT USING "###,###,###"; Freespace;
 PRINT " bytes remaining free."


 555. PRINT SPC(80) Statement May Not Wrap to the Next Line

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q42329

 In Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50, Microsoft
 BASIC Compiler Versions 6.00 and 6.00b, and Microsoft BASIC PDS
 Version 7.00, the SPC() function does not cause output to wrap around
 to the next line(s). In QuickBASIC Version 3.00, the SPC() function
 wraps to the next line.

 For comparison, the SPACE$() function wraps to the next line in all
 versions.

 The nonwrapping behavior of the SPC() function is an intentional
 feature in QuickBASIC Versions 4.00, 4.00b, and 4.50, BASIC compiler
 Versions 6.00 and 6.00b, and Microsoft BASIC PDS Version 7.00. If the
 value given to the SPC() function is greater than the defined screen
 width, the spacing will be: <desired spacing> MOD <width>. For
 example, the following line would actually print "Hello" in column 3
 of the same line:

    PRINT SPC(83);"Hello"

 The documentation on this function is incomplete and will be
 corrected. Microsoft will post new information here as it becomes
 available.

 In the following code example, both outputs will incorrectly be on the
 same line:

 REM *** SPC() problem example ***
 CLS : LOCATE 1,1 : PRINT "           XXX"
 LOCATE 1,1 : PRINT SPC(80); "Hello";
 END

 The SPC(80) function should force the "Hello" literal to be displayed
 on the second line. The SPACE$() function can be used to simulate the
 line wrap, when given the space (Hex 20) character. Note that the
 SPACE$() function overwrites any screen information that comes in its
 path with the new SPACE$() character.


 556. CALL ABSOLUTE Hang; Assembly Must Use CB Return Instruction

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890222-47 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q42465

 An assembly-language routine accessed with CALL ABSOLUTE must use a
 machine-language return instruction of CB hex (a far return), instead
 of C3 hex (a near return).

 The two programs shown below demonstrate that a program hangs if it
 uses CALL ABSOLUTE on an assembly-language routine that returns with a
 return instruction of C3 (Hex). To correct this problem, you must use
 a return instruction of CB (hex).

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 The far-return instruction CB (hex) correctly pops 4 bytes off the
 stack for a segment and offset to return. Near-return C3 (hex) pops
 only 2 bytes off the stack for an offset, which is inappropriate.

 The following is a good reference for the machine instructions in the
 Intel 8086 family of microprocessors: "The 80386 Book: Assembly
 Language Programmer's Guide for the 80386," by Ross Nelson (published
 by Microsoft Press, 1988).

 The following program is TEST1.BAS. It calls an assembly-language
 routine that prints an "A" on the screen. It uses the correct return
 code of CB.

 DIM ASMROUTINE(1 TO 6) AS INTEGER
 DATA &H55       : ' PUSH BP       Save base pointer
 DATA &H8B,&HEC  : ' MOV BP,SP     Get our own
 DATA &HB4,2     : ' MOV AH,2      Function 2 - print to screen
 DATA &HB2,65    : ' MOV DL,65     Character 'A'
 DATA &HCD,&H21  : ' INT 21H       Make ROM BIOS call
 DATA &H5D       : ' POP BP        Restore base pointer
 DATA &HCB,0     : ' RET           Far Return (correct)     <-----
 OFFSET = VARPTR(ASMROUTINE(1))
 DEF SEG = VARSEG(ASMROUTINE(1))
 ' Poke assembly routine into memory:
 FOR I = 0 TO 11
      READ ASMCODE
      POKE (OFFSET + I), ASMCODE
 NEXT I
 CALL ABSOLUTE(VARPTR(ASMROUTINE(1)))     ' call routine we poked in
 DEF SEG
 END

 The following program, TESTS.BAS, uses the incorrect return code and
 hangs the machine:

 DIM ASMROUTINE(1 TO 6) AS INTEGER
 DATA &H55           : ' PUSH BP      Save base pointer
 DATA &H8B,&HEC      : ' MOV BP,SP    Get our own
 DATA &HB4,2         : ' MOV AH,2     Function 2 - print to screen
 DATA &HB2,65        : ' MOV DL,65    Character 'A'
 DATA &HCD,&H21      : ' INT 21H      Make ROM-BIOS call
 DATA &H5D           : ' POP BP       Restore base pointer
 DATA &HC3,0         : ' RET          Near Return (incorrect)  <-----
 OFFSET = VARPTR(ASMROUTINE(1))
 DEF SEG = VARSEG(ASMROUTINE(1))
 ' Poke assembly routine into memory:
 FOR I = 0 TO 11
      READ ASMCODE
      POKE (OFFSET + I), ASMCODE
 NEXT I
 CALL ABSOLUTE(VARPTR(ASMROUTINE(1)))      ' call routine we poked in
 DEF SEG
 END


 557. "RETURN Without GOSUB"; Btrieve BTVRFAR Fails with BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890227-68 B_BasicCom
 Last Modified: 20-AUG-1990    ArticleIdent: Q42466

 Btrieve now has a procedure named BTRVFAR, which is intended to allow
 Btrieve to access variables outside of the near heap. This procedure
 is not compatible with BASIC and may cause the error message "RETURN
 without GOSUB" to be displayed, even though no such error exists. In
 some cases, the program may work correctly in the trace mode or even
 in the normal mode after the program has been run once with the trace
 function on.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler Version 6.00 and 6.00b for MS-DOS and MS
 OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and OS/2. Please
 note that BASIC PDS 7.00 for MS-DOS and has its own ISAM file system,
 making Btrieve, a third-party ISAM support product, unnecessary.

 This compatibility problem occurs whether executed from within the
 QB.EXE environment of QuickBASIC, the QBX.EXE environment of the BASIC
 PDS 7.00, or from an executable program compiled with BC.EXE.

 The solution to the problem is to use the older Btrieve procedure
 named BTRV. Shown below is the only change necessary for most programs
 using BTRVFAR to convert them to use BTRV.

 Code Example
 ------------

 ' This code is incomplete; only the highlights are shown
 OPEN "NULL" FOR RANDOM AS #1 LEN = 40
 FIELD #1 40 AS A$
 OP%=0
 BLK$=SPACES(128)
 BLEN%= 40
 KBUF$ = "FileName"
 KNUM% = 0

 FCB% = SADD(A$) - 188

 'Use:
   CALL BTRV( OP%, STAT%, BLK$, FCB%, BLEN%, KBUF$, KNUM%)
 'Instead of:
 '  CALL BTRVFAR(OP%,STAT%,BLK$,SADD(A$),VARSEG(A$),BLEN%,KBUF$,KNUM%);


 558. If FRE(-2) Returns Small Negative Values, Increase Stack

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890218-1 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q42467

 FRE(-2) returns negative values if bytes are added to the stack in
 small increments as the stack starts to run out of space. The negative
 number is an indication that stack space is extremely low. To increase
 stack space use

    CLEAR ,,stacksize

 if using QuickBASIC 4.00, 4.00b, or 4.50 or Microsoft BASIC Compiler
 Version 6.00 or 6.00b.

 If using Microsoft BASIC PDS Version 7.00, you can use either the
 CLEAR statement or the STACK statement. For example, to set the stack
 size as the program is running use:

    STACK stacksize

 where stacksize is the number of bytes that you want for the stack.
 The default stack size is in QuickBASIC 4.00, 4.00b, 4.50 and the
 BASIC compiler 6.00 and 6.00b is 2000 bytes. The default stacksize in
 BASIC PDS 7.00 is 3K under DOS or 3.5K under OS/2 protected mode.
 CLEAR also closes all files and releases file buffers, clears all
 COMMON variables, sets numeric variables and arrays to zero, sets
 string variables to null, and deallocates dynamic arrays. To save
 values in variables, use CLEAR to set the stack size in the beginning
 of the program. The STACK statement in BASIC PDS 7.00 resets the stack
 size without any of the side effects of the CLEAR statement. The stack
 space can also be set at link time with the /ST:stacksize option,
 where stacksize is the number of bytes in the stack.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.


 559. QB.EXE Hang or "Division by Zero" with Labeled REM $INCLUDE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q42468

 In the QB.EXE environment in QuickBASIC Version 4.50, a statement
 consisting of a line number (or label) followed by two or more spaces
 and then REM $INCLUDE: 'file', where "file" does not exist, displays a
 "Binding" message and hangs your machine at compile time.

 In QuickBASIC Versions 4.00 and 4.00b, attempting to compile the same
 program from within the QB.EXE environment generates the error
 "Division By Zero."

 Microsoft has confirmed these to be problems in QuickBASIC Versions
 4.00, 4.00b, and 4.50. This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).

 If there is only one space between the line-number or label and REM
 $INCLUDE, the correct error message is generated: "File Not Found."

 Your machine will not hang and the correct error message will be
 generated if compiled using BC.EXE.

 Code Example
 ------------

 05  '**** PROGRAM #1 ****
 06  '
 10  ' Compiling this program from within the environment will hang
 20  ' your machine in QB 4.50 and will give "DIVISION BY ZERO ERROR"
 30  ' in QB 4.00 and QB 4.00b.
 40  '
 50   REM $INCLUDE: 'missing'
 55  ' (Two or more spaces between line-number and REM, and 'missing'
 60  ' does not exist in the current directory.)

 05 '**** PROGRAM #2
 06 '
 10 ' This program will compile and generate the expected error of
 20 '  "FILE NOT FOUND"
 30 '
 40 REM $INCLUDE: 'missing'       --one space between line number and REM


 560. FOR...NEXT with Floating-Point Counter May Not Execute Fully

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890301-38 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q42469

 Because of the nature of the IEEE floating-point format, using a
 floating-point counter (single or double precision) in a FOR NEXT loop
 can result in the loop being executed one fewer time than anticipated.
 Using an integer or long integer instead of floating point for the
 loop counter is the only way to guarantee that all iterations will
 execute.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 The following is an example:

    DEFSNG A-Z
    FOR x = 0 to .8 step .2
      PRINT x" ";
    NEXT x

 This will generate the following results:

    0 .2 .4 .600000000000001

 Note that due to the rounding error in the fourth value, the loop
 counter will be greater than .8 on the next iteration, and the loop
 will execute only four times instead of the expected five times.

 This IEEE rounding behavior occurs in Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50, in the BASIC compiler Versions 6.00 and 6.00b,
 and in BASIC PDS 7.00.

 In most cases, the rounding differences will be minimal when the
 variables and numbers involved are double precision. Changing the
 first line of the example program to the following will allow the loop
 to properly execute five times:

    DEFDBL A-Z


 561. If BC /O, CHAIN "x.BAS" Fails to Give Run-Time Error and Hangs

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890217-22 buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q42470

 If two programs are compiled with the BC /O (stand-alone option), and
 the first program CHAINs to the second program with the following
 CHAIN statement, then the program fails to give an error message for
 the ".BAS" extension:

    CHAIN "prog2.BAS"

 The CHAIN is not executed, and program execution either ends or hangs
 the machine.

 The correct response should be the following run-time error:

   Illegal Function Call in Module "module name" at address XXXX:XXXX

 This information applies only to programs compiled with the
 stand-alone (/O) switch in QuickBASIC Version 4.50. The debug (/D)
 switch does not change the problem. If compiled requiring BRUN45, the
 problem does not occur. The problem also doesn't occur with QuickBASIC
 Version 4.00 or 4.00b or Microsoft BASIC Compiler Version 6.00 or
 6.00b.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50. This problem was corrected in Microsoft BASIC Professional
 Development System (PDS) Version 7.00, (fixlist7.00).

 In Microsoft BASIC PDS 7.00, the run-time error message generated is
 as follows:

   Bad file mode in module MODULE NAME at address XXXX:XXXX

 To work around the problem, do not include an extension on the program
 name in the CHAIN statement. QB.EXE and BC.EXE are able to determine
 which program to CHAIN to if there are two files with the same name
 but different extensions:

   CHAIN "PROG2" will CHAIN to PROG2.BAS in QB.EXE
   CHAIN "PROG2" will CHAIN to PROG2.EXE in BC.EXE

 Code Example
 ------------

 Compiling the following two programs with BC /O demonstrates the
 problem:

    '*** PROGRAM #1 (PROG1.EXE)
    '************
    PRINT "CHAINing to PROGRAM #2"
    CHAIN "prog2.bas"
    END

    '*** PROGRAM #2 (PROG2.EXE)
    '**************
    PRINT "INSIDE PROGRAM #2"
    END


 562. How to Scroll Text in Separately Defined Windows in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890220-5 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q42471

 This article describes how to use a hardware interrupt to define
 scrollable text windows with viewing limits on all four sides. This
 information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50, to
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft
 BASIC PDS Version 7.00 running under MS-DOS.

 In some languages such as PASCAL, text windows are easily defined with
 a function called WINDOW. After a window is defined, all text written
 to the screen appears only within the defined window, and only text
 within the window is scrolled up or down. There are two additional
 functions, DELLINE and INSLINE, that scroll the window contents up or
 down one line.

 Using the VIEW PRINT statements in QuickBASIC, a window can be
 defined, but only Rows (top and bottom, ymax and ymin) can be defined.
 Column limits (left and right, xmin and xmax) cannot be defined. Any
 window defined will always use the entire width of the screen.

 Defining Windows with left, right, top, and bottom limits in
 QuickBASIC requires just a little more work, but it can be done using
 the CALL INTERRUPT routine with Interrupt 10 Hex, functions 06 Hex
 (scroll up) and 07 Hex (scroll down).

 Interrupt 10 Hex, functions 06 Hex and 07 Hex, can define windows and
 scroll text within the defined window, but it does not prevent text
 from being written to other coordinates on the screen. Therefore, it
 is up to the programmer to write routines that will write text to the
 areas defined as Windows. Interrupt 10 Hex, functions 06 Hex and 07
 Hex will scroll the text up or down.

 Code Example
 ------------

 The following program demonstrates the use of Interrupt 10 Hex,
 functions 06 Hex and 07 Hex. Three separate Windows are defined by the
 following:

    Window number
    Window color
    Window limits: left, right, top, bottom

 Random text is written to each Window, scrolling the text up or down
 as required.

 '***************************************
 ' Text Windowing Demonstration program.
 ' (Interrupt 10H, functions 06H and 07H)
 '***************************************
 ' Define the TYPE needed for INTERRUPT (you could
 ' use REM $INCLUDE:'QB.BI' as an alternative under QuickBASIC
 ' 4.00, 4.00b, 4.50 or the BASIC compiler 6.00 or 6.00b. Use
 ' REM $INCLUDE:'QBX.BI' as an alternative under the BASIC
 ' PDS 7.00):

 TYPE RegType
      ax    AS INTEGER
      bx    AS INTEGER
      cx    AS INTEGER
      dx    AS INTEGER
      bp    AS INTEGER
      si    AS INTEGER
      di    AS INTEGER
      flags AS INTEGER
 END TYPE
 DECLARE SUB Interrupt (intnum%, inregs AS RegType, _
                        outregs AS RegType)
 DECLARE SUB ScrollWindowUp (windowN%, numlines%)
 DECLARE SUB ScrollWindowDown (windowN%, numlines%)
 DECLARE SUB InitializeWindow (windowN%,Wcolor%,left%,_
                               top%,right%,bottom%)
 DECLARE SUB DrawBorder (windowN%)
 DIM SHARED windows(5, 5) AS INTEGER      'allow max of 5 windows
 DIM SHARED inregs AS RegType, outregs AS RegType

 CLS
 VIEW PRINT                           'use entire screen 25 X 80
 LOCATE 25, 27
 COLOR 15, 6
 PRINT " PRESS ANY KEY TO QUIT ";
 InitializeWindow 1, 5, 10, 35, 3, 21               'Initialize 3
 InitializeWindow 2, 2, 45, 70, 3, 11               'separate windows
 InitializeWindow 3, 1, 40, 70, 15, 21

 DO
   LOCATE 22, 11
   COLOR 15, windows(1, 1)
   FOR I% = 1 TO 26                           'print one full line of
     PRINT CHR$(INT(RND * 200) + 32);         'random characters at
   NEXT I%                                    'bottom of Window #1 and
   ScrollWindowUp 1, 1                        'Scroll Up one line

   LOCATE 12, 46
   COLOR 15, windows(2, 1)
   FOR I = 1 TO 26                            'print one full line of
     PRINT CHR$(INT(RND * 200) + 32);         'random characters at
   NEXT                                       'bottom of Window #2 and
   ScrollWindowUp 2, 1                        'Scroll Up one line

   LOCATE 16, 41
   COLOR 15, windows(3, 1)
   FOR I = 1 TO 31                            'print one full line of
     PRINT CHR$(INT(RND * 200) + 32);         'random characters at
   NEXT I                                     'top of Window #3 and
   ScrollWindowDown 3, 1                      'Scroll Down one line
 LOOP UNTIL INKEY$ <> ""
 END

 '********************************************************************
 ' SUBprogram: InitializeWindow - Interrupt 10H function 06H or 07H
 '             Stores the Window information for the Window specified
 '             in the ARRAY windows, then uses
 '             CALL INTERRUPT with Interrupt 10H to initialize Window
 '
 '                AH = function 06H or 07H (scroll up or scrol down)
 '                AL = 00H   if zero, window is blanked
 '                BH = color of window
 '                CH = top window border
 '                CL = left window border
 '                DH = bottom window border
 '                DL = right window border
 '********************************************************************
 SUB InitializeWindow(windowN%, Wcolor%, left%, right%, top%, bottom%)
   windows(windowN%, 1) = Wcolor%
   windows(windowN%, 2) = left%
   windows(windowN%, 3) = top%
   windows(windowN%, 4) = right%
   windows(windowN%, 5) = bottom%
   inregs.ax = &H600
   inregs.bx = Wcolor% * 4096
   inregs.cx = top% * 256 + left%
   inregs.dx = bottom% * 256 + right%
   CALL Interrupt(&H10, inregs, outregs)
   DrawBorder windowN%
 END SUB

 '**********************************************************
 ' SUBprogram: ScrollWindowDown - Interrupt 10H function 07H
 '
 '             AH = function 07H
 '             AL = number of lines to scroll
 '             BH = window color
 '             CH = top window border
 '             CL = left window border
 '             DH = bottom window border
 '             DL = right window border
 '**********************************************************
 SUB ScrollWindowDown (windowN%, numlines%)
   inregs.ax = 1792 + numlines%
   inregs.bx = windows(windowN%, 1) * 4096
   inregs.cx = windows(windowN%, 3) * 256 + windows(windowN%, 2)
   inregs.dx = windows(windowN%, 5) * 256 + windows(windowN%, 4)
   CALL Interrupt(&H10, inregs, outregs)
 END SUB

 '********************************************************
 ' SUBprogram: ScrollWindowUp - Interrupt 10H function 06H
 '
 '             AH = function 06H
 '             AL = number of lines to scroll
 '             BH = window color
 '             CH = top window border
 '             CL = left window border
 '             DH = bottom window border
 '             DL = right window border
 '********************************************************
 SUB ScrollWindowUp (windowN%, numlines%)
   inregs.ax = 1536 + numlines%
   inregs.bx = windows(windowN%, 1) * 4096
   inregs.cx = windows(windowN%, 3) * 256 + windows(windowN%, 2)
   inregs.dx = windows(windowN%, 5) * 256 + windows(windowN%, 4)
   CALL Interrupt(&H10, inregs, outregs)
 END SUB

 '***********************************************
 ' SUBprogram: DrawBorder
 '             Draws a solid border around window
 '             specified using character #219
 '***********************************************
 SUB DrawBorder (windowN%)
   COLOR 14, 0
   FOR I% = windows(windowN%, 3) TO windows(windowN%, 5) + 2
     LOCATE I%, windows(windowN%, 2)
     PRINT CHR$(219)
     LOCATE I%, windows(windowN%, 4) + 2
     PRINT CHR$(219)
   NEXT I%
   FOR I% = windows(windowN%, 2) + 1 TO windows(windowN%, 4) + 1
     LOCATE windows(windowN%, 3), I%
     PRINT CHR$(219)
     LOCATE windows(windowN%, 5) + 2, I%
     PRINT CHR$(219)
   NEXT I%
 END SUB


 563. BASIC Cannot Get Child Process' Return Code or "Error Level"

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890226-3 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q42472

 Languages such as C or Microsoft assembly language allow a program to
 set a return code as the program terminates. The only Microsoft BASIC
 product capable of setting a return code is Microsoft BASIC PDS
 Version 7.00. These return codes are referred to as "error levels" in
 MS-DOS batch file processing.

 However, it is not possible to determine from a BASIC program (even
 BASIC PDS 7.00) what return code was set, even if the C or MASM
 program is executed (SHELLed) as a child process of the BASIC parent
 program.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50; to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 BASIC executes a child process with the SHELL "commandstring"
 statement. When the child process has terminated, the only means to
 determine the returned error code would be a CALL to the DOS INTERRUPT
 21h, function 4Dh ("Get Return Code"). Calling this function from
 BASIC will execute with no adverse effects but will not retrieve the
 correct return code.

 It is also not possible to return an error code from a BASIC program
 to the process that spawned it. For further information on this, query
 on the following words:

    ERRORLEVEL and BASIC

 The following is a code example:

 '*********************** CODE.BAS **************************
 ' This program demonstrates that BASIC cannot retrieve
 ' its child process' return code or "error level".
 ' You must use QB.LIB or QB.QLB for this program.

 ' Under the QBX.EXE environment of BASIC PDS 7.00
 ' the libraries above are QBX.LIB and QBX.QLB respectively.
 ' Additionally the $INCLUDE filename below would be 'QBX.BI'

 REM $INCLUDE: 'qb.bi'
 DIM inregs AS RegType, outregs AS RegType
 CLS
 SHELL "errcode.exe"     ' See C routine below.
 inregs.ax = &H4D00
 CALL INTERRUPT(&H21, inregs, outregs)
 ' Blank out AH. The code is returned in AL
 outregs.ax = outregs.ax AND &HFF
 PRINT "The error level returned was "; outregs.ax
 END

 /***
    Name this C program ERRORCODE.C and ERRORCODE.EXE.
    When this routine is executed as part of a batch file,
    its return code is correctly interpreted when this
    program is SHELLed to by the above BASIC program.
 ***/

 int
 main(void)
 {
 static char prompt[] = {"inside of the c routine\n"};
 printf("%s", prompt);
 return(5);
 }

 REM ************************* TEST.BAT *************************
 ECHO OFF
 REM This batch file demonstrates that the C routine above
 REM correctly returns a return code of 5.
 ERRCODE.EXE
 IF ERRORLEVEL 5 ECHO THE RETURN CODE IS 5


 564. "Overflow" Error Might Be the Result of 0/0

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890309-179 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q42473

 When the error "Overflow" is encountered in a Microsoft QuickBASIC
 program, one possibility is to check for a zero divided by zero (0/0)
 condition.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 Any numeric value divided by zero will produce the error "Division By
 Zero," but zero (0) being divided by zero produces a special floating-
 point exception. This error will cause the compiler to respond with an
 "Overflow" message.

 Both of these errors are correct. The machine could respond by either
 a "Division By Zero" error or an "Overflow" error, depending on the
 following factors:

 1. Is the computer using a coprocessor?

 2. Is the coprocessor functioning correctly?

 3. What operating system are you using? (There was a problem with
    PC-DOS Version 3.20.)

 When diagnosing an "Overflow" error, you may wish to first determine
 if the expression reduces to zero divided by zero. This might save you
 work trying to figure out why your expression is overflowing (or
 exceeding some numerical limit).

 The following is a code example:

 b# = 5
 c# = 5
 PRINT (b#-c#) / (b#-c#) ' This will result in an "Overflow" error


 565. "Array Not Defined"; Must DIMension Array Above Its First Use

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890313-67 B_BasicCom
 Last Modified: 18-DEC-1989    ArticleIdent: Q42474

 Microsoft QuickBASIC Versions 4.00 4.00b and 4.50, Microsoft BASIC
 Compiler Versions 6.00 and 6.00b, and Microsoft BASIC PDS Version 7.00
 are single-pass compilers. This means that all arrays (static or
 dynamic) that are to be used within a BASIC program must be
 DIMensioned physically above where they are first used. The exception
 to this is when they are dynamically declared in a COMMON statement.

 The program below demonstrates how the array dimension is unknown when
 an attempt is made to pass the array to a SUBprogram, even though it
 is DIMensioned logically before it is used. The resulting error will
 be "Array not defined" on the CALL statement. This is expected
 behavior in QuickBASIC, Microsoft BASIC Compiler, and BASIC PDS. The
 program is as follows:

 DECLARE SUB GetStartPos (letterWidth!())
 DEFINT A-Z
 GOSUB DimLetterWidths
 CALL GetStartPos(letterWidth!())
 END

 DimLetterWidths:
   REDIM SHARED letterWidth! (128)  ' REDIM dimensions a dynamic array.
   RETURN

 SUB GetStartPos (letterWidth!())
   PRINT UBOUND (letterWidth!, 1)
 END SUB

 If the array is declared as dynamic by a COMMON statement, the error
 does not occur. Placing the statement COMMON letterWidth!() after the
 DEFINT A-Z line eliminates the error.


 566. BASIC Uses ALIAS to DECLARE C Routines with Underscore in Name

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 30-MAY-1990    ArticleIdent: Q42475

 To call a Microsoft C routine from QuickBASIC, the C routine must
 first be declared using a DECLARE statement. If the C routine name
 contains an embedded underscore, which is improper syntax in
 QuickBASIC, you must use the ALIAS clause to give it a valid BASIC
 name.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler versions 6.00 and 6.00b, and
 Microsoft BASIC Professional Development System (PDS) version 7.00.
 The references to DECLARE, ALIAS, and CDECL can be found on Pages 142
 to 146 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference"
 manual.

 C functions added to a library or Quick library have an underscore
 added to the front of the function name (that is, "foo_bar" will
 become "_foo_bar" in a library). When you DECLARE a C routine in a
 BASIC program, you must use the CDECL clause, which automatically
 adjusts for the underscore at the front of the routine name.

 However, if you want to use the ALIAS clause to DECLARE a C function
 that has an embedded underscore (for example, "foo_bar"), the CDECL
 clause will not add the underscore automatically to the front of the
 ALIAS name.

 The following is an example:

 REM *** BASIC program to call foo_bar ***
 DECLARE SUB foobar CDECL ALIAS "_foo_bar"
 CALL foobar
 END

 /* C function with embedded underscore */
 void foo_bar()
 {
   putch('A');
 }


 567. "Subscript Out of Range" Then Add REM $DYNAMIC Hangs QB 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890228-60 buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q42476

 The following series of actions hang the QuickBASIC 4.50 editor when
 dimensioning a $DYNAMIC huge array:

 1. Start QB with the /AH switch.

 2. Dimension a STATIC array larger than 64K of any type of data except
    variable length strings, as follows:

       'example code. Do not use the metacommand yet.
       DIM  ARRAY1(32000) AS SINGLE ' 128000 bytes

 3. Run the program (press SHIFT+F5). This produces the error "Subscript
    out of range," as expected.

 4. Add REM $DYNAMIC before the DIMension.

 5. Run the program (press SHIFT+F5). The machine usually hangs at this
    point. Occasionally, it produces the error message "String Space
    Corrupt" and returns to the DOS prompt.

 This problem does not occur in the QuickBASIC Versions 3.00, 4.00, or
 4.00b editors and does not apply to .EXE applications compiled with
 BC.EXE in 4.50.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Version 4.50. The problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).
 When the program is run a second time, it does not hang or produce an
 error message.


 568. "Illegal Function Call" Using VIEW, WINDOW, GET, or PUT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890130-51 B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q42553

 When using the QuickBASIC graphics functions GET, PUT, VIEW, and
 WINDOW, it is very easy to encounter the error "Illegal Function
 Call." The error can be generated for many reasons.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 If you encounter the above error, the following are some suggestions
 for determining where the error occurs:

 1. If "Illegal Function Call" occurs on a GET statement, do the
    following:

    a. Make sure you are actually GETting part of the screen or VIEW.

    b. Make sure your array is large enough to hold the image. There is
       a formula in the "Microsoft QuickBASIC: Programming in BASIC"
       manual for Version 4.50 on Page 194 that calculates the size of
       the array:

       sizeinbytes=4+height*planes*INT((width*bitsperpixel/planes+7)/8)

 2. If "Illegal Function Call" occurs on the PUT statement, do the
    following:

    a. Make sure you are PUTting the image within the boundary of your
       WINDOW or VIEW statement.

    b. Certain problems that occur with the WINDOW statement may not
       occur with the WINDOW SCREEN statement. The use of this
       statement is discussed in the "Microsoft QuickBASIC 4.0: BASIC
       Language Reference" manual for Versions 4.00 and 4.00b.

 3. If you use the following code example, when run under QuickBASIC
    Version 4.50, you will get an "Illegal Function Call" when trying
    to execute the PUT statement:

    DEFINT A-Z
    DIM image(40) AS LONG
    SCREEN 9
    VIEW (0,0)-(300,95)     ' Sets the view for the screen
    WINDOW (0,0)-(300,190)  ' Sets screen coordinates
    LINE (0,0)-(300,190),,B ' Draws a box around the vie
    GET (0,1)-(0,189),Image ' Gets vertical image
    SLEEP       10                ' Pause
    PUT (0,1),Image,PSET    ' Put image back to screen
    SLEEP 10                ' Pause

    This error can be corrected in one of two ways:

    a. The VIEW statement can be enlarged, from 95 to 96 or more.

    b. The WINDOW statement can be changed to a WINDOW SCREEN.

    The current program will not accept values of 95 or less with the
    current WINDOW statement, but it will if a WINDOW SCREEN is used.
    This WINDOW SCREEN statement alters the coordinates of the screen
    to create a right-hand coordinate system.


 569. Variable with Periods in COMMON Block Can Cause Problems

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q42586

 In the Microsoft QB.EXE editor, CHAINing between programs that have a
 COMMON block can cause errors, under the following conditions:

 1. The programs have a COMMON block.

 2. The COMMON block contains an array, a user-defined TYPE variable,
    and a simple variable that contains one or more periods.

 The result is an "array not defined" error message in the CHAINed-to
 program. If the period(s) are removed from the simple variable, the
 programs CHAIN and run correctly. This error occurs only when running
 in the QB.EXE editor. The programs execute properly after being
 compiled with BC.EXE.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50. This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).
 Microsoft also recommends that you do not use periods in variable
 names, since the period is now used to distinguish between
 user-defined-TYPE variables. There may be conflicts between the two
 usages.

 In the following program examples, the COMMON block consists of an
 integer array, a user-defined-TYPE variable, and a single-precision
 variable. If PROG1.BAS is run inside the QuickBASIC environment, a
 "Subscript out of range" error occurs in PROG2.BAS, on the PRINT
 statement. This is because the array dimensions have not been
 correctly passed in the COMMON block.

 If the periods are removed from the variable x.to.y in PROG2.BAS, the
 program executes normally. Also, if the programs are compiled as they
 appear here with BC.EXE, they CHAIN together and run properly.

 Code Example
 ------------

 '----------------------------------- PROG1.BAS
 '$DYNAMIC
 TYPE test
   a AS INTEGER
   b AS INTEGER
 END TYPE
 COMMON SHARED c() AS INTEGER
 COMMON SHARED Typed AS test
 COMMON SHARED x.to.y
 DIM SHARED c(1 TO 60) AS INTEGER

 c(3) = 42
 PRINT "Press a key to CHAIN to PROG2..."
 WHILE INKEY$ = "": WEND
 CHAIN "PROG2"
 END

 '----------------------------------- PROG2.BAS
 '$DYNAMIC
 TYPE test
   a AS INTEGER
   b AS INTEGER
 END TYPE
 COMMON SHARED c() AS INTEGER
 COMMON SHARED Typed AS test
 COMMON SHARED x.to.y

 PRINT UBOUND(c), c(3)
 END


 570. QuickBASIC Program to Change the Mouse Shape in Graphics Mode

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890222-68 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q42587

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and
 Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The code shown below demonstrates a method of creating a mouse cursor
 of a different shape when in a graphics mode. This example shape is
 taken from Page 7-31 of the "Microsoft Mouse Programmer's Reference
 Guide" and requires an IBM EGA or IBM VGA or compatible graphics
 adapter.

 The sample BASIC code on Page 6-15 of the same manual is not
 appropriate for QuickBASIC or the BASIC compiler. The following
 changes must be made:

 1. The array "CURSOR" must be dimensioned.

 2. The array "CURSOR" must be in a COMMON block.

 3. The fourth parameter passed to MOUSE on line 4500 must be
    VARPTR(CURSOR(0,0))

 When using BASIC PDS 7.00 it is also possible to use the MOUSEDRIVER
 SUBprogram in the MOUSE.BAS portion of the User Interface Toolbox
 (rather then the CALL INTERRUPT method shown below) to change the
 mouse pointer shape.

 Code Example
 ------------

 DECLARE SUB mouse (m1%, m2%, m3%, m4%)
 DECLARE FUNCTION MouseInit% ()
 DECLARE SUB MouseShow ()
 DECLARE SUB MouseButPos (ButStat%, CurHor%, CurVert%)

 ' The following $INCLUDE filename would be 'QBX.BI' if you
 ' are using the BASIC PDS 7.00:
 ' $INCLUDE: 'qb.bi'

 DEFINT A-Z
 DIM cursor(16, 2)
 COMMON cursor()
 ' Data for an HOUR Glass shape
 'Array Screen Mask             binary
 Cursor(0, 0) = &H07E0         '0000011111100000
 Cursor(1, 0) = &H0180         '0000000110000000
 Cursor(2, 0) = &H0000         '0000000000000000
 Cursor(3, 0) = &HC003         '1100000000000011
 Cursor(4, 0) = &HF00F         '1111000000001111
 Cursor(5, 0) = &HC003         '1100000000000011
 Cursor(6, 0) = &H0000         '0000000000000000
 Cursor(7, 0) = &H0180         '0000000110000000
 Cursor(8, 0) = &H07E0         '0000011111100000
 Cursor(9, 0) = &HFFFF         '1111111111111111
 Cursor(10 0) = &HFFFF         '1111111111111111
 Cursor(11, 0) = &HFFFF        '1111111111111111
 Cursor(12, 0) = &HFFFF        '1111111111111111
 Cursor(13, 0) = &HFFFF        '1111111111111111
 Cursor(14, 0) = &HFFFF        '1111111111111111
 Cursor(15, 0) = &HFFFF        '1111111111111111

 ' Cursor mask                 binary
 Cursor(0, 1) = &H0000         '0000000000000000
 Cursor(1, 1) = &H700E         '0111000000001110
 Cursor(2, 1) = &H1C38         '0001110000111000
 Cursor(3, 1) = &H0660         '0000011001100000
 Cursor(4, 1) = &H03C0         '0000001111000000
 Cursor(5, 1) = &H0660         '0000011001100000
 Cursor(6, 1) = &H1C38         '0001110000111000
 Cursor(7, 1) = &H700E         '0111000000001110
 Cursor(8, 1) = &H0000         '0000000000000000
 Cursor(9, 1) = &H0000         '0000000000000000
 Cursor(10, 1) = &H0000        '0000000000000000
 Cursor(11, 1) = &H0000        '0000000000000000
 Cursor(12, 1) = &H0000        '0000000000000000
 Cursor(13, 1) = &H0000        '0000000000000000
 Cursor(14, 1) = &H0000        '0000000000000000
 Cursor(15, 1) = &H0000        '0000000000000000

 Button$(0) = "Left Up   / Right Up  "
 Button$(1) = "Left Down / Right Up  "
 Button$(2) = "Left Up   / Right Down"
 Button$(3) = "Left Down / Right Down"

 SCREEN 9
 ' this part initializes the mouse
 IF MouseInit = 0 THEN
   PRINT "can not initialize mouse"
   END
 END IF

 ' this is the part that makes the shape
 m1 = 9
 m2 = 7
 m3 = 7
 m4 = VARPTR(cursor(0, 0))
 CALL mouse(m1, m2, m3, m4)

 ' this call turns the mouse cursor on
 MouseShow

 LOCATE 10, 10: PRINT "Button Status :";
 LOCATE 11, 10: PRINT "Horizontal pos :";
 LOCATE 12, 10: PRINT "Vertical pos  :";

 WHILE INKEY$ = ""
 CALL MouseButPos(ButStat, CurHor, CurVert)

 LOCATE 10, 25: PRINT Button$(ButStat)
 LOCATE 11, 25: PRINT CurHor
 LOCATE 12, 25: PRINT CurVert
 WEND

 SUB mouse (m1, m2, m3, m4)
   DIM InRegs AS RegType
   InRegs.ax = m1
   InRegs.bx = m2
   InRegs.cx = m3
   InRegs.dx = m4
   CALL INTERRUPT(51, InRegs, InRegs)
   m1 = InRegs.ax
   m2 = InRegs.bx
   m3 = InRegs.cx
   m4 = InRegs.dx

 END SUB

 SUB MouseButPos (ButStat, CurHor, CurVert)
   m1 = 3
   CALL mouse(m1, m2, m3, m4)
   ButStat = m2
   CurHor = m3
   CurVert = m4
 END SUB

 FUNCTION MouseInit
    m1 = 0
    CALL mouse(m1, m2, m3, m4)
    MouseInit = m1

 END FUNCTION

 SUB MouseShow
   m1 = 1
   CALL mouse(m1, m2, m3, m4)

 END SUB


 571. "Variable Required" Versus "Duplicate Definition" Error

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890227-97 B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q42588

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 When a program attempts to define a variable and a function to have
 the same name, an error occurs. Normally, this error is "DUPLICATE
 DEFINITION." However, if the variable is first used in a FOR...NEXT
 statement, then the error message issued from QB.EXE (or QBX.EXE under
 the BASIC PDS 7.00) is "Variable Required", but from BC.EXE the two
 error messages "Variable Required" and "NEXT WITHOUT FOR" are
 generated.

 The following Code will generate a "Variable Required" error in
 QB.EXE / QBX.EXE:

 DECLARE FUNCTION bit% ()

 FOR bit% = 0 TO 7
 NEXT

 FUNCTION bit%
   bit% = 5
 END FUNCTION

 Under QuickBASIC 4.50, pressing the HELP button for the "Variable
 Required" error box misleadingly gives the following run-time error
 explanation instead of the compile-time explanation:

    "A GET or PUT statement must specify a variable when operating
     on a file opened in binary mode. ERR code: #40.

 The compile-time meaning of "Variable Required" explained in the
 "Microsoft QuickBASIC: Programming in BASIC" manual for Version 4.50
 is more accurate.


 572. Problem Using the Edit Keys on Zenith 184 Supersport Laptop

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890224-117
 Last Modified: 21-MAR-1989    ArticleIdent: Q42593

 Microsoft has not tested QuickBASIC Version 4.50 with the Zenith 184
 Supersport laptop computer. We do not claim compatibility between
 QuickBASIC 4.50 and the Supersport, and there may be some hardware
 incompatibility problems.

 For example, it has been reported that the edit keys (SHIFT+DEL,
 SHIFT+INS, and CTRL+INS) do not perform correctly on the Supersport.
 The workaround for this problem is to use the QuickBASIC Edit menu
 choices (Cut, Paste, and Copy), which can be accessed with the ALT
 key.

 Microsoft has not confirmed this information.


 573. VARSEG Incorrect for COMMON String Array Passed Through CHAIN

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.50
 Last Modified:  7-FEB-1990    ArticleIdent: Q42595

 The programs shown below demonstrate that VARSEG does not return the
 correct segment address of a string array passed in a COMMON block
 through a CHAIN.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50 for MS-DOS and in Microsoft BASIC Compiler Version 6.00b
 (buglist6.00b) for MS-DOS and MS OS/2. This problem was corrected in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 (fixlist7.00).

 The following program is TEST.BAS, which dimensions the string array
 and passes it in COMMON:

    COMMON a$()
    DIM a$(4)
    CHAIN "test2"
    END

 The following separately compiled program is TEST2.BAS, which
 dimensions another string array and passes both to the C routine. The
 second string array is used for comparison.

    DECLARE SUB crot CDECL (BYVAL plo AS INTEGER, BYVAL pls AS INTEGER)
    COMMON a$()
    DIM b$(1)
    a$(0) = "a0" + chr$(0)
    b$(0) = "b0" + chr$(0)
    print varseg(a$(0))
    print varseg(b$(0))
    CALL crot(VARPTR(a$(0)), VARSEG(a$(0)))
    CALL crot(VARPTR(b$(0)), VARSEG(b$(0)))

 The following is the C routine CR.C, which should print out the first
 string in each array:

    #include <stdio.h>
    struct struct_string {
        int length;
        char *address;
                         };
     void crot(struct struct_string far *string)
     {
          printf("%s\n", string->address);
     }

 To demonstrate the problem from .EXE programs, compile and link as
 follows:

      BC TEST.BAS ;
      LINK TEST.OBJ ;

      BC TEST2.BAS ;

      CL /AM /c CR.C ;

      LINK /NOE TEST2.OBJ CR.OBJ ;

 When TEST.EXE is run, the first line prints garbled, while the second
 prints correctly, as shown below:

    $#lkds
    b0

 Note: If the C routine is changed so that near addressing is used, the
 routine works correctly, as follows:

    #include <stdio.h>
    struct struct_string {
        int length;
        char *address;
                         };
    void crot(struct struct_string *string) /* changed to near pointer */
     {
          printf("%s\n", string->address);
     }

 Making the above change correctly displays the following:

    a0
    b0

 This change works because with near addressing, the C routine ignores
 the VARSEG part of the address. This only works if the array a$ lies
 within the default data segment.


 574. BASIC's SETMEM Doesn't Free C Far Allocation; _fmalloc, _ffree

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890227-157 B_BasicCom S_C S_QuickC
 Last Modified: 21-DEC-1989    ArticleIdent: Q42596

 When reducing far-heap size with the SETMEM statement in BASIC and
 then calling a Microsoft C or QuickC function that does a far
 allocation, the reduced far-heap memory is not recoverable with SETMEM
 after returning to the QuickBASIC program. C routines do far-memory
 allocation with "_fmalloc" and "_ffree" functions. This is expected
 behavior for the following reasons:

 1. The C _fmalloc obtains memory from MS-DOS. Once far memory is
    obtained by a C program, it becomes part of the C far heap.

 2. The _ffree does not release the memory back to MS-DOS, but rather
    stores it in the C far heap along with a linked-list data structure
    that C uses to manage its heap space.

 Thus, SETMEM cannot recover this memory.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 To recover the memory in the BASIC program, the C routine should do a
 huge allocation with the "halloc" and "hfree" functions. The C huge
 allocation routines differ from the far allocation routines. The
 halloc function always requests the memory directly from MS-DOS. The
 hfree function returns the memory directly back to MS-DOS. Once a C
 routine has executed an hfree, this memory can be recovered from a
 BASIC program with SETMEM.

 There is one disadvantage to using huge allocation. With huge
 allocation, there is no memory management involved on the part of the
 C routines. This can lead to memory fragmentation if the C routines do
 repeated allocations and frees.

 The C routine should be carefully constructed to avoid this
 fragmentation. For more information on C memory management, please see
 Page 114, "Memory Management: A Two-Step Process," "The Waite Group's
 Microsoft C Bible."

 Code Example
 ------------

 /***********************************************************/
 /* The following C function HugeMemTest can be called from */
 /* BASIC to demonstrate that huge allocation returns       */
 /* memory to the BASIC program.                            */
 /***********************************************************/

 #include <stdio.h>
 #include <malloc.h>

 void
 HugeMemTest(void)
 {
   long huge *lalloc;
   printf("Inside of C routine\n");

   lalloc = (long huge *)halloc(10000L,sizeof(long));
   if (lalloc == NULL)
      printf("\nInsufficient memory available\n");
   else
      printf("Memory successfully allocated\n");
   hfree(lalloc);

   printf("Leaving C routine\n");
 }

 '***********************************************************
 '* This BASIC routine releases memory to DOS using         *
 '* SETMEM. It then calls a C routine that does huge        *
 '* allocation and a huge free. SETMEM is used to recover   *
 '* the memory and success or failure is reported.          *
 '***********************************************************
 DECLARE SUB HugeMemTest CDECL ()

 ' Report far heap size before the C call.
 CLS
 BeforeCall = FRE(-1)
 PRINT "AVAILABLE MEMORY ON THE FAR HEAP:     ", BeforeCall
 Storage = SETMEM(-50000)
 PRINT "SIZE OF FAR HEAP AFTER SETMEM:        ", FRE(-1)

 ' Call to the C routine
 PRINT
 CALL HugeMemTest
 PRINT : PRINT : PRINT : PRINT

 ' Report far heap size after call to C.
 PRINT "SIZE OF FAR HEAP AFTER CALL TO C:     ", FRE(-1)
 Storage = SETMEM(50000)
 AfterCall = FRE(-1)
 PRINT "AVAILABLE MEMORY ON THE FAR HEAP : ", AfterCall

 ' Report success or failure.
 IF AfterCall <= BeforeCall THEN
    PRINT "SETMEM FUNCTIONED PROPERLY"
 ELSE
    PRINT "SETMEM DID NOT FUNCTION PROPERLY"
 END IF
 END


 575. Corrupt Parameters in SUB Using PRINT with Comma; BC.EXE 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890309-98 buglist4.50
 Last Modified: 14-FEB-1991    ArticleIdent: Q42662

 In the example below, parameters that are passed to a SUBprogram and
 printed out with a comma separating them will be corrupted within the
 SUBprogram. This problem occurs only when the program has been
 compiled to an EXE file. Altering the compile switches does not change
 the incorrect results.

 The program below demonstrates this problem. The problem exists only
 when the parameters have been passed to a SUBprogram and are compiled
 to an EXE file.

 This problem occurs in .EXE programs only in QuickBASIC version 4.50.
 Microsoft is researching this problem and will post new information
 here as it becomes available. Previous versions of QuickBASIC, and
 Microsoft BASIC Compiler versions 6.00, 6.00b, and 7.00, produce the
 correct results (fixlist6.00 fixlist6.00b fixlist7.00).

 The following program is TEST.BAS, which creates two variables and
 passes them to a subroutine. The subroutine then prints the variables.

    DECLARE SUB test (a, b)
    a = 1
    b = 2
    CALL test(a, b)
    PRINT a, b

    SUB test (a, b)
       PRINT a, b
       b = 100
       PRINT a, b   ' This prints incorrectly.
       b = 256
    END SUB

 The compiled EXE file prints the following incorrect output:

    1             2
    1             3.363116E-44
    1             100

 If any PRINT statement is altered (for example, the first "PRINT a, b"
 in the SUB is changed to a "PRINT a; b"), or if the program is run
 from the QB.EXE environment, the correct output will be produced, as
 follows:

    1             2
    1             100
    1             256

 Another workaround for the problem is to compile with BC /X, or to add
 "ON ERROR GOTO label" and "RESUME" statements to the program.

 Another workaround is to assign a local variable to the passed
 variable and then print the local variable instead of the passed
 variable, for example:

    SUB test (a, b)
       x = a  ' Assign passed parameter to local variable.
       y = b  ' Assign passed parameter to local variable.
       PRINT x, y
       y = 100
       PRINT x, y   ' This prints correctly.
       y = 256
       a = x  ' Pass back values to parameters
       b = y  ' Pass back values to parameters
    END SUB


 576. Suppressing CR/LF on "LPT1:BIN" after Every 80 Printable Bytes

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890310-85 B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q42663

 The two sample programs shown below suppress the automatic forcing of
 a LineFeed (LF) character that normally follows a Carriage Return (CR)
 character sent to the printer.

 The "LPT1:BIN" device requires a WIDTH#n,255 statement to suppress
 CR/LF pairs added by BASIC after every 80th printable ASCII character.
 The "LPT1" device doesn't require a WIDTH#n statement.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft
 BASIC PDS Version 7.00.

 Example 1, which uses the BASIC device name "LPT1", does not require a
 WIDTH#n statement to suppress extra CR/LF pairs.

 Example 2, which uses the BASIC device name "LPT1:BIN", requires the
 statement WIDTH#n,255 to prevent BASIC from appending a Carriage
 Return plus LineFeed (Hex 0A plus Hex 0D) pair to the characters Hex
 6F (decimal 111) and Hex BF (decimal 191). (Bytes 111 and 191 are 80
 bytes apart. Bytes 0 through 31 at the beginning are not counted in
 the width.)

 To examine printer byte values more easily, the printer should be
 initialized in Hex dump mode. (On an Epson printer, Hex dump mode is
 turned on by holding down the Form Feed button while turning on the
 printer. Refer to your printer manual if your printer differs.)

 Code Example
 ------------

 REM **** Program 1 ****
 OPEN "LPT1" FOR BINARY AS #1
 FOR I = 0 TO 255
     C$= CHR$(I)
     PUT #1,,C$
 NEXT

 REM **** Program 2 ****
 ' Adding WIDTH#1,255 eliminates the CR/LF addition for "LPT1:BIN":
 OPEN "LPT1:BIN" FOR RANDOM AS #1
 ' WIDTH#1,255    ' Required to suppress CR/LF at bytes 111 and 191.
 FOR I = 0 TO 255
    PRINT#1, CHR$(I);
 NEXT


 577. QB.EXE Confusing If TYPE Statement Used in SUB/FUNCTION

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890220-4
 Last Modified: 14-DEC-1989    ArticleIdent: Q42664

 TYPE definitions must all be contained in the module level code, and
 are not allowed within SUB...END SUB or FUNCTION...END FUNCTION
 blocks.

 However, the QB.EXE environment of QuickBASIC Versions 4.00, 4.00b,
 and 4.50 can give confusing error messages if a TYPE definition is
 entered into a SUBprogram or FUNCTION, making it seem as if TYPE
 definitions are allowed in SUBprograms and FUNCTIONS.

 This problem occurs only when using QB.EXE. If you compile your
 program with BC.EXE and a TYPE definition exists within a SUBprogram
 or FUNCTION, the following appropriate (and unconfusing) error message
 displays:

   "TYPE statement improperly nested
    Skipping forward to END TYPE statement"

 Within the QBX.EXE environment supplied with Microsoft BASIC PDS
 Version 7.00, the following correct error message is generated when
 you attempt to put a TYPE declaration in a SUBprogram:

   "Illegal in SUB, FUNCTION, and DEF FN"

 The following sequence of events demonstrates the problem:

 1. The following program is entered:

    TYPE typeA
      a AS INTEGER
    END TYPE
    END

    SUB suba
    TYPE typeA
      b AS INTEGER
    END TYPE
    DIM c AS typeB

 2. Attempting to run the above program generates the following error
    message, pointing to the TYPE statement in "subA":

    "Duplicate Definition"

 3. Changing "TYPE typeA" to "TYPE typeB" in "subA" and then running
    the program generates the following error message, pointing to the
    DIM statement in "subA":

    "TYPE not Defined"

 4. Changing the DIM statement in "subA" to "DIM c AS typeA" and then
    running the program, then generates the following expected error
    message:

    "Illegal in Procedure or DEF FN"

 If a TYPE statement is encountered in a SUB or FUNCTION, it should be
 flagged as an error prior to flagging errors related to the TYPE
 statement that are past the TYPE statement.


 578. "Bad Record Length" GET#n,,x$ Variable-Length String from File

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890222-61 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q42665

 The run-time error "Bad record length" occurs when a QuickBASIC
 Version 4.00b or 4.50 program uses a variable-length string as the
 third argument in a GET statement to input a string that was PUT in
 the file as a fixed-length string. This information also applies to
 Microsoft BASIC Compiler Version 6.00b for MS-DOS and MS OS/2 and
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 No error occurs in QuickBASIC Version 4.00 or BASIC compiler Version
 6.00 because these earlier versions don't expect a 2-byte string
 length when you input a variable-length string as the third argument
 of the GET statement. For a related article discussing PUT, query on
 the following words in this Knowledge Base:

    BAD RECORD LENGTH and PUT

 When reading from a random file that was created using fixed-length
 strings, you should GET them using fixed-length strings also.

 The "Details" listed under "GET" in the QuickBASIC 4.50 QB Advisor
 on-line Help system misleadingly suggest using a variable-length
 string in the following manner:

    VarStrings$ = STRING$(10, " ")
    GET #1, , VarString$

 This method works in QuickBASIC Version 4.00, but not in Versions
 4.00b or 4.50.

 To avoid the "Bad record length" error message, use a fixed-length
 string in your GET statement or create the file using a
 variable-length string in QuickBASIC 4.00b or 4.50, BASIC compiler
 6.00b, or BASIC PDS 7.00. (Making the variable-length string 2 bytes
 longer than the original string does not correct the problem.)

 The following code fragment works without error in QuickBASIC Version
 4.00 or BASIC compiler 6.00, but gives a "Bad record length" error in
 QuickBASIC 4.00b or 4.50, BASIC compiler 6.00b, or BASIC PDS 7.00:

 REM  This fragment places information in a file.
 REM  It prompts for 8 strings to be placed in a fixed-length
 REM  string "a" and then PUT into file #1

 OPEN "afile.dat" FOR RANDOM AS #1 LEN = 80
 DIM a AS STRING * 80
 FOR i = 1 TO 8
   INPUT a
   PUT #1, , a
 NEXT i
 CLOSE #1

 REM  This fragment reads in the data from the file and echoes to the
 REM  screen. The strings are retrieved using the statements listed
 REM  under "GET" under the "Details" on-line Help hyperlink.
 REM  To fix the problem, make VarString$ a fixed-length string
 REM  with DIM VarString as string * 80, to replace the STRING$
 REM  statement

 OPEN "afile.dat" FOR RANDOM AS #1 LEN = 80
 VarStrings$ = STRING$(10, " ")
 FOR i = 1 TO 8
   GET #1, , VarString$     'this line will give error message
   PRINT VarString$
 NEXT i
 CLOSE #1


 579. QB.EXE "Type Mismatch", BC.EXE "String Expression Required"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890217-143 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q42666

 This article describes a case where a syntax error in the filename for
 an OPEN statement gives "Type Mismatch" in the environment and a
 different (but more informative) message, "String Expression
 Required," in BC.EXE. This is a design limitation.

 The following program line causes the QB.EXE environment of QuickBASIC
 to highlight "LEN = 20" and issue the error message "Type Mismatch."
 Under the QBX.EXE environment of Microsoft BASIC PDS 7.00, "FILE.DAT"
 is highlighted when the "Type Mismatch" error occurs:

    OPEN FILE.DAT FOR RANDOM AS #1 LEN = 20

 "Type Mismatch" occurs because a string variable was expected instead
 of FILE.DAT, which is by default a single-precision variable.

 The BC.EXE compiler instead identifies this syntax error as "String
 Expression Required" and points to the "T" in FILE.DAT.

 This information applies to QB.EXE in QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to QB.EXE in Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and to QBX.EXE in Microsoft BASIC PDS Version 7.00 for MS-DOS.

 QuickBASIC Versions 2.00, 2.10, and 3.00 issue the "String Expression
 Required" message in both the environment and the separate compilation
 method.

 The following is the necessary correction to follow proper syntax:

    OPEN "FILE.DAT" FOR RANDOM AS #1 LEN = 20


 580. Accessing Huge Array (Larger Than 64K) Can Hang 386 Computers

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 SR# S890227-131
 Last Modified: 26-FEB-1990    ArticleIdent: Q42667

 The program shown below, which works correctly on computers using
 8088, 8086, and 80286 processors, causes many computers using the
 80386 processor to hang when a huge array exceeds 64K and leaves a gap
 with an odd number of bytes in far heap. If the gap is an even number
 of bytes, the problem does not occur. You can also work around the
 problem by making the array record size a power of 2, so that no gap
 is created in far heap.

 To obtain the size of the gap, calculate the quantity (65,536) MOD
 (array record size) or obtain the value returned by the VARPTR
 function invoked for the first array element.

 This problem occurs in QuickBASIC Versions 4.00, 4.00b, and 4.50 for
 MS-DOS and in Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2 (buglist6.00, buglist6.00b). This problem was
 corrected in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 To duplicate the problem, compile the following program with BC /AH or
 QB /AH, and run it on a computer that has an Intel 80386 chip.

 Code Example
 ------------

 ' $DYNAMIC
 DIM a(4000) AS STRING * 25
 FOR x% = 1 TO 4000
   PRINT a(x%); x%
 NEXT

 Note: The 80386 computers hang after printing the array element number
 2619. Therefore, the hang occurs as the program accesses element
 number 2620, which is 2621 elements from the start (starting at
 element 0). Each element is 25 characters long, and the program hangs
 after byte position 65,525 (25 * 2621), which is immediately before
 the 64K (65,536-byte) boundary.

 Array elements cannot be split across the 65,536-byte (64K) boundary;
 thus, an 11-byte (odd-length) gap is automatically created in front of
 the array within far heap so the array can be aligned exactly at a 64K
 boundary. When the gap has an odd length, the 80386 computer hangs.
 When the gap has an even length (such as by using an array of
 STRING*26), the program runs correctly.

 Background Information for Huge Arrays
 --------------------------------------

 Space is allocated for a huge array contiguously in far heap, with the
 restriction that no single array element (or record) is allowed to be
 split across a 64K boundary. If a record size is not a power of 2, the
 array is allocated at an offset high enough, relative to the array's
 base segment address (returned by the VARSEG function), so that no
 array element is split across the boundary at exactly 64K above the
 base segment. The value returned by the VARPTR function for the first
 element of the array then indicates both the offset of the array and
 the size of a gap created in far heap. The size of the gap is also
 equal to <65,536> MOD <array record size>. This gap fragments far heap
 and is wasted, unused memory. In the worst case, the gap can be up to
 <array record size> minus 1 in size.

 A "Subscript Out of Range" message correctly displays when allocating
 a huge array larger than 128K if the array elements have a size that
 is not an even power of 2. Arrays larger than 128K must have an
 element (or record) size that is a power of 2 (2, 4, 8, 16, 32, 64,
 etc.), since arrays are stored contiguously and no single array
 element is allowed to span across a 64K boundary.

 A huge array must be DIMensioned as a dynamic array, either with a
 variable in the array subscript or with a preceding metacommand REM
 $DYNAMIC. The /AH option allows dynamic arrays of user-defined TYPEs,
 fixed-length strings, and numeric data to occupy all of available
 memory.

 Huge (larger than 64K) arrays are not available in versions of
 QuickBASIC earlier than Version 4.00.

 Additional reference word: B_BasicCom


 581. "Statement Illegal in TYPE Block" Using F7 in QB.EXE Debug

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890309-14 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q42668

 The following information applies to QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to the QB.EXE programs supplied with Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and OS/2, and to the
 QBX.EXE environment supplied with the BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 The F7 function in the QB.EXE editor/debugger causes the program to
 execute up to the current location of the cursor. If you attempt to
 execute a program using F7 while the cursor is inside a user-defined
 TYPE...END TYPE block, the error message "Statement illegal in TYPE
 block" is returned. This only happens the first time that the program
 is executed.

 Code Example
 ------------

 TYPE USER
    ANYDATA AS INTEGER
 END TYPE
 CLS


 582. LINE INPUT#n Drops Null Characters from File; Use INPUT$

 Product Version(s): 1.x 2.x 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_MQuickB B_BasicInt SR# S890306-99
 Last Modified: 16-DEC-1989    ArticleIdent: Q42669

 The LINE INPUT #n statement strips null characters (CHR$(0)) from
 input files. If you want to input null bytes, you must use the INPUT$
 function instead of the LINE INPUT #n statement.

 This information applies to the following products:

 1. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh.

 2. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh.

 3. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh.

 4. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC.

 5. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS.

 6. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2
    and MS-DOS.

 7. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 8. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23.

 Code Sample
 -----------

 The following code segment will print "helloworld" instead of
 "hello world":

 OPEN "test.dat" FOR INPUT AS #1
 LINE INPUT #1, a$
 PRINT a$
 CLOSE #1

 where the TEST.DAT data file was created as follows:

 OPEN "test.dat" FOR OUTPUT AS #1
 PRINT #1, "hello" + CHR$(0) + "world"
 CLOSE #1


 583. Put COMMAND.COM on Each Disk with Two-Floppy DOS 2.10 System

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890316-75
 Last Modified: 24-MAR-1989    ArticleIdent: Q42699

 When operating QuickBASIC Version 4.50 on a two-floppy system that is
 using DOS Version 2.10, it is recommended that you put a copy of
 COMMAND.COM on all of your operating QuickBASIC disks that have
 executable (.EXE) files on them.

 This information is found in the QuickBASIC Version 4.50 README.DOC
 file, found on the Utilities 2 disk. This also applies to QuickBASIC
 Versions 4.00 and 4.00b.


 584. File with Double Underscore Hangs the QB.EXE Environment

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q42703

 When a file consisting of only two underscore characters (__) is
 loaded into the QuickBASIC editor, the "Loading and Parsing" message
 is displayed at the bottom and the machine hangs.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in the QB.EXE program shipped with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b. This problem was
 corrected in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 (fixlist7.00).


 585. Logically Same DOUBLE Precision Assignments, Different Results

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q42853

 Assigning SINGLE or DOUBLE precision variables to logically equivalent
 expressions that use functions and temporary variables differently may
 return values that vary slightly at the limits of their precision.
 These variations can range above or below the expected integral value,
 and can thus affect results returned from the INT function. This is
 not a software problem, but is due to the way that the compiler
 optimizes different expressions and rounds off values at the limits of
 precision differently in different expressions. The binary math used
 by the compiler cannot precisely represent all floating-point values
 at each intermediate step in a calculation, and round-off errors are
 unavoidable. For more information, query on the word IEEETUTR.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00. This occurs both in the QuickBASIC
 environment (or the QuickBASIC Extended environment of BASIC PDS 7.00)
 and in executable programs compiled with BC.EXE.

 The following program demonstrates the behavior. The variable "A#" is
 assigned to three different expressions that are logically equivalent
 but yield different floating-point results that vary at the limits of
 double precision. These slight variations affect the results returned
 by the INT function if the floating-point value is slightly less than
 the "expected" integral value.

 CLS
 Log10# = LOG(10#)
 FOR I% = 1 TO 3
    X# = 1#
    SELECT CASE I%
      CASE 1
        PRINT "A# = LOG(X#) / LOG(10#)"
      CASE 2
        PRINT "A# = LOG(X#) / Log10#"
      CASE 3
        PRINT "A# = logX# / Log10#"
      CASE ELSE
    END SELECT
    DO
      X# = X# * 10#
      logX# = LOG(X#)
      ' The following three assignment statements are all logically
      ' identical but all produce slightly different results for
      ' different values of X#.
      ' Values of X# used: 10, 100, 1000, 10000
      SELECT CASE I%
        CASE 1
          A# = LOG(X#) / LOG(10#)
        CASE 2
          A# = LOG(X#) / Log10#
        CASE 3
          A# = logX# / Log10#
        CASE ELSE
      END SELECT
      IntegPart# = INT(A#)
      FractPart# = A# - INT(A#)
      PRINT "A# = "; A#; TAB(27); "INT(A#) = "; IntegPart#;
      PRINT TAB(43); "A# - INT(A#) = "; FractPart#
    LOOP UNTIL X# > 1000#
    PRINT
 NEXT I%
 END

 The program output is as follows:

 A# = LOG(X#) / LOG(10#)
 A# =  1                   INT(A#) =  1    A# - INT(A#) =  0
 A# =  2                   INT(A#) =  2    A# - INT(A#) =  0
 A# =  3                   INT(A#) =  3    A# - INT(A#) =  0
 A# =  4                   INT(A#) =  4    A# - INT(A#) =  0

 A# = LOG(X#) / Log10#
 A# =  .9999999999999999   INT(A#) =  0
                           A# - INT(A#) =  .9999999999999999
 A# =  2                   INT(A#) =  1
                           A# - INT(A#) =  .9999999999999998
 A# =  3                   INT(A#) =  2
                           A# - INT(A#) =  .9999999999999996
 A# =  4                   INT(A#) =  3
                           A# - INT(A#) =  .9999999999999996

 A# = logX# / Log10#
 A# =  1                   INT(A#) =  1    A# - INT(A#) =  0
 A# =  2                   INT(A#) =  2    A# - INT(A#) =  0
 A# =  3                   INT(A#) =  2    A# - INT(A#) =
                                                    .9999999999999996
 A# =  4                   INT(A#) =  4    A# - INT(A#) =  0


 586. Fast Load Format Can Cause "Binding..." Hang in QB.EXE Editor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890316-48 buglist4.00 buglist4.00b buglist4.50
 Last Modified:  1-JAN-1990    ArticleIdent: Q42855

 If your machine hangs in the QB.EXE environment (often with a
 "Binding..." message displayed on the bottom of the screen) when
 trying to run your program, one possible cause is QuickBASIC's Fast
 Load and Save (i.e., Binary) file format.

 A workaround is to save in Text Format, reload the program, and run
 again. Other possible causes of a "Binding..." hang are described
 further below.

 Microsoft has confirmed this to be a problem with the Fast Load and
 Save format in QuickBASIC Versions 4.00, 4.00b, and 4.50, and with
 QB.EXE included with Microsoft BASIC Compiler Versions 6.00 and 6.00b.
 We are researching this problem and will post new information here as
 it becomes available.

 If QB.EXE hangs, and modules are saved in the Fast Load and Save
 format, try the following as a workaround:

 1. Save your source file(s) in Text format with Save As... from
    the File menu in QB.EXE.

 2. Exit QuickBASIC.

 3. If your program uses multiple modules, delete the file with the
    .MAK extension (which is created when you save a multiple-module
    program in QB.EXE 4.x). (Note: This .MAK file is unrelated to the
    .MAK files used by the Microsoft Program Maintenance Utility,
    MAKE.EXE.)

 4. Run QuickBASIC again.

 5. Reopen (Open...) the program from disk, manually Load... any
    separate module source files (if any), then try to run your
    program again. The problem should disappear.

 Other possible causes of a "Binding..." hang are as follows:

 1. Memory-resident software, i.e., terminate-and-stay-resident (TSR)
    programs

 2. Nonstandard device drivers

 To find out if your device drivers or TSRs are causing a problem,
 remove them from your AUTOEXEC.BAT and CONFIG.SYS files, reboot, and
 then run QuickBASIC with a "clean" machine. QuickBASIC is sensitive to
 and incompatible with many TSR programs. For an explanation of why,
 query on the following words:

    why and QuickBASIC and TSR and incompatible

 The following are other problems in QuickBASIC that cause the
 "Binding..." machine hang, instead of generating an error:

 1. $INCLUDE with an unfindable file and line label with more than one
    space between the line label and the REM or ' (Version 4.50 only)

 2. An IF THEN GOTO with an invalid line label (Version 4.00 only)

 3. SWAP on fixed-length string fields of user-defined types (Version
    4.50 only)

 For more information, query on the following words:

    binding and hang and QuickBASIC


 587. BC.EXE "Line Too long" with ASCII 128 and Fast Load Format

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890221-68 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q42856

 The BC.EXE compiler in QuickBASIC Versions 4.00, 4.00b, and 4.50
 produces the error message "Line too long" if the character ASCII 128
 is included into a string literal and the file being compiled is in
 Fast Load and Save format. (This character is entered into the QB.EXE
 editor by holding down CTRL+ALT while typing the numbers "128" on
 the numeric keypad and then releasing the keys.)

 This problem does not occur when the program is run in the QB.EXE
 editor.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 400b, and 4.50. This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 BC.EXE correctly compiles the program with the character ASCII 128 if
 it is saved in TEXT format (instead of Fast Load format).

 The extended ASCII characters are not legal for BASIC variable names.
 If used, they produce the error message "Expected: end-of-statement"
 when using QB.EXE or "Illegal character" when using BC.EXE.

 An ASCII 128 character compiles without errors in QuickBASIC Version
 3.00.

 You can use either of the following methods to work around the
 problem:

 1. Save the file as text before compiling.

 2. This character can be included in strings by using the CHR$
    function. The following example shows how to print this character
    as part of a string:

       PRINT "ABCD" + CHR$(128) + "EFG"
       PRINT "ABCD";CHR$(128);"EFG"
       END

 The following is a code example:

    ' This program produces the compile time error
    ' "Line too long" if saved in QuickLoad format.
    PRINT "CTRL+ALT+128"
    END

 Additional reference word: B_BasicCom


 588. C Escape Sequence Like "\n" Doesn't Function When Passed to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890320-23 B_BasicCom
 Last Modified: 21-DEC-1989    ArticleIdent: Q42857

 When CALLing a C function from QuickBASIC and passing a C-format
 string that contains C escape sequences, the escape sequence does not
 execute, but rather displays as part of the string. When the following
 example is used, the C "\n" escape sequence for carriage
 return/linefeed will not be executed from the C function as expected;
 the "\n" will simply be displayed as part of the string:

    FORMAT$ = "number1= %d   number2= %d\n" + CHR$(0)
    CALL CROUTINE(SADD(FORMAT$),LEN(FORMAT$)

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft
 BASIC PDS Version 7.00.

 Escape sequences, such as "\n", are replaced with the carriage
 return/linefeed characters when the C code is compiled. Therefore, if
 they are passed to a C program at run time, "\n" is not recognized as
 anything more than part of the string to be displayed.

 For the C program to execute an escape sequence passed to it from a
 QuickBASIC program, the actual characters for the desired operation
 must be appended to the passed string, as in the following example:

 FORMAT$ = "number1= d%   number2= d%" + CHR$(13) + CHR$(10) + CHR$(0)
 CALL CROUTINE(SADD(FORMAT$),LEN(FORMAT$)

 This passes the carriage return/linefeed sequence to the C function.


 589. OPEN "A:NUL" Activates Device Specified; "A:\DEV\NUL" Doesn't

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890320-38 B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q42858

 QuickBASIC allows you to OPEN the file "NUL" for INPUT or OUTPUT. When
 CLOSEd, this temporary file loses all information that was written to
 it. Even though a FILE is not actually created, the device specified
 in the OPEN statement is activated. The following example will
 activate the "A:" drive:

    OPEN "A:NUL" FOR OUTPUT AS #1

 If the device is not ready, a "Device Not Ready" error is generated.
 To prevent the device from being activated, the MS-DOS prefix "\DEV"
 must be included. The following OPEN statement will not activate the
 "A:" drive:

    OPEN "A:\DEV\NUL" FOR OUTPUT AS #1

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
 and to Microsoft BASIC Compiler Versions 6.00 and 6.00b.

 Under Microsoft BASIC PDS Version 7.00, you cannot prevent the named
 device from being activated with the "\DEV" prefix. Both the above
 statements result in a "Disk not ready" error message from either a
 compiled program or one run under the QBX.EXE environment. The error
 can still be trapped using normal BASIC error handling, however.


 590. Wrong Mouse Cursor Position Using Menus on PS/2 Model 25 or 30

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.50
 Last Modified: 29-JUN-1990    ArticleIdent: Q42946

 When using QB.EXE from QuickBASIC version 4.50 on an IBM PS/2 Model 25
 or 30 with an MCGA, the mouse cursor position is not tracked
 correctly. This does not happen if the machine has a color graphics
 card.

 For example, if you pull down the File menu in the QuickBASIC 4.50
 editor, hold down the mouse button and drag the cursor down the menu,
 you will see that the highlight bar indicating the current menu
 selection does not keep up with the movement of the mouse cursor.
 Also, the farther the mouse cursor is moved down the screen, the wider
 the disparity becomes.

 The same problem exists in the QBX.EXE environment supplied with
 Microsoft BASIC Professional Development System (PDS) version 7.00.
 This problem does not occur in versions of QuickBASIC earlier than
 4.50.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 that comes with QuickBASIC version 4.50 and in the QBX.EXE environment
 that comes with Microsoft BASIC PDS version 7.00 (buglist7.00). We are
 researching this problem and will post new information here as it
 becomes available.


 591. Instant Watch on $INCLUDE File CONST Name May Hang QB.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890320-95 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q42947

 The QuickBASIC environment may hang when attempting to add an Instant
 Watch on a CONST data name that is in an $INCLUDE file. Microsoft has
 confirmed this to be a problem in Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 and in the QB.EXE that is shipped with Microsoft BASIC
 Compiler Versions 6.00 and 6.00b (buglist6.00, buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 (fixlist7.00).

 The two files involved are the following:

    REM ---- TEST.BI -------
    CONST TRUE = -1

    REM ---- TEST.BAS ------
    REM $INCLUDE: 'test.bi'

 The following steps should cause the machine to hang. The steps must
 be followed closely to reproduce the problem:

 1. Load and run the TEST.BAS file.

 2. Choose the Include File command on the View pull-down menu.

 3. Highlight the "TRUE" CONSTant data name.

 4. Set an Instant Watch variable (press SHIFT+F9).

 The machine is now hung and a reboot is required. If the same
 sequence of events is followed as described above with the following
 exception, then the machine will not hang:

    In Step 2, choose Include File Lines instead of the Include File
    command.

 Additional reference word: B_BASICCOM


 592. Compiled INPUT Doesn't Read Text Previously PRINTed on Screen

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890307-84 B_BasicCom B_GWBasicI
 Last Modified: 15-DEC-1989    ArticleIdent: Q42948

 Unlike in Microsoft GW-BASIC, the INPUT or LINE INPUT statement in
 compiled BASIC will not read text that was previously displayed on the
 screen. (Instead, you must use the SCREEN function to read existing
 text on the screen.)

 In compiled BASIC, if you LOCATE to an area on the screen, print text,
 LOCATE there again, and do an INPUT or LINE INPUT, then moving the
 direction keys will erase what was previously on the screen. GW-BASIC
 does not do this erase. In addition, the INPUT statement in GW-BASIC
 will read the string that was previously displayed at that position.

 This is a fundamental design difference between Microsoft GW-BASIC
 Interpreter (Versions 3.20, 3.22, and 3.23) and compiled BASIC.

 The GW-BASIC Interpreter is resident in memory when a program runs,
 and can perform the INPUT of existing text on the screen using its
 built-in editor feature. This feature is not available in compiled
 programs, which do not have resident code (overhead) allocated for
 this form of screen editing.

 This article applies to the following compilers:

 1. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 3. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2
    and MS-DOS

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2

 Code Example
 ------------

 ' In GWBASIC, if you hit <ENTER> at the INPUT prompt,
 ' This will print "HELLO". QuickBASIC prints nothing.

 LOCATE 10, 10
 PRINT "HELLO"
 LOCATE 10, 10
 INPUT A$
 PRINT A$
 END


 593. Example of Buffered Keyboard Input Using QuickBASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890319-6 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q42949

 The following is a program example of buffered keyboard input with
 Microsoft QuickBASIC. Buffered input allows input from the screen, but
 limits the total number of characters that can be input and typed. It
 is a standard form of input for business applications. Microsoft
 QuickBASIC does not offer this as a built-in form of input. It must be
 programmed with a combination of other BASIC statements and functions.

 Note that BASIC does allow input into a fixed-length string, but will
 read only up to the maximum length for that string. However, this does
 not prevent you from typing any number of characters, which is
 undesirable when doing formatted screen input. This example shows only
 one way to do this. An added feature would be the addition of a
 cursor.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 Code Example
 ------------

 DECLARE SUB BufInput (StringVar$, Limit%)
 'NOTE: The DECLARE statement is not supported under Microsoft
 '      QuickBASIC Version 3.00 or earlier, and can be removed.

 CLS
 Limit% = 10 'Number of characters to input

 'Prompt for the input string.
 LOCATE 10, 5
 PRINT "PLEASE INPUT A STRING OF TEN CHARACTERS: ";
 COLOR 0, 7: PRINT SPACE$(Limit%)
 LOCATE 10, 46

 'Input a buffered string
 CALL BufInput(a$, Limit%)

 COLOR 7, 0
 CLS

 ' Print out the result
 LOCATE 10, 10
 PRINT "THE STRING YOU INPUT WAS: ";
 COLOR 0, 7
 PRINT a$
 COLOR 7, 0

 END

 SUB BufInput (StringVar$, Limit%)
 BackSp$ = CHR$(8)
 Enter$ = CHR$(13)
 Length% = 0

 'Loop waiting for input. ENTER terminates the routine.
 WHILE char$ <> Enter$
 char$ = INKEY$
    IF char$ <> "" THEN
      IF (Length% < Limit%) OR (char$ = BackSp$) THEN
         SELECT CASE char$
         CASE " " TO "~"  ' Input printable characters only
            StringVar$ = StringVar$ + char$
            PRINT char$;
            Length% = Length% + 1
         CASE BackSp$  'If BackSpace is pressed, erase.
           IF Length% <> 0 THEN
              Length% = Length% - 1
              StringVar$ = LEFT$(StringVar$, Length%)
              CurrX% = CSRLIN
              CurrY% = POS(0) - 1
              LOCATE CurrX%, CurrY%
              PRINT " "
              LOCATE CurrX%, CurrY%
           END IF
         END SELECT
      ELSE
         PLAY "o1AL32"
      END IF
    END IF
 WEND

 END SUB


 594. Multiple Event Traps Can Malfunction in QB.EXE

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50 SR# S890315-133 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q43023

 The programs below demonstrate that SETUEVENT is mistakenly remembered
 in the QuickBASIC Version 4.50 environment between program
 invocations. Also, any other event trap causes the UEVENT to activate.
 This is incorrect behavior, since starting a new program should reset
 and remove event handlers from programs previously run in the QB.EXE
 environment.

 Microsoft has confirmed this to be a problem with QB.EXE in QuickBASIC
 Versions 4.00b and 4.50, and with QB.EXE in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS (buglist6.00 buglist6.00b). This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 (fixlist7.00).

 The following program is EVENT1.BAS, which sets up a user-defined
 event trap but never activates it. The second program is EVENT2.BAS,
 which sets up and activates another user-defined event trap.

 The first time EVENT1.BAS is run in QB.EXE, the user-defined event
 trap never occurs (which is correct). If it is run after EVENT2.BAS,
 the EVENT1 procedure is activated. This is because the SETUEVENT is
 remembered between the programs.

 The steps to reproduce this are as follows:

 1. Invoke QB.EXE.

 2. Load EVENT1.BAS, and it runs correctly.

 3. Load EVENT2.BAS and run it.

 4. Load EVENT1.BAS again. User event remembers TIMER event.

 The following is the program EVENT1.BAS:

 CLS
 ON UEVENT GOSUB event1
 UEVENT ON
 DO: LOOP UNTIL INKEY$ <> ""
 END

 event1:
  PRINT "user event"
  RETURN

 The following is the program EVENT2.BAS:

 '**** PROGRAM #2
 CLS
 ON UEVENT GOSUB event1
 ON TIMER(1) GOSUB timeout
 UEVENT ON
 TIMER ON
 CALL setuevent
 DO: LOOP UNTIL INKEY$ <> ""
 END

 timeout:
   PRINT "timeout"
 RETURN

 event1:
   PRINT "user event"
 RETURN


 595. BC.EXE Command-Line Options for QuickBASIC and BASIC Compiler

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890329-57 B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q43090

 This article documents the BC.EXE command-line options available in
 QuickBASIC Versions 4.00, 4.00b, and 4.50 and in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b (with the exception of the /t option
 which is not available in QuickBASIC 4.00).

 These BC.EXE command-line options can also be found in the following
 manuals:

 1. Pages 210 and 211 of the "Microsoft QuickBASIC 4.0: Learning and
    Using" manual for QuickBASIC 4.00 and 4.00b

 2. Pages 210 and 211 of the "Microsoft BASIC Compiler 6.0: Learning
    and Using Microsoft QuickBASIC" manual, and additional options on
    Pages 6, 7, 8 of the "Microsoft BASIC Compiler 6.0: User's Guide"
    for 6.00 and 6.00b

 3. Pages 353 to 355 of the "Microsoft QuickBASIC 4.5: Programming in
    BASIC" manual for QuickBASIC Version 4.50.

 Option  Definition
 ------  ----------

 /a      Creates a listing of the disassembled object code for each
         source line and shows the assembly-language code generated by
         the compiler.

 /ah     Allows dynamic arrays of records, fixed-length strings, and
         numeric data to occupy all of available memory. If this option
         is not specified, the maximum size is 64K per array. Note that
         this option has no effect on the way data items are passed to
         procedures. (See also the REM $DYNAMIC metacommand.)

 /c:<n>  Sets the size (<n> = bytes) of the buffer receiving remote
         data using an asynchronous communications adapter for each
         communications port. (The transmission buffer is allocated 128
         bytes for each communications port and cannot be changed on
         the BC command line.)  This option has no effect if the
         asynchronous communications card is not present. The default
         buffer size is 256 bytes total for BOTH ports; the maximum
         size is 32,767 bytes. The default, /c:512, is automatically
         added when invoking the Make EXE File command from the Run
         menu in QuickBASIC 4.00b and 4.50 (not in QuickBASIC 4.00).

 /d      Generates debugging code for run-time error checking and
         enables CTRL+BREAK. This option is the same as the Produce
         Debug Code option from the Run menu's Make EXE File command
         within the environment.

 /e      Indicates the presence of ON ERROR with RESUME linenumber
         statements. (See also the discussion of the /x option in this
         list.)

 /mbf    Causes the QuickBASIC conversion functions to treat
         IEEE-format numbers as Microsoft Binary format numbers. The
         intrinsic functions MKS$, MKD$, CVS, and CVD are converted to
         MKSMBF$, MKDMBF$, and CVSMBF, and CVDMBF, respectively. See
         the "Microsoft QuickBASIC 4.0: BASIC Language Reference"
         manual or corresponding help for more information about these
         functions.

 /o      Substitutes the appropriate BCOMxx.LIB stand-alone program
         library for the BRUNxx.LIB run-time module library.

 /r      Stores arrays in row-major order. BASIC normally stores arrays
         in column-major order. This option is useful if you are using
         other language routines that store arrays in row order.

 /s      Writes quoted strings to the object file instead of the symbol
         table. Use this option when an "Out of memory" error message
         occurs in a program that has many string constants.

 /t      This option stands for terse. It suppresses warning messages
         during compilation. However, severe error messages still are
         displayed. This option is not available in QuickBASIC 4.00.
         Also, /t is automatically added to the BC command line in
         QuickBASIC 4.00b and 4.50 whenever you choose Make EXE
         File from within QB.EXE.

 /v      Enables event trapping for communications (COM), light pen
         (PEN), joystick (STRIG), timer (TIMER), music buffer (PLAY),
         and function keys (KEY). Use this option to check between
         statements for an occurrence of an event.

 /w      Enables event trapping for the same statements as /v, but
         checks between lines for occurrence of an event.

 /x      Indicates presence of ON ERROR with RESUME, RESUME NEXT, or
         RESUME 0.

 /zd     Produces an object file containing line-number records
         corresponding to the line numbers of the source file. This
         option is useful when you want to perform source-level
         debugging using the Microsoft Symbolic Debug Utility (SYMDEB)
         available with Microsoft Macro Assembler Version 4.00.

 /zi     Produces an object file containing debugging information used
         by the Microsoft CodeView debugger, available with Microsoft C
         Version 5.00, Microsoft Macro Assembler Version 5.00, and
         Microsoft BASIC Compiler Version 6.00.

 The following BC.EXE options are supported in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b, but not in QuickBASIC 4.00, 4.00b, or 4.50:

 /LP     Creates a protected-mode object file for use in MS OS/2
         protected mode, no matter which operating system you are in at
         compile time.

 /LR     Creates a real-mode object file for use in MS-DOS or MS OS/2
         real mode (DOS 3.x box), no matter which operating system you
         are in at compile time.

 /FPi    Generates in-line (i) coprocessor instructions for floating
         point (FP) math. If a coprocessor is not present at run time,
         the BASIC run-time system will emulate a coprocessor.

 /FPa    Generates code using alternate (a) math library, which runs
         faster than emulating a coprocessor when none is present.


 596. Underscore (_) Not OK in Variable Name or Line Continuation

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890327-20 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43092

 The underscore character (_) is not allowed within a QuickBASIC
 variable, SUBprogram, or FUNCTION name in all versions of QuickBASIC.
 Also, you cannot type an underscore as a line continuation character
 within the QB.EXE environment of QuickBASIC Versions 4.00, 4.00b, and
 4.50, the QB.EXE environment in Microsoft BASIC Compiler Versions 6.00
 and 6.00b, or the QBX.EXE environment in Microsoft BASIC PDS Version
 7.00.

 If an editor other than QB.EXE / QBX.EXE is used to write your
 program, the underscore character is recognized as a valid line
 continuation character by the BC.EXE compiler (but still cannot be
 used within variable, SUBprogram, or FUNCTION names).

 QB.EXE / QBX.EXE can load text files that use underscores for line
 continuation, but the underscore is stripped out and the continued
 lines are concatenated. Total concatenated line length is limited to
 255 characters in QB.EXE / QBX.EXE and BC.EXE.

 This information applies to QuickBASIC 4.00, 4.00b, and 4.50, the
 QB.EXE environment included with the BASIC compiler 6.00 and 6.00b,
 and the QBX.EXE environment of BASIC PDS 7.00.

 QuickBASIC Versions 3.00 and earlier allowed you to continue lines
 with an underscore (_) character. However, in Versions 4.00 and later,
 the underscore character is not allowed, due to conflicts with the
 threaded p-code used within the environment and with the ability to
 perform interlanguage calling, especially with Microsoft C.

 If you create your program within another editor using the underscore
 as a line continuation character, and then attempt to load the program
 into the QuickBASIC environment Version 4.00 or later (or the QBX.EXE
 environment of BASIC PDS 7.00), the underscores used as line
 continuation characters are removed and the fragments of lines
 separated by the underscore are concatenated into one line.

 For example, write the following program using an editor other than
 QB.EXE 4.00 or later (or QBX.EXE):

     A = _
     5 * _
     B
     END

 If the above program is loaded into the Version 4.00 or later QB.EXE
 environment or the QBX.EXE of BASIC PDS 7.00, it will be converted to
 the following:

     A = 5 * B
     END


 597. RENaming a FAST LOAD/SAVE BASIC Program Makes It Inaccessible

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890331-67
 Last Modified: 10-APR-1989    ArticleIdent: Q43201

 If you save a QuickBASIC Version 4.50 program in the FAST LOAD/SAVE
 format and then exit to DOS and rename the file, QuickBASIC may not be
 able to recognize the new filename.

 The environment will either bring up an empty view window with that
 filename under the OPEN file option or produce "BAD FILE MODE" when
 trying to load that file as a module through the LOAD file option.

 Apparently, when saving a file with the FAST LOAD/SAVE format,
 QuickBASIC retains the original name of the file; therefore, if you go
 to DOS and rename the file, QuickBASIC will not recognize the file
 when trying to load it.

 This error has not been reproduced yet, but it was reported by one
 person using QuickBASIC Version 4.50. A workaround for this situation
 is to exit to DOS and rename the file back to the original name when
 saved under FAST LOAD/SAVE format, then enter into QuickBASIC again,
 and OPEN the file. If you then want to change the name, select SAVE AS
 under the FILE menu and change the name and also save it as ASCII
 (Text), so that it can be read by other software.


 598. NUM LOCK On Affects QB.EXE Cut, Copy, Paste on Numeric Keypad

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890404-247 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43209

 If NUM LOCK is on in the QB.EXE editor, pressing SHIFT+DEL, CTRL+INS,
 or SHIFT+INS does not Cut, Copy, or Paste when pressed on the numeric
 keypad. NUM LOCK must be off for these "quick keys" to work on the
 numeric keypad; when you turn on NUM LOCK, the numbers become active
 on the keypad instead of INS and DEL.

 The NUM LOCK status does not affect the dedicated, INS and DEL keys on
 the IBM extended keyboard (which are usually colored gray to show
 their unique function). Use these dedicated keys if you have an
 extended keyboard and wish to be independent of the NUM LOCK status.

 This information applies to the QB.EXE environment of QuickBASIC
 Versions 4.00, 4.00b, and 4.50 and to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b. The information also applies to the QBX.EXE
 environment of Microsoft BASIC PDS Version 7.00.

 The following are the quick-key functions:

    Quick Key           Function
    ---------           --------

    SHIFT+DEL           Cut
    CTRL+INS            Copy
    SHIFT+INS           Paste


 599. "Make EXE" within QB.EXE 4.00 Editor Can Hang OS/2 Real Mode

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890403-185
 Last Modified: 15-DEC-1989    ArticleIdent: Q43211

 When running QB.EXE from QuickBASIC Version 4.00 in MS OS/2 real mode
 (that is, in the MS-DOS Version 3.x compatibility box), choosing "Make
 EXE" from the RUN menu usually hangs the system, requiring a warm or
 cold reboot. It may also cause the machine to reboot spontaneously.

 To work around this problem, compile with BC.EXE 4.00 from the DOS
 command line or use a later version of QuickBASIC.

 The problem does not occur in QB.EXE from other versions, including
 QuickBASIC Versions 3.00, 4.00b, and 4.50, the QB.EXE that comes with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and the QBX.EXE
 environment that comes with Microsoft BASIC PDS Version 7.00. The
 BC.EXE compiler which comes with QuickBASIC 4.00 was not developed or
 tested for OS/2 compatibility. Only BC.EXE from the BASIC compiler
 6.00 and 6.00b and BASIC PDS 7.00 was developed and tested for OS/2.


 600. Language Support Directory for QuickBASIC/BASIC Add-Ons

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890403-181 B_BasicCom
 Last Modified: 11-APR-1989    ArticleIdent: Q43251

 The "Language Support Directory for Microsoft QuickBASIC and BASIC
 Compiler" is distributed with the Microsoft BASIC Compiler Versions
 6.00 and 6.00b. QuickBASIC owners can order it (free) from
 Sales/Consumer Response (Microsoft Information Center) by calling
 (800) 426-9400.

 This document lists third-party software that may be used as add-ons
 to compiled BASIC programs. Any comments, corrections, or requests to
 have your products included in this directory should be directed to
 the following department and address:

    Microsoft Corporation
    Language Support Directory
    16011 NE 36th Way
    Box 97017
    Redmond, WA 98073-9717

 If you want your add-on products considered for entry in this
 directory, include the following:

 1. An entry as it would appear in the catalogue that would include:
    company name, address, phone, product name, and a paragraph
    explaining the product (this entry may be edited by Microsoft)

 2. The actual product being considered, along with any support
    materials and marketing information (such as manuals and
    brochures)

 The above information is summarized in a paragraph at the end of the
 language support directory on Page 17.


 601. Must DECLARE a FUNCTION Invoked from an External Library

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890405-127 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43252

 To use a FUNCTION that is in a library (.LIB) or Quick Library (.QLB),
 you must have a DECLARE statement at the top of each module that uses
 the FUNCTION. This is documented in the "Microsoft QuickBASIC 4.0:
 BASIC Language Reference" manual for Versions 4.00 and 4.00b, Page
 139, and the QuickBASIC 4.50 on-line QB Advisor by choosing <Help>
 <Index> DECLARE Statement (BASIC Procedures) <Details> and in the
 "Microsoft BASIC 7.0: Programmer's Guide" on Page 53.

 The documentation states that you must use DECLARE if you invoke a
 FUNCTION that is defined in another module. Library files (.LIB and
 .QLB) are "other modules," as are SUBprogram or FUNCTION modules
 that start from a separate .BAS or MS-DOS file.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 There are two reasons that DECLAREs are necessary for FUNCTIONs and
 not for SUBprograms.

 1. The only way to identify a SUBprogram without a DECLARE is with a
    CALL. You cannot use CALL with a FUNCTION because a FUNCTION
    returns a value and must be used in an assignment statement.

 2. Without the DECLARE, the compiler cannot know if you are referring
    to a variable, array, or FUNCTION.

 Consider the following BASIC statements:

    'Is this a FUNCTION call or assignment of a variable?
    VAR1# = Func1#

    ' Is this a FUNCTION call or is this assigning
    ' an array element to a variable?
    VAR1# = Func1#(VAR2,VAR3)

 The DECLARE FUNCTION Func1#(<variables>) statement tells the compiler
 that you are using a FUNCTION when you use the name Func1# and that
 this is not a variable or an array.


 602. CALL INTERRUPT RegType in Manual Inconsistent with QB.BI File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890406-35 docerr B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43256

 In the following manuals, the RegType (user-defined TYPE) documented
 with the CALL INTERRUPT statement is inconsistent with the TYPE in
 QB.BI, the $INCLUDE file:

 1. Page 90 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference"
    for QuickBASIC Versions 4.00 and 4.00b for MS-DOS and for
    Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 2. Page 74 of the "Microsoft QuickBASIC 4.5: BASIC Language
    Reference," which is available for separate purchase after you buy
    QuickBASIC Version 4.50

 To correct the inconsistency, remove the following two statements from
 the RegType in the manual:

    DS AS INTEGER
    ES AS INTEGER

 The RegType shown in the manual is actually the RegTypeX in the QB.BI
 $INCLUDE file.

 This documentation error has been corrected in Microsoft BASIC PDS
 Version 7.00 for MS-DOS and MS OS/2. The TYPE descriptions in the
 "Microsoft BASIC 7.0: Language Reference" for RegType and RegTypeX on
 Pages 172-173 agree with the TYPE declarations in the QBX.BI $INCLUDE
 file supplied with BASIC PDS 7.00.

 The RegType defined in the QB.BI file (used with $INCLUDE) does not
 contain the DS and ES registers. The DS and ES registers are only
 needed for the CALL INTERRUPTX statement, which uses RegTypeX.


 603. QB/H Not Reset to 25-Line Mode After Using Make EXE And Exit

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q43266

 The QuickBASIC environment can be invoked with the /H option, which
 enables the highest line mode supported by the video card. If QB.EXE
 is invoked with the /H option from MS-DOS while in 25-line mode, and a
 normal exit from the environment is performed (by pressing ALT+F X),
 then the video mode is reset to 25-line mode upon returning to MS-DOS.

 If an exit is performed using the Run menu's Make EXE And Exit
 command, the video mode is properly reset to 25-line mode during the
 compilation and LINKing process, but upon completion, the video mode
 is reset to 43-line mode.

 Microsoft has confirmed this to be a problem with QuickBASIC Versions
 4.00, 4.00b, and 4.50, and with the QB.EXE included with Microsoft
 BASIC Compiler Versions 6.00 and 6.00b (buglist6.00, buglist6.00b).
 This problem was corrected in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 (fixlist7.00).


 604. How to Flush File Buffers from within a BASIC Program

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890403-182 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43267

 The following information applies to QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00.

 Flushing a file buffer to disk from within a BASIC program can be done
 with one of the following two methods using MS-DOS Interrupt CALLs:

 1. Using MS-DOS Version 3.30 or later, the MS-DOS Interrupt 21 Hex
    with Function 68 Hex commits the file buffer to disk.

 2. Using MS-DOS earlier than Version 3.30, the MS-DOS Interrupt 21 Hex
    with Function 45 Hex creates a duplicate file handle, followed by a
    Interrupt 21 Hex with Function 3E Hex to close the duplicate file
    handle, which commits the file buffer to disk.

 Using Interrupt 21 Hex with Function 68 Hex has the advantage of not
 failing due to an insufficient number of file handles, or not risking
 losing control of the file in network environments. Its disadvantage
 is its limitation to MS-DOS 3.30 or later.

 Code Example
 ------------

 DECLARE SUB commit (filenum%)     'for use with DOS 2.10 & up
 DECLARE SUB commit330 (filenum%)  'for use with DOS 3.30 & up

 'The INCLUDE file name below would be 'QBX.BI' in the BASIC PDS 7.00
 '$INCLUDE: 'QB.BI'                'include file with regtype structure

 CLS
 DIM SHARED inregs AS RegType      'define inregs of regtype
 DIM SHARED outregs  AS RegType    'define outregs of regtype

 '-----------------------------------------------------------
 PRINT "press any key to open file"
 SLEEP                             'wait for keyboard input
 OPEN "b:stuff2" FOR RANDOM AS #1 LEN = 80
 PRINT "press a key to write to buffer"
 SLEEP
 a$ = "this and that"
 PUT #1, 1, a$                     'Write buffer

 '-----------------------------------------------------------
 PRINT "press any key to commit the buffer to disk"
 SLEEP                             'wait for keyboard input
 CALL commit330(1)                 'commit buffer for file 1

 '-----------------------------------------------------------
 PRINT "press any key to close file"
 SLEEP
 CLOSE 1
 END

 SUB commit (filenum%)
 inregs.ax = &H4500                'set funct 45H duplicate handle
 inregs.bx = FILEATTR(filenum%, 2) 'set file handle to duplicate
 CALL interrupt(&H21, inregs, outregs)  'call int 21H function 45H
 inregs.ax = &H3E00                'set function 3EH close file
 inregs.bx = outregs.ax            'set duplicated handle to close
 CALL interrupt(&H21, inregs, outregs) 'call int 21H function 3EH
 END SUB

 SUB commit330 (filenum%)
 inregs.ax = &H6800                'function 68h
 inregs.bx = FILEATTR(filenum%, 2) 'place file handle in register BX
 inregs.flags = &H0                'initialize flag values
 CALL interrupt(&H21, inregs, outregs)  'call interrupt 21 to
 '                                       commit buffer
 END SUB


 605. Differences among QuickBASIC Versions 2.00, 3.00, 4.00, 4.50

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 18-OCT-1989    ArticleIdent: Q43308

 This article describes differences among Microsoft QuickBASIC Versions
 2.00, 3.00, 4.00, and 4.50. (2.01 can be grouped with 2.00, and 4.00b
 can be grouped with 4.00 in the comparisons below.)

 FEATURE
 -------
                                          QuickBASIC Version
 Development Environment         2.00       3.00       4.00       4.50
 -----------------------         ----       ----       ----       ----

 Assembly-language listings      No         No         Yes        Yes
 during separate compilation
 (compiler /A option)

 Error listings during           No         Yes        Yes        Yes
 separate compilation

 Microsoft CodeView support      No         No         Yes        Yes

 Hercules graphics card support  No         No         Yes        Yes

 Immediate mode execution        No         No         Yes        Yes

 Insert/overtype modes           No         Yes        Yes        Yes

 Instant Watches for variables   No         No         No         Yes
 and expressions

 Multiple modules in memory      No         No         Yes        Yes

 Multifile/multiwindow editing   No         No         Yes        Yes

 On-line QuickBASIC Advisor      No         No         No         Yes

 On-line help                    No         No         Yes        Yes

 ProKey, SideKick, and           No         Yes        Yes        Yes
 SuperKey compatibility

 Selectable right mouse button   No         No         No         Yes
 function

 Set default search paths        No         No         No         Yes

 Syntax checking on entry        No         No         Yes        Yes

 WordStar-style keyboard         No         No         Yes        Yes
 interface

                                          QuickBASIC Version
                                 2.00       3.00       4.00       4.50
 Language Features               ----       ----       ----       ----
 -----------------

 BINARY file Input/Output        No         No         Yes        Yes

 Block IF/THEN/ELSE              Yes        Yes        Yes        Yes

 DEF FN                          Yes        Yes        Yes        Yes

 Definable lower array-bounds    No         No         Yes        Yes

 Fixed-length strings            No         No         Yes        Yes

 FUNCTION procedures             No         No         Yes        Yes

 Long (32-bit) integers          No         No         Yes        Yes

 Recursive procedures            No         No         Yes        Yes

 User-defined variable types     No         No         Yes        Yes

                                          QuickBASIC Versions
                                 2.00       3.00       4.00       4.50
 Math Support                    ----       ----       ----       ----
 ------------

 IEEE format, math coprocessor   No         Yes        Yes        Yes
 support

 8087/80287 support              No         Yes        Yes        Yes

 8087/80287 emulation            No         Yes        Yes        Yes

                                          QuickBASIC Versions
                                 2.00       3.00       4.00       4.50
 Memory Model and Linking        ----       ----       ----       ----
 ------------------------

 Build quick libraries from      No         No         Yes        Yes
 environment

 Compatibility with other        MASM only  MASM only  Yes        Yes
 languages

 Huge arrays                     No         No         Yes        Yes

 Quick library support or        User       User       Quick      Quick
 user library support            Library    Library    Library    Library

 FEATURES NEW TO QuickBASIC 4.50
 -------------------------------

 In QuickBASIC 4.50, you can access on-line help for QuickBASIC's
 keywords, commands, and menus, and on-line help for general topics and
 your own variables. Examples shown on the help screens can be copied
 and pasted directly into your own program, reducing development time.

 In the 4.50 editor, you can set the function of the right mouse button
 with the Right Mouse command from the Options menu. Use the function
 that best suits your needs.

 For faster debugging, QuickBASIC 4.50 offers an Instant Watch command
 for immediately identifying the value of a variable or the condition
 (true or false) of an expression.

 Version 4.50 also lets you set default search paths to specific types
 of files. This lets you organize your files by type and keep them in
 separate directories. QuickBASIC searches the correct directory after
 you set the new default search path. You can set default paths for
 executable, include, library, and help files.


 606. PRINT USING Incorrect Results, Hang for Double Precision

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist 4.00b buglist4.50 SR# S890319-2 B_BasicC
 Last Modified: 26-FEB-1990    ArticleIdent: Q43309

 PRINT USING for double precision numbers assigned to an expression in
 the range of (&H1D - 128) to (&H1D - 256) (where hex and decimal
 notations are mixed) can produce incorrect results in the program
 below. In the QB.EXE editor, it ignores the format string and prints a
 very large number. When compiled to an executable .EXE, it produces
 varied results depending on the version of the compiler and the
 options used. Compiling for Debug (with BC /d) does not affect the
 result.

 The following program, when compiled with BC.EXE Version 4.00 for use
 with BRUN, or with 4.00b, 6.00, or 6.00b for use with BCOM, prints
 large numbers as it does in the editor, but does not hang. When
 compiled with BC.EXE 4.00b, 4.50, 6.00, or 6.00b for use with BRUN, it
 prints very large numbers, and if run twice, it hangs the machine.
 When compiled with /O with BCOM in 4.00 and 4.50, it prints garbled
 output to the screen, but does not hang the machine.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS and MS
 OS/2. This problem was corrected in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 (fixlist7.00).

 Code Example
 ------------

 ' You can substitute "#" for each
 ' double precision number with the same result.
 DEFDBL A-Z
 CLS

 j = &H1D - 128

 FOR i = 1 TO 128
   j = j / 10
   PRINT USING "##.#######"; j
   NEXT
 END


 607. Assigning Values by PMAP to INTEGERs Can Map Incorrectly

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890406-58 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43526

 The PMAP FUNCTION can be used to map physical VIEW port coordinates to
 WINDOW coordinates, or WINDOW coordinates to VIEW port coordinates.
 When mapping physical coordinates of a VIEW port to the WINDOW
 coordinates, to ensure that correct results are obtained for all
 WINDOW coordinates, the value returned by PMAP should be assigned to a
 SINGLE or DOUBLE PRECISION variable. If assigned to an INTEGER
 variable, incorrect values can result, depending on the WINDOW
 coordinates assigned to the VIEW port.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and
 OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 When a VIEW port is defined, the physical coordinates refer to the
 actual SCREEN coordinates that are contained within the VIEW port. The
 following is a two-step illustration:

 1. SCREEN mode 2 has a resolution of 640 x 200. The physical
    coordinates of a VIEW port defined as "VIEW (20, 20) - (40, 40)"
    are 0 to 20 for both X and Y values. A "PSET(10, 10)" would turn on
    the pixel at VIEW port coordinates (10,10), which correspond to
    actual SCREEN coordinates of (30,30).

 2. If a WINDOW function is now performed, e.g. WINDOW (0, 0) - (10,
    10), the physical coordinates remain the same, but a "PSET(10, 10)"
    would turn on the pixel at VIEW port coordinates (20, 20), which
    correspond to actual screen coordinates of (40, 40).

 The problem occurs when a WINDOW statement defines coordinates for a
 VIEW port for which each of the physical coordinates do not map to
 "WHOLE NUMBER" coordinates. The following is an illustration:

 SCREEN 2
 VIEW (5, 0) - (10, 5)         'Defines a 6 x 6 VIEW port with
                               'physical coordinates of (0,0) to (5,5)
 WINDOW SCREEN (0,0)-(1,1)  'SCREEN places (0,0) at upper-left corner

 The coordinates from the above three lines of code would map to each
 other as follows:

 SCREEN X-Coordinates:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 VIEW X-Coordinates:                   0  1  2  3  4  5
 WINDOW X-Coordinates:                 0 .2 .4 .6 .8  1

 Using the above chart:   VIEW Coordinates   WINDOW Coordinates
                          ----------------   ------------------

                                 0      maps to      0
                                 1      maps to     .2
                                 2      maps to     .4
              PMAP(Xview, 3)     3      maps to     .6
                                 4      maps to     .8
                                 5      maps to      1

                          WINDOW Coordinates   VIEW Coordinates
                          ------------------   ----------------

                                 0      maps to      0
                                .2      maps to      1
            PMAP(Xwindow, 1)    .4      maps to      2
                                .6      maps to      3
                                .8      maps to      4
                                 1      maps to      5

 IF the value of PMAP(Xview, 3) is assigned to a SINGLE or DOUBLE
 precision variable, the correct value is obtained:

    Xmap! = PMAP(1, 3)     'Xmap! would equal .2

 If the value of PMAP(Xview, 3) is assigned to an INTEGER, a correct
 value is returned, but the INTEGER variable rounds the returned value
 up or down to the nearest INTEGER value, thus giving an incorrect
 mapping:

    Xmap% = PMAP(1, 3)     'Xmap% would equal 0, when the correct
                           'mapped value is .2 as shown above

 Code Example
 ------------

 The following program demonstrates the potential problem. It defines a
 VIEW port of 21 x 21 at SCREEN coordinates of (20, 20) to (40, 40),
 and then defines WINDOW coordinates of (0, 0) to (10, 10), which
 demonstrates a situation where INTEGERS won't work. The window is then
 redefined using WINDOW coordinates of (0, 0) to (20, 20), which
 demonstrates a situation where INTEGERS will work:

 SCREEN 2
 VIEW (20, 20)-(40, 40)
 FOR n% = 1 TO 2
   wxy% = n% * 10
   WINDOW SCREEN (0, 0)-(wxy%, wxy%)

   PRINT "VIEW (20, 20)-(40, 40)             YmapReal = PMAP(I%,3)"
   PRINT "WINDOW SCREEN (0, 0)-("; wxy%; ","; wxy%; ")   YmapInt% =
   PMAP(I%,3)"
   PRINT
   PRINT "I%     PMAP(YmapReal, 1)    PMAP(YmapInt%, 1)"

   FOR I% = 0 TO 9

     Ymapreal = PMAP(I%, 3)    'Maps I% to VIEW coordinates, assigns to
                               'REAL
     YmapInt% = PMAP(I%, 3)    'Maps I% to VIEW coordinates, assigns to
                               'INTEGER

     RemapFromReal = PMAP(Ymapreal, 1)  'Remaps Back to Physical
                                        'coordinates
     RemapFromInt = PMAP(YmapInt%, 1)   'and should be equal to I%

     PRINT I%, RemapFromReal;

     IF RemapFromReal <> RemapFromInt THEN
         PRINT " <- NOT EQUAL -> ";
       ELSE
         PRINT "                 ";
     END IF

     PRINT RemapFromInt

   NEXT I%
   PRINT
 NEXT n%
 END

 *********** PROGRAM OUTPUT **********

 VIEW (20, 20)-(40, 40)             YmapReal = PMAP(I%,3)
 WINDOW SCREEN (0, 0)-( 10 , 10 )   YmapInt% = PMAP(I%,3)

 I%     PMAP(YmapReal, 1)    PMAP(YmapInt%, 1)
  0             0                   0
  1             1  <- NOT EQUAL ->  0
  2             2                   2
  3             3  <- NOT EQUAL ->  4
  4             4                   4
  5             5  <- NOT EQUAL ->  4
  6             6                   6
  7             7  <- NOT EQUAL ->  8
  8             8                   8
  9             9  <- NOT EQUAL ->  8

 VIEW (20, 20)-(40, 40)             YmapReal = PMAP(I%,3)
 WINDOW SCREEN (0, 0)-( 20 , 20 )   YmapInt% = PMAP(I%,3)

 I%     PMAP(YmapReal, 1)    PMAP(YmapInt%, 1)
  0             0                   0
  1             1                   1
  2             2                   2
  3             3                   3
  4             4                   4
  5             5                   5
  6             6                   6
  7             7                   7
  8             8                   8
  9             9                   9


 608. BASIC Program to Read Characters from the Screen into a String

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43527

 The program below demonstrates a method to read text that is printed
 on the screen into a BASIC string variable. The program accesses video
 memory (at segment B000 hex) to read the characters from the screen.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00.

 For a color display, you must change the address of the DEF SEG
 statement in the function from HEX B000 to HEX B800. Note that any
 attributes (blinking, highlight, etc.) will be lost when the text is
 put into the string.

 The program is as follows:

 DECLARE FUNCTION readstr$ (xline%, xstart%, xstop%)

 CLS
 PRINT "Now is the time"         'Put some text on the screen
 PRINT "for all good men"
 PRINT "to come to the aid"
 PRINT "of their country."

 a$ = readstr$(1, 1, 6)          'Read the first six characters of the
                                 'first line  (i.e. "Now is")

 b$ = readstr$(4, 10, 18)        'Read the last nine characters (10-18)
                                 'on line four (i.e. "country.")
 LOCATE 10, 1
 PRINT "A$ = "; a$
 PRINT "B$ = "; b$

 'readstr$ takes three integers and returns a string.
 'The integers are:    1) The line on the screen to read from
 '                     2) The starting character position
 '                     3) The ending character position
 'It returns a string containing the characters on the screen
 'on the specified line between the start and stop positions.
 '
 FUNCTION readstr$ (xline%, xstart%, xstop%)

   DEF SEG = &HB000              'Change to B800 for color display

   fstart% = (160 * (xline% - 1)) + (2 * (xstart% - 1))
   fstop% = (160 * (xline% - 1)) + (2 * (xstop% - 1))
   FOR x% = fstart% TO fstop% STEP 2
     s$ = s$ + CHR$(PEEK(x%))
   NEXT x%
   readstr$ = s$
 END FUNCTION


 609. VARPTR$ Malfunctions on Local Variable Length STRING Arrays

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 21-APR-1989    ArticleIdent: Q43528

 The VARPTR$ function returns a string representation of a variable's
 address that can be used by the DRAW or PLAY statements. If VARPTR$ is
 used on an element of a local SUBprogram variable length STRING array,
 it generates an "Illegal Function CALL" during run time. This problem
 does not occur when run from within the QuickBASIC environment, but
 only when run as a compiled program. The problem occurs when the
 program is compiled with or without /D, or if it is compiled as a
 stand-alone executable file or one requiring the run-time module.

 Microsoft has confirmed this problem in Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50, and the Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00, buglist6.00b). We are researching this problem
 and will post new information as it becomes available.

 Workarounds to this problem follow in the "More Information" section.

 If the following program is compiled and then executed, it will
 generate an "Illegal Function CALL" when VARPTR$ is CALLed:

 DECLARE SUB Drawit()
 SCREEN 9
 Drawit
 END

 SUB Drawit
 DIM A$(10)
 A$(1) = "U100L100D100R100"     'commands to draw a box
 DRAW "X" + VARPTR$(A$(1))
 END SUB

 There are several easy workarounds for this problem:

 1. Do not use the VARPTR$ function. The following two statements will
    execute identically, and the second is much easier to implement:

       DRAW "X" + VARPTR$(A$(1))
       DRAW A$(1)

 2. Move the DIM statement to the Module level (main) code and change
    it to DIM SHARED A$(10).

 3. Assign a temporary variable to A$(1) and use the temporary variable
    in the VARPTR$ function.


 610. COBOL LINK.EXE 5.02.05 Causes BASIC Program to Hang

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890411-6 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43529

 A program compiled with Microsoft QuickBASIC Version 4.00, 4.00b, or
 4.50, with Microsoft BASIC Compiler Version 6.00 or 6.00b, or with
 Microsoft BASIC PDS Version 7.00 hangs if it is linked with LINK.EXE
 Version 5.02.05 using /E for EXEPACK. This version of LINK.EXE is
 bundled with Microsoft COBOL Versions 3.00 and 3.00a and is not meant
 to be used with products other than Microsoft COBOL.

 In general, we recommend that the linker provided with a product be
 used with that product. The linkers provided with QuickBASIC and with
 the BASIC compiler work correctly with those products. The linker
 provided is tested with the product during its development and may
 also contain features or options that are specific to that product.


 611. QB.EXE 4.50 Hangs If File Unloaded While Watch Is Set

 Product Version(s): 4.50
 Operating System:   OS/2
 Flags: ENDUSER | SR# S890410-127 buglist4.50 B_BasicCom
 Last Modified: 21-FEB-1991    ArticleIdent: Q43530

 Choosing to UNLOAD a file while a Watch on a variable is set hangs the
 QB.EXE editor, requiring a warm or cold reboot if operating under
 MS-DOS. If you are running under OS/2, this choice hangs the DOS
 compatibility box. This problem does not occur when UNLOADing a file
 if a Watchpoint is set to watch an expression.

 Microsoft has confirmed this to be a problem with QB.EXE in QuickBASIC
 version 4.50. This problem was corrected in QBX.EXE in Microsoft BASIC
 Professional Development System (PDS) version 7.00 (fixlist7.00).

 Example 1
 ---------

 To demonstrate this problem do the following:

 1. Type the following two lines in the QuickBASIC editor:

       B$ = "Hello"
       END

 2. Save the file by choosing Save As from the File menu.

 3. Choose Add Watch from the Debug menu by pressing ALT+D and then
    pressing "A".

 4. Enter B$ as the expression to watch. Press ENTER.

 5. Choose Unload from the File menu by pressing ALT+F and then
    pressing "U". Press ENTER to UNLOAD the program. The editor will
    then display a menu prompting you to choose a new main module. If
    the editor does not hang, press ENTER again to choose "Untitled" as
    the main module. At this point the editor will hang, requiring a
    cold or warm reboot.

 Example 2
 ---------

 The following exact steps also cause QB.EXE version 4.50 to hang under
 similar circumstances:

  1. Start QuickBASIC and load any Quick library:

        QB /L QB.QLB

  2. Type the following and press ENTER:

        PRINT "any text"

  3. Press the UP ARROW cursor key, thus placing the cursor under the
     "P" in PRINT.

  4. Press F9, thus placing a breakpoint on that line.

  5. Run the program by pressing SHIFT+F5.

  6. Select the Debug menu with ALT+D and press ENTER, thus choosing to
     set a watch variable.

  7. Type FRE("") as the watch variable and press ENTER.

  8. Press ALT+F+L (to select the Load File command), and press ESC.

 10. Press ALT+F+U (to select the Unload File command), and press
     ENTER.

 11. Press TAB, then the SPACE key, then ENTER, and the editor will
     be hung.


 612. INKEY$ Does Not Trap Extended Keys; Must Use Softkeys

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890411-42 B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q43531

 The INKEY$ function does not produce a unique KeyboardFlag + Scancode
 for the extended keys on the enhanced or extended 101-key keyboard.
 For instance, INKEY$ produces the same 2-byte code for the LEFT ARROW
 key on the numeric keypad as for the extended LEFT ARROW key. The same
 applies to the INS, HOME, PGUP, DEL, END, and PGDN keys and to the
 other arrow keys. Thus, you cannot trap for the extended keys
 separately using the INKEY$ function.

 This is not a problem with the INKEY$ function. Normally, an
 application's extended keys should behave exactly like the keys'
 equivalents on the numeric keypad. You would expect the cursor to move
 left if you pressed the LEFT ARROW from the numeric keypad or from the
 separate arrow keys.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2, and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 To trap the extended keys separately, use the combination of KEY n, ON
 KEY(n), and KEY(n) ON statements. The ability to do this is a unique
 feature of BASIC's key trapping routines. The following code example
 demonstrates how to do this:

 Code Example
 ------------

 '**** NOTE ******
 ' For this program to work properly, the NUM LOCK
 ' and CAPS LOCK keys must be turned off.
 '****************

 ' Define softkeys.
 KEY 15, CHR$(&H80) + CHR$(&H4B)
 KEY 16, CHR$(&H0) + CHR$(&H4B)

 ' Handle key events.
 ON KEY(1) GOSUB terminate
 ON KEY(15) GOSUB keytrap2
 ON KEY(16) GOSUB keytrap1

 ' Turn the keys on.
 KEY(1) ON
 KEY(15) ON
 KEY(16) ON

 ' Sign on message.
 CLS
 LOCATE 1, 18
 PRINT "PRESS ONE OF THE LEFT ARROW KEYS"
 LOCATE 2, 20
 PRINT "PRESS F1 TO EXIT THE PROGRAM"

 'Loop waiting for keyboard input.
 WHILE 1
 WEND

 finish:
 CLS

 END
 terminate:
   RETURN finish
 keytrap1:
   PRINT "THAT IS THE LEFT ARROW ON THE NUMERIC PAD"
   RETURN
 keytrap2:
   PRINT "THAT IS THE EXTENDED LEFT ARROW KEY"
   RETURN


 613. Getting Full EXEC Pathname from Environment Table Using PSP

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900406-139 B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q43560

 In MS-DOS versions 3.00 and later, the full path of any executing
 program is stored after the environment variables in the environment
 segment that is found in the program segment prefix (PSP). This
 article provides a description of how to extract the EXEC path and
 gives an example of how to do this with BASIC.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10.

 The segment address of the PSP for the currently executing process can
 be checked with the DOS Interrupt 21 hex, function 62 hex.

 The environment segment can be found in the PSP at offset 2C hex. The
 environment table has an entry for each environment variable of the
 format <name>=<parameter>. Each entry is terminated by a null
 character [CHR$(0)] and the entire table is followed by an additional
 null character. After the additional null character, there is a 2-byte
 word count. Immediately after the word count, the full path of the
 executing program is listed as

    <drive>:<path>\<filename>.<extension>

 and is also terminated by a null character.

 For more information about the PSP and the environment table, see
 "Advanced MS-DOS Programming, 2nd Edition" by Ray Duncan, published by
 Microsoft Press (1988).

 Code Example
 ------------

 The following code example provides a function that will return the
 full path of the currently executing program in DOS 3.00 and later:

 'Compile and link lines:
 ' BC FULLPATH;
 ' LINK FULLPATH,,,QB.LIB;    NOTE: QBX.LIB should be used for PDS
 '                                 7.00 or 7.10
 '$INCLUDE: 'qb.bi'  ' NOTE: QBX.BI should be used for PDS 7.00/7.10
 DECLARE FUNCTION FullPath$ ()
 CONST EnvOffInPSP = &H2C

 PRINT FullPath$

 FUNCTION FullPath$
   DIM inregs AS RegType, OutRegs AS RegType

   inregs.ax = &H6200 'Get PSP
   CALL INTERRUPT(&H21, inregs, OutRegs)

   PSPSeg% = OutRegs.bx
   EnvironSeg& = 0
   OffSet& = 0
   tmp$ = ""

   DEF SEG = PSPSeg%
     EnvironSeg& = 256 * PEEK(EnvOffInPSP + 1) + PEEK(EnvOffInPSP)

   DEF SEG = EnvironSeg&
     WHILE (PEEK(OffSet&) <> 0 OR PEEK(OffSet& + 1) <> 0)
       OffSet& = OffSet& + 1
     WEND

     'Skip extra bytes between Env Table and Fullpath
     OffSet& = OffSet& + 4

     'Build FullPath$ (until null terminates string)
     WHILE PEEK(OffSet&) <> 0
       tmp$ = tmp$ + CHR$(PEEK(OffSet&))
       OffSet& = OffSet& + 1
     WEND
   DEF SEG

   FullPath$ = tmp$
 END FUNCTION


 614. Function MENU%() Fails in Hergert's "QuickBASIC, 2nd Edition"

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43563

 The MENU%() function in the Microsoft Press book "Microsoft
 QuickBASIC, Second Edition" by Douglas Hergert will fail if it is
 coded without the variables "true%" and "false%" defined in the main
 program. If these lines are not included, the program will eventually
 enter an infinite loop that can only be exited with CTRL+BREAK.

 The program can be found on Pages 68-71 in Hergert's book. This
 program, which is designed to be incorporated into your program,
 displays a menu box with menu options and returns a value equal to
 your selection. The book assumes that you have defined the variables
 "true%" and "false%" in the title of your main program. This is a
 documentation omission.

 This information applies to Microsoft QuickBASIC Versions 3.00, 4.00,
 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b,
 and to Microsoft BASIC PDS Version 7.00.

 The workaround for this problem is to add one of the following lines
 of code to the beginning of the program:

    false% = 0 : true% = NOT false%
    true% = -1 : false% = NOT true%


 615. L2025: Symbol Already Defined Error Caused by SIGNAL.H in .QLB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q43564

 LINKing C subfunctions into a QuickBASIC Quick library (.QLB) may
 generate many "L2025: Symbol defined more than once" errors. This can
 be caused when the C subfunction is compiled with the SIGNAL.H C
 include file that comes with Microsoft QuickC version 2.00 and
 Microsoft C Compiler versions 5.00, 5.10, and 6.00.

 If the SIGNAL.H include file is not used, or if the C subfunction is
 directly LINKed to the BASIC program when producing an .EXE file, the
 errors do not occur.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions
 6.00 and 6.00b (buglist6.00, buglist6.00b); and in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10
 (buglist7.00, buglist7.10). We are researching this problem and will
 post new information here as it becomes available.

 Below is the source code that, when LINKed into a Quick library, will
 create the "Symbol defined more than once" errors.

 C Routine
 ---------

 /* SIGNAL.C */
 /* Demonstration of signal.h failing with QuickBASIC 4.50 */

 #include <signal.h>

 int handler ()
 {  }
 void far testc()
 {
     signal(SIGINT, handler);
 }

 Link Command
 ------------

    LINK /Q SIGNAL.OBJ,,,BQLB45.LIB;

 The Quick library support module used in the above LINK line should be
 BQLB45.LIB in QuickBASIC 4.50, BQLB41.LIB in QuickBASIC 4.00b or BASIC
 Compiler 6.00b, BQLB40.LIB in QuickBASIC 4.00 or BASIC Compiler 6.00,
 and QBXQLB.LIB in BASIC PDS 7.00 or 7.10.


 616. QuickBASIC Program to Detect if a Math Coprocessor Is Present

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890412-46 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43565

 Below is a QuickBASIC or BASIC compiler program that will detect
 whether or not a particular machine has a math coprocessor installed.
 This code will execute correctly in the Microsoft QuickBASIC Compiler
 Versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00
 and 6.00b, and Microsoft BASIC PDS Version 7.00.

 The program is as follows:

 DECLARE SUB display ()
 '===================================================================
 'Program MATH.BAS to detect math coprocessor, if present
 '===================================================================
 DEFINT A-Z

 CALL display

 DEF SEG = 0
 chip = PEEK(&H410)               'Look at 2nd bit of 0000:0410 Hex
 chipthere = chip \ 2 AND 1       'Equipment List Word bit
                                  'for math coprocessor (8087 etc.)
 IF chipthere = 1 THEN
    COLOR 2, 0
    PRINT "                       Math coprocessor present";
 ELSE
    COLOR 4, 0
    PRINT "                       No math coprocessor detected";
 END IF

 DO UNTIL INKEY$ <> ""            'Wait for key then clear screen
 LOOP
 CLS
 END

 SUB display
 '===================== Display Screen Control =====================
 CLS
 VIEW PRINT 25 TO 25
 COLOR 7, 1
 PRINT
 LOCATE 25, 29
 PRINT "Press any key to exit";
 VIEW PRINT 1 TO 1
 COLOR 7, 1
 PRINT
 LOCATE 1, 34
 PRINT "MATH.BAS";
 VIEW PRINT 12 TO 12
 COLOR 0, 0
 PRINT
 END SUB


 617. SUBprogram to Convert Integer to a String in Binary Notation

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890412-99 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43567

 Below is a QuickBASIC SUBprogram that converts an integer to binary
 notation (represented in a string form). Both an integer and a string
 variable are passed to the SUBprogram and the result is returned in
 the string variable. The integer is broken down bit by bit and
 converted into its hexadecimal equivalent.

 This code will execute correctly in Microsoft QuickBASIC Versions
 3.00, 4.00, 4.00b, and 4.50, in Microsoft BASIC Compiler Versions 6.00
 and 6.00b, and in Microsoft BASIC PDS Version 7.00.

 The code example is as follows:

 DEFINT A-Z
 '__________________________________________________________________
 '
 '    IntToBin() takes an INTEGER argument and produces a
 '    binary string representation of the INTEGER.
 '__________________________________________________________________
 '
 SUB IntToBin (byte%, bin$)         'Add STATIC here to get SUB to
 bin$ = ""                          'work in QuickBASIC 3.00
 temp% = byte%

         FOR i = 0 TO 7
                 IF temp% AND 1 THEN
                         bin$ = "1" + bin$
                 ELSE
                         bin$ = "0" + bin$
                 END IF
                  temp% = temp% \ 2
         NEXT

 END SUB


 618. Program That Returns the Address of an Interrupt Vector

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890412-84 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q43568

 The QuickBASIC program below will return the address of the interrupt
 vector whose number you input. This program operates correctly with
 Microsoft QuickBASIC Versions 3.00, 4.00, 4.00b, and 4.50, the
 Microsoft BASIC compiler Versions 6.00 and 6.00b, and the Microsoft
 BASIC PDS Version 7.00.

 'Program GETVECTR.BAS looks in low memory to get the address of
 'any interrupt vector that you input.

 DEFINT A-Z
 DEF SEG = 0
 CLS
 VIEW PRINT 25 TO 25
 COLOR 15, 1
 PRINT
 LOCATE 25, 30
 PRINT "Ctrl-Break to EXIT";
 VIEW PRINT 1 TO 1
 PRINT
 LOCATE 1, 34
 PRINT "GETVECTOR";

    VIEW PRINT 9 TO 15
    COLOR 0, 7
    PRINT : PRINT : PRINT : PRINT : PRINT : PRINT : PRINT

 DO
   PRINT "  Enter the Number of the Interrupt. Use &H to specify a "
   PRINT "  Hex Number (such as &H5 for Interrupt 5 Hex)"
    PRINT
    INPUT "  Interrupt ", intnum
    offset = 4 * intnum
    byte1$ = HEX$(PEEK(offset))
    byte2$ = HEX$(PEEK(offset + 1))
    byte3$ = HEX$(PEEK(offset + 2))
    byte4$ = HEX$(PEEK(offset + 3))
    vector$ = byte4$ + " " + byte3$ + " : " + byte2$ + " " + byte1$
    LOCATE 13, 1
    PRINT SPACE$(40)
    LOCATE 13, 1
    PRINT "Handler for Interrupt      "; HEX$(intnum) + " Hex"
    PRINT "is located at address -->  "; vector$
    PRINT
 LOOP
 DEF SEG
 CLS


 619. Program That Prints a Hex Dump of a File to LPT1

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890413-101 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43569

 The following is QuickBASIC or BASIC compiler code that will print a
 HEX dump of a given file to a standard out or IBM or Epson printer
 connected to LPT1. This program is also a good example of how to get
 arguments from the command line and how to check if a file exists.

 This program will execute correctly with Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50, with Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and with Microsoft BASIC PDS Version 7.00.

 The code example is as follows:

 DECLARE SUB banner ()
 DECLARE SUB filter (byte%)
 '======================= HEXDUMP.BAS ===============================
 ' Program to print a Hexadecimal dump of a file to a standard out or
 ' IBM or Epson printer connected to the LPT1: port.
 '===================================================================
 DEFINT A-Z
 CONST TRUE = -1
 CONST FALSE = NOT TRUE

 ON ERROR GOTO handler
 CLS
 datafile$ = COMMAND$                'Get filename from command line

   IF datafile$ = "" THEN            'Check for no filename input
      LOCATE 12
      PRINT "Usage  c:>hexdump [filename]   Output goes to LPT1:"
      END
   END IF

 OPEN datafile$ FOR INPUT AS #1      'Easy way to check for file exit
 CLOSE #1                            'IF NOT ERROR will force jump to

 OPEN datafile$ FOR BINARY AS #1
 CALL banner
 DO UNTIL EOF(1) = TRUE              'Read the file 2 bytes at a time
    ascii$ = ""
    offset$ = HEX$(LOC(1))
    offlen = LEN(offset$)

    out$ = STRING$(8 - offlen, 48) + offset$ + ":  "
    FOR i% = 1 TO 8
       GET #1, , dataword
       IF EOF(1) = TRUE THEN
          fudge = 47 - (3 * (LOF(1) MOD 16) - 1)
          ascii$ = SPACE$(fudge + 3) + ascii$
          EXIT FOR
       END IF

       IF dataword < 0 THEN
          highbyte = (dataword + 2 ^ 16) \ 256
       ELSE
          highbyte = dataword \ 256  'Integer divide off low byte
       END IF

       lowbyte = dataword AND 255    'AND off the top byte
       CALL filter(highbyte)
       CALL filter(lowbyte)
       lowbyte$ = RIGHT$("0" + HEX$(lowbyte), 2)
       highbyte$ = RIGHT$("0" + HEX$(highbyte), 2)
       out$ = out$ + " " + lowbyte$ + " " + highbyte$

       ascii$ = ascii$ + CHR$(lowbyte) + CHR$(highbyte)
    NEXT i%
 '  LPRINT out$ + "   " + ascii$    'Remove comment for printed output
    PRINT out$ + "   " + ascii$
 LOOP
 END

 handler:
    PRINT "An ERROR has occurred: ERROR "; ERR
  END

 '=================================================================
 '                        Prints the heading banner
 '=================================================================
 SUB banner
   PRINT "__________________________ HEXDUMP ________________________"
   PRINT
   PRINT "Length of"; COMMAND$; " ["; HEX$(LOF(1)); "] Hex Bytes";
   PRINT "    "; LOF(1); " Decimal Bytes"
   PRINT "___________________________________________________________"
   PRINT
   VIEW PRINT 5 TO 25
 END SUB

 SUB filter (byte%)
 SELECT CASE byte%
   CASE 7, 9, 10, 11, 12, 13, 14, 27
      byte% = 32
   END SELECT
 END SUB


 620. ENVIRON Sets Environment Variables Used by SHELL in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890421-61 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43691

 The ENVIRON statement in BASIC can change the MS-DOS environment
 variables to different values to be used by that program or a child
 process invoked with the SHELL statement.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 The ENVIRON statement allows you to alter the environment variables
 for use by child processes started through BASIC. Once set, these
 variables will remain set to the new values as long as you are in your
 BASIC program or SHELL out to a child process.

 BASIC makes a copy of the original DOS environment variables, and the
 local copy can be changed with the ENVIRON statement. These changes to
 the temporary copy of the DOS environment variables remain in effect
 when BASIC SHELLs to another process.

 When altering the environment table through BASIC, it is common for an
 "OUT OF MEMORY" error message to be displayed. For more information on
 the workaround for this error, query on the following keywords:

    ENVIRON$ Memory QuickBASIC

 The following code example will print out the current copy of the
 environment table, alter the PATH and PROMPT environment variables,
 print out the environment table again, then SHELL and perform the DOS
 SET command:

 Code Example
 ------------

 CLS
 i = 1

 DO WHILE ENVIRON$(i) <> ""   ' prints BASIC's environment table
     PRINT ENVIRON$(i)
     i = i + 1
 LOOP

 ENVIRON "PATH=;"              ' clear the PATH environment variable
 ENVIRON "PATH=C:\DOS"         ' set the PATH environment variable
 ENVIRON "PROMPT=;"            ' clear the PROMPT environment variable
 ENVIRON "PROMPT=$P$G"         ' set the PROMPT environment variable

 PRINT : PRINT

 i = 1
 DO WHILE ENVIRON$(i) <> ""    ' prints BASIC's environment table
     PRINT ENVIRON$(i)
     i + i + 1
 LOOP

 PRINT : PRINT
 SHELL "set"   ' prints the environment table in BASIC's child process
 END


 621. Problem of a Line Disappearing in QB.EXE Version 4.50 Editor

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER  | SR# S890406-49 S890728-43 buglist4.50 B_BasicCom
 Last Modified:  2-MAR-1990    ArticleIdent: Q43696

 Under certain circumstances, a line of code can disappear in the
 QuickBASIC Version 4.50 editor. Microsoft has isolated two sets of
 conditions (shown below) under which this problem occurs. Although the
 line of code is not visible on the screen, it has NOT been removed
 from the source code. It usually reappears after any of a variety of
 actions (for example, after a carriage return on any line).

 Microsoft has confirmed this to be a problem with QuickBASIC Version
 4.50. This problem was corrected in Microsoft BASIC Professional
 Development System (PDS) Version 7.00 (fixlist7.00).

 Example 1
 ---------

 The following steps re-create the problem:

 1. Generate a nonfatal error (for example, "Bad filename"), such as in
    the following example:

       ' this can be any line
       OPEN "com1:3" FOR RANDOM AS #1     'change baud from 3 to 300

 2. Edit (correct) the highlighted line that has the error.

 3. Go to the previous line and press ENTER. This causes the
    highlighting to incorrectly go to the previous line.

 4. Enter a statement, such as "a=1", that will bring up the dialog box
    that has the following message:

       You will have to restart your program after this edit. Proceed
       anyway?

 5. Choose either OK or Cancel, and the statement that originally
    caused the error will disappear from the edit screen.

 Example 2
 ---------

 In the Microsoft QuickBASIC Version 4.50 QB.EXE environment,
 performing the steps below causes some of the following code to
 disappear:

    REM DIM x as integer
    PRINT "BOO!"

 1. Use F8 (single step) or F10 (procedure step) to move the statement
    pointer to the PRINT statement.

 2. Remove the "REM" portion of the first line.

 3. Press the DOWN ARROW key.

 The above procedure causes the PRINT statement to disappear.

 You can make the PRINT statement reappear by pressing the SPACEBAR
 where the PRINT statement used to be or by pressing F4 (view output
 screen) twice.


 622. "COMMON in Quick Library Too Small" -- Use NAMED COMMON

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890416-1 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43698

 If the COMMON block in a main program module is larger than the COMMON
 block of a loaded Quick library subprogram, the error "COMMON in Quick
 library too small" occurs. In an executable (EXE) form (LINKed with an
 equivalent LIB), the error does not occur.

 To work around this behavior, use a named COMMON block for the Quick
 library subprograms.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to the QB.EXE environment shipped with Microsoft BASIC Compiler
 Versions 6.00 and 6.00b, and to the QBX.EXE environment shipped with
 Microsoft BASIC PDS Version 7.00.

 Code Example
 ------------

 The following code example causes the "COMMON in Quick library too
 small" error when run in the environment; the workaround is described
 in comments:

 REM Calling program
 COMMON a%, b%, c%        'workaround: COMMON /qlbcommon/ a%, b%
 REM    So other programs can use also: COMMON a%, b%, c%
 CALL test
 END

 REM Quick Library TEST.QLB
 COMMON a%, b%            'workaround: COMMON /qlbcommon/ a%, b%
 SUB Test
 PRINT a%, b%
 END SUB


 623. Cannot Search and Replace String Longer Than 39 Characters

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890410-125 buglist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q43743

 In the QB.EXE environment in Microsoft QuickBASIC Version 4.50,
 searching for and replacing a string does not work correctly if the
 replacement string is longer than 39 characters. A longer replacement
 string can be entered, but the editor truncates this string to 39
 characters.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50. We are researching this problem and will post new information
 here as it becomes available.

 This problem does not occur in the QBX.EXE editor provided with
 Microsoft BASIC Professional Development System (PDS) Version 7.00.

 QuickBASIC Versions 2.00 and 3.00 correctly make the substitution for
 strings longer than 39 characters. QuickBASIC Versions 4.00 and 4.00b
 do not allow a string longer than 39 characters to be entered as the
 replacement string, so the problem doesn't occur in these versions.

 To duplicate this problem, do the following:

 1. Start a new program in QB.EXE from QuickBASIC 4.50 and enter the
    following line:

       PRINT

 2. Choose the Search menu by pressing ALT+S, then press C.

 3. Enter "PRINT" as the string to find and
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1234567890" as the
    replacement string (39 a's, followed by numbers).

 4. Choose Change All by pressing ALT+C.

 The editor will replace PRINT with the given string, but it will
 truncate the numbers off of the end.


 624. QuickBASIC Program to Send a Break through COM1 Port

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890418-97 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q43746

 Below is a Microsoft QuickBASIC program that sends a Break through
 COM1 using the OUT statement. To cause a Break condition to be output
 on the communications line, the Line-Control Register must be read in,
 the Break bit set (bit number 6), and the register rewritten to the
 port. The Line-Control Register is an 8250 register at I/O port
 address 3FB hex. More information concerning the Line-Control Register
 and other 8250 registers can be found on Pages 177-181 in "8088
 Assembler Language Programming: The IBM PC," 2nd edition, by David C.
 Willen and Jeffrey I. Krantz (published by SAMS, 1988).

 A simple outline of the program below is as follows:

 1. Get current Line-Control Register -- value% = INP(&H3FB)

 2. Set the Break bit, bit 6, 2^6= 64 -- value% = value% OR 64

 3. Rewrite Line-Control Register     -- OUT &H3FB, value%

 The following program executes correctly in Microsoft QuickBASIC
 Compiler Versions 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler
 Versions 6.00 and 6.00b, and Microsoft BASIC PDS Version 7.00:

 '--------------------------------------------------------------------
 ' SETBREAK.BAS:
 '
 ' This is a sample QuickBASIC program that reads the Line-Control
 ' Register for the communications port (address &H3FB), sets the
 ' Break, and puts it back to the port. This causes a Break to be sent
 ' through the communications port.
 '
 '--------------------------------------------------------------------

 DECLARE SUB IntToBin (byte%, bin$)
 DECLARE SUB BreakWord (dataword%, highbyte%, lowbyte%)
 CLS

 OPEN "com1:9600,n,8,,CS0,DS0,CD0,RB8192,TB8192" FOR RANDOM AS 1

 LineContlReg1% = INP(&H3FB)                        'Get line control
                                                    'register

 CALL BreakWord(LineContlReg1%, high1%, low1%)
 CALL IntToBin(LineContlReg1%, LCR1$)
 PRINT "---BEFORE SETTING BREAK---"
 PRINT "Line-Control Register (LCR) :  "; LineContlReg1%
 PRINT "LCR representation in binary:  "; LCR1$
 PRINT

 LineContlReg2% = LineContlReg1% OR 64              'Set Break -- 6th
                                                    'bit

 CALL BreakWord(LineContlReg2%, high2%, low2%)
 CALL IntToBin(LineContlReg2%, LCR2$)
 PRINT "---AFTER SETTING BREAK---"
 PRINT "Line-Control Register (LCR) :  "; LineContlReg2%
 PRINT "LCR representation in binary:  "; LCR2$

 OUT &H3FB, LineContlReg2%    'Reset the Line-Control Register to send
                              'a Break

 END

 '____________________________________________________________________
 '
 '     BreakWord() takes an integer argument and returns two integers
 '     representing the high and low bytes of the original.
 '____________________________________________________________________
 '
 SUB BreakWord (dataword%, highbyte%, lowbyte%)
     IF dataword% < 0 THEN
        highbyte% = (dataword% + 2 ^ 16) \ 256   'check for high BIT
                                                 'set
     ELSE
        highbyte% = dataword% \ 256              'integer divide off
                                                 'low byte
     END IF

     lowbyte% = dataword% AND 255                'AND off the top byte
 END SUB

 '____________________________________________________________________
 '
 '    IntToBin() takes an INTEGER argument and produces a
 '    binary string representation of the INTEGER.
 '____________________________________________________________________
 '
 SUB IntToBin (byte%, bin$)
 bin$ = ""
 temp% = byte%

 FOR i = 0 TO 7
     IF temp% AND 1 THEN
        bin$ = "1" + bin$
     ELSE
        bin$ = "0" + bin$
     END IF
     temp% = temp% \ 2
 NEXT

 END SUB


 625. QB Versus C, Benchmark Time Comparison for Recursive Program

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890210-55
 Last Modified: 14-DEC-1989    ArticleIdent: Q43782

 The Towers of Hanoi is a problem that can be programmatically solved
 through the use of recursion. Listed below are the recursive
 implementations in QuickBASIC Version 4.50 and Microsoft C Version
 5.10. When compiled with the compiler option giving the greatest speed
 (BC /O stand-alone option), the QuickBASIC .EXE routine was roughly
 40 percent slower than the C routine. No coprocessor was used, since
 the program uses all integers and no floating-point calculations.

 This benchmark comparison for QuickBASIC 4.50 is similar for Microsoft
 QuickBASIC Versions 4.00 and 4.00b, for Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and for Microsoft
 BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The table below shows the execution speeds (in seconds) of the
 recursive routine in both QuickBASIC Version 4.50 and Microsoft C
 Version 5.10. The benchmark was performed on a Wyse 286, running
 MS-DOS 3.30, operating at 10 megahertz. As you can see in the
 following timings (based on the number of disks on the Hanoi Towers),
 the QuickBASIC routine was roughly 40 percent slower than the C
 routine:

    Number of Disks       QuickBASIC 4.50      C 5.10

           1                  0.0000           0.0000
           2                  0.0000           0.0000
           3                  0.0000           0.0000
           4                  0.0000           0.0000
           5                  0.0000           0.0000
           6                  0.0000           0.0000
           7                  0.0000           0.0000
           8                  0.0125           0.0000
           9                  0.0368           0.0000
          10                  0.0624           0.0000
          11                  0.1093           0.0000
          12                  0.1601           0.0802
          13                  0.3789           0.1739
          14                  0.8203           0.3674
          15                  1.5898           0.7812
          16                  3.1911           1.7310
          17                  6.4296           3.8761
          18                  12.796           7.2687
          19                  25.539           15.234
          20                  51.132           31.021

 Code Example

 REM ** QuickBASIC program:
 REM Compile as follows:  BC HANOI.BAS/O;
 REM Link as follows:     LINK HANOI.OBJ;
 DEFINT A-Z
 DECLARE SUB HANOI(DISKS,TOWERA(),TOWERB(),TOWERC())
 CLEAR ,, 4096
 DIM TOWERA(2)
 DIM TOWERB(2)
 DIM TOWERC(2)
 PRINT
 PRINT"                   RECURSIVE TOWERS OF HANOI"
 DO
 INPUT "NUMBER OF DISKS? ", DISKS
 PRINT
      IF DISKS<>0 THEN
           TOWERA(0)=1
           TOWERB(0)=2
           TOWERC(0)=3
           PRINT
           CALL HANOI(DISKS,TOWERA(),TOWERB(),TOWERC())
      END IF
 LOOP UNTIL DISKS=0
 END

 FUNCTION WHICHTOWER$(TOWER%)
   SELECT CASE TOWER%
      CASE 1:     WHICHTOWER$=" A "
      CASE 2:     WHICHTOWER$=" B "
      CASE 3:     WHICHTOWER$=" C "
   END SELECT
 END FUNCTION

 SUB HANOI (DISKS,TOWERA(),TOWERB(),TOWERC())
      IF DISKS=1 THEN
           DESTINATION$=WHICHTOWER$(BYVAL TOWERC(0))
           SOURCE$=WHICHTOWER$(BYVAL TOWERA(0))
           PRINT "MOVED DISK FROM"; SOURCE$;"TO";DESTINATION$
      ELSE
            CALL HANOI(DISKS-1,TOWERA(),TOWERC(),TOWERB())
           DESTINATION$=WHICHTOWER$(BYVAL TOWERC(0))
           SOURCE$=WHICHTOWER$(BYVAL TOWERA(0))
           PRINT "MOVED DISK FROM"; SOURCE$;"TO";DESTINATION$
           CALL HANOI(DISKS-1,TOWERB(),TOWERA(),TOWERC())
      END IF
 END SUB

 #include <time.h>
 #include <stdio.h>
 char *source=" Z  ",*destination=" Z  ";

 void hanoi(disks,TowerA,TowerB,TowerC)
 int disks;
 int TowerA,TowerB,TowerC;
 {
     extern char *source,*destination;

     if (disks == 1)
      {
        switch (TowerA)
         {
          case 1 :
              source=" A \0";
              break;
       case 2 :
              source=" B \0";
              break;
       case 3 :
              source=" C \0";
              break;
         }
        switch (TowerC)
      {
       case 1 :
              destination=" A \0";
              break;
       case 2 :
              destination=" B \0";
              break;
       case 3 :
              destination=" C \0";
              break;
         }
       /*printf("\nMOVED DISK FROM %s to %s",source,destination);*/
      }
    else
      {
       hanoi(disks-1,TowerA,TowerC,TowerB);
        switch (TowerA)
         {
          case 1 :
              source=" A \0";
              break;
       case 2 :
              source=" B \0";
              break;
       case 3 :
              source=" C \0";
              break;
         }
        switch (TowerC)
      {
       case 1 :
              destination=" A \0";
              break;
       case 2 :
              destination=" B \0";
              break;
       case 3 :
              destination=" C \0";
              break;
         }
        /*printf("\nMOVED DISK FROM %s to %s",source,destination);*/
     hanoi(disks-1,TowerB,TowerA,TowerC);
     }
 }

 main ()
 {
    int           TowerA=1,TowerB=2,TowerC=3,disks,thatone;
    long       start=01,finish=01;
    clock_t     clock(void);
    float       amnttime;

    printf("number of disks? ");
    scanf("%d",&disks);
    while (disks!=0)
    {
      start=(long)clock();
      hanoi(disks,TowerA,TowerB,TowerC);
      finish=(long)clock();
      amnttime=(float)((finish-start)/(float)CLK_TCK);
      printf("\nPROGRAM TOOK %04.04f", amnttime);
      printf(" SECONDS WITH %d DISKS",disks);
      printf("\nnumber of disks? ");
      scanf("%d",&disks);
    }
   fcloseall();

 }


 626. No Color in QB Editor with Tandy RGB Adapter on Tandy 1200

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890215-61
 Last Modified: 27-APR-1989    ArticleIdent: Q43783

 It has been reported that the QuickBASIC Version 4.50 editor does not
 display colors with a Tandy RGB video adapter on a Tandy 1200.
 Microsoft has not tested QuickBASIC Version 4.50 with the Tandy RGB
 video adapters, and we do not claim compatibility with the Tandy RGB
 adapters. Running QuickBASIC Version 4.50 with a Tandy RGB video
 adapter may result in display or editor problems.

 It has also been reported that invoking the QB.EXE editor with the /h
 (high resolution) switch corrects this problem.

 Microsoft has not confirmed this information.


 627. Obtaining the Local Drive Name and Network Name; INT 21 Hex

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890210-109
 Last Modified: 15-DEC-1989    ArticleIdent: Q43784

 MS-DOS Interrupt 21 Hex function 5F Hex, subfunction 02 allows you to
 return the local drive name and the network name of a device that has
 been redirected. An example of this is when you connect to a server
 and use it as the logical drive. If you wanted to obtain the drive
 name and the path to the server from within a QuickBASIC program, you
 could CALL this MS-DOS interrupt.

 The following requirements need to be observed when calling this
 interrupt:

 1. The MS-DOS network utility SHARE.EXE must be run before you can
    successfully call this interrupt.

 2. It is important that the network being used is a Microsoft Network
    configuration, such as IBM PC-NET. Otherwise, the information that
    is returned may not be correct.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS,
 and Microsoft BASIC PDS Version 7.00 for MS-DOS.

 Code Example
 ------------

 '*****************GET REDIRECTION LIST ENTRY******************
 'If you are using BASIC PDS 7.00 the INCLUDE file should be 'QBX.BI'
 '$INCLUDE: 'QB.BI'
 DIM inregs AS RegTypeX
 DIM devname%(8)
 DIM networkname%(64)

     inregs.ax = &H5F02
     inregs.bx = &H0
     inregs.ds = VARSEG(devname%(0))
     inregs.si = VARPTR(devname%(0))
     inregs.es = VARSEG(networkname%(0))
     inregs.di = VARPTR(networkname%(0))

     CLS
     CALL INTERRUPTX(&H21, inregs, inregs)
     PRINT "REDIRECTED LOCAL DEVICE NAMES:"
     X% = CSRLIN
     LOCATE X% + 1, 15
     DEF SEG = inregs.ds
     FOR looper = 0 TO 7
         PRINT (CHR$(PEEK(inregs.si + looper)));
     NEXT
     DEF SEG
     PRINT
     PRINT
     PRINT "NETWORK NAME(S):"
     X% = CSRLIN
     LOCATE X% + 1, 15
     DEF SEG = inregs.es
     FOR llooper = 0 TO 63
         PRINT (CHR$(PEEK(inregs.di + llooper)));
     NEXT
     DEF SEG
 END


 628. QB 4.00/4.00b Can Wrongly Assign User-TYPE Variable; 4.50 OK

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 SR# S890117-41
 Last Modified: 27-APR-1989    ArticleIdent: Q43786

 In the program below, the QB.EXE editor (from QuickBASIC Versions 4.00
 and 4.00b) fails to correctly assign a value to a variable of a
 user-defined type (f.inx). This variable remains zero at all times.
 The problem does not occur when the program is compiled into an .EXE.

 Almost any change to the program corrects the error, such as renaming
 the variable. It is difficult to find the same problem in a different
 program.

 Microsoft has confirmed this to be a problem in Versions 4.00 and
 4.00b. This problem was corrected in QB.EXE from QuickBASIC Version
 4.50.

 Code Example

 TYPE rectype
   a AS SINGLE
   inx AS INTEGER
 END TYPE

 DIM f AS rectype

 f.a = 355
 f.inx = 5

 CLS
 PRINT f.a
 PRINT f.inx   ' this value will print out 0
 END


 629. LINK.EXE 3.69 Warning L4045 When No .QLB on Quick Library Name

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890122-1 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43787

 When creating a Quick library with LINK.EXE Version 3.69 or 5.05, the
 linker warning message "L4045 NAME OF OUTPUT FILE IS <NAME>" is given
 if the extension .QLB is left off the new Quick library name in the
 LINK command line. This happens even if the /Q (Quick Library) option
 is the first item on the LINK line. Normally, this warning message
 occurs if one of the following is true:

 1. The .QLB extension was left off the Quick library name.

 2. The /Q option was placed at the end of the command line.

 The following LINK command line should not produce this warning with
 Microsoft QuickBASIC Version 4.00, 4.00b, or 4.50, with Microsoft
 BASIC Compiler Version 6.00 or 6.00b, or with Microsoft BASIC PDS
 Version 7.00; however, it will produce this warning using the LINK.EXE
 of QuickBASIC Version 4.50 or BASIC PDS 7.00:

    LINK /Q MYLIB.LIB, QUICKLIB,,BQLB40.LIB;

 The following line produces the warning number 4045 in QuickBASIC
 4.00, 4.00b, and 4.50, in Microsoft BASIC Compiler 6.00 and 6.00b, and
 in BASIC PDS 7.00:

    LINK MYLIB.LIB, QUICKLIB,,BQLB40.LIB /Q;

 The warning message is telling you that because you did not give an
 extension to the library name and because /Q was used at the end of
 the LINK line, the output library will have the default extension of
 .QLB. It does not affect the resulting Quick library in any way. The
 library can be renamed and used without problems.

 LINK.EXE Version 3.69 is shipped with QuickBASIC Version 4.50.
 LINK.EXE Version 5.05 is shipped with BASIC PDS Version 7.00.


 630. $INCLUDE with DATA Statements in SUB May Hang QB.EXE Editor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  2-MAR-1990    ArticleIdent: Q43791

 Using an $INCLUDE file containing DATA statements that are (illegally)
 located inside a SUB or a FUNCTION can cause the QB.EXE editor to
 hang. This problem occurs when you attempt to View Subs, Save, or Run
 the program. The problem also occurs when you use the Merge command
 (from the File menu) to merge a file that contains DATA statements
 into a SUB or FUNCTION block.

 Note that DATA statements are not legal inside SUB ... END SUB or
 FUNCTION ... END FUNCTION blocks.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50. This problem was corrected in
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 (fixlist7.00).

 In the QBX.EXE editor that comes with PDS, this problem is caught by
 the error message "Illegal in SUB, FUNCTION, or DEF FN."

 This problem can be worked around by observing the rule that DATA
 statements cannot be placed (or included) inside SUBs or FUNCTIONs.

 On one occasion, trying to change SUBs in the described case caused
 the message "String Space Corrupt" to be displayed and control was
 transferred to MS-DOS.

 If the program is edited in a different editor and then taken into the
 QB.EXE editor, the INCLUDEd DATA statements are placed on the module
 level. The program then runs correctly. If this version is then saved,
 the DATA statements will be duplicated the next time this program is
 edited.

 Code Example
 ------------

 Entering the following program example while in the QB editor
 illustrates the problem:

    CALL test
    END

    SUB test
    '$INCLUDE: 'DATA.INC'
    END SUB

 This example assumes that you have previously created DATA.INC to
 contain the following:

    DATA 1,2,3


 631. "Device Unavailable"; PS/2 SETUP Doesn't Recognize COM2 Port

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890424-38 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43895

 A "Device unavailable" error may occur when a QuickBASIC program
 attempts to OPEN "COM2:" and the IBM PS/2 system SETUP utility hasn't
 been configured or can't be configured to recognize COM2.

 This problem has been reported with the IBM PS/2 Model 30 computer.
 The SETUP utility doesn't make provisions for a second communications
 port. Therefore, the BIOS data area RS232_BASE does not contain the
 proper information that QuickBASIC is looking for. A good example is
 an internal modem card configured as COM2 that is put in the PS/2 but
 not recognized as an actual communications port. QuickBASIC looks in
 the BIOS data area to see if there is a COM2 port to use and doesn't
 find the proper information. This problem is caused by the PS/2 Model
 30 (and possibly other models) and is not a problem with QuickBASIC.

 The RS232_BASE area can be set with the proper COM2 information using
 a simple QuickBASIC program. This program can be found in this
 Knowledge Base by querying on the following words:

    COM2 and Bad Filename and QuickBASIC

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 Microsoft BASIC PDS Version 7.00.


 632. Example of Graphics PUT on SCREEN 9 Using Bitmap DATA

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890424-56 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43896

 Below is an example of READing an image stored in DATA statements into
 an array, which is then used in a graphics PUT on SCREEN 9 (for EGA
 cards).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00.

 Code Example
 ------------

      SCREEN 9
      sx = 102: sy = 104
      DIM f395%(241)      'full screen 395 bitmap
      FOR v% = 0 TO 241
        READ f395%(v%)    'read 395 font
      NEXT v%
      PUT (sx, sy), f395%, XOR          'put 395 on screen
      INPUT A$
      END

 ' bit map used to put 395 on screen
 DATA 46 , 20
 DATA 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
 DATA -129 ,-1 ,-769 ,-129 ,-1 ,-769 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA -129 ,-1 ,-769 ,-129 ,-1 ,-769 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA  96 , 0 , 3072 , 96 , 0 , 3072 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA  96 , 0 , 3072 , 96 , 0 , 3072 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA  96, 0, 3072,-157 ,-7921 ,-29441 , 124 , 7920 , 31744 , 0, 0, 0
 DATA  96, 0, 3072,-157 ,-3809 ,-29441 , 124 , 3808 , 31744 , 0, 0 , 0
 DATA  96, 0, 3072, 3680 , 31036 , 3264 ,-3713 ,-31037 ,-961, 0, 0 , 0
 DATA  96, 0, 3072, 7264 , 14648 , 3264 ,-7297 ,-14649 ,-961, 0, 0 , 0
 DATA  96, 0, 3072, 15456, 31036, 3327,-15489,-31037,-1024, 0 , 0 , 0
 DATA  96, 0, 3072, 32352,-1761 ,-29441 ,-32385, 1760, 31744, 0, 0, 0
 DATA  96, 0, 3072, 3936,-18417,-13309 ,-3969, 18416, 15612, 0 , 0 , 0
 DATA  96, 0, 3072, 1895, 14336 ,-13311 ,-1928 ,-14337, 15614, 0, 0, 0
 DATA  96, 0, 3072,-28825, 31032,-13085, 28792,-31033, 15388, 0, 0, 0
 DATA  96, 0, 3072,-413 ,-4065 ,-29441 , 380 , 4064 , 31744, 0, 0, 0
 DATA  96, 0, 3072,-927 ,-8177 , 3199 , 894 , 8176 ,-896 , 0 , 0 , 0
 DATA  96, 0, 3072, 96 , 0 , 3072 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA  96, 0, 3072, 96 , 0 , 3072 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA -129 ,-1 ,-769 ,-129 ,-1 ,-769 ,-129 ,-1 ,-769 , 0 , 0 , 0
 DATA -129 ,-1 ,-769 ,-129 ,-1 ,-769 ,-129 ,-1 ,-769 , 0 , 0, 0


 633. Floating-Point Errors in QB.EXE with Coprocessor; Use SET NO87

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890419-109 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43899

 When floating-point errors occur while a program is running in either
 the QuickBASIC environment or as a compiled .EXE file, and the machine
 is equipped with a math coprocessor, the problem may be due to the
 configuration of the math coprocessor.

 Math coprocessor problems can be identified by testing QuickBASIC with
 the coprocessor disabled. To disable the coprocessor, SET the NO87
 environment variable at the MS-DOS command prompt. This action must be
 performed before QuickBASIC is invoked and not with a SHELL from the
 editor. The MS-DOS command is as follows:

    SET NO87=Coprocessor is Disabled for QuickBASIC

 This command disables the coprocessor for QuickBASIC. The string,
 "Coprocessor is Disabled for QuickBASIC," may be any string with one
 or more characters. If no characters follow the SET NO87= command, the
 coprocessor is turned back on.

 If the errors no longer occur after SETting the NO87 variable, then
 the coprocessor should be checked for correct installation and
 configuration.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 Microsoft BASIC PDS Version 7.00.


 634. VIEW SCREEN Parameters Passed through CHAIN Using BRUNxx.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890421-68 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43900

 An "Illegal function call" may be generated by a graphics PUT
 statement under the following conditions:

 1. The first BASIC program performs a VIEW SCREEN statement to set up
    a graphics area.

 2. The first program CHAINs to a second BASIC program.

 3. The second program attempts to perform a graphics PUT statement
    outside the boundaries of that previously defined VIEW SCREEN.

 This error occurs only when the BASIC programs are run from the QB.EXE
 environment or when compiled requiring the run-time module (BRUNxx.EXE
 in QuickBASIC and the BASIC compiler; BRT70xxx.EXE in BASIC PDS
 Version 7.00).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 Using the VIEW SCREEN statement in BASIC allows you to create a
 virtual view port for all graphic images created or PUT on the screen.
 Graphic images are displayed on the screen only if they fall in that
 virtual view port. This feature can be a useful for writing graphic
 routines that are to be used with CHAINed QuickBASIC programs.

 This error can be avoided by using any or all of the following
 methods:

 1. Changing screen modes with the SCREEN statement.

 2. Issuing another VIEW SCREEN statement with parameters large enough
    to handle additional graphic images.

 3. Compiling the programs with the /O (stand-alone) switch.

 Code Example
 ------------

 The following code generates the "Illegal function call" error as soon
 as the image is displayed outside of the previously defined VIEW
 SCREEN port.

 ' PROGRAM:   A.BAS
 SCREEN 8
 VIEW SCREEN (250,75)-(390,125)
 LINE (250,75)-(390,125), ,B
 PRINT "This is the View Screen Box"
 LOCATE 22,1
 PRINT "Press a key to CHAIN to B.BAS"
 SLEEP
 CHAIN "B.BAS"
 END

 ' PROGRAM:   B.BAS
 DIM C#(3000)
 SCREEN 8
 LINE (250,75)-(390,125), , B
 LINE (300,85)-(350,110), 1, BF
 GET (300,85)-(350,110), C#
 FOR i = 1 TO 100
    PUT (225 + i, 50 + i), C#  'This will generate the error as soon as
 NEXT i                               'the box leaves the bottom of the views
 END


 635. Multiple CASE ELSE Allowed in QB.EXE; Causes Compile Errors

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified:  2-MAR-1990    ArticleIdent: Q43901

 The SELECT CASE statement allows multiple occurrences of the same CASE
 condition. Because a SELECT CASE statement operates in sequential
 order, the first instance of any CASE is always taken. If there are
 other CASE conditions listed after the CASE ELSE statement, these may
 cause the compiler errors "SELECT without END SELECT" and "END SELECT
 without SELECT."

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50, and in the QB.EXE that is shipped with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b (buglist6.00
 buglist6.00b). This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).

 Code Example
 ------------

 In the following code example, the QB.EXE environment will not produce
 an error. During compilation, the error "SELECT without END SELECT"
 occurs on the second CASE ELSE and the error "END SELECT without
 SELECT" occurs on the END SELECT.

 In the QBX.EXE environment that is shipped with PDS, the second CASE
 ELSE statement is flagged with the error message "CASE without
 SELECT."

 CLS
 DO
 INPUT "", x
 SELECT CASE x
   CASE IS = 1
     PRINT "ONE"
   CASE IS = 2
     PRINT "TWO"
   CASE IS = 3
     PRINT "THREE"
   CASE IS = 3           'This CASE never chosen
     PRINT "THREE 2"
   CASE ELSE
     PRINT "OTHER"
   CASE ELSE             'This line causes "SELECT without END SELECT"
     PRINT "OTHER 2"
 END SELECT              'This line causes "END SELECT without SELECT"
 LOOP UNTIL x = 0


 636. Incorrect SEEK Statement Example on QB Advisor On-Line Help

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890424-3 docerr
 Last Modified: 15-DEC-1989    ArticleIdent: Q43902

 There are several errors in the example for the SEEK statement in the
 QuickBASIC Advisor on-line Help system for QuickBASIC Version 4.50.
 The lines that should be corrected are marked in the code sample
 below.

 The example given on Page 385 of the "Microsoft QuickBASIC 4.0: BASIC
 Language Reference" operates correctly.

 This documentation error has been corrected in the Microsoft Advisor
 on-line Help system of the QBX.EXE environment supplied with
 Microsoft BASIC PDS Version 7.00. Below is a corrected version of the
 code example.

 Code Example
 ------------

 The following is a corrected version of the SEEK program example taken
 from the QuickBASIC Version 4.50 QuickBASIC Advisor on-line Help
 system:

 '*** Programming example for the SEEK function and statement
 '
 CONST FALSE = 0, TRUE = NOT FALSE
 '  Define record fields.
 TYPE TestRecord
    NameField  AS STRING * 20
    ScoreField AS SINGLE
 END TYPE
 ' Define a variable of the user type.
 DIM RecordVar AS TestRecord
 '********************************************************************
 ' This part of the program is an insert whose only function is to
 ' create a random-access file to be used by the second part of the
 ' program, which demonstrates the CVSMBF function
 '********************************************************************
 OPEN "TESTDAT2.DAT" FOR RANDOM AS #1 LEN = LEN(RecordVar)
 '*************** above line has correction **************
 CLS
 RESTORE
 READ NameField$, ScoreField
 I = 0
 DO WHILE UCASE$(NameField$) <> "END"
    I = I + 1
    RecordVar.NameField = NameField$
    RecordVar.ScoreField = ScoreField
    PUT #1, I, RecordVar
    READ NameField$, ScoreField
    IF NameField$ = "END" THEN EXIT DO
 LOOP
 CLOSE #1
 '
   DATA "John Simmons", 100
   DATA "Allie Simpson", 95
   DATA "Tom Tucker", 72
   DATA "Walt Wagner", 90
   DATA "Mel Zucker", 92
   DATA "END", 0

 '  Open the test data file.
 '
 DIM FileBuffer AS TestRecord
 OPEN "TESTDAT2.DAT" FOR RANDOM AS #1 LEN = LEN(FileBuffer)
 '  Calculate number of records in the file.
 Max = LOF(1) / LEN(FileBuffer)
 '  Read and print contents of each record.
 FOR I = 1 TO Max
    GET #1, I, FileBuffer
    IF RTRIM$(FileBuffer.NameField) = "Tom Tucker" THEN
 '*************** above line has correction **************
       ReWriteFlag = TRUE
       EXIT FOR
    END IF
 NEXT I
 '
 IF ReWriteFlag = TRUE THEN
    ' Back up file by one record
 '*************** above line has correction **************
    FileBuffer.ScoreField = 100
    SEEK #1, SEEK(1) - 1
 '*************** above line has correction **************
    PUT #1, , FileBuffer
 '*************** above line has correction **************
 END IF
 '
 CLOSE #1
 KILL "TESTDAT2.DAT"
 END


 637. Recursive Procedure Variables Not Saved When in COMMON

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890424-119 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q43930

 QuickBASIC procedures can recursively CALL themselves. Any needed
 variables to be used in the recursive procedure should be passed as
 parameters, and all local variables (variables dimensioned only in the
 SUB itself) variables whose values need to be preserved through each
 recursive CALL should be declared as STATIC. STATIC declaration causes
 each variable's values to be retained on the stack for later use.

 One important note is that all variables that are located in a COMMON
 or COMMON SHARED block and are used in a recursive procedure will not
 be saved through each recursive CALL.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 More information concerning recursive procedures can be found on Pages
 79-83 of the "Microsoft QuickBASIC 4.0: Programming in BASIC: Selected
 Topics" manual for Versions 4.00 and 4.00b, and on Pages 69-72 of the
 "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for Version
 4.50.

 Code Example
 ------------

 The following program can be found in either the "Microsoft QuickBASIC
 4.0: BASIC Language Reference" manual on Pages 62-63, or on Pages
 50-51 of the ring-bound "Microsoft QuickBASIC 4.5: BASIC Language
 Reference" manual for Version 4.50:

 DECLARE FUNCTION Reverse$ (StringVar$)
 LINE INPUT "Enter string to reverse: ", X$
 PRINT Reverse$(X$)
 END

 FUNCTION Reverse$ (S$)
   C$ = MID$(S$, 1, 1)
   IF C$ = "" THEN
     Reverse$ = ""
   ELSE
     Reverse$ = Reverse$(MID$(S$, 2)) + C$
   END IF
 END FUNCTION


 638. How Bits in PAINT Tiling String Represent Pixels in BASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890427-81 B_BasicCom
 Last Modified:  7-FEB-1990    ArticleIdent: Q44034

 For the best explanation of tiling with the PAINT statement, please
 refer to one of the following manuals:

 1. Pages 181 to 191 (Section 5.8.2, "Painting with Patterns: Tiling")
    of the "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for
    Version 4.50

 2. Pages 228 to 239 (Section 5.8.2, "Painting with Patterns: Tiling")
    of the "Microsoft QuickBASIC 4.0: Programming in BASIC: Selected
    Topics" manual for Versions 4.00 and 4.00b

 3. Pages 228 to 239 (Section 5.8.2, "Painting with Patterns: Tiling")
    of "Microsoft BASIC Compiler 6.0: Programming in BASIC: Selected
    Topics" for Versions 6.00 and 6.00b for MS OS/2 and MS-DOS

 4. Pages 179 to 189 ("Painting with Patterns: Tiling") of "Microsoft
    BASIC 7.0: Programmer's Guide" for Microsoft BASIC Professional
    Development System (PDS) Version 7.00 for MS OS/2 and MS-DOS

 The tiling information on these pages also applies to QuickBASIC 2.00,
 2.01, and 3.00 (which support only SCREENs 0, 1, 2, 7, 8, 9, 10).

 Please also see a separate article in this Knowledge Base, which can be
 found by querying on the following words:

    PAINT and tiling and QuickBASIC

 Consider the following sentence taken from the PAINT statement in the
 language reference manual:

    In the tile string, each byte masks eight bits along the x-axis
    when putting down points.

 The effect of each bit on screen pixels depends upon how many
 attributes are in that screen mode. On two-attribute screen modes
 (SCREENs 2, 3, 4, 11), each bit in the tile string directly represents
 a pixel, and each byte in the tile string represents 8 pixels along
 the x-axis. In graphics screens with more than two attributes (1, 7,
 8, 9, 10, 12, 13), each pixel is represented by more than 1 bit (in
 order to carry the extra color information). In SCREEN 13, which has 8
 bits per pixel, tiling is not very useful. Tiling is most flexible in
 SCREENs 2, 3, 4, and 11.


 639. WAIT Statement Can Access All 65535 Ports, Not Just 0 to 255

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr
 Last Modified: 15-DEC-1989    ArticleIdent: Q44035

 The documentation for the WAIT statement incorrectly states that the
 input port number given as an argument to a WAIT statement can range
 from 0 to 255 only. WAIT can actually address all 65,536 machine ports
 (0 to 65535).

 This information applies to the WAIT statement in the following
 manuals:

 1. Page 446 of "Microsoft QuickBASIC 4.0: BASIC Language Reference"
    for Versions 4.00 and 4.00b for MS-DOS

 2. Page 446 of "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" for Versions 6.00 and 6.00b for MS-DOS and MS OS/2

 3. Page 507 of "Microsoft QuickBASIC Compiler" manual for Versions
    2.0x and 3.00 for MS-DOS

 This documentation error has been corrected in the "Microsoft BASIC
 7.0: Language Reference" manual and in the Microsoft BASIC PDS 7.00
 QBX.EXE Microsoft Advisor on-line Help system.


 640. How to Continue Long FIELD Statements; 255-Character Limit

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  6-AUG-1990    ArticleIdent: Q44109

 This article describes four different methods to make long FIELD
 statements easier to work with when writing programs that use random
 access files. Microsoft highly recommends the first technique. The
 four methods are the following:

 1. Instead of defining your file's record structure with the FIELD
    statement, use a user-defined TYPE variable (defined with the
    TYPE...END TYPE statement). This record variable can be
    conveniently used as the third argument of the random file PUT and
    GET statements.

 2. You can use consecutive FIELD statements with dummy string
    placeholders to redefine further into the same file buffer, as
    shown in Method 2 below. You can use this method to make long FIELD
    statements readable without having to scroll to the right in the
    QB.EXE editor. You can also put long string arrays in FIELD
    statements by incremental definition in a FOR ... NEXT loop.

 3. You can FIELD the entire buffer as one string and extract pieces of
    the string using the MID$ function. However, MID$ slows down the
    program compared to Methods 1 and 2.

 4. A less desirable alternative is to use an editor other than
    QB.EXE version 4.00, 4.00b, or 4.50 to avoid QuickBASIC's automatic
    concatenation of lines that are continued with the underscore (_)
    character, which your program may have used from QuickBASIC
    versions earlier than 4.00.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The maximum length for any statement in QB.EXE or BC.EXE is 255
 characters, including the text in lines concatenated with the
 underscore character. You can use Method 1, 2, or 3 to break up the
 FIELD statement if it physically exceeds 255 characters. (The RANDOM
 buffer size itself can be defined up to 32,767 bytes.)

 Method 1
 --------

 The easiest method is to do away with the FIELD statement altogether
 and use a TYPE/END TYPE variable as your record buffer:

 TYPE RecType
        xname AS STRING * 30
        xaddress AS STRING * 30
        xcity AS STRING * 40
        xstate AS STRING * 2
        xzip AS STRING * 9
        xmore AS STRING * 17
 END TYPE
 OPEN "File.DAT" FOR RANDOM AS #1 LEN = 128   ' OPEN existing file.
 Max = LOF(1) / 128   ' Max=Number of records in existing file.
 DIM label(Max) AS RecType
 FOR i = 1 TO Max
    GET #1, i, label(i)
    PRINT label(i).xname
 NEXT i

 Method 2
 --------

 You can break up the FIELD statement into more than one FIELD
 statement for the same file number, using a dummy placeholder string
 to account for the data previously fielded in that same file buffer:

    FIELD #1, 30 AS xname$, 30 AS xaddress$, 40 AS xcity$
    FIELD #1, 100 AS dummy1$, 2 AS xstate$, 9 AS xzip$
    FIELD #1, 111 AS dummy2$, 17 as xmore$

 In this example, dummy1$ and dummy2$ are equivalenced (overlapped)
 with the total buffer defined to that point, allowing subsequent
 variables to be defined further into the buffer.

 Here is a trickier example, this time using a temporary placeholder
 string temp$ and FIELDing a string array within a FOR ... NEXT loop:

 OPEN "test.dat" FOR RANDOM AS #1 LEN = 300
 DIM F$(30)   ' This array will delimit the buffer in the FIELD statement.
 i = 1
 FOR j = 1 TO 10
 FIELD #1, (j - 1) * 30 AS temp$, 10 AS F$(i), 10 AS F$(i + 1), 10 AS F$(i + 2
 i = i + 3
 NEXT
 LSET F$(30) = "1234567890"
 LSET F$(15) = "ABCDEFGHIJ"
 PUT #1, 1
 CLOSE
 OPEN "test.dat" FOR RANDOM AS #1 LEN = 300
 i = 1
 FOR j = 1 TO 10
 FIELD #1, (j - 1) * 30 AS temp$, 10 AS F$(i), 10 AS F$(i + 1), 10 AS F$(i + 2
 i = i + 3
 NEXT
 GET #1, 1
 PRINT F$(30), F$(15)

 Method 3
 --------

 You can FIELD the entire buffer as one string and extract pieces of
 the string using the MID$ function:

    OPEN "TEST" AS #1  'Assume data file TEST already has data in it.
    FIELD #1, 512 AS buffer$   'fields entire buffer in one string
    GET#1,2   ' Get record number 2 (written by some other program).
    'Extract the 8-byte double precision number beginning at byte 500:
    component1# = CVD(MID$(buffer$,500,8))
    'Extract a long integer (4 bytes) beginning at byte 508:
    component2& = CVL(MID$(buffer$,508,4))

 You could also write a function to extract the fields:

    ' Below is a function to extract a long integer from buffer$.
    ' FieldOffset% is the byte offset where the data starts.
    ' Note that buffer$ doesn't have to be a fielded string, it
    ' just has to be a minimum of FieldOffset% + 4 bytes long:
    DEF FNL&(FieldOffset%) = CVL( MID$( buffer$, FieldOffset%, 4 ))
    ' Example of using the function:
    component2& = FNL&(508)

 Method 4
 --------

 The QB.EXE environment in QuickBASIC versions 4.00, 4.00b, and 4.50,
 and the QBX.EXE environment in Microsoft BASIC PDS versions 7.00 and
 7.10 strip out the underscore (_) line-continuation character, forcing
 you to scroll long lines horizontally to view and edit.

 If you want to preserve the underscore characters in your source code,
 you must use an editor other than QB.EXE 4.00, 4.00b, 4.50, or QBX.EXE
 7.00 or 7.10. For example, you can edit with the Microsoft Editor or
 Microsoft Word, and then compile the source code using BC.EXE from the
 DOS prompt (or from within the Microsoft Editor, M.EXE).


 641. BASIC Program That Passes a STATIC or DYNAMIC Array to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890425-35 B_BasicCom H_MASM
 Last Modified: 20-DEC-1989    ArticleIdent: Q44135

 Below is a QuickBASIC program that passes a STATIC or DYNAMIC array to
 an assembly routine assembled with the Microsoft Macro Assembler
 (MASM). The assembly routine assigns a 1 to each element in the array.
 In the QuickBASIC program, the array can be initially defined as
 DYNAMIC or STATIC, using REM $DYNAMIC or REM $STATIC.

 This QuickBASIC program can be compiled with QuickBASIC Versions 4.00,
 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 with Microsoft BASIC PDS Version 7.00. The assembly program should be
 assembled with MASM Version 5.10.

 Code Examples
 -------------

 The following is the QuickBASIC program, MAIN.BAS, which calls the
 assembly routine:

 REM Program that calls an assembly routine that fills each
 REM element with a 1. The segment, offset, and number of elements
 REM in the array need to be passed BYVAL.
 REM

 DEFINT A-Z
 DECLARE SUB MasmSub (BYVAL segment, BYVAL offset, BYVAL number)

 'REM $DYNAMIC     'Can be either STATIC (the default) or DYNAMIC
 DIM x%(1 TO 10)   'Remove comment to define array DYNAMICally

 CLS
 PRINT "Calling assembly routine to fill array elements..."
 CALL MasmSub(VARSEG(x%(1)), VARPTR(x%(1)), 10)
 PRINT "Values in array:"
 FOR i = 1 TO 10
     PRINT x%(i);
 NEXT
 END

 The following is the assembly program, MASMSUB.ASM, which assigns 1
 to each array element:

 ;-------------------------------------------------------------------
 ; This assembly program loops through the array elements of an
 ; integer array that is passed to it via QuickBASIC and assigns a 1
 ; to each element. The segment, offset, and number of elements of
 ; the array need to be passed BYVAL from the QuickBASIC main module.
 ;
 ;-------------------------------------------------------------------

           .model medium
           .code
           public MasmSub
 MasmSub   proc                 ;can use proc far here too
 begin:    push bp              ;save registers for BASIC
           mov  bp,sp           ;get the stack pointer

           mov  es,[bp+10]      ;get segment of array
           mov  bx,[bp+8]       ;get offset of array

           mov  cx,[bp+6]       ;get length of array
           mov  al,1            ;fill array elements with 1's

 next:     mov  es:[bx],al      ;put one in the array element
              add  bx,2   ;increment counter to next array element
                                ; -- add two bytes for integers, four bytes
                                ; -- for single precision and long integers,
                                ; -- and 8 bytes for double precision numbers
           loop next               ;loop to assign next array element
           pop  bp              ;restore bp for BASIC
           ret  6               ;restore stack
 MasmSub   endp
           end

 To compile and LINK each program, type the following MS-DOS commands:

    BC MAIN;
    MASM MASMSUB;
    LINK MAIN+MASMSUB;

 To run the resulting executable, type the following (at the MS-DOS
 prompt):

    MAIN


 642. CALLing C to Return Single-Precision Gives Incorrect Results

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom S_QuickC S_C
 Last Modified:  8-NOV-1990    ArticleIdent: Q44137

 From within a BASIC program, invoking a Microsoft C or QuickC function
 that attempts to return a single-precision number may give
 unpredictable results. Returning any other numeric type from a C
 function gives correct results.

 To work around the problem, you can pass the single-precision number
 as a parameter (whose value is set inside the C function and passed
 back).

 This information applies to Microsoft C Compiler versions 5.00, 5.10,
 and 6.00, and to Microsoft QuickC versions 1.00, 1.01, 2.00, 2.01,
 2.50, and 2.51.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS, in Microsoft BASIC Compiler versions
 6.00 and 6.00b (buglist6.00, buglist6.00b) for MS-DOS and OS/2, and in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 Note that only certain versions of BASIC link with certain versions of
 C, as explained in a separate article found by searching in this
 Knowledge Base for the following words:

    BASIC and C and QuickC and link and compatible and pass and calling

 Code Example
 ------------

 'BASIC code to show incorrect return of a single
 DECLARE FUNCTION doublefun# CDECL ALIAS "_doublefun"
 DECLARE FUNCTION singlefun! CDECL ALIAS "_singlefun"
 DECLARE SUB floatchange CDECL (BYVAL offset%)

 x# = doublefun#                   'Works correctly
 y! = singlefun!                   'Returns wrong value
 z! = 0
 CALL floatchange (VARPTR(z!))     'Workaround - pass as parameter
 PRINT x#
 PRINT y!
 PRINT z!
 END

 /* C code, compile with /AM (medium memory model)*/
 double doublefun()        /* returns a double */
 {
   double x;
   x = 1.45;
   printf("%f\n",x);
   return x;
 }

 float singlefun()         /* returns a single */
 {
   float x;
   x = 1.45;
   printf("%f\n",x);
   return x;
 }

 void floatchange (x)     /* Takes a single as a parameter */
 float *x;
 {
   *x = 1.45;
   printf("%f\n",x);
 }

 Program Output
 --------------

   1.450000
   1.450000              <--These are the C PRINTF statements.
   1.450000

   1.45
   2                     <--These are the BASIC PRINT statements.
   1.45


 643. PRINT Statements in Manual Okay without Semicolons

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890426-59 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q44229

 In many of the program examples in the "Microsoft QuickBASIC 4.0:
 BASIC Language Reference," the PRINT statements appear to be missing
 semicolons (;) before and after each double quotation mark. For
 example:

   PRINT X "squared is" X^2 "!"

 When you type the above statement in the QB.EXE environment (or
 QBX.EXE environment of Microsoft BASIC PDS Version 7.00), semicolons
 are automatically inserted, as follows:

   PRINT X; "squared is"; X^2; "!"

 The syntax of these two examples is equivalent. This information
 applies to QuickBASIC Versions 4.00, 4.00b, and 4.50, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft BASIC PDS
 Version 7.00.

 This is not a documentation error, but rather demonstrates some of the
 syntax versatility of Microsoft BASIC languages.


 644. Only One Video Page with Hercules SCREEN 0; HELP Correction

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890502-115 docerr B_BasicCom
 Last Modified: 17-OCT-1990    ArticleIdent: Q44236

 Only one page (page 0) is supported in SCREEN mode 0 on a Hercules
 adapter. To obtain two pages, Hercules graphics mode (SCREEN 3) should
 be used.

 The indicated documentation sources below incorrectly show two pages
 (pages 0 and 1) available in SCREEN mode 0 (TEXT mode) on a Hercules
 adapter. This is incorrect.

 The information covering "Hercules Adapter Screen Modes" in the
 following sources incorrectly states you can have 2 pages under SCREEN
 mode 0 when using a Hercules video adapter:

 1. The documentation error occurs in QB.EXE 4.50 QB Advisor online
    Help system under the HELP menu, SCREEN statement, Details section,
    Adapters and Displays ("HELP: SCREEN Statement Details - Adapters")

    This documentation error has been corrected in the Microsoft
    Advisor on-line Help system of the QBX.EXE environment supplied
    with Microsoft BASIC PDS versions 7.00 and 7.10 for MS-DOS.

 2. This documentation error occurs on Page 327 of the "Microsoft
    QuickBASIC 4.5: BASIC Language Reference" manual.

    This documentation error has been corrected in the "Microsoft BASIC
    7.0: Language Reference" manual for BASIC PDS version 7.00 and 7.10.

 3. This documentation error occurs in the QBX.EXE 7.00 and 7.10
    Microsoft Advisor online Help system under the HELP menu, PCOPY
    statement, Details section ("HELP: PCOPY Statement Details").

    This documentation error does not occur for PCOPY HELP in QB.EXE
    4.50.


 645. Hercules Page Support for SCREEN 0 and SCREEN 3

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890428-106 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q44237

 The following information summarizes the use of screen pages in
 Microsoft QuickBASIC for MS-DOS with a Hercules monochrome graphics
 adapter.

 SCREEN mode 3 supports two screen pages, page 0 and page 1. However,
 SCREEN 3 has only one screen page if there is another graphics adapter
 installed.

 SCREEN mode 0 with a Hercules adapter has only one screen page, even
 though other adapters support up to eight pages in text mode. This is
 not a problem with QuickBASIC or a limitation of the adapter.
 QuickBASIC was designed to conform to the behavior of other IBM
 monochrome adapters.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and 4.50
 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 All IBM monochrome adapters assume that there is enough memory to
 support only one screen page in text mode, SCREEN 0. QuickBASIC, being
 a well-behaved application, makes this assumption so that its
 applications can run correctly on both IBM and Hercules monochrome
 systems in text mode without any detectable difference to you.

 The ROM BIOS function, Interrupt 10 hex with function 5 hex, "Set
 Display Page," cannot be used to work around this problem. This BIOS
 function correctly changes to another display page, but QuickBASIC
 does not utilize the BIOS and continues to write text directly to
 video memory to the first display page. Therefore, calling this BIOS
 function results only in a blank screen, which may appear to hang the
 machine. Setting the page back to page 0 restores the screen.


 646. Commodore Colt Limited to 112 Files in a Directory

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q44239

 It has been reported that on the Commodore Colt IBM-compatible
 computer, a disk can have a maximum of 112 files in any directory. On
 most machines, 255 files are normally allowed in the root directory,
 and the number allowed in a subdirectory is only limited by available
 disk space.

 This limitation can result in error 67, "Too many files."

 This information applies to QuickBASIC Versions 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 This is a problem in the ROM BIOS of the Commodore Colt computer and
 not a problem with QuickBASIC. Contact Commodore Business Machines
 Customer Support at (215) 436-4200 for information regarding the
 availability of a correction.


 647. Problem Editing QuickBASIC 4.50 Module Without COMMON

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890501-102 buglist4.50 B_BasicCom
 Last Modified: 28-FEB-1990    ArticleIdent: Q44240

 The procedure below reproduces a problem editing a file that is a
 secondary module that does not include the same named COMMON block as
 the main module. After you follow the steps below, QB.EXE hangs
 when trying to execute the program.

 Microsoft has confirmed this to be a problem in the Microsoft
 QuickBASIC Compiler Version 4.50. This problem was corrected in the
 QBX.EXE environment of Microsoft BASIC Professional Development System
 (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 The problem occurs whether the programs are saved in the "Fast Load
 and SAVE" or "Text" format.

 Refer to the following modules in the procedure below:

 MODULE A
 --------

    COMMON /c/ d()
    DIM d(1)

 MODULE B
 --------

    (contains nothing)

 The steps that reproduce the problem are as follows:

  1. Get into QuickBASIC and create MODULE A (which contains the code
     above).

 2. Press ALT+F C to create MODULE B (which has no code in it).

  3. Press ALT+F V (save all) and ALT+F X to exit QB.EXE.

  4. Start QuickBASIC again, loading MODULE A with the command "QB A"
     (this also loads B.BAS).

  5. Press F5 to start the program.

  6. Go to MODULE B with F2 and select B.BAS.

  7. Type anything into MODULE B and backspace over it so that nothing
     is in the module, as before.

  8. Save all the modules with ALT+F V. (Actually, any sort of save here
     reproduces the problem.)

  9. Press F5 to continue.

 10. Press F5 and the program hangs. [Any combination of F5, SHIFT+F5,
     and ALT+R R (restart) in Steps 7 and 8 reproduces this problem.]


 648. TIME$ Problem in IF Statement at Midnight (24:00:00)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q44305

 The following program demonstrates a possible programming mistake with
 the TIME$ function in the Microsoft QuickBASIC environment. If you
 test the TIME$ function twice in one IF statement, the returned time
 may change between invocations and give you a conditional result that
 you did not expect. In the example below, the symptoms occur only
 intermittently during the tenth of a second at midnight (24:00:00). To
 correct this programming mistake, you should assign the value returned
 by TIME$ to a temporary string variable, which can then be reliably
 tested multiple times in the IF statement.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS. (Programs compiled
 with BC.EXE may not be as sensitive to this timing issue as the QB.EXE
 or QBX.EXE environment.)

 When run inside the QuickBASIC environment (QB.EXE), the two TIME$
 functions in the following program may return different values
 (depending upon timing) and sometimes make the IF statement STOP the
 program. You might think that the IF statement should never be
 executed, and the programmed loop should continue until you press
 CTRL+BREAK. But after the program runs long enough, it will eventually
 show the behavior in QB.EXE or QBX.EXE. This behavior may not occur in
 the executable version (.EXE) of the program.

 To correct this programming error, assign a string variable to the
 TIME$ function and execute the IF statement using this variable
 instead of TIME$, as noted in the commented portions of the program
 below.

 The following code demonstrates this behavior. At 24:00:00, this
 program will (sometimes) unexpectedly execute the IF statement. The
 faster the machine, the more likely the behavior will show up. The
 behavior occurs only during the tenth of a second at midnight, since
 at that time, the TIME$ function may return 24:00:00 and then 00:00:00
 at the next invocation. You may have to run the program a number of
 times to demonstrate the behavior, since it does not occur every time.

 CLS
 MISSED:
        TIME$ = "23:59:00"
 START:
        '*** The IF statement below sometimes executes, even though
        '*** you may have thought it was not logically possible:
        IF TIME$ >= "10:00:00" AND TIME$ < "16:59:58" THEN STOP
        'To correct this behavior, replace the line above with the
        'following two lines:
        '  TimeVar$ = TIME$
        '  IF TimeVar$ >= "10:00:00" AND TimeVar$ < "16:59:58" THEN STOP
        LOCATE 3, 1
        PRINT TIME$
        '*** If program didn't stop, reset time and try again:
        IF MID$(TIME$, 5, 1) = "1" THEN GOTO MISSED
        GOTO START

 If you implement the correction shown above, the program will not stop
 in QB.EXE or QBX.EXE until you press CTRL+BREAK.


 649. Method for Clearing GOSUB...RETURN Subroutine Stack in BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_GWBasicI B_BasicCom B_BasicInt B_BBasic B_MQuickB
 Last Modified: 15-DEC-1989    ArticleIdent: Q44306

 When a program jumps out of a GOSUB subroutine without executing a
 RETURN statement, the return address is left on the stack. If the
 program jumps out multiple times, an "Out of Stack Space" or "Out of
 Memory" error eventually occurs. You must make your program execute an
 equal number of GOSUB and RETURN statements to avoid this error.

 The program below demonstrates a method for clearing the subroutine
 stack when a program executes more GOSUB statements than RETURN
 statements. Generally, a program should get out of a GOSUB subroutine
 with a RETURN statement, but when that is not feasible, the method
 below may be used.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; Microsoft GW-BASIC
 Interpreter Versions 3.20, 3.22, and 3.23 for MS-DOS; Microsoft BASIC
 Interpreter Version 5.28 for MS-DOS; Microsoft BASIC Compiler Versions
 5.35 and 5.36 for MS-DOS; Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 The following program, STACK.BAS, invokes RETURN in a continuous loop
 to clear the stack until a "RETURN Without GOSUB" error occurs. This
 error is trapped, and the program resumes execution. The program
 STACK.BAS is as follows:

 10 A = A + 1
    IF A < 10 THEN GOSUB 10      ' Put 10 GOSUB addresses on the stack.
    ON ERROR GOTO 30
 20 RETURN 20                    ' Pop addresses off stack until
 30 ON ERROR GOTO 0              ' "RETURN without GOSUB" error.
    END

 Note: This method will not work with the SUB...END SUB subprogram
 procedure. A SUB...END SUB procedure should always be exited with
 either an EXIT SUB or an END SUB statement.


 650. Orchid Pro-Designer VGA Card Needs NMI Jumper Off for QB 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 16-MAY-1989    ArticleIdent: Q44307

 It has been reported that an Orchid Pro-Designer VGA card can hang
 QuickBASIC Version 4.50 when it starts up. Reportedly, you can correct
 the hanging by removing the NMI (nonmaskable interrupt) jumper on the
 card.

 Microsoft has not tested or confirmed this information.


 651. DATA Column in BC /A Assembly .LST Listing Is DGROUP Data

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q44309

 The BC.EXE compiler supports the /A option, which outputs a listing
 (.LST) that shows the assembly-language code that the compiler
 generates for each line of the source file.

 The "Data" column in this assembly-language code listing is a
 hexadecimal value showing how many bytes have been statically
 allocated in the default data segment (DGROUP).

 This information applies to Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 As a demonstration, compile the following program using the BC /A
 option:

    x% = 5              'Allocates 2 bytes
    y! = 100            'Allocates 4 bytes
    z# = 200            'Allocates 8 bytes

 The following listing (.LST) file is generated:

 Offset  Data    Source Line

  0030   0006    x% = 5              'Allocates 2 bytes
  0030   0006
  0030   0006    y! = 100            'Allocates 4 bytes
  0030   0006
  0030   0006    z# = 200            'Allocates 8 bytes
  0030   0006
  0030   0006
  0030    **            I00002: mov   X%,0005h
  0036    **                    int   35h
  0038    **                    db    06h
  0039    **                    dw    <0000C842>
  003B    **                    int   35h
  003D    **                    db    1Eh
  003E    **                    dw    Y!
  0040    **                    int   3Dh
  0042    **                    int   39h
  0044    **                    db    06h
  0045    **                    dw    <0000000000006940>
  0047    **                    int   39h
  0049    **                    db    1Eh
  004A    **                    dw    Z#
  004C    **                    int   3Dh
  004E    **                    call  B$CENP
  0053   0014

 The last entry in the "Data" column shows that a total of 20 bytes (6
 + 2 + 4 + 8 = 20) have been allocated in near data. Note the value is
 shown as a hexadecimal number (0014 hex = 20 decimal).


 652. Importing Pictures from Other Programs into BASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 20-DEC-1989    ArticleIdent: Q44311

 Screen images displayed in some painting and picture-viewing programs
 can be imported to QuickBASIC. To do this, you must be able to exit
 program that displays the picture, and leave the viewed picture on the
 screen. Most programs that can terminate while leaving the screen
 intact can be used, as described below.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50; Microsoft GW-BASIC Interpreter Versions
 3.20, 3.22, and 3.23; Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and MS OS/2; and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2.

 1. The BASIC program must first activate the screen mode that the
    picture will be displayed in. This is done with a SCREEN statement.

 2. The BASIC program should then SHELL out to the picture viewing
    program, which should display the picture and then exit, leaving
    the picture displayed (check the picture program's manual for the
    proper procedure to do this).

 3. When the picture-viewing program has terminated, control is passed
    back to BASIC. The BASIC program can then use the BSAVE statement
    to save the screen image to disk.

 Note: There are several graphics programs available on CompuServe and
 GE GEnie (General Electric Network for Information Exchange) that are
 suitable for this use.


 653. DRAW Statement Doesn't Affect WINDOW's Physical Coordinates

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890503-247 B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q44352

 The DRAW statement does not change the screen's logical coordinates,
 which are set using the WINDOW statement. The DRAW statement uses only
 physical coordinates, whereas normal graphics statements (PSET, LINE,
 CIRCLE) are specified with view coordinates.

 While the view coordinates are not changed by the DRAW statement, the
 physical coordinates [returned in POINT(0) and POINT(1)] are changed
 by the normal graphics statements.

 This information applies to QuickBASIC Versions 3.00, 4.00, 4.00b, and
 4.50, to Microsoft BASIC Compiler 6.00 and 6.00b, and to Microsoft
 BASIC PDS Version 7.00.

 In the following code sample, the first CIRCLE specified with view
 coordinates sets the physical coordinates [returned by POINT(0) and
 POINT(1)] to the equivalent point (at the center of the CIRCLE). The
 ensuing DRAW statement draws a line from the center point to the point
 specified in the DRAW. This DRAW statement changes the physical
 coordinates [shown by the values of POINT(0) and POINT(1)] but leaves
 the view coordinates unchanged [POINT(2) and POINT(3)]. The second
 CIRCLE statement will be centered on the view coordinates of the
 center point of the first CIRCLE, rather than the physical coordinates
 of the other end of the line created with the DRAW.

 Code Example
 ------------

 SCREEN 9
 WINDOW (0, 0)-(60, 60)
 CIRCLE (10, 10), 4   ' Set the 1st point Physical and view correspond

 PRINT "First CIRCLE Coordinates:"
 PRINT "Physical coordinates = ("; POINT(0); ","; POINT(1); ")"
 PRINT "View     coordinates = ("; POINT(2); ","; POINT(3); ")"
 PRINT

 DRAW "M20,20"         ' DRAW line -- Physical changed; view unchanged

 PRINT "DRAW Coordinates:"
 PRINT "Physical coordinates = ("; POINT(0); ","; POINT(1); ")"
 PRINT "View     coordinates = ("; POINT(2); ","; POINT(3); ")"
 PRINT

 CIRCLE STEP(0, 0), 8  ' Centers around 1st CIRCLE not far end of DRAW

 PRINT "Second CIRCLE Coordinates:"
 PRINT "Physical coordinates = ("; POINT(0); ","; POINT(1); ")"
 PRINT "View     coordinates = ("; POINT(2); ","; POINT(3); ")"
 PRINT

 END


 654. SMALLERR.OBJ Makes Smaller .EXE in QuickBASIC 4.50 and BC 6.00

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q44358

 SMALLERR.OBJ is an object module shipped with Microsoft QuickBASIC
 Version 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and OS/2, and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2. LINKing with SMALLERR.OBJ causes your executable
 program to report a limited subset of error messages, but reduces the
 size of your executable file by about 2K.

 SMALLERR.OBJ can be linked only with BASIC programs compiled as
 stand-alone programs. Standalone programs are created with BC /O,
 using BCOMxx.LIB in QuickBASIC and BASIC compiler 6.00 or 6.00b. In
 BASIC PDS 7.00 you link in BCL70xxx.LIB. With all of the above, you
 must LINK with the /NOE switch, as SMALLERR redefines the error report
 routines in the BCOMxx or BCL70xxx library.

 Linking with SMALLERR.OBJ maps all run-time error messages to one of
 the following:

    "Error occurred"
    "Internal error"
    "Unprintable error"

 Microsoft QuickBASIC Versions 4.00 and 4.00b were not shipped with a
 SMALLERR.OBJ file. QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01,
 and 3.00 were shipped with a SMALLERR.OBJ.


 655. Keyboard Scan Code Table Is Missing Line 3 in QB 4.50 Manual

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890509-141 docerr
 Last Modified: 15-MAY-1989    ArticleIdent: Q44407

 The third line is missing from Table R.4, "Keyboard Scan Codes",
 under the KEY(n) statement on Page 198 of the "Microsoft QuickBASIC:
 BASIC Language Reference" manual for Version 4.50. (This manual is
 sold separately for Version 4.50.)

 The first 4 lines of the table should read as follows:

 Key    Code in Hex        Key    Code in Hex        Key    Code in Hex

 ESC         01            CTRL        1D            SPACE       39

 ! or 1      02            A           1E            CAPS        3A

 @ or 2      03            S           1F            F1          3B

 # or 3      04            D           20            F2          3C


 656. Passing Dynamic Array of User-Defined TYPE from QB to MASM 5.x

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890510-57 B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q44409

 This article contains a code example of passing a dynamic array of
 user-defined TYPEs to an assembly routine that copies the array to
 another array that is passed back to BASIC.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2. The assembly routine requires Microsoft Macro Assembler
 Version 5.00 or later.

 The arrays being passed can be larger than 64K when the BASIC program
 is compiled with the BC /AH option (or if the QB.EXE or QBX.EXE editor
 is started with the /AH option).

 Code Example
 ------------

 'Please note that it is necessary to pass the segment and
 'the offset of a dynamic array being passed to assembly using
 'VARSEG and VARPTR respectively.

 'The following BASIC program passes two arrays to a routine called MASM.
 'The MASM routine copies the first array to the second array,
 'passing it back to BASIC through a parameter.

 REM $DYNAMIC

 TYPE testType
   StrElem AS STRING * 11
   NumElem AS INTEGER        ' Size of integer is 2
 END TYPE

 ' The underscore character for BASIC PDS 7.00 must be taken out to
 ' use with BC.EXE. QBX.EXE will remove the underscores at load time
 ' and concatenate the line.

 DECLARE SUB Masm (
        BYVAL TypeLength AS INTEGER,_
        BYVAL Length AS INTEGER,_
        BYVAL SegAddr1 AS INTEGER,_
        BYVAL Addr1 AS INTEGER,_
        BYVAL SegAddr2 AS INTEGER,_
        BYVAL Addr2 AS INTEGER)
 Size% = 20%     'Size of the array (# of elements)
 TypeSize% = 13%  'Size of TYPEs stored in array
 CLS
 DIM inArray(1 TO Size%) AS testType
 DIM outArray(1 TO Size%) AS testType

 'Load inArray with a 11 character string " *inArray* " and index:
 FOR i = 1 TO Size%
   inArray(i).StrElem = " *inArray* "
   inArray(i).NumElem = i
 NEXT i

 ' The underscore character for BASIC PDS 7.00 must be taken out to
 ' use with BC.EXE. QBX.EXE will remove the underscores at load time
 ' and concatenate the line.

 ' Masm will copy the contents of inArray to outArray:
 CALL Masm(TypeSize%,_
           Size%,_
           VARSEG(inArray(1)),_
           VARPTR(inArray(1)),_
           VARSEG(outArray(1)),_
           VARPTR(outArray(1)))

 ' Print the inArray:
 PRINT
 PRINT
 PRINT "inArray: "
 FOR i = 1 TO Size%
   PRINT inArray(i).StrElem; inArray(i).NumElem
 NEXT i

 ' Print the outArray to see that the contents of inArray
 ' were copied to it:

 PRINT
 PRINT "outArray: "
 FOR i = 1 TO Size%
   PRINT outArray(i).StrElem; outArray(i).NumElem
 NEXT i
 END

 The Assembly Routine That Copies the Array
 ------------------------------------------

 ;***********************************************************
 ; The routine 'Masm' copies a dynamic TYPE array of any
 ;   length to another TYPE array.
 ; Warning:
 ;   -- Arrays must be adequately and equally dimensioned.
 ; Masm takes six parameters from the BASIC routine:
 ;   1 - Size of TYPEs in array to be copied (BX)
 ;   2 - # of elements in Array
 ;   3 - Segment of source array
 ;   4 - Offset of first element of source array
 ;   5 - Segment of destination array
 ;   6 - Offset of first element of destination array
 ;***********************************************************

 .MODEL MEDIUM
 .CODE
 PUBLIC Masm

 Masm    PROC
      push   bp
      mov    bp, sp

      mov    bx, [bp+16]   ; Size of TYPEs in array -> bx
      mov    ax, [bp+14]   ; Elements in array -> ax
      mul    bx     ; multiply ax by bx and put answer in ax
      mov    cx,ax  ; Number of bytes in array -> cx

      mov    es, [bp+12]   ; Segment of first array (inArray)
      mov    bx, [bp+10]   ; Offset of first element in first
                           ; array
 ; body
      mov    si,0 ; initialize first array index (inArray)
 again:
      mov    al,es:[bx] ; Load byte to copy to second array
                        ;  in al
      push   bx         ; save bx
      push   es         ; save es
      mov    es, [bp+8] ; Segment of second array (outArray)
      mov    bx, [bp+6] ; Offset of second arrays first
                        ; element
      add    bx,si ; Get correct offset into 2nd array from
                   ; index
      mov    es:[bx],al ; Move the byte into the second array
      pop    es ; restore es
      pop    bx ; restore bx
      add    bx,1 ; point to next element in first array
                  ; (inArray)
      add    si,1 ; increment second array (outArray) index
      loop    again ; Loop until cx is 0

      pop    bp
      ret
 Masm ENDP
      END


 657. QB.EXE "Not Watchable" Error in SUB for SHARED Watch Variable

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890508-149
 Last Modified: 20-DEC-1989    ArticleIdent: Q44410

 Watch variables (which are set in QuickBASIC's Debug menu) have a
 local scope. That is, you must reset a Watch on that variable in each
 SUBprogram or FUNCTION procedure, even if the variable is in a SHARED
 or COMMON SHARED statement.

 If you Add a Watch at the main module level for a SHARED or COMMON
 SHARED variable, when you Step into a SUB or FUNCTION, the message
 "<Not watchable>" appears in the Debug window.

 This information applies to the QB.EXE environment in QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and to the QBX.EXE environment of
 Microsoft BASIC PDS Version 7.00.


 658. Color and Monochrome Attributes in SCREEN 0 (Text) Explained

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890508-33 B_BasicCom docerr
 Last Modified: 20-DEC-1989    ArticleIdent: Q44412

 This information below refers to the SCREEN 0 description in the
 following sources: the QB Advisor on-line Help system of QuickBASIC
 Version 4.50; Page 373 of "Microsoft QuickBASIC 4.0: BASIC Language
 Reference" for Versions 4.00 and 4.00b; Page 373 of "Microsoft BASIC
 Compiler 6.0: BASIC Language Reference" for MS OS/2 and MS-DOS
 Versions 6.00 and 6.00b; and Page 310 of the "Microsoft BASIC Version
 7.0: Language Reference" for Microsoft BASIC PDS Version 7.00.

 The documentation for SCREEN 0 states that you may assign "16 colors
 to any of 16 attributes (with EGA)." However, this is misleading
 because colors 0 through 15 are available on all color cards (CGA,
 EGA, and VGA), and the word "attribute" is used inaccurately.

 A more accurate statement is that for each character in SCREEN 0, you
 can assign 16 colors for the foreground and any of 8 colors for the
 background on a color adapter. In addition, you can make the character
 blink (flash on and off).

 On a monochrome adapter, only certain combinations of display
 attributes are supported, as described further below.

 Attribute Byte for Color Adapters
 ---------------------------------

 The reason for having only 8 colors (0 through 7) available for the
 background of each character is because of the arrangement of video
 memory. In text mode, each character position on the display screen is
 controlled by two contiguous bytes in video memory. The first byte
 contains the ASCII code for the character, and the second byte is that
 character's attribute byte, which controls colors, brightness, and
 blinking.

 In the foreground, there are 8 base colors, plus a 4th bit for
 intensity, which gives 16 colors (2^4 = 16). The background has only
 the 8 base colors. Another bit turns on blinking, which flashes
 foreground and background together for a given character.

 The following are the 8 bits of the attribute byte allocated per
 character in text mode (SCREEN 0) for color display adapters:

  ---------------------------------------------------------------
 |       |       |       |       |       |       |       |       |
 | Blink |  Red  | Green | Blue  |Intense|  Red  | Green | Blue  |
 |       |       |       |       |       |       |       |       |
 |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  ---------------------------------------------------------------
           \______     ______/       \_________     _________/
                  \   /                        \   /
                Background                  Foreground

 Attribute Byte for Monochrome Adapters
 --------------------------------------

 The following are the 8 bits of the attribute byte allocated per
 character in text mode (SCREEN 0) for monochrome display adapters:

  ---------------------------------------------------------------
 |       |       |       |       |       |       |       |       |
 |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
 |       |       |       |       |       |       |       |       |
  ---------------------------------------------------------------
    \_/    \______     ______/      \_/     \______     ______/
     |            \   /              |             \   /
  Blinking      Background      Intensified      Foreground

 Only the following combinations of attribute bits are recognized by a
 monochrome adapter card. The appearance of some display attributes
 depends on the setting of the enable-blink bit at I/O port 3B8 hex.
 The attribute-bit combinations are as follows:

 Value of Attribute Byte
   (Binary)      (Hex)    Description of Display Attributes
 -----------------------  ---------------------------------
   00000000       00      Not displayed
   00000001       01      Underlined
   00000111       07      Normal (white on black)
   00001001       09      High intensity, underlined
   00001111       0F      High intensity
   01110000       70      White background, black foreground
                              (i.e., reverse video)
   10000111    *  87      If blinking enabled: blinking white on black
                          If blinking disabled: dim background, normal
                              foreground
   10001111    *  8F      If blinking enabled: blinking high intensity
                          If blinking disabled: dim background, high-
                              intensity foreground
   11110000       F0      If blinking enabled: blinking reverse video
                          If blinking disabled: high-intensity
                              background, black foreground

 * Combinations marked with asterisk (*) are not displayed on all
   monochrome monitors.

 For more information about video memory, please see the following
 book, which is sold at bookstores or can be ordered by calling
 Microsoft Press at (800) 638-3030 or (206) 882-8080:

    "Programmer's Guide to PC and PS/2 Video Systems," by Richard
    Wilton (published by Microsoft Press, 1987)


 659. .EXE with PRINT TAB or SPC Can Hang If Compiled with BC /S

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890208-138 buglist4.50
 Last Modified: 16-MAY-1989    ArticleIdent: Q44241

 An .EXE program compiled in Microsoft QuickBASIC Version 4.50 can
 hang when all of the following three conditions are met:

 1. The program was compiled with the BC /s option.

 2. The program was printed with the PRINT or PRINT# statement.

 3. Any combination of TAB or SPC functions was used in the PRINT or
    PRINT# statement.

 The following are workarounds for the problem:

 1. Break your program into smaller modules so that the /s switch is
    not needed.

 2. When compiling, include the /X switch, which is normally used to
    indicate the presence of ON ERROR with RESUME, RESUME NEXT, or
    RESUME 0.

 This problem occurs only with Microsoft QuickBASIC Version 4.50, not
 with QuickBASIC Version 4.00 or 4.00b or with the Microsoft BASIC
 Compiler Version 6.00 or 6.00b. We are researching this problem and
 will post new information as it becomes available.

 The following program example demonstrates the problem that occurs
 when a program is compiled with the BC /s option:

    c$ = "hello"
    d$ = "bye"
    print tab(8); c$; tab(16); d$


 660. QB.EXE /NOHI Option Uses Color Instead of High-Intensity White

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890504-63 B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q44489

 When invoking the QB.EXE environment of QuickBASIC Version 4.50 or the
 QBX.EXE environment of Microsoft BASIC PDS Version 7.00, the /NOHI
 switch is used for monitors that display high intensity poorly or not
 at all. If the /NOHI switch is used with a CGA, EGA, or VGA color
 monitor, certain menu items are displayed in color. If the /NOHI
 switch is not used with these monitors, the menus are displayed with
 white, high-intensity white, black, and gray. Whether or not the /NOHI
 switch is used when invoking the QB.EXE environment of QuickBASIC,
 these colors cannot be changed from the Options menu. In the QBX.EXE
 environment of BASIC PDS 7.00, the pull-down menu colors can be
 changed using the Options menu.

 With the /NOHI option, menu items in the pull-down menus are displayed
 in the following default colors:

    Color                 Menu Item
    -----                 ---------

    Red                   Highlighted letter of menu items

    Green or purple       Highlighted letter of selected menu items
    (depending on where
    the cursor is)

    Orange                Special menu items such as the items in the
                          Edit pull-down menu

    Gray                  Background of pull-down menus

    Black                 Background of selected menu item


 661. Current Statement Color Defaults to Green on Blue with /NOHI

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890504-69
 Last Modified: 20-DEC-1989    ArticleIdent: Q44490

 When you invoke the QB.EXE environment of QuickBASIC Version 4.50 or
 the QBX.EXE environment of Microsoft BASIC PDS Version 7.00 with the
 /NOHI switch on a color monitor, the color of the Current Statement
 always starts out as Green on Blue, regardless of color changes in the
 previous QB or QBX session. This is a design limitation for the /NOHI
 option.

 You can change the color of the Current Statement by choosing Display
 from the Options pull-down menu.

 To reproduce this behavior, do the following:

 1. Bring up the environment (QB.EXE or QBX.EXE).

 2. Choose Display from the Options menu.

 3. Change the color of the Current Statement.

 4. Exit the environment (by pressing ALT+F+X).

 5. Restart the environment with the /NOHI option.

 /NOHI makes the color for the Current Statement always start out as
 Green on Blue (the default), regardless of the colors chosen in the
 previous QB or QBX session. This behavior occurs only with the Current
 Statement color setting. Changes to the Normal Text and Breakpoint
 Line colors are retained between sessions. The QB.INI or QBX.INI file
 remembers the color options.

 The /NOHI switch is only available in the QB.EXE environment of
 QuickBASIC 4.50 and the QBX.EXE environment of Microsoft BASIC PDS
 7.00.


 662. Tandy 4000 "Invalid Configuration" after "Disk Not Ready"

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890504-158
 Last Modified: 17-MAY-1989    ArticleIdent: Q44491

 It has been reported that a critical error on a floppy disk drive,
 such as error 71 "Disk not ready," can change the system configuration
 on a Tandy 4000 that is running QuickBASIC Version 4.50.

 After a critical error occurs, the drive is unreadable by the program
 or the operating system. This error causes the message "Invalid
 configuration, press F1 to reconfigure," to appear the next time the
 system is rebooted.

 The customer reported (after checking with a Tandy source) that the
 problem is caused by pin 34 (ready disk connect) on the drive
 controller. Apparently, the Tandy system normally ignores this pin,
 but when QuickBASIC gets the critical error, the status is changed. To
 correct the problem, open the circuit for pin 34.

 Microsoft has not confirmed this information.


 663. Mandelbrot Example Needs to Change "LogicY" to a SINGLE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr
 Last Modified: 20-DEC-1989    ArticleIdent: Q44492

 The MANDEL.BAS program example on Pages 213-217 of the "Microsoft
 QuickBASIC 4.5: Programming in BASIC" manual for Version 4.50, on
 Pages 263-267 of the "Microsoft QuickBASIC 4.0: Programming in BASIC:
 Selected Topics" manual for Versions 4.00 and 4.00b, and on Pages
 211-215 of the "Microsoft BASIC 7.0: Programmer's Guide" for Microsoft
 BASIC PDS Version 7.00 does not work correctly for all WINDOW
 coordinates, unless the variable "LogicY" is changed to a SINGLE or
 DOUBLE precision variable.

 To correct the problem, change all occurrences of LogicY to LogicY! or
 add the following line to the beginning of the program:

    DIM LogicY AS SINGLE

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 For more information, query on the following words in this
 Knowledge Base:

    PMAP and MAP and WINDOW and INTEGER


 664. Arrays Declared Twice in COMMON, Do Not Give Error in QB.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 27-FEB-1990    ArticleIdent: Q44493

 If an array is declared twice in a COMMON or a COMMON SHARED
 statement, it does not give you an error while running in the
 QuickBASIC environment. The error is correctly flagged at compile time
 with a "duplicate definition" error.

 Microsoft has confirmed this to be a problem in the QB.EXE shipped
 with QuickBASIC Versions 4.00, 4.00b, and 4.50 and in the QB.EXE
 shipped with Microsoft BASIC Compiler Versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b). This problem was corrected in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 Code Examples
 -------------

 The following examples reproduce the problem:

    'example 1
    COMMON SHARED A$(),A$()

    'example 2
    COMMON SHARED A$()
    COMMON SHARED A$()

    'example 3
    DIM A(200) AS DOUBLE
    COMMON SHARED A() AS DOUBLE, B$, C$, A() AS DOUBLE

    'example 4
    COMMON SHARED A%(),
    COMMON SHARED B#,C#,A%()


 665. QuickBASIC 4.50 Arrays Can Have 60 Elements, Not Just 8

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890423-1 docerr
 Last Modified: 20-DEC-1989    ArticleIdent: Q44494

 Appendix C, "Limits of QuickBASIC," on Page 337 of the "Microsoft
 QuickBASIC 4.5: Programming in BASIC" manual for Version 4.50 and the
 QuickBASIC Advisor on-line Help system incorrectly state that there
 is a limit of 8 dimensions for arrays. The actual limit is 60.

 Appendix C and the on-line Help system should read as follows:

    Arrays                        Maximum             Minimum
    -----------------------------------------------------------------
    Array Dimensions                60                   1

 This information was not included in the documentation for earlier
 versions of QuickBASIC or Microsoft BASIC compiler.

 This documentation error has been corrected in the "Microsoft BASIC
 7.0: Programmer's Guide" for Microsoft BASIC PDS Version 7.00 and in
 the Microsoft Advisor on-line Help system of the QBX.EXE environment
 in Microsoft BASIC PDS 7.00.


 666. ALT+File+Print After CTRL+BREAK May Hang Machine Using DTK ROM

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890511-153
 Last Modified: 26-MAY-1989    ArticleIdent: Q44761

 It has been reported that printing code (with ALT+File+Print) from the
 QuickBASIC Version 4.50 environment after breaking out of a program
 (with CTRL+BREAK) hangs a machine using DTK ROM BIOS. The problem was
 corrected by updating the machine's BIOS.

 Microsoft has not confirmed this information.


 667. CLEAR Causes "Illegal Function Call" after RETURN <linelabel>

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890517-108 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q44795

 A CLEAR statement causes an "Illegal function call" error message
 after the following steps are performed:

 1. CALL a SUBprogram.

 2. Trap a key with ON KEY(n) GOSUB.

 3. RETURN to a label.

 4. Execute a CLEAR statement.

 This information applies to QuickBASIC Version 4.50 and to Microsoft
 BASIC Compiler Versions 6.00, and 6.00b for MS-DOS and MS OS/2 and to
 Microsoft BASIC PDS 7.00 for MS OS/2 and MS-DOS.

 The reason this condition causes an "Illegal function call" is that
 the SUBprogram was not exited with END SUB or EXIT SUB. Even though
 execution is not physically in the SUBprogram when the CLEAR statement
 is executed, BASIC assumes that control is still within the SUBprogram
 because the information pushed onto the stack during the CALL to the
 SUBprogram is still on the STACK. The CLEAR statement is not allowed
 in SUBprograms or FUNCTIONs; therefore, the "Illegal function call"
 error message is generated.

 The fact that the CLEAR statement is not allowed in SUBprograms or
 FUNCTIONS is documented in the BASIC language reference manuals for
 QuickBASIC Version 4.50 and the BASIC compiler Versions 6.00, and 6.00b,
 and the Microsoft BASIC PDS Version 7.00, as well as in the on-line
 help in QuickBASIC 4.50 and Microsoft Basic PDS 7.00.

 Code Example
 ------------

 The following code sample causes an "Illegal function call" error at
 the CLEAR statement after you press F1:

    ON KEY(1) GOSUB KeyHand
    KEY(1) ON
    CALL test
    END

    ErrorHere: CLEAR    'This statement causes "Illegal function call"
    END

    KeyHand:
    RETURN ErrorHere

    SUB test
    DO : LOOP          'Wait for F1 to be pressed
    END SUB


 668. "Error Loading - Invalid Format," MOUSE.LIB in Quick Library

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q44797

 When creating a Quick library using the MOUSE.LIB library (from the
 "Microsoft Mouse Programmer's Reference Guide") for use with
 QuickBASIC 4.00 or 4.00b or BASIC compiler 6.00 or 6.00b, you must
 place another object module or library before MOUSE.LIB in the Quick
 library. This can be accomplished using any other object module or
 library and the following LINK syntax:

    LINK /Q otherlib+MOUSE.LIB, MOUSE.QLB,, BQLB40.LIB

 If MOUSE.LIB is the first (or only) element in the Quick library,
 trying to load the Quick library into QuickBASIC 4.00 or 4.00b or
 BASIC compiler 6.00 or 6.00b (with QB /L Mouse.QLB) results in an
 "Error loading file - invalid format" error message. This problem does
 not occur in QuickBASIC 4.50 or BASIC PDS 7.00.


 669. INSTR() Function Performs ASCII Compare and Is Case Sensitive

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_BasicInt B_MQuickB B_BBasic
 Last Modified: 13-DEC-1989    ArticleIdent: Q44799

 The INSTR function (provided in all Microsoft BASICs) compares the
 ASCII values of the search string with the ASCII values of the string
 to be searched, and is, therefore, case sensitive. For example, when
 INSTR compares "AB" with "Ab", INSTR returns 0 (zero) because the
 strings are different.

 This information applies to the following products:

 1. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh

 2. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 3. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh

 4. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for the IBM PC

 5. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 6. Microsoft BASIC Compiler Versions 6.00, and 6.00b for MS OS/2
    and MS-DOS

 7. Microsoft BASIC Profesional Development System 7.00 for MS-DOS and
    MS OS/2

 8. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 The INSTR function returns the character position of the first
 occurrence of a string in another string. The syntax for INSTR
 is as follows

    INSTR ( [Start,] string1, string2 )

 where the variables refer to the following:

    Variable  Description

    Start     The [optional] character location to begin searching in
              string1

    string1   The character string to be searched

    string2   The character string to be searched for

 The values returned by the INSTR function are as follows:

    Value     Description

    n         Refers to the character position of string2 in string1.

    0         string2 was not found in string1.

    0         string1 is a null string ("").

    0         The value for Start is greater than the length of string1.

 If string2 is a null string (""), then INSTR returns the value of 1
 unless a Start argument was specified, in which case it returns a
 value equal to Start.

 For more information about the INSTR function, please consult your
 BASIC language reference manual.

 Code Example
 ------------

    PRINT INSTR("ABCDEF","D")   ' Found in column 4.
    PRINT INSTR("ABCDEF","d")   ' Not found, since case differs

 Output:

    4
    0


 670. Set Paths Menu in QB 4.50 Finds $INCLUDE and Library Files

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890523-116 B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q45051

 The Set Paths menu item in the Options menu is a feature new to the
 QuickBASIC Version 4.50 environment. (Earlier versions of the
 QuickBASIC editor do not have an Options menu or a Set Paths option.)
 QBX.EXE for Microsoft BASIC PDS Version 7.00 also has this feature.

 The Set Paths option lets you establish the search path that the
 QB.EXE environment will use for finding executable (.EXE, .COM) files,
 $INCLUDE files, library files (.LIB, .QLB), and the help file (.HLP).
 The search paths specified in Set Paths work in addition to any paths
 that were SET with MS-DOS environment variables (such as SET PATH=,
 SET INCLUDE=, and SET LIB=).

 Note that QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
 4.00, and 4.00b for MS-DOS and Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS do NOT support the MS-DOS SET INCLUDE search path
 (for QB.EXE or BC.EXE). The support for SET INCLUDE is added for
 QuickBASIC Version 4.50 and BASIC PDS 7.00.

 More information about the Set Paths menu is on Pages 220-221 and
 271-272 of the "Microsoft QuickBASIC: Learning to Use" manual for
 QuickBASIC Version 4.50.

 The SET command in MS-DOS can also specify a subdirectory path with
 the INCLUDE environment variable to search for $INCLUDE files. Both
 QB.EXE and BC.EXE (in QuickBASIC Versions 4.00, 4.00b, and 4.50 and in
 BASIC PDS 7.00) find $INCLUDE files along the path specified by the
 INCLUDE environment variable.

 The following is an example of the MS-DOS SET command that specifies
 the INCLUDE file path. It can be invoked in an AUTOEXEC.BAT batch file
 or typed at the DOS prompt.

    SET INCLUDE=D:\QB45\INCLUDE

 The Set Paths menu item is an additional method for finding $INCLUDE
 files when compiling in the QB.EXE Version 4.50 environment and in the
 QBX.EXE Version 7.00 environment.


 671. Bad Random GET Record Order with TYPE's Element as Next Record

 Product Version(s): 4.00 4.00B 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890515-70 B_BasicCom
 Last Modified:  1-JUN-1989    ArticleIdent: Q45055

 The following issue can arise when you use user-defined TYPEs, and
 each record in your random-access file contains a field that points
 to the next record number.

 It has been reported that when running a compiled BASIC program, it is
 possible to get inconsistent results when the record-number argument
 of a random-access GET is based upon an element of a user-defined-TYPE
 record that is input in the same GET statement.

 The following is an example:

    GET #1, ARec.NextRec, ARec

 ARec.NextRec is an element of the user-defined record ARec, and is
 also the pointer to the next record number in the file (which is known
 as a linked-list file structure).

 The behavior of such a GET statement has been reported as
 inconsistent from a compiled .EXE program, and records may be read in
 the wrong order. The same program works correctly running from within
 the QB.EXE environment.

 Microsoft does not advise using an element that you are reading data
 into as the pointer to the record being read in the same GET
 statement. Instead, assign the element containing the next record to
 be read to a temporary variable, and use that temporary variable in
 the next GET statement.

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 and to the BASIC Compiler Versions 6.00 and 6.00b.

 The following code fragment helps explain the problem (but is not
 sufficiently complete to reproduce the error):

    TYPE atype
       NextRec as integer
       CurrentData as single
    END TYPE
    DIM ARec as atype
    ' Please avoid doing GETs such as the following, which use an
    ' element of the input record as the next record number to input
    ' in the same GET statement:
    GET #1, ARec.NextRec, ARec

 As a workaround, use a temporary variable to specify the next record
 to GET:

    TYPE atype
       NextRec as integer
       CurrentData as single
    END TYPE
    DIM ARec as atype
    temp%=ARec.NextRec
    GET #1, temp%, ARec


 672. "Too Many Segments" LINKing More Than 128 Modules

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890512-130 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q45165

 The linker error message L1049 "Too many segments" occurs when you are
 trying to LINK more than 128 modules into an .EXE program or a Quick
 library. The default number of segments for LINK.EXE is 128. To
 correct this problem, combine two or more of the modules (the .BAS
 source files).

 If the modules are too large to combine, you must set the number of
 segments to more than 128 with the /SEGMENTS linker option. The
 maximum number of segments is 1024, or 1K. If you compile and link
 within the QuickBASIC environment instead of from the DOS command
 line, you can set the /SEGMENTS option by including the following line
 in your AUTOEXEC.BAT file:

    SET LINK= /SEGMENTS:<number of segments>

 Note that there is no space before the "=", and one space after the
 "=".

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 and to Microsoft BASIC Compiler Versions
 6.00, and 6.00b and to Microsoft BASIC PDS 7.00.

 To determine the number of segments you are generating, use the
 following guidelines. A module in QuickBASIC is exactly the same as a
 .BAS file. Each module compiles to one code segment. All of the data
 in the program is combined at LINK time into one single data segment.
 There is only one data segment, no matter how many modules you
 compile. Therefore, the number of segments is as follows:

    NumberOfSegments = [number of .BAS files you start with] + 1

 If you are using a library, each .BAS file that was compiled and put
 into the library must be included in the above formula.

 The "Too many segments" error message can also occur when using the
 BUILDRTM utility of Microsoft BASIC Compiler 6.00, 6.00b and to
 Microsoft BASIC PDS 7.00 to combine more than 128 modules into a
 run-time module. This happens because BUILDRTM.EXE uses LINK.EXE to
 create a run-time module. The workarounds are the same as above: combine
 one or more modules or SET the LINK environment variable.


 673. Floating Point Formats Used by Microsoft BASIC Products

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890505-43 B_BasicCom B_BasicInt B_GWBasicI B_MQuickB
 Last Modified: 17-OCT-1990    ArticleIdent: Q45166

 The floating point formats used by Microsoft BASIC products depend on
 which BASIC product and version number are being used, as shown below.

 The following products support decimal math, which is very accurate
 (such as for dollars and cents calculations), but slow:

 1. Microsoft Business BASIC Compiler versions 1.00 and 1.10 for
    MS-DOS

 2. Microsoft BASIC (d) Interpreter versions 2.00, 2.10, and 3.00 for
    the Apple Macintosh

 3. Microsoft QuickBASIC (d) version 1.00 for the Apple Macintosh

 4. Microsoft BASIC Compiler version 1.00 for the Apple Macintosh
    (compiled with the D option, "Compile for Decimal Math")

 The following products support the Microsoft Binary Format (MBF):

 1. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS

 2. Microsoft BASIC Interpreter version 5.28 for MS-DOS

 3. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, and 2.01 for
    the IBM PC and compatibles

 4. Noncoprocessor version (QB.EXE) of Microsoft QuickBASIC version
    3.00 for the IBM PC and compatibles

 5. Microsoft GW-BASIC Interpreter versions 2.00, 2.10, 3.20, 3.22,
    and 3.23 for MS-DOS

 6. Microsoft BASIC Interpreter version 5.21 for CP/M-80

 7. Microsoft BASIC Compiler version 5.30 for CP/M-80

 8. All versions of the IBM BASICA Interpreter

 9. IBM BASIC Compiler through version 2.00

 The following products support the IEEE floating point format:

 1. Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 for the IBM PC
    and compatibles.

 2. The coprocessor version of Microsoft QuickBASIC 3.00 (QB87.EXE) for
    the IBM PC and compatibles.

 3. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and
    MS OS/2. This product also supports the Alternate Math package
    (BC /FPa), which follows the IEEE format but does not emulate or
    use a coprocessor, and is faster than the Emulation Math package
    (BC /FPi, the default) on machines without a coprocessor.

 4. Microsoft BASIC PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2.
    This product also supports the Alternate Math package (BC /FPa),
    which follows the IEEE format but does not emulate or use a
    coprocessor, and is faster than the Emulation Math package (BC /FPi,
    the default) on machines without a coprocessor.

 5. Microsoft BASIC (b) Interpreter versions 1.00, 1.01, 2.00, 2.10,
    and 3.00 for the Apple Macintosh.

 6. Microsoft BASIC Compiler version 1.00 for the Apple Macintosh
    (compiled WITHOUT the compiler's D option).

 7. Microsoft QuickBASIC (b) for the Apple Macintosh version 1.00.

 The following product supports the CURRENCY Data type, which stores
 decimal numbers exactly and accurate to four decimal places (ideal for
 business applications using dollars and cents):

    Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2

 (See the table below for a quick reference to floating-point support
 by BASIC products.)

 For more information concerning IEEE format versus Microsoft Binary
 Format, please see Pages 131-134 in the "Microsoft Macro Assembler
 5.1: Programmer's Guide," or see the "IEEE and Rounding" application
 note, which can be obtained by calling Microsoft Product Support
 Services. More information is also available in this database by
 querying on the following keywords:

    floating point and format

 Table: Floating Point Support, by BASIC Product and Version
 -----------------------------------------------------------

     Product and Version     |  Decimal  |  Microsoft |  IEEE | CURRENCY
                             |   Math    |   Binary   |       |   Data
 ----------------------------|-----------|------------|-------|----------
 MS BASIC PDS, MS-DOS and    |           |            |       |
 MS OS /2:  7.00, 7.10       |           |            |   X   |    X
                             |           |            |       |
 MS BASIC Compiler, MS-DOS:  |           |            |       |
     6.00, 6.00b             |           |            |   X   |
     5.35, 5.36              |           |      X     |       |
                             |           |            |       |
 MS BASIC Interpreter MS-DOS:|           |            |       |
     5.28                    |           |      X     |       |
                             |           |            |       |
 MS QuickBASIC for IBM PC:   |           |            |       |
     1.00, 1.01, 1.02        |           |      X     |       |
     2.00, 2.01              |           |      X     |       |
     3.00 (QB.EXE)           |           |      X     |       |
     3.00 (QB87.EXE)         |           |            |   X   |
     4.00, 4.00b, 4.50       |           |            |   X   |
                             |           |            |       |
 MS GW-BASIC for MS-DOS:     |           |            |       |
     2.00, 2.10 (OEM only),  |           |      X     |       |
     3.20, 3.22, 3.23        |           |      X     |       |
                             |           |            |       |
 MS BASIC Interpreter CP/M-80|           |            |       |
     5.21                    |           |      X     |       |
                             |           |            |       |
 MS BASIC Compiler, CP/M-80: |           |            |       |
     5.30, 5.35              |           |      X     |       |
                             |           |            |       |
 The IBM BASIC Compiler      |           |            |       |
     for MS-DOS:             |           |            |       |
     2.00 (and earlier)      |           |      X     |       |
                             |           |            |       |
 IBM BASICA Interpreter      |           |            |       |
     for MS-DOS:             |           |            |       |
     All versions            |           |      X     |       |
                             |           |            |       |
 Microsoft BASIC Interpreter |           |            |       |
     for Macintosh:          |           |            |       |
     1.00, 1.01,             |           |            |   X   |
     2.00, 2.10,             |     X     |            |   X   |
     3.00                    |     X     |            |   X   |
                             |           |            |       |
 Microsoft BASIC Compiler    |           |            |       |
     for Macintosh:          |           |            |       |
     1.00                    |     X     |            |   X   |
                             |           |            |       |
 Microsoft QuickBASIC for    |           |            |       |
     Macintosh:              |           |            |       |
     1.00                    |     X     |            |   X   |
                             |           |            |       |
 Microsoft Business BASIC    |           |            |       |
     MS-DOS:                 |           |            |       |
     1.00, 1.10              |     X     |            |       |


 674. Finding Address of Run-Time Error Line Using .LST or LINK /LI

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890511-147 docerr B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q45168

 This article describes how to find the line in the source code that
 gives an "ERROR nn AT ADDRESS segment:offset" message from an .EXE
 program at run time.

 When you compile with the BC /a/Zi or /a/Zd option, the LINK /LI
 (Linenumber) option creates a .MAP file that includes (at the bottom)
 the relative address of every line in the source program. (A
 documentation correction for the /LI option is shown farther below.)

 However, instead of using LINK /LI, it is easier to use the .LST
 listing file generated by the BC.EXE compiler to find the source line
 at the address given in the run-time error message.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS.

 Use .LST File Instead of .MAP File to Find Error Address
 --------------------------------------------------------

 A .MAP file generated with the LINK /LI option is not the most
 convenient way to find the line in the source code that gives an
 "ERROR nn AT ADDRESS segment:offset" error message from an .EXE
 program at run time. Instead of using the .MAP file, you only need the
 .LST file for each module, which conveniently displays the code
 offsets next to the lines in your source file. The offset given in the
 error message is the approximate area of your code where the error
 occurs. (However, some errors aren't reported until the code has run
 past the actual problem area).

 To create an .LST file, you need to compile from the BC.EXE command
 line. When BC.EXE prompts you for a source listing ("Source listing
 [NUL.LST]:"), give it a name. Alternatively, you can specify the .LST
 file as the third argument. You can end the BC.EXE command line with a
 semicolon to suppress prompting, as follows:

    BC TEST.BAS,,TEST.LST/A;

 The BC /A option includes an assembler translation of the program in
 the .LST file, which can help when debugging.

 Documentation Error for LINK /LI
 --------------------------------

 The LINK /LI (Linenumbers) option is incorrectly documented as follows
 in the manuals listed further below:

    This option has effect only if you are linking object files
    compiled with the /M option.  [** Incorrect **]

 There is no /M compiler option, only a LINK /M option. This sentence
 should be changed to read as follows:

    This option has effect only if you are linking object files
    compiled with the /a/Zi or /a/Zd options.

 This correction applies to the following manuals:

 1. Page 367 of the "Microsoft QuickBASIC: Programming in BASIC" manual
    for version 4.50

 2. Page 225 of the "Microsoft QuickBASIC Version 4.00: Learning and
    Using Microsoft QuickBASIC" manual for versions 4.00 and 4.00b

 3. Page 225 of the "Microsoft BASIC Compiler: Learning and Using
    Microsoft QuickBASIC" manual for versions 6.00 and 6.00b for MS-DOS
    and MS OS/2

 The BASIC PDS manuals correctly document the /LI option.


 675. PCOPY Causes Screen Snow on Some CGA Video Cards

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q45169

 The program below demonstrates that the PCOPY statement may produce
 "snow" on some CGA video cards. This is caused by a timing-dependent
 refresh problem common to many CGA adapters.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS
 and MS OS/2.

 The following program is PCOPY.BAS, which uses PCOPY to copy several
 lines of text to the second page of video memory. When run on a CGA
 system, screen "snow" will appear during PCOPY.

 SCREEN 0
 PRINT "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 PRINT "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
 PRINT "Watch the snow"
 PCOPY 0, 1
 SCREEN 0, , 1, 1


 676. Using CALL INTERRUPT to Return DOS Version Number

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q45170

 The program shown below demonstrates how to use CALL INTERRUPT to
 return the DOS version number.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and to the Microsoft BASIC Compiler Versions 6.00, and 6.00b
 for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The following program is INTVER.BAS:

 ' $INCLUDE: 'qb.bi'
 ' For BC.EXE and QBX.EXE in BASIC 7.00 the include is 'QBX.BI'

 DIM inregs AS RegType, outregs AS RegType
 inregs.ax = &H3000
 CALL INTERRUPT(&H21, inregs, outregs)
 majorver = outregs.ax AND &HFF
 minorver = (outregs.ax AND &HFF00) / 256
 PRINT "MS-DOS Version: "; majorver; "."; minorver


 677. How to Detect Keypress in BASIC without Reading in Character

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM
 Last Modified: 13-DEC-1989    ArticleIdent: Q45171

 The program shown below demonstrates how to check for a keypress
 without reading in the character, thus leaving the character in the
 keyboard buffer.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and to Microsoft BASIC Compiler Versions 6.00, and 6.00b for
 MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The following program, INTKEY.BAS, uses an MS-DOS interrupt to check
 if a key has been pressed. This can be used to check for a keypress
 before doing an INPUT, LINE INPUT, or INKEY$ statement. This approach
 is an alternative to invoking the INKEY$ function, which takes one
 character at a time out of the keyboard buffer.

 This example uses MS-DOS interrupt 33 (21 hex) with function call 11
 (0B hex), "Check Input Status." For more information about MS-DOS
 interrupts, please refer to "Advanced MS-DOS Programming" (Second
 Edition) by Ray Duncan (published by Microsoft Press, 1988).

 Example
 -------

 ' $INCLUDE: 'qb.bi'
 ' For BC.EXE and QBX.EXE in BASIC 7.00 the include file is 'QBX.BI'

 DIM inregs AS RegType, outregs AS RegType
 inregs.ax = &HB00  ' Move a hex value of B into the AH register
 outregs.ax = 0
 PRINT "Press any key: "
 DO
   CALL INTERRUPT(&H21, inregs, outregs)
 LOOP UNTIL (outregs.ax AND &HFF) = &HFF
 INPUT X$   ' The first character typed appears in the INPUT line.
 ' Or you can PRINT INKEY$ instead of using INPUT X$ to see the
 ' character waiting in the keyboard buffer.


 678. QB 4.50 On-Line Help Correction for UBOUND Statement

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890525-16 docerr
 Last Modified:  1-JUN-1989    ArticleIdent: Q45176

 The QuickBASIC Version 4.50 on-line help utility contains a
 documentation error under the UBOUND statement. The incorrect sentence
 reads as follows:

       UBOUND(array[,Dimension])

    -- Dimension, an numeric-expression that has an integer value,
       indicates the dimension of the array for which you want to see
       the smallest available subscript.

 The sentence should be corrected to read as follows:

       UBOUND(array[,Dimension])

    -- Dimension, a numeric-expression that has an integer value,
       indicates the dimension of the array for which you want to see
       the largest available subscript.


 679. Example to Get and Set File Attributes in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q45423

 The program below demonstrates how to use CALL INTERRUPT to get and
 set the attributes of files in MS-DOS.

 This information applies to QuickBASIC Versions 4.00, 4.00b and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft
 BASIC PDS Version 7.00.

 The following program is FILEATT.BAS:

 DECLARE SUB showattributes (status AS INTEGER)
 ' $INCLUDE: 'qb.bi'
 ' For QBX.EXE and BC.EXE in BASIC PDS 7.00 use the include file 'QBX.BI'

 CONST SETREADONLY = &H1
 CONST SETHIDDEN = &H2
 CONST SETSYSTEM = &H4
 CONST SETARCHIVE = &H32
 DIM inregs AS RegTypex, outregs AS RegTypex
 CLS
 INPUT "Enter File Name (with full pathname): "; filename$

 ' add CHR$(0) to make ASCII Z string
 filename$ = filename$ + CHR$(0)

 inregs.ax = &H4300                    ' get file attributes
 inregs.dx = SADD(filename$)
 '   For BC.EXE and QBX.EXE for BASIC PDS 7.00 add the following line:
 ' inregs.ds = SSEG(filename$)

 CALL INTERRUPTX(&H21, inregs, outregs)
 showattributes outregs.cx

 ' set hidden attribute
 inregs.ax = &H4301                    ' set file attributes

 ' mask off the volume labels directory and reserved bits
 setstatus% = outregs.cx AND &H27

 setstatus% = setstatus% OR SETHIDDEN ' set hidden attribute bit
 inregs.cx = setstatus%
 CALL INTERRUPTX(&H21, inregs, outregs)
 showattributes outregs.cx

 SUB showattributes (status AS INTEGER)
   PRINT
   PRINT "File Attributes Set"
   PRINT "-------------------"
   IF status% AND SETREADONLY THEN PRINT "read-only"
   IF status% AND SETHIDDEN THEN PRINT "hidden"
   IF status% AND SETSYSTEM THEN PRINT "system"
   IF status% AND 8 THEN PRINT "volume label"
   IF status% AND 16 THEN PRINT "directory"
   IF status% AND SETARCHIVE THEN PRINT "archive"
 END SUB


 680. SCREEN 9; 16 Foreground and Background Colors Simultaneously

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890522-4 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q45424

 Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50, Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS, and Microsoft BASIC PDS
 Version 7.00 for MS-DOS support up to SCREEN 13, depending on the
 video card installed in your machine. Using the COLOR statement, in
 all color modes you can simultaneously display all foreground colors
 available in that particular mode.

 However, simultaneously displaying multiple background colors is
 supported only in SCREEN mode 0 (zero) (character mode). SCREEN 0 is
 the only SCREEN mode that supports displaying all 16 foreground colors
 and all 8 background colors simultaneously. When you invoke the COLOR
 statement with a background color argument in any SCREEN mode other
 than 0, you get only one background color, and the entire screen
 background is affected.

 The QuickBASIC program below contains routines that, if used in place
 of PRINT and COLOR when in SCREEN 9, provide the ability to display 16
 foreground colors and 16 "background" colors simultaneously. This
 program uses foreground colors with bit masking to draw inverse-video
 characters with multiple background colors simultaneously on the
 screen in graphics mode. The routines could easily be modified to
 support SCREEN 12. The support module, without any modification, can
 be converted into a .LIB library or left as an .OBJ object file and
 linked into your program.

 This support module operates correctly if compiled using QuickBASIC
 Versions 4.00, 4.00b, or 4.50, Microsoft BASIC Compiler Version 6.00
 or 6.00b for MS-DOS, or Microsoft BASIC PDS Version 7.00 for MS-DOS.

 For information on a similar technique for Hercules SCREEN 3, query on
 the word INVERSEPRINT.

 The module below contains two SUBprograms that can be CALLed in the
 same way as the PRINT or COLOR statements when the following $INCLUDE
 file is included, or can be used with the CALL statement. The INCLUDE
 file contains the DECLARE statements for the S9COLOR and S9PRINT and
 CONST declarations for all 16 colors so the colors can be referenced
 by name. The two routines are as follows:

 1. S9COLOR: Takes two parameters: foreground color and background
    color, respectively. Unlike the COLOR statement, the parameters are
    not optional. If you want to change only the foreground color, both
    parameters must be provided. The COLOR statement can still be used,
    but it will not affect strings printed using S9PRINT. The following
    is an example:

       S9COLOR Green, BrRed
       CALL S9COLOR (BrBlue, Cyan)

 2. S9PRINT: Takes only one parameter, the STRING to be printed. The
    parameter can be a simple STRING literal or a STRING expression. No
    special formatting characters are supported, but they could easily
    be added. Placing a pipe character (|) at the end of the STRING
    causes a carriage return-linefeed to be executed after the STRING
    is printed. The following is an example:

       S9PRINT "This is the text to be printed"
       S9PRINT A$+B$
       S9PRINT STRING$(50,"X")
       S9PRINT "The PIPE causes a CRLF|"  'the PIPE is not printed
       CALL S9PRINT "CALL statement used"

 Code ($INCLUDE File S9LIB.BI)
 -----------------------------

 DECLARE SUB S9COLOR (fcolor%, bcolor%)
 DECLARE SUB S9PRINT (text$)
 CONST Black = 0, Blue = 1, Green = 2, Cyan = 3, Red = 4, Magenta = 5
 CONST Brown = 6, White = 7, Gray = 8, BrBlue = 9, BrGreen = 10
 CONST BrCyan = 11, BrRed = 12, Pink = 13, Yellow = 14, BrWhite = 15

 Code (Support Module S9LIB.BAS)
 -------------------------------

 '* Module level code:  Shared variables between SUBprograms
 DIM SHARED bgblock%(2242), tempblock%(2242)
 DIM SHARED fcolor%, bcolor%

 '* S9COLOR:  Simply stores the color values passed to the routine
 '*           in bcolor% and fcolor%, which are used in S9PRINT.
 SUB S9COLOR (nfcolor%, nbcolor%)
   bcolor% = nbcolor%
   fcolor% = nfcolor%
 END SUB

 '*********************************************************************
 'S9PRINT:  This routine will not wrap around if the string exceeds
 'column 80. It truncates whatever text is being printed at column 80.
 'The string length in pixels is first calculated. A LINE statement with
 'the BF option (Box Fill) using the desired background color is
 'executed. The resulting block of color is saved with a GET statement.
 'The string is then printed in the background color. The saved block of
 'background color is then PUT over the string. The resulting block of
 'text, which is a black foreground with the desired background color,
 'is then saved using another GET statement. The string is then
 'reprinted in the desired foreground color, and the block save with the
 'last GET statement is PUT over the text, resulting in the text printed
 'with the desired foreground and background colors, without affecting
 'the rest of the screen. The PUT statements are all executed using the
 'XOR action verb.
 '**********************************************************************
 SUB s9print (text$)
   tx% = POS(0)
   ty% = CSRLIN
   col% = (tx% - 1) * 8
   row% = (ty% - 1) * 14
   maxpix% = 639 - col%
   maxlength% = 81 - tx%
   IF RIGHT$(text$, 1) = "|" THEN
     CR% = 1
     tlength% = (LEN(text$) - 1)
     text$ = LEFT$(text$, tlength%)
     tlength% = tlength% * 8 - 1
   ELSE
     CR% = 0
     tlength% = LEN(text$) * 8 - 1
   END IF
   IF tlength% > maxpix% THEN
     text$ = LEFT$(text$, maxlength%)
     tlength% = maxpix%
   END IF
   LINE (col%, row%)-STEP(tlength%, 13), bcolor%, BF
   GET (col%, row%)-STEP(tlength%, 13), bgblock%(0)
   COLOR bcolor%
   PRINT text$;
   LOCATE ty%, tx%
   PUT (col%, row%), bgblock%(0), XOR
   GET (col%, row%)-STEP(tlength%, 13), bgblock%(0)
   COLOR fcolor%
   PRINT text$;
   PUT (col%, row%), bgblock%(0), XOR
   IF CR% = 1 THEN PRINT
 END SUB

 Code (Example of Main Program)
 ------------------------------

 The program below demonstrates the use of the S9COLOR and S9PRINT
 routines. It simultaneously displays all the possible combinations of
 foreground and background colors.

 To compile the program, do the following:

 1. To create S9LIB.OBJ, issue the following command:

       BC S9LIB;

    To create S9LIB.LIB, issue the following command:

       LIB S9LIB S9LIB.OBJ;

 2. If using S9LIB.OBJ, issue the following command:

       BC S9DEMO;
       LINK S9DEMO S9LIB;

    If using S9LIB.LIB, issue the following command:

       BC S9DEMO;
       LINK S9DEMO,,,S9LIB

 S9DEMO.BAS
 ----------

 '* S9DEMO.BAS     Demo for S9LIB.BAS  *
 '$INCLUDE: 'S9LIB.BI'
 DIM colornames$(15)
 FOR I% = 0 TO 14
   READ colornames$(I%)
 NEXT I%
 SCREEN 9
 CLS
 FOR bc% = 0 TO 15
   LOCATE , 2
   FOR fc% = 0 TO 14
     S9COLOR fc% + 1, bc%
     S9PRINT colornames$(fc%)
   NEXT
   PRINT
 NEXT
 S9COLOR black, brred
 a$ = "PRESS ANY KEY|"
 LOCATE 23, 40 - (LEN(a$) \ 2)
 S9PRINT a$
 SLEEP
 END
 DATA Blue,Green,Cyan,Red,Magenta,Brown,White,Gray
 DATA BrBlue,BrGreen,BrCyan,BrRed,Pink,Yellow,BrWhite


 681. PAINT Fills Entire Screen If Border Color Is Not the Same

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890524-91 B_GWBasicI B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q45443

 The PAINT statement fills a graphics area with a specified color or
 pattern. PAINT fills the entire screen if the graphics area is not
 bound by a border of the same color or pattern.

 The PAINT statement is available in Versions 1.00, 1.01, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50 of Microsoft QuickBASIC, Version for
 MS-DOS 3.21, 3.22, and 3.23 of Microsoft GW-BASIC, and Versions 6.00, 6.00b
 for MS-DOS and the Microsoft BASIC PDS 7.00 for MS-DOS.

 The PAINT statement has the following syntax:

    PAINT [step] (x,y) [,[paint] [, [bordercolor] [,background]]]

 Note the following:

 1. step - Defines coordinates to be relative to the most recently
    plotted point.

 2. (x,y) - The coordinates where painting begins. The point must lie
    inside or outside of the figure, not on the border itself.

 3. paint - A numeric or string expression. If numeric, the number must
    be a valid color attribute. The corresponding color is then used to
    paint the graphic area. If no value for paint is used, the
    foreground color attribute is used. If the corresponding paint
    argument is a string, then PAINT does a "tiling" process to paint
    the area. Consult the BASIC language reference manual for more on
    "tiling."

 4. bordercolor - A numeric expression identifying the color attribute
    to use to paint the border of the figure.

 5. background - A string value giving the "background tile slice" to
    skip when checking for termination of the boundary.

 PAINT can be used to fill a graphic area denoted by the starting point
 (x,y). PAINT continues filling the screen until it reaches the
 termination color, which is the same color that it is currently
 filling, or the background argument specified above. If no background
 argument is specified, the default is CHR$(0).

 To fill only a specific image, the color that the graphic image was
 drawn in must match the fill color. The following code example
 illustrates this. Although the code example illustrates this feature
 with the DRAW functions, this feature is built into the PAINT
 statement and therefore holds true for all graphics functions (LINE,
 CIRCLE, etc.).

 Code Examples
 -------------

 '          PAINT.BAS
 SCREEN 9                      ' Sets video mode to EGA screen 9

 PSET (100, 100)               ' Positions pen to line 100 column 100
 DRAW "D50 R50 U50 L50"   ' Draws a 50x50 box starting from
                           ' (100,100), with the default color
                           ' (white).
 PAINT (125, 125)         ' Paints the box with the default color
                      ' (white)

 DO WHILE INKEY$ = ""     ' Continuous loop until key pressed
 LOOP

 PSET (200, 200)               ' Reposition pen to line 200 column 200
 DRAW "D50 R50 U50 L50"   ' Draws a 50x50 box starting from
                           ' (200,200), with the default color
                           ' (white).

 DO WHILE INKEY$ = ""      ' Continuous loop until key pressed
 LOOP

 PAINT (225, 225), 1           ' Attempt to PAINT box with color BLUE,
                           ' but will result in the whole screen
                           ' being PAINTed.  If the box was drawn
                           ' in BLUE, then this would work.

 '(DRAW "C1 D50 R50 U50 L50").
 END


 682. CLEAR Resets ON ERROR GOTO and Turns Off Error Trapping

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890224-103 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q45451

 The CLEAR statement in a QuickBASIC program turns off error handling
 routines. Any error that happens after a CLEAR statement is not
 trapped by an error handling routine that was initiated before the
 CLEAR statement. To trap errors after a CLEAR statement, you must
 reinstate the error handling routine with a new ON ERROR GOTO clause.

 This applies to Microsoft QuickBASIC Versions 3.00, 4.00, 4.00b, and
 4.50, and Microsoft BASIC Compiler Versions 6.00, 6.00b for MS-DOS and
 MS OS/2, and Microsoft BASIC PDS 7.00 for MS-DOS and MS OS/2.

 The following two programs show an error trapping routine that does
 not work correctly and an error trapping routine that does work:

 Program 1
 ---------

 REM  This error handling routine will not trap the error.
   ON ERROR GOTO Handler
   CLEAR
 REM The ERROR handling routine is now turned off
   ERROR 1
 END
 Handler: Print "In the ERROR Handler"
          RESUME

 The output for this program is only an error message from QuickBASIC.

 Program 2
 ---------

 REM This ERROR Handling routine will trap the error.
   ON ERROR GOTO Handler
   CLEAR
 REM The ERROR Handling routine is now turned off.
   ON ERROR GOTO Handler
 REM The ERROR Handling routine is now turned back on.
   ERROR 1
 END
 Handler : Print "In the ERROR Handler"
           RESUME

 The output for this program is as follows:

    In the ERROR Handler


 683. Incorrect Number of Parameters to Quick Library Can Hang QB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890525-13
 Last Modified: 20-DEC-1989    ArticleIdent: Q45483

 When using FUNCTIONs or SUBprograms that are located in a Quick
 library under QuickBASIC Versions 4.00, 4.00b, and 4.50 and under
 QuickBASIC Extended in BASIC PDS Version 7.00, it is important to
 DECLARE all Quick library routines that your program will be CALLing.
 If fewer parameters than expected are passed to a SUBprogram in a
 Quick library, your machine may hang, sometimes requiring the power to
 be cycled to reboot the machine. This problem occurs only within the
 environment and only when CALLing a Quick library routine.

 If the program is CALLing a routine in another module that is loaded
 into the QB.EXE environment, the expected error of "Argument count
 mismatch" displays. When compiled to an EXE file, the error "Illegal
 function call" displays.

 Microsoft does not consider this to be a problem with QuickBASIC or
 QBX.EXE of any version. The environment cannot perform parameter
 checking without a DECLARE statement for each SUB or FUNCTION.
 Therefore a DECLARE statement is required for each routine in a Quick
 library in order for a program to function normally.

 If SUBprograms are not DECLAREd at the top of the module that makes
 the calls, the SUBroutine must be CALLed. If you have a DECLARE SUB
 for that SUBroutine, you need only to mention the SUBprograms followed
 by any expected parameters.

 When using FUNCTIONs, whether in another module or a Quick library,
 the FUNCTION must be DECLAREd at the top of the calling module. If the
 FUNCTION is not DECLAREd, the QuickBASIC environment interprets the
 FUNCTION as an array.

 For more information on SUBprograms and FUNCTIONs, consult Chapter 2
 of the "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for
 Microsoft QuickBASIC Version 4.50 or Chapter 2 of the "Microsoft BASIC
 7.0: Programmer's Guide" for Microsoft BASIC PDS Version 7.00.

 The code example below illustrates the necessity of the DECLARE
 statement. If the FUNCTION and SUBroutine are combined into a Quick
 library and only one of the arguments is passed to the SUBprogram, the
 computer hangs. If both arguments are passed, it executes as expected.
 If the DECLARE FUNCTION is removed, a "Subscript out of range" is
 generated when the FUNCTION is referenced.

 Code Example
 ------------

 Main Program
 ------------

 DECLARE FUNCTION calculatesomething%(t AS INTEGER)
 DEFINT A-Z
 t = 100
 x = 100                     'to hang machine, change CALL statement to:
 CALL printhello(t, x)       'CALL printhello(t)
 a = calculatesomething(t)
 PRINT a

 Quick Library Routines
 ----------------------

 SUB printhello(t AS INTEGER, x AS INTEGER)
     PRINT "Hello from the SUBprogram: "; t, x
 END SUB

 FUNCTION calculatesomething%(t AS INTEGER)
     calculatesomething% = t + t * t
 END FUNCTION


 684. 4.50 Manual Has Misleading Note for Calling FUNCTION Procedure

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S890518-133
 Last Modified: 20-DEC-1989    ArticleIdent: Q45514

 The Note on Page 46 of the "Microsoft QuickBASIC: Programming in
 BASIC" manual for Version 4.50 is misleading. It reads as follows:

    NOTE: The program example above is written for use in the QB
    environment only. It cannot be compiled using the BC command
    from DOS.

 Technically, this note is correct because the program example leaves
 out the DECLARE statement for the FUNCTION procedure (GetInput$). The
 DECLARE is necessary for compilation. However, if the program is
 entered in the QuickBASIC environment, the DECLARE will automatically
 be added when the program is Saved. This misleading comment does not
 appear in the documentation for Microsoft BASIC PDS Version 7.00.


 685. QB Debugger Step Problem with Breakpoint in Watched FUNCTION

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q45545

 The Step (press F8) command in the QuickBASIC version 4.50 editor may
 not operate correctly when all of the following conditions are met:

 1. You declared and defined a FUNCTION procedure.
 2. You chose Add Watch or Instant Watch on the FUNCTION name.
 3. You set a breakpoint inside the FUNCTION procedure being watched.

 The symptom of the problem is that when the Step process (F8) begins,
 it causes the watched FUNCTION to be executed from the beginning to
 the breakpoint, instead of executing intervening lines individually
 with each press of the F8 key. Choosing Restart from the Run menu or
 pressing F8 again causes the editor to again step through the FUNCTION
 from the beginning to the breakpoint.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; in the QB.EXE
 environment of Microsoft BASIC compiler versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b); and in the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are researching
 this problem and will post new information here as it becomes
 available.

 To work around this problem, either remove the breakpoint from the
 watched FUNCTION, or delete the watch on the FUNCTION.

 Code Example
 ------------

 After you choose Add Watch on test% and set a breakpoint on the PRINT
 "world" line, the following code example executes the FUNCTION test%
 from the beginning to the PRINT "world" line when you perform a Step
 (F8) operation:

    DECLARE FUNCTION test% ()
    x% = test%
    END

    FUNCTION test%     'Add Watch... on test%
      PLAY "CDEFGAB>C"   'These two lines are executed
      PRINT "Hello"      'on every Step (F8)
      PRINT "world"    'Set Breakpoint here
      ' Never gets here
      test% = 1
    END FUNCTION

 To work around this problem, Add Watch on x% instead of test%, or
 remove the breakpoint.


 686. How to Round Up a Fraction to Its Integral Ceiling in BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_BasicInt B_BBasic B_MQuickB
 Last Modified: 13-DEC-1989    ArticleIdent: Q45686

 The mathematical ceiling function (which rounds up to the next higher
 integral value for any fraction) is not built into the BASIC language.
 To compute the ceiling, use the following function:

    DEF FNceil#(x#) = -INT(-x#)

    x# = 50.0001
    PRINT FNceil#(x#)    ' Prints 51

 This function is equivalent to the ceil() function in the C language.

 This function works in the following products:

 1. Microsoft QuickBASIC Version 1.00 for the Macintosh

 2. Microsoft BASIC Compiler Version 1.00 for the Macintosh

 3. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Macintosh

 4. Microsoft QuickBASIC Compiler Versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, 4.50 for the IBM PC

 5. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 6. Microsoft BASIC Compiler Versions 6.00 and 6.00b and Microsoft
    BASIC PDS Version 7.00 for MS OS/2 and MS-DOS

 7. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23 for
    MS-DOS

 The code example below can be used in Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50 for MS-DOS and in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b and Microsoft BASIC PDS Version 7.00 for
 MS-DOS and MS OS/2, but not in earlier versions:

 DECLARE FUNCTION ce& (x#)   ' Function returns long integer
 DECLARE FUNCTION ceil# (x#) ' Function returns double precision
 CLS
 x# = 40000005.001#
 y# = 50.000000000001#
 PRINT ceil#(x#)  ' Prints 40000006
 PRINT ceil#(y#)  ' Prints 51
 PRINT ce&(y#)    ' Prints 51
 PRINT ce&(x#)    ' Prints 40000006
 FUNCTION ceil# (x#) STATIC
 ceil# = -INT(-x#)  ' Can pass values of x# in double-precision range
 END FUNCTION

 FUNCTION ce& (x#) STATIC
 ce& = -INT(-x#)    ' Values of x# outside -2147483648 to 2147483647
 END FUNCTION       ' will give a long-integer overflow error.


 687. "Out of String Space" Concatenating Variable-Length String

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890606-8 B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q45687

 For variable-length string concatenation to execute successfully, even
 if only 1 byte is to be added, there must be enough available memory
 [reported by FRE("")] for the length of a copy of the existing string,
 plus the length of the string being added, plus its new 4-byte string
 descriptor. Otherwise, you will get an "Out of String Space" error,
 caused by the temporary old string remaining in memory during the
 string concatenation. The old string is deallocated only after a
 successful concatenation.

 This information applies to QuickBASIC Versions 1.00, 1.01, 1.02,
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50, and to BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and OS/2.

 This information also applies to Microsoft BASIC PDS Version 7.00 when
 using BC.EXE without the /Fs compiler switch. Inside the QBX.EXE
 environment and when using /Fs compiler switch, BASIC 7.00 uses a 64K
 segment for temporary string storage and procedure-level strings (that
 is, strings declared inside subroutines). To see how much temporary
 string space you have when using far strings, use FRE("StringLiteral"),
 where StringLiteral is any constant string (for example, "Hello"). For
 more information about far strings, read Chapter 11 in the "Microsoft
 BASIC 7.0: Programmer's Guide" for BASIC PDS Version 7.00.

 When you concatenate a variable-length string with another string in
 BASIC, a new 4-byte string descriptor is created. A copy of the
 original string is moved to a new location in string space and the
 string to be concatenated is appended to it. The length field in the
 new string descriptor is updated to reflect the length of the
 concatenated string. Only then is the memory used by the original
 string and its descriptor released (deallocated).

 New strings are allocated above existing strings and deallocated
 strings in DGROUP. When deallocated strings fragment string space to
 the point where a new string fills the last space at the top of
 DGROUP, BASIC automatically performs string space compaction (garbage
 collection) to make free string space contiguous again. Passing a
 string argument (such as "", the null string) to the FRE("") function
 always forces string space compaction before reporting the amount of
 string space available in DGROUP.

 For example, assume FRE("") returns 20,004. An attempt to add a single
 byte to an existing string of 20,000 bytes would fail because 20,005
 bytes are needed for the concatenation to be successful:

    Existing string   = 20,000 bytes
    String to add     =      1 byte longer
    String descriptor =      4 bytes
                     -----------
    Memory needed       20,005 bytes

 Because only 20,004 bytes of memory are available, an "Out of String
 Space" message will be generated.


 688. BC.EXE 4.50 "Internal Error Near 361F" Passing Integers to SUB

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890606-96 buglist4.50
 Last Modified:  9-JUL-1990    ArticleIdent: Q45688

 A compiler error message, "Internal error near 361F," occurs when the
 code below is compiled with the BC.EXE that comes with QuickBASIC
 version 4.50.

 This problem does NOT occur in the QuickBASIC 4.50 environment, in
 QuickBASIC Compiler versions 4.00 or 4.00b, in BASIC Compiler versions
 6.00 or 6.00b, or in BASIC Professional Development System (PDS)
 version 7.00.

 The code example below will cause an "Internal error near 361F" with
 BC.EXE in QuickBASIC 4.50. The problem seems to stem from the
 complicated integer computation.

 To work around this problem, use a temporary variable for part of the
 calculation.

 Microsoft has confirmed this to be a problem in QuickBASIC version
 4.50. Microsoft is researching this problem and will post new
 information here as it becomes available.

 The following is a code example:

 SUB test (i0%, i1%, i2%, i3%)       '4 integer parameters necessary
 'Work-around: use temporary variable:
 ' temp% = i3% \ i2%
 ' i1% = i1% + temp% + 1
 i1% = i1% + i3% \ i2% + 1           'remove any operation fixes
 i3% = 1                             'this line is necessary
 END SUB


 689. QB 4.50 Help Incorrectly Displays Context Strings As Titles

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QuickC S_QuickPas
 Last Modified: 19-JUN-1989    ArticleIdent: Q45837

 When using the HELPMAKE utility to create new help screens for
 QuickBASIC Version 4.50, you must use the ":n" command to force the
 help screen titles to display correctly. If the context string is used
 as the title, the first character of the title will not be printed.

 There are two methods for specifying a help screen title for
 customized help screens. Both are valid and work correctly in Quick
 Pascal 1.00 and later and QuickC 2.00 and later. However, QuickBASIC
 4.50's help system is slightly older and does not correctly display
 titles that result from the first method. The two methods are as
 follows:

 1. Method 1: Using the context string as a title

    .context MyHelpContext
    :l13

    This method results in a help screen that is 13 lines long, with a
    title that reads as follows:

                    HELP: MyHelpContext

    QuickBASIC incorrectly displays the following:

                    HELP: yHelpContext

 2. Method 2: Using the ":n" Command to specify a separate title

    .context MyFirstHelpContext
    .context MySecondHelpContext
    .context MyThirdHelpContext
    :l13
    :n MyHelpContext

    This method displays the "HELP: MyHelpContext" screen whenever the
    user requests information regarding any of the three help contexts
    listed just above the ":l" command. This is always displayed
    correctly by QuickBASIC (decoding QB45QCK.HLP shows that this is
    the method that the original programmers always used for
    QuickBASIC).

 There is no way to work around this problem, other than to use the
 ":n" command to specify the title. The actual search mechanism
 interprets the line correctly (as a context), so it is not possible to
 alter the context string (by padding an extra character, for example)
 and still have the help file work properly.


 690. QuickBASIC Can Corrupt COMSPEC under PC-DOS 3.30, Maybe Hang

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50
 Last Modified: 26-JUN-1989    ArticleIdent: Q45891

 Under certain circumstances, it is possible for the DOS COMSPEC
 variable to become corrupted, and consequently, the system may hang.
 The circumstances vary among different versions of DOS. For example,
 it has been reported and confirmed to be a problem with PC-DOS Version
 3.30. That is, the problem does not occur (under these circumstances)
 in other versions of PC-DOS or even MS-DOS.

 Microsoft has confirmed this to be a problem with Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler Versions
 6.00 and 6.00b. We are researching this problem and will post new
 information as it becomes available.

 The steps required to make the program below corrupt the COMSPEC
 variable are as follows:

 1. Compile and LINK the example into an .EXE using QuickBASIC Version
    4.50.

 2. Reboot with PC-DOS Version 3.30.

 3. Execute the .EXE version of program.

 4. Set an environment variable at the DOS prompt (e.g. SET FOO=A:NEWCOM).

 5. Enter the QuickBASIC editor.

 6. Immediately exit the editor, and the following message will appear:

       "Insert disk with newcom in drive A
        and strike any key when ready"

 This error can also be achieved by POKEing a 7 into 9F86:0008, the
 address assigned in the offending statement.

 Code Example
 ------------

 CALL TEST

 ' MakeSound IS NOT CALLED; ONLY REQUIRED TO FORCE StringArr
 ' IN SUB Test TO BE ALLOCATED AT THE PROPER ADDRESS (9F86:0000).
 SUB MakeSound
    SOUND 880, 10
 END SUB

 SUB Test
       ' IntArr IS ONLY DECLARED TO INSURE THAT StringArr IS
       ' ALLOCATED
       ' AT THE PROPER ADDRESS
    DIM IntArr(0 TO 794) AS INTEGER
    DIM StringArr(0 TO 4) AS STRING * 13  'Address 9F86:0000

       ' THIS IS THE OFFENDING STATEMENT -- can be any character
    MID$(StringArr(0), 9, 1) = CHR$(7)    'Address 9F86:0008

       ' StringArr ADDRESS IS PRINTED OUT FOR DIAGNOSTIC PURPOSES.
    PRINT "StringArr ADDRESS = " HEX$(VARSEG(StringArr(0))) ":" _
                                 HEX$(VARPTR(StringArr(0)))
 END SUB

 Additional reference words: SR# S890511-152 B_BasicCom


 691. CALL BYVAL "Parameter Type Mismatch" After DECLARE AS ANY

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890512-58 B_BasicCom buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q45892

 Using the CALL subprogramname (BYVAL variable) method of calling an
 external (non-BASIC) routine, where the parameter is specified AS ANY
 in the DECLARE statement, correctly causes a "Parameter Type Mismatch"
 at compile time.

 To avoid this error, you must add BYVAL and specify the exact type
 (instead of using AS ANY) in the DECLARE statement, and you must not
 use BYVAL in the CALL statement. This information applies to Microsoft
 QuickBASIC Versions 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00.

 Note that the "Parameter Type Mismatch" error fails to be flagged in
 the QuickBASIC Version 4.50 environment when the external routine is
 in a Quick Library. Microsoft has confirmed this to be a problem in
 QuickBASIC Version 4.50. We are researching this problem and will post
 new information here as it becomes available. QuickBASIC Versions 4.00
 and 4.00b correctly flag the error.

 The following is taken from the DECLARE statement documentation in the
 BASIC language reference manuals for QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and BASIC compiler Versions 6.00 and 6.00b:

    You cannot use ANY [in the DECLARE statement] with arguments
    passed by value.

 Code Example
 ------------

 The following code sample should correctly cause a "Parameter Type
 Mismatch" error on the CALL statement at compile time (where test is
 an external SUB):

    DECLARE SUB test (variable AS ANY)
    i%=10
    CALL test(BYVAL i%)

 The following is the correct method to pass by value to the external
 procedure:

    DECLARE SUB test (BYVAL variable AS INTEGER)
    i%=10
    CALL test(i%)


 692. QuickBASIC 4.50 Conflict with Tornado Notes TSR Software

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890606-70
 Last Modified: 22-JUN-1989    ArticleIdent: Q45895

 It has been reported that QuickBASIC Version 4.50 has a conflict with
 the TSR software "Tornado Notes." The reported conflict is a complete
 system lockup (hang), requiring a cold boot.

 This apparently was not a problem with QuickBASIC Version 3.00 or
 4.00. The version of Tornado Notes was not listed, but has a Copyright
 of 1986.

 Microsoft does not support running QuickBASIC with this TSR program
 and varying problems may occur.


 693. How to Make QuickBASIC 4.50 Recognize Custom Help Files

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QuickC S_QuickPas S_UTILity
 Last Modified: 29-DEC-1989    ArticleIdent: Q45897

 You can use the HELPMAKE.EXE utility that is included with QuickC
 Version 2.00 and Quick Pascal Version 1.00 to make customized Help
 files for QuickBASIC Version 4.50. However, QuickBASIC 4.50 does not
 acknowledge the "HELPFILES" environment setting. The only Help file
 that it acknowledges is QB45QCK.HLP. How you implement support for
 your customized Help files depends upon whether you want to replace
 QuickBASIC's original Help file or merely to supplement it.

 This information applies to QuickBASIC Version 4.50.

 Microsoft BASIC PDS Version 7.00 includes the HELPMAKE.EXE utility. To
 use HELPMAKE.EXE with QBX.EXE 7.00, see Chapter 22 of the "Microsoft
 BASIC 7.0: Programmer's Guide" for Microsoft BASIC PDS Version 7.00.

 If you want to replace QuickBASIC's Help file, rename your customized
 Help file as QB45QCK.HLP and place it in the directory with QB.EXE.
 You can now access your own customized contexts but have no access to
 the original Help screens for QuickBASIC.

 If you want to supplement QuickBASIC's Help file, do the following:

 1. Use HELPMAKE to decode QuickBASIC's QB45QCK.HLP as follows:

       HELPMAKE /D /OQB45QCK.TXT QB45QCK.HLP

    (Note: There is no space when using HELPMAKE's /Odestfile switch,
    which specifies the output destination filename.)

 2. Load QB45QCK.TXT into a text editor or word processor.

 3. Append the source for your customized contexts to the end of
    QB45QCK.HLP.

 4. Save the file under the name QB45QCK.TXT.

 5. Rename QB45QCK.HLP to QB45QCK.OLD.

 6. Use HELPMAKE to encode the new Help file, as follows:

       HELPMAKE /A: /E /OQB45QCK.HLP QB45QCK.TXT

    (Note: The /A: switch specifies a colon (:) to be the control
    character to mark lines containing special control information
    for use by the QB.EXE application's Help system.)

 You can now access your customized Help contexts, in addition to the
 original contents of the Help screens, with QuickBASIC's Help system.

 For more information about running HELPMAKE, please refer to Chapter 8
 of the "Microsoft QuickC Tool Kit" manual for Version 2.0.


 694. No Extended ASCII in SCREEN 4 on Olivetti/AT&T 6300

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890606-97
 Last Modified: 22-JUN-1989    ArticleIdent: Q45906

 It has been reported that when using QuickBASIC Version 4.00b or 4.50,
 characters in the extended ASCII character set (codes 128 to 255) are
 not visible in SCREEN 4 on an AT&T 6300. However, the extended
 characters are visible in SCREEN 0 (text mode).

 This may be a hardware limitation. Microsoft is researching this
 problem and will post new information as it becomes available.

 Code Example
 ------------

 The following code example displays blanks in SCREEN 4, but displays
 the correct extended characters in SCREEN 0:

 SCREEN 4     'works for SCREEN 0
 FOR i%=128 TO 255
    PRINT CHR$(i%)
 NEXT i%


 695. QuickBASIC's Hierarchy of Operations

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890605-156 B_BasicCom B_GWBasicI
 Last Modified: 27-DEC-1989    ArticleIdent: Q45907

 The following information on "Hierarchy of Operations" was taken from
 Pages 45-46 of the "Microsoft QuickBASIC 4.0: BASIC Language
 Reference" manual for Versions 4.00 and 4.00b. This information also
 applies to the following products:

 1. Microsoft GW-BASIC Versions 3.20, 3.22, and 3.23

 2. QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00,
    4.00b, and 4.50

 3. Microsoft BASIC Compiler Versions 5.35, 5.36, 6.00, and 6.00b

 4. Microsoft BASIC PDS Version 7.00.

 The BASIC operators have an order of precedence, that is, when several
 operations take place within the same program statement (without being
 grouped by parentheses), some operations are executed before others.
 Operations are executed in the following order:

 1. Arithmetic operations

    a. Exponential (^)

    b. Negation (-)

    c. Multiplication and division (*, /)

    d. Integer division (\)

    e. Modula arithmetic (MOD)

    f. Addition and subtraction (+, -)

 2. Relational operations (=, >, <, <>, <=, >=)

 3. Logical operations

    a. NOT

    b. AND

    c. OR

    d. XOR

    e. EQV

    f. IMP

 An exception to the order of operations listed above occurs when an
 expression has adjacent exponentiation and negation operators. In this
 case, the negation is done first. For example, the following statement
 prints the value .0625 (equivalent to 4^-2), not -16 (equivalent to
 -(4^2)):

    PRINT 4 ^ -2

 If operators on the same precedence level appear in the same
 expression, they are computed from left to right.

 For more information on the "Hierarchy of Operations," consult the
 BASIC language reference manual for your version of BASIC.


 696. QuickBASIC Cannot RUN or CHAIN to Batch Files; Use SHELL

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890612-57 B_BasicCom B_GWBasicI
 Last Modified: 13-DEC-1989    ArticleIdent: Q45908

 Batch (.BAT) files can be executed only from a BASIC program SHELL
 statement. The RUN and CHAIN statement cannot be used to execute a
 batch file.

 This information applies to the following BASIC products:

 1. Microsoft GW-BASIC Versions 3.20, 3.22, and 3.23

 2. QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00,
    4.00b, and 4.50

 3. Microsoft BASIC Compiler Versions 6.00, and 6.00b for MS-DOS and
    MS OS/2.

 4. Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 The SHELL statement can be used to execute a .COM, .EXE, or .BAT file,
 or almost any MS-DOS command, and then return to the original BASIC
 program. However, the SHELL statement cannot pass any information or
 variables to the program or statement it is executing.

 The statement or program being executed from the SHELL statement is
 being executed as a "child" process of BASIC. The BASIC program is
 exited (but remains in memory), the command string is executed, and
 then control is returned to the BASIC program. Two methods can be used
 to pass information down to a batch file:

 1. Write the information to a file and have the batch file access the
    file for the necessary information.

 2. Set a special environment variable with ENVIRON that can be read
    by the batch file.

 The RUN and CHAIN statements expect to RUN or CHAIN to a program that
 has an extension of .BAS or .EXE, depending on whether the program is
 being executed within the QB.EXE or QBX.EXE environment or as a compiled
 application.

 For more information, consult the BASIC language reference manual
 included with your BASIC package.


 697. Example of How to Use 1- and 2-Byte Return Codes from INKEY$

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890606-37 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q45909

 The following information applies to QuickBASIC Versions 3.00, 4.00,
 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b,
 and to Microsoft PDS Version 7.00. The Version 4.50 QuickBASIC Advisor
 and the BASIC PDS 7.00 Microsoft Advisor on-line Help system state the
 following:

    The INKEY$ function returns a 1- or 2-byte string containing a
    character read from the standard input device. A null string is
    returned if no character is waiting there. A 1-character string
    contains the actual character read from the keyboard, while a
    2-character string indicates an extended code, the first character
    of which is hexadecimal 00.

 When two bytes are received from an extended key, the second character
 of the string is the scan code associated with the extended key. The
 chart in the Version 4.50 QuickBASIC Advisor and Microsoft Advisor
 on-line Help system for BASIC PDS 7.00 contains the scan code listing.
 The extended keys include the function keys, arrow keys, HOME, PGUP,
 END, PGDN, and SHIFT+TAB keys.

 The following program example demonstrates how to use the INKEY$
 function to return either a 1-byte character or 2-byte extended code.
 The length, ASCII representation, and the numeric representation for
 each key that is pressed are displayed. In addition, the arrow keys
 and the SHIFT+TAB key combination are trapped for 2-byte returns, and
 the ESC, TAB, and SPACEBAR are trapped for 1-byte returns.

 Code Example
 ------------

 'SCAN CODES to be used with a 2-byte return code from INKEY$
 CONST left = &H4B
 CONST right = &H4D
 CONST up = &H48
 CONST down = &H50
 CONST tabscan = 15

 'ASCII CODES  to be used with a 1-byte return from INKEY$
 CONST escape = 27
 CONST tabchar = 9
 CONST space = 32

 DO UNTIL UCASE$(t$) = "Q"  'PROGRAM ENDS WHEN 'Q' OR 'q' IS ENTERED
  CLS
  LOCATE 23, 35
  PRINT "Q to quit"
  t$ = INKEY$
  IF t$<>"" THEN
   LOCATE 10, 1
   length% = LEN(t$)
   PRINT "length "; length%
   PRINT "ASCII representation "; t$
   PRINT "numeric representation ";
   SELECT CASE length%
          CASE 2
            FOR i = 1 TO 2
              PRINT ASC(MID$(t$, i, 1)); " ";
            NEXT i
                  SELECT CASE ASC(RIGHT$(t$, 1))
                          CASE up
                           PRINT "up           "
                          CASE down
                           PRINT "down         "
                          CASE left
                           PRINT "left         "
                          CASE right
                           PRINT "right        "
                          CASE tabscan
                           PRINT "Shift tab"
                  END SELECT
          CASE 1
            PRINT ASC(t$);
            SELECT CASE ASC(LEFT$(t$, 1))
                  CASE escape
                    PRINT "escape       "
                  CASE tabchar
                    PRINT "tab character"
                  CASE space
                    PRINT "space        "
            END SELECT
          CASE ELSE
            PRINT "                    "
   END SELECT
  END IF
 LOOP
 END


 698. Failure to Trap Event Compiled BC /w; Needs Line Label or /v

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890613-138 B_BasicCom
 Last Modified: 29-DEC-1989    ArticleIdent: Q45948

 The /w compiler option produces smaller EXE files, but event checking
 is done much less frequently than if /v is used.

 In programs without line labels or line numbers, event trapping
 requires the /v (check between statements) compiler option. In
 programs compiled with the /v option, events are checked before every
 statement.

 If your program is compiled with the /w option, events are checked
 only when a labeled or numbered line is encountered at run time. As a
 result, if compiled with the /w switch, your program will never trap
 an event if it doesn't pass through a statement that has a label or
 line number.

 This information applies to all ON Event GOSUB statements [where Event
 can be COM(n), KEY(n), PEN, PLAY(n), STRIG(n), or TIMER(n)] for event
 trapping in Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2; and Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2. In QuickBASIC 4.00b and
 later, BASIC compiler 6.00 and 6.00b, and BASIC PDS 7.00, the ON
 UEVENT GOSUB and CALL SetUEvent statements were added for user-defined
 event trapping.

 Code Sample
 -----------

 The following code sample, which requires QuickBASIC 4.00b or later,
 or BASIC compiler 6.00 or later, will not trap the user-defined event
 if compiled with the /w option. To trap the event, either use the /v
 option or place a line label in the idle loop as shown.

 ON UEVENT GOSUB handle:
 UEVENT ON
 WHILE i$ <> CHR$(27)      'Press escape to exit
   IF i$ = " " THEN        'Press space to cause UEVENT
 'linelabel:         'Remove comment at start of line for /w to trap
     CALL SetUEvent
   END IF
   i$ = INKEY$
 WEND
 END

 handle: PRINT "ON UEVENT"
 RETURN

 Note that the command-line compiler has a different name in different
 versions, as shown.

 QuickBASIC Versions 4.x and BASIC compiler 6.00 and 6.00b and BASIC
 PDS 7.00 compile with BC.EXE, as follows:

    BC test/V

 QuickBASIC Versions 2.x and 3.00 compile with QB.EXE, as follows:

    QB test/V;

 QuickBASIC Versions 1.x compile with BASCOM.EXE, as follows:

    BASCOM test/V;


 699. Function to Round Floating Point to Specified Decimal Places

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890620-96 B_BasicCom B_MQuickB B_GWBasicI B_BasicInt
 Last Modified: 10-AUG-1990    ArticleIdent: Q46069

 There is no function built into BASIC to round a floating-point
 variable to a specified number of decimal places and store the new
 value in a floating-point variable.

 Below are two examples of functions that round the value stored in the
 variable through the use of integer rounding and reassignment to
 floating point. Note that the number of digits accepted by these
 functions is limited by the integer (or long integer) format.

 Please also note that many floating-point decimal-notation numbers
 cannot be represented exactly in the binary format used for internal
 storage (IEEE or MBF, depending upon the BASIC version), and you may
 notice a variation from the expected result at the limits of single or
 double precision. For example, where you expect 2.0, BASIC might PRINT
 1.9999999, even after using the rounding function code examples
 provided below.

 The following numeric formats store numbers exactly: Decimal math
 packages (BCD), and CURRENCY, INTEGER, and LONG integer data types.

 Alternative Methods for Rounding Floating-Point Variables
 ---------------------------------------------------------

 Note that BASIC's PRINT USING statement rounds displayed values to any
 decimal place, but does not change the actual value stored in the
 variable. Also, the PRINT #n USING statement can output rounded values
 as ASCII strings to a disk file, but can't change the values stored in
 the floating-point variable.

 For great accuracy in financial calculations (or other calculations
 that require a fixed number of decimal places), Microsoft recommends
 using the CURRENCY data type introduced in BASIC PDS 7.00 and 7.10.
 The CURRENCY data type is very fast and gives decimal math accurate to
 19 digits, with four digits to the right of the decimal point.

 You may also use LONG integers (stored in number of cents) so that all
 calculations are performed using whole numbers. LONG integers are
 supported in QuickBASIC versions 4.00, 4.00b, and 4.50 for MS-DOS, in
 Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, in Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS and MS OS/2, and in QuickBASIC
 version 1.00 for Apple Macintosh. (Note that in the Macintosh versions
 of BASIC and QuickBASIC, Microsoft recommends the decimal math (d)
 version rather than the binary math (b) version for the best accuracy
 for floating-point numbers.)

 Another alternative is to store and manipulate floating-point numbers
 entirely as ASCII strings stored in string variables, but this is a
 low-speed alternative.

 As another alternative, BASIC PDS 7.00 and 7.10 introduce the add-on
 library FORMATx$ functions (FormatI$, FormatL$, FormatS$, FormatD$,
 FormatC$), which take a number and return a formatted string.

 Code Example 1
 --------------

 The Round# FUNCTION below is designed for QuickBASIC versions 4.00,
 4.00b, and 4.50 for MS-DOS, BASIC compiler versions 6.00 and 6.00b for
 MS-DOS and OS/2, and BASIC PDS versions 7.00 and 7.10 for MS-DOS and
 MS OS/2. (You can convert this FUNCTION procedure to a SUBprogram
 procedure for use in QuickBASIC for Macintosh, which doesn't support
 the FUNCTION statement but does support LONG integers.)

 This FUNCTION rounds to the specified significant digits. For example,
 the program below rounds "3.12345" to 4 decimals as "3.1235":

    DECLARE FUNCTION Round# (x#, n%)
    PRINT Round#(3.12345#, 4)
    '
    ' Round# rounds x# to n% decimal places.
    ' Single or Double can be passed.
    '
    ' WARNING: This FUNCTION is limited by the shifted number
    '          x# * (10^n%)  <  2,147,483,647 (maximum LONG)
    '
    FUNCTION Round# (x#, n%)
      temp&  = x# * (10 ^ (n%))     'Shift the number; store in LONG
      Round# = temp& / (10 ^ (n%))  'Shift number back
    END FUNCTION

 Code Example 2
 --------------

 A similar DEF FN function is as follows for other BASICs that do not
 support LONG integers or FUNCTION procedures:

    10 DEF FNRound(x!,n%) = (CINT(x! * (10^n%))) / (10^n%)
    20 x! = 3.4567
    30 n% = 3
    40 PRINT FNRound(x!, n%)  ' Prints 3.457

 Warning: This function is limited by the following shifted number:

    x! * (10^n%) < 32767 (maximum short integer)

 This DEF FN function can be used in the following products:

 1. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23 for
    MS-DOS

 2. Microsoft QuickBASIC Compiler versions 1.00, 1.01, 1.02, 2.00,
    2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS

 3. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS

 4. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 5. Microsoft BASIC PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2

 6. Microsoft QuickBASIC version 1.00 for Apple Macintosh

 7. Microsoft BASIC Compiler version 1.00 for Apple Macintosh

 8. Microsoft BASIC Interpreter versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for Apple Macintosh


 700. STATIC FUNCTION Fails to Retain Value Between Invocations

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q46180

 A function that has been declared with the STATIC attribute should
 retain its value between calls. When a STATIC function is called and
 assigned a value, subsequent calls to the function that do not assign
 a new value to the function should always return the previous value,
 even if you leave the function with an EXIT FUNCTION statement. This
 behavior is correctly exhibited by programs compiled with BC.EXE.

 However, when you attempt the same procedure in the QB.EXE or QBX.EXE
 environment, a STATIC FUNCTION fails to retain its value in multiple
 invocations, and incorrectly returns a 0 (zero) or null string,
 depending on the type of the function.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; in the QB.EXE
 environment of Microsoft BASIC Compiler versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b); and in the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 (buglist7.00, buglist7.10). We are researching this problem
 and will post new information here as it becomes available.

 The following sample program demonstrates the problem:

    x% = staticfun%(1)
    PRINT x%   ' Should print 5.
    x% = staticfun%(0)
    PRINT x%   ' Should print 5.
    END

    FUNCTION staticfun%(parm%) STATIC
      IF parm% = 0 THEN
        EXIT FUNCTION
      ELSE
        staticfun% = 5
      END IF
    END FUNCTION

 When this program is compiled with BC.EXE, it correctly prints the
 values 5 and 5. From inside the QuickBASIC QB.EXE or QBX.EXE
 environment, it incorrectly prints 5 and 0.


 701. ON TIMER Can Wrongly Trigger CALL SETUEVENT, ON UEVENT Trap

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50 SR# S890614-84 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q46182

 You cannot use the UEVENT and TIMER event trapping simultaneously.
 After CALL SETUEVENT is invoked just once, each subsequent timer event
 from the ON TIMER statement improperly activates the user-defined
 event (UEVENT) trap.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00b and 4.50, and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00, buglist6.00b). This problem was corrected in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2 (fixlist7.00).

 SETUEVENT improperly activates at the same frequency as the ON TIMER
 event. This behavior continues to occur until the TIMER OFF statement
 is used. The problem occurs both in a compiled .EXE program and in the
 QB.EXE environment. SETUEVENT can be called from another language or
 from the BASIC program itself to reproduce the problem.

 The problem does not apply to QuickBASIC Version 4.00 and earlier
 versions because they don't support user-defined event trapping (ON
 UEVENT GOSUB and CALL SETUEVENT).

 The following sample code demonstrates the problem in a compiled .EXE
 program or in the QB.EXE environment:

 ' Turn the timer and uevent on:
 TIMER ON
 UEVENT ON

 ' Set up the handler routines for events:
 ON UEVENT GOSUB ueventhandler
 ON TIMER(1) GOSUB timerhandler   ' Timer event occurs every 1 second.

 'Invoke a user-defined event just once:
 CALL setuevent
 PRINT "Press any key to end."
 WHILE INKEY$ = ""
 WEND
 END

 ueventhandler:
   PRINT "This uevent should only occur once."
   RETURN

 timerhandler:
   PRINT "A timer event occurred."
   ' TIMER OFF   'Add this line to work around the problem.
   RETURN

 Related Problem
 ---------------

 In the QB.EXE environment, simply stopping the execution of the
 program and commenting out the ON TIMER statement fails to stop the
 activation of the SETUEVENT event during subsequent program runs. For
 more information on this separate QB.EXE environment problem, query on
 the following words:

    SETUEVENT and buglist4.50


 702. Search/Change "Match Not Found" If Previous Search/Label

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 B_BasicCom SR# S890616-7
 Last Modified: 26-FEB-1990    ArticleIdent: Q46183

 In the QuickBASIC Version 4.50 environment, if you attempt to perform
 a Search/Change after previously performing a Search/Label, then a
 "Match Not Found" message or similar message may display. If the
 Search/Change is performed first, it functions correctly.

 Microsoft has confirmed this to be a problem in the QB.EXE editor in
 Microsoft QuickBASIC Version 4.50. This problem was corrected in the
 QuickBASIC Extended (QBX.EXE) environment of Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 (fixlist7.00).

 When using the Label command on the Search menu, the Change command
 doesn't function correctly until another option is chosen from that
 menu. The Change command appears to work in all situations except
 after the Label command has been invoked.

 This problem is associated only with the QuickBASIC Version 4.50
 environment and does not occur in earlier versions.

 To reproduce the problem, do the following:

 1. Enter the following lines of code:

       LPRINT "Hello"
       LPRINT "GoodBye"
       label1:
       LPRINT "The end"

 2. Choose Label from the Search menu and find the label "label1".

 3. Choose Change from the Search menu and find LPRINT and change it
    to PRINT. The message "No Match Found" is displayed.


 703. How to Pipe ( | ) Input into a QuickBASIC Program

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890621-89 B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q46376

 It is possible to use DOS redirection to pipe output from a program
 into a QuickBASIC program. To do this, the QuickBASIC program must
 CALL INTERRUPT 21 Hex, with function 3F Hex, to get the input from the
 DOS device CON.

 This information applies to Microsoft QuickBASIC Versions 3.00, 4.00,
 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00
 and 6.00b for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS.

 DOS redirection is a feature of DOS Versions 2.00 and later. It allows
 you to take the output that would normally go to a device like the
 terminal's screen and redirect or "pipe" the output into another
 program. The program on the receiving end then takes the input and
 processes or "filters" the input. This is why these programs are often
 called "filters." The syntax for the DOS pipe command is the
 following:

    DOS-PROMPT> p1 | p2

 In this command, p1 is the program performing the output, | is called
 the pipe symbol, and p2 is the program performing the input or
 filtering. An example of a common use for this feature of DOS is as
 follows:

    DOS-PROMPT> dir | sort

 The "dir" command gives a listing of the current directory, which is
 piped into the DOS "sort" program. Sort then filters the input and
 displays the directory listing in sorted order.

 However, the output from p1, the first program, can be piped into a
 QuickBASIC program as well. The QuickBASIC program can then read the
 input from the DOS device CON. This is possible because DOS stores the
 output from the first program in a temporary file. The QuickBASIC
 program can then CALL INTERRUPT 21H function 3FH to retrieve the
 input. This function inputs a specific number of bytes from a file or
 device, such as the CON device.

 Interrupt 21 Hex, with function 3F hex, requires five register
 parameters to be passed:

    AH = The function number, 3F Hex.
    BX = Handle to the file or device.
    CX = The number of bytes to read.
    DS = Segment of the buffer area. The buffer will be a string.
    DX = Offset of the buffer area.

 For more detailed information on INTERRUPT 21 Hex and function 3F Hex,
 redirection, and filters, consult "Advanced MS-DOS Programming" by Ray
 Duncan, published by Microsoft Press, copyright 1988.

 For more information on using the QuickBASIC CALL INTERRUPT, search on
 the following word:

    QB4INT

 Note: You can pipe information into a QuickBASIC program, but it is
 more difficult to pipe information from a QuickBASIC program to
 another program. QuickBASIC usually does not output information
 through DOS services but accesses the hardware directly. The PRINT
 statement, for example, displays text directly to video memory, not to
 the DOS CON device. To direct output from a BASIC program to CON, you
 must either OPEN the BASIC device "CONS" (with no colon) for output as
 a file and PRINT#n all information to that file number (#n), or use
 INTERRUPT 21 Hex, with function 40 Hex, to output to the CON device.
 This output could be piped into another program.

 Code Example
 ------------

 '***********************************************************
 '* This program calls the DOS INTerrupt 21H function 3FH   *
 '*  in order to read any input that has been redirected    *
 '*  to it with the | operator from DOS. It then echoes the *
 '*  input to the screen, and filters out any extra Line    *
 '*  Feed characters.                                       *
 '***********************************************************

 REM $INCLUDE: 'qb.bi'
 ' For BC.EXE and QBX.EXE for BASIC 7.00 use the include file 'QBX.BI'

 DIM inregs AS RegTypeX, outregs AS RegTypeX

 REM $DYNAMIC
 DIM tempvar(10) AS STRING * 10
 'NOTE: The length of the string and the number of bytes read
 '      (inregs.cx) should be the same.

 DO
      ' Set up the parameters for the CALL INTERRUPTX
      inregs.ax = &H3F00  ' AH gets the functions number.
      inregs.bx = 0       ' The is the handle to the CON device is 0.
      inregs.cx = 10      ' Request to read 10 characters at a time.
      inregs.ds = VARSEG(tempvar(1)) ' Segment of the buffer area.
      inregs.dx = VARPTR(tempvar(1)) ' Offset of the buffer area.

      'INT 21H function 3FH to read a file or device.
      CALL INTERRUPTX(&H21, inregs, outregs)

      'The number of bytes actually read is returned in AX.
      'We requested 10, so if it reads fewer, then we are done.
      IF outregs.ax < 10 THEN EXIT DO

      ' Filter the string returned
      FOR i = 1 TO LEN(tempvar(1))
        a$ = MID$(tempvar(1), i, 1)
       ' DOS puts a line feed (LF) after its carriage return.
       ' We want to avoid this, because the PRINT will add an
       ' extra carriage return after this line feed.

        IF NOT (a$ = CHR$(10)) THEN
       PRINT a$;
        END IF
     NEXT
 LOOP
 END


 704. VARPTR(#filenumber) Not Supported in QB 4.x or BC 6.00, 7.00

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q46720

 Instead of passing the file number (#n) to the VARPTR function for a
 random access file, you may use VARPTR to take the address of the
 first variable defined in the FIELD statement to return the address of
 the FIELD buffer.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 In QuickBASIC Versions 2.00, 2.01, and 3.00, the VARPTR function can
 be passed the file number (#n) of a previously OPENed file. For
 sequential access files, VARPTR(#n) then returns the starting address
 of the disk I/O buffer assigned to that file number. For random access
 files, VARPTR(#n) returns the address of the FIELD buffer assigned to
 that file number.

 In QuickBASIC Versions 4.00, 4.00b, and 4.50 (and in the BASIC
 compiler Versions 6.00 and 6.00b and BASIC PDS 7.00), you cannot use
 VARPTR with a file number (#n) as an argument. This feature has been
 eliminated. You can now use the FILEATTR function, which returns the
 BASIC access mode and the DOS file handle, which may be useful for DOS
 file interrupts.


 705. BC.EXE "Cannot Generate Listing for BASIC Binary Source Files"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890628-52 B_BasicCom
 Last Modified: 30-MAY-1990    ArticleIdent: Q46816

 When compiling with BC.EXE in Microsoft QuickBASIC version 4.00,
 4.00b, or 4.50 or in Microsoft BASIC Compiler 6.00 or 6.00b, or
 Microsoft BASIC Professional Development System (PDS) version 7.00,
 the error "Cannot generate listing for BASIC binary source files" can
 occur when creating a listing file.

 This error occurs when the source file is saved in Fast Load and Save
 format. To create the listing file, the program must be saved in Text
 format.

 The error "Binary source file" occurs if you are trying to compile a
 binary file with Microsoft BASIC PDS 7.00 using the /Zi switch.

 To save the file as text, do the following in the QB.EXE or QBX.EXE
 editor:

 1. From the File menu, choose Save As.

 2. Tab down to the <Text> box.

 3. Press SPACEBAR.

 4. Press ENTER and the file will be saved as text.


 706. Getting High-Intensity Background Color in SCREEN 0

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q46817

 To print text with a high-intensity background, you must meet the
 following requirements:

 1. Be in SCREEN 0 (text mode)
 2. Operate on a machine with an EGA, VGA, or MCGA graphics adapter

 To get a high-intensity background, use ROM BIOS interrupt 10 Hex,
 with function 10 Hex and subfunction 3 Hex, to set the third bit in
 the Attribute Controller's Mode Control Register. This disables
 blinking and enables high intensity. Once this is done, you can print
 characters to the screen through the BIOS, using BIOS interrupt 10 Hex
 with function 9 Hex. In this way, a background color that had
 previously been blinking is now in high intensity.

 For information on controlling background color in screen modes other
 than SCREEN 0, query in this Knowledge Base on the word S9COLOR. This
 query locates an article about using foreground colors to emulate
 background colors.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS.

 For a detailed discussion of the Attribute Controller and BIOS
 interrupts, please refer to the following sources:

 1. "Programmer's Guide to the EGA and VGA Cards" by Richard F.
    Ferraro.

 2. "Programmer's Guide to PC and PS/2 Video Systems" by Richard
    Wilton, published by Microsoft Press (1987). See especially Pages
    53-54 and 466-472.

 The following program demonstrates printing with a high-intensity
 background color; it operates in SCREEN 0 on machines equipped with an
 EGA, VGA, or MCGA graphics card:

 ' $INCLUDE: 'QB.BI'
 ' For BC.EXE and QBX.EXE for BASIC 7.00/7.10 use include file 'QBX.BI'

 'DIM InReg as RegType, OutReg as RegType

 CLS
 COLOR 15,13
 PRINT "Before the call to the interrupt"
 PRINT "CCCCCCCC"

 InReg.ax = &H943                   'Call BIOS interrupt to
 InReg.bx = &HDF                    'display characters
 InReg.cx = &H8
 CALL Interrupt(&H10, InReg, OutReg)

 LOCATE 4, 1
 INPUT "Press ENTER to change to high intensity..."; a$

 InReg.ax = &H1003                  'Call BIOS interrupt to
 InReg.bx = 0                       'enable high intensity
 CALL Interrupt(&H10, InReg, OutReg)

 PRINT "After the call to the interrupt"
 PRINT "CCCCCCCC"

 InReg.ax = &H943                   'Call interrupt to print
 InReg.bx = &HDF                    'characters again. Both
 InReg.cx = &H8                     'the BIOS-printed sets of
 CALL interrupt(&H10, InReg,OutReg) 'characters will have a
                                    'high-intensity background.
 END


 707. QuickC 2.00 Routines Using malloc() Fail in QB Quick Library

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 S_QuickC B_BasicCom SR# S900118-96
 Last Modified:  8-FEB-1990    ArticleIdent: Q57923

 Microsoft QuickC Version 2.00 routines that attempt memory allocation
 [with malloc()] do not allocate any memory when used in a Quick
 library in the QuickBASIC environment. If the pointers are then
 referenced in the C routine, the following error message halts the
 program and returns to DOS:

    run-time error R6013 - illegal far pointer use

 Microsoft has confirmed this to be a problem in Microsoft QuickC
 Version 2.00 (buglist2.00), in the QB.EXE editor in Microsoft
 QuickBASIC Version 4.50, and in the QBX.EXE (QuickBASIC Extended)
 editor in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 (buglist7.00). We are researching this problem and will
 post new information here as it becomes available.

 C routines that use malloc() to allocate memory work correctly when
 linked with compiled BASIC programs. Furthermore, these routines work
 correctly in Quick libraries when compiled with C Compiler Version
 5.00 and 5.10.

 The following code example causes the above error (R6013) in the
 QuickBASIC environment. The code is the SETMEM example from the
 QuickBASIC QB Advisor online Help system, with one line added to
 reference the pointer.

 Code Example
 ------------

 The example below uses the SETMEM function to free memory for a C
 function that uses the C routine malloc() to get dynamic memory.

 Note: To run this program, you must separately compile the C function
 and put it in a Quick library. The C function must be compiled using
 the large memory model, so calls to malloc() use the far space freed
 by the BASIC program.

    DECLARE SUB CFunc CDECL (BYVAL X AS INTEGER)
 'Decrease the size of the far heap so CFunc can use malloc
 'to get dynamic memory:
    BeforeCall = SETMEM(-2048)
 'Call the C function:
    CFunc (1024)
 'Return the memory to the far heap; use a larger value so
 'all space goes back into the heap.
    AfterCall = SETMEM(3500)
    IF AfterCall <= BeforeCall THEN PRINT "Memory not reallocated."
    END

 /* Filename: Setmemc.c,  C Function */
 void far cfunc(bytes)
 int bytes;
 {
    char *malloc();
    char *workspace;

    /* Allocate working memory using amount BASIC freed. */
    workspace=malloc((unsigned) bytes);

    /* Working space would be used here. */
    *workspace='X';    // Added line to reference ptr/cause error

    /* Free memory before returning to BASIC. */
    free(workspace);
 }

 The following are the QuickC and C compiler compiling lines for the
 above C code:

    QCL -c -AL setmemc.c ;
    CL -c -AL setmemc.c ;

 To create a Quick library from the C routine, the link line is as
 follows:

    LINK /Q /NOE setmem.c,,,bqlb45.lib;


 708. INKEY$ Example to Work Around ON KEY GOSUB Suspended by INPUT

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890703-77 B_GWBasicI B_BasicCom
 Last Modified: 19-OCT-1990    ArticleIdent: Q46847

 This article includes a sample program demonstrating how to emulate a
 cursor during an INKEY$ loop, and how to trap the ESC, ENTER, and
 BACKSPACE keys using the INKEY$ function. This program allows you to
 enter text into a variable while supporting the option to exit the
 data entry by pressing the ESC key or the ENTER key. The BACKSPACE key
 lets you delete input data in this INKEY$ example.

 You may be motivated to use the INKEY$ function to accept user input
 because ON KEY GOSUB event trapping is suspended during an INPUT or
 LINE INPUT statement or an INPUT$ function. Instead of using ON KEY
 GOSUB event trapping to detect special key presses during input, and
 instead of using INPUT, LINE INPUT, or INPUT$ for your input, you can
 use the INKEY$ function in a continuous loop to process all keys.

 This information applies to the following:

 1. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23 for
    MS-DOS

 2. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for MS-DOS

 3. Microsoft BASIC Compiler versions 6.00, and 6.00b for MS-DOS
    and MS OS/2

 4. Microsoft BASIC PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2

 The trapping of keys using the ON KEY GOSUB statement is temporarily
 suspended while INPUT, INPUT$, or LINE INPUT is pending. If a key
 being trapped by ON KEY GOSUB is pressed while an INPUT, INPUT$, or
 LINE INPUT is pending, the first occurrence of that event is remembered
 but is not executed until you satisfy the INPUT, INPUT$, or LINE
 INPUT. Only one key press for a given ON KEY GOSUB trap is remembered
 while an INPUT, INPUT$, or LINE INPUT is pending.

 As an alternative to using ON KEY GOSUB, and in order to continue
 event trapping during input, you can write a routine to input and
 process one character at a time using the INKEY$ function in a loop.
 Such a program example is shown at the bottom of this article.

 Related Topics
 --------------

 Note: INKEY$ returns a 2-byte STRING for all keys returning an
 extended keyboard KEY code, such as function keys F1 through F10. For
 additional information on this topic, query in this Knowledge Base
 using the following words:

    INKEY$ and EXTENDED and 2-byte codes

 If you want to use both INKEY$ and ON KEY GOSUB trapping in the same
 program, you must take into account an extra required key press, as
 explained in a separate article, which may be found by querying using
 the following words:

    INKEY$ and trap and additional and key and press

 For more information about the ON KEY GOSUB statement's key trapping
 being suspended by INPUT$, INPUT, or LINE INPUT, search for a separate
 article using the following words:

    LINE INPUT and event and suspended

 Code Example
 ------------

 When invoking INKEY$ in a loop, no cursor automatically displays
 (unlike for the INPUT or LINE INPUT statement). The following code
 example demonstrates how to emulate a cursor during an INKEY$ loop and
 also trap the ESC, the ENTER, and the BACKSPACE keys.

 '          INPTCHAR.BAS
 '    Written under QuickBASIC 4.50
 ' Note: Line Labels, DECLARE, SELECT CASE, and SUBprograms are not
 ' supported under GW-BASIC. The program would need to be
 ' rewritten for GW-BASIC; however, the same principles using
 ' INKEY$ apply to GW-BASIC.
 DECLARE SUB Cursor ()
 DECLARE SUB GetKey (a$)
 Col = 1
 Row = 7
 NewCol = 1
 CLS
 PRINT "---------------------------------------------------------"
 PRINT "This program will allow you to enter text into a"
 PRINT "variable while having control to exit the data entry with"
 PRINT "the ESCape key or the ENTER key. The BACKSPACE key is"
 PRINT "functional for editing."
 PRINT "---------------------------------------------------------"
 LOCATE Row, NewCol
 Cursor                   ' Emulate DOS cursor on screen

 DO WHILE NewCol < 81
    LOCATE Row, NewCol
    GetKey a$             ' Get User input
    SELECT CASE ASC(a$)   ' Evaluate the character input from the
                          ' keyboard
       CASE 13, 27        ' Codes for CARRIAGE RETURN and ESCAPE
          GOTO Done
       CASE 8             ' Code for BACKSPACE
          GOSUB Backspace
       CASE ELSE
          WholeLine$ = WholeLine$ + a$
          LOCATE Row, Col
          PRINT WholeLine$;
          Cursor
          NewCol = LEN(WholeLine$) + 1
    END SELECT
 LOOP

 Done:               ' The ESCape key or ENTER key was pressed
    LOCATE Row, Col
    PRINT WholeLine$ + " "
    PRINT
    PRINT "The String you Entered is:  "; WholeLine$
    END

 Backspace:          ' The BACKSPACE key was pressed
    LOCATE Row, LEN(WholeLine$): PRINT "  "
    WholeLine$ = LEFT$(WholeLine$, LEN(WholeLine$) - 1)
    LOCATE Row, Col
    PRINT WholeLine$;
    Cursor
    RETURN

 SUB Cursor
    COLOR 23
    PRINT "Ü"
    COLOR 7
 END SUB

 SUB GetKey (a$)
    DO
       a$ = INKEY$
    LOOP WHILE a$ = ""
 END SUB


 709. TAB Function Documentation Error in QuickBASIC 4.50 Manual

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890627-141 docerr
 Last Modified:  8-DEC-1989    ArticleIdent: Q46848

 The example for the TAB function on Page 369 of the "Microsoft
 QuickBASIC 4.5: BASIC Language Reference" for Version 4.50 is
 incorrect. The output for the first display is in Column 1 when it
 should be in Column 7.

 This is not an error in the following:

 1. The on-line help for the QuickBASIC 4.50 environment

 2. The on-line help for the BASIC PDS 7.00 QuickBASIC Extended
    environment

 3. The "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
    Versions 6.00 and 6.00b for MS OS/2 and MS-DOS

 4. The "Microsoft BASIC 7.0: BASIC Language Reference" manual for
    Version 7.00

 5. The "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
    Versions 4.00 and 4.00b

 The output on Page 369 should correctly show

        one
                two
 three
 0123456789012345678901234567890
                     four

 to correspond to the code given for the TAB function.


 710. During INPUT, CTRL+T Displays Softkeys on Line 25

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890627-171 B_BasicCom
 Last Modified: 27-DEC-1989    ArticleIdent: Q46849

 During an INPUT statement, pressing CTRL+T causes a number line to
 display on line 25 of the screen. These numbers correspond to the
 softkeys that you can define and label with the KEY statement in
 BASIC. This behavior is not documented and occurs in all screen modes.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00.

 To prevent this behavior, you can trap for CTRL+T using the KEY
 statement. The key combination is trapped during the INPUT statement
 but is not acted upon until after the INPUT statement is terminated.
 This delay allows you to trap for the key and simply RETURN from the
 label.

 The following sample code prevents display of the softkey line during
 the INPUT of the string:

 KEY 15, CHR$(&H04) + CHR$(&H14)     'delete these lines
 KEY(15) ON                          'to see the softkey
 ON KEY(15) GOSUB KeyPressed         'display during input

    PRINT "hit CTRL+T then,"
    PRINT "enter a string"
    INPUT AnyString$

 END

 KeyPressed:
      RETURN


 711. Increasing the Efficiency of QuickBASIC 4.50's QuickSort Demo

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890628-48
 Last Modified: 12-JAN-1990    ArticleIdent: Q46850

 The SORTDEMO.BAS QuickSort program's speed can be increased by moving
 in toward the pivot point after each iteration. The speed increase is
 more noticeable as the array gets larger. This information applies to
 the SORTDEMO.BAS sample program provided with Microsoft QuickBASIC
 Version 4.50 for MS-DOS.

 In the QuickSort SUBprogram, you must move the "end elements", "I" and
 "J", inward after each iteration of the pivot loop. Currently, "I" and
 "J" are reset after after each loop iteration back to their initial
 values.

 The following is a portion of the QuickSort SUBprogram outlining the
 change that can be made.

 The code currently reads as follows:

    .
    .
    .
 'Pick a pivot element at random. Then move it to the end.
 RandIndex = RandInt%(Low,High)
 SWAP SortArray(High),SortArray(RandIndex)
 Swapvars High, RandIndex
 Partition = SortArray(High),Length

 DO

    '***** THE NEXT TWO LINES ARE THE ONES *****
    '***** THAT YOU WILL BE MOVING UPWARDS *****

    'Move in from both sides toward the pivot element
    I = Low: J = High

    DO WHILE (I<J) AND SortArray(I).Length <= Partition

 The code should read as follows:

    .
    .
    .
 'Pick a pivot element at random. Then move it to the end.
 RandIndex = RandInt%(Low,High)
 SWAP SortArray(High),SortArray(RandIndex)
 Swapvars High, RandIndex
 Partition = SortArray(High),Length

 '***** THE FOLLOWING TWO LINES HAVE BEEN MOVED UPWARDS *****

 'Move in from both sides toward the pivot element
 I= Low: J = High

 DO

    DO WHILE (I < J) AND SortArray(I).Length <= Partition


 712. Calling C Function That Uses getenv() Doesn't Work

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890601-20 B_BasicCom S_C S_QuickC
 Last Modified: 28-DEC-1989    ArticleIdent: Q46851

 When a compiled BASIC program CALLs a C function that uses the
 getenv() function, no path is returned from getenv(). The getenv()
 function in C uses the ENVIRON variable to access the environment
 table. The ENVIRON variable is an array of pointers to the strings
 that constitute the process environment. This variable is initialized
 by the C start-up code. Since the C function is CALLed from the BASIC
 program, the C start-up code is not executed; therefore, the ENVIRON
 variable is not initialized (it is NUL by default).

 To work around this problem, use the ENVIRON$ function in the BASIC
 program and pass the desired path to the C function.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler Versions 6.00 and 6.00b; to
 Microsoft BASIC PDS Version 7.00; to Microsoft QuickC Compiler
 Versions 1.00, 1.01, 2.00, 2.01; and to Microsoft C Compiler Versions
 5.00 and 5.10.

 Code Example
 ------------

 The following are the BASIC and C source files that demonstrate that
 CALLing a C function that uses the getenv() function returns a NUL
 ENVIRON variable:

 ' BASIC Source Code:
 DECLARE SUB EnvironTest CDECL ()
 CLS
 CALL EnvironTest
 END

 /* C source code: */
 #include <stdlib.h>
 #include <stdio.h>
 void EnvironTest(void)
 {
   char *temp;
   temp = getenv( "PATH" );
   printf( "Path: %s\nenviron: %x\n", temp, environ );
 }


 713. Loading File with DOS Device Name (CON) Can Hang QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q46878

 Loading or saving files that have the same base name as a DOS device
 (e.g. COM1, AUX, CON, PRN, etc.) can cause the QB.EXE editor to hang
 for varying lengths of time. This information applies to Microsoft
 QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS.

 With the QBX.EXE editor for Microsoft BASIC PDS 7.00, the message
 "Operation Requires Disk" is displayed and returns you to the MS-DOS
 prompt when you try to load a file with a MS-DOS device name as the
 base filename from the QBX.EXE command line. When trying to load or
 save files from the File menu, QBX.EXE editor gives the message "File
 already exists. Overwrite?" If you answer yes to the prompt, the
 message "Path/File access error" is displayed.

 To avoid hanging, or error messages, do not use DOS device names as
 base names for your files.

 For example, trying to load a file in QB.EXE with the base name of
 "comX", where "X" is the number of an installed serial port, causes
 the QuickBASIC environment to hang for approximately one minute.
 Attempting to save a file named "comX" results in a longer delay and a
 "Disk full" error message. This occurs regardless of the extension of
 the base filename. "COM1.BAS", for example, will cause the behavior.

 QuickBASIC attempts to access the DOS device "comX" and delays until
 the device times out. Similar results can occur when you use other
 device names. Using the DOS device name CON causes QuickBASIC to hang.
 To avoid this, do not use the DOS device names as base names for your
 files.


 714. Suppressing STOP Statement's "Hit Any Key to Return" Message

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890705-11
 Last Modified: 13-DEC-1989    ArticleIdent: Q46880

 The following message displays when a compiled BASIC program is
 terminated with a STOP statement:

    "STOP in module xxxxx at address ****:****

    Hit any key to return to system"

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS and to Microsoft BASIC Compiler Versions 6.00,
 6.00b for MS-DOS and MS OS/2  and to Microsoft BASIC PDS 7.00 for
 MS-DOS and MS OS/2.

 To suppress this message and return directly to the system without
 having to press a key, use the END statement instead of the STOP
 statement. You can have multiple END and STOP statements in your
 program.

 Eliminating the need to press a key may be useful when running BASIC
 programs from within MS-DOS batch files or from MS-DOS itself.


 715. CALL INTERRUPT Example to Get Disk Drive Capacity & Free Space

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890705-65 B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q46980

 A compiled BASIC program can retrieve a disk drive's free space by
 using an MS-DOS interrupt. The interrupt 21 Hex, with subfunction 36
 Hex, allows a program to obtain a drive's allocation information,
 which provides the drive size and available space. The sizes are
 returned in clusters and must be converted to bytes.

 This method is faster than using BASIC's SHELL statement to execute
 the MS-DOS CHKDSK (check disk) command.

 The code sample below shows how to use the CALL INTERRUPT routine to
 display a drive's used space, available space, and total capacity. The
 example works under MS-DOS in Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50, Microsoft BASIC Compiler Versions 6.00 and 6.00b, and
 Microsoft BASIC PDS Version 7.00 for MS-DOS. For QuickBASIC 2.00,
 2.01, or 3.00, you need to modify the program to use the CALL INT86
 statement instead of CALL INTERRUPT.

 Below is further information about MS-DOS interrupt 21 Hex (33
 decimal), with subfunction 36 Hex (54 decimal). This subfunction gets
 disk-drive allocation information, from which the drive's capacity and
 remaining free space can be calculated.

 Invoke this function with the following register values:

    AH = 54
    DL = drive code (0 = default, 1 = A, 26 = Z)

 If the function is successful, it returns the following:

    AX = Sectors per cluster
    BX = Number of available clusters
    CX = Bytes per sector
    DX = Clusters per drive

 If the function is unsuccessful (drive invalid), it returns the
 following:

    AX = FFFF Hex

 Code Sample
 -----------

 You can compile this program within the QuickBASIC environment as
 follows:

    QB filename /L [ QB.QLB ]

 For BASIC PDS 7.00, start the QBX.EXE environment as follows:

    QBX filename /L [ QBX.QLB]

 Or, compile with BC.EXE and LINK.EXE as follows:

    BC filename [ options ]
    LINK filename,,,QB.LIB [ options ]

 For BASIC PDS 7.00, use BC.EXE and LINK.EXE as follows:

    BC filename [ options ]
    LINK filename,,,QBX.LIB [ options ]

 REM ******************************************************************
 REM **                                                              **
 REM ** RegType is a user-defined type used by the CALL INTERRUPT    **
 REM ** routine. The file QB.BI contains the user-defined type and   **
 REM ** the prototyping for the subprogram INTERRUPT. The            **
 REM ** INTERRUPT routine is located in the QB.QLB and the QB.LIB.   **
 REM **                                                              **
 REM ** For BASIC PDS 7.00 use QBX.BI for the include file and the   **
 REM ** library QBX.QLB or QBX.LIB for CALL INTERRUPT support.       **
 REM **                                                              **
 REM ** NOTE: When not using the user-defined type provided with     **
 REM **       the QuickBASIC package, the length of the TYPE must    **
 REM **       be 20 bytes long. Unpredictable results will occur     **
 REM **       if the length is less than 20 bytes.                   **
 REM **                                                              **
 REM ******************************************************************

 TYPE RegType
   AX    AS INTEGER
   BX    AS INTEGER
   CX    AS INTEGER
   DX    AS INTEGER
   BP    AS INTEGER
   SI    AS INTEGER
   DI    AS INTEGER
   FLAGS AS INTEGER
   DS    AS INTEGER
   ES    AS INTEGER
 END TYPE
 DIM REGS AS RegType
 CLS
 PRINT "**  Drive Capacity Utility  **" : PRINT
 PRINT "NOTE: Drive number ranges 0 through 26, where A = 1, C = 3"
 PRINT
 INPUT "Drive number to obtain drive capacity from : ", DriveNum%
 IF DriveNum% < 0 OR DriveNum% > 26 THEN
    PRINT
    PRINT "ERROR: Invalid Drive Number (RANGE: 0 thru 26)"
    PRINT
    END
 END IF
 REGS.AX = &H3600      '** AH = 36, AL = 00
 REGS.DX = DriveNum%   '** DH = ??, DL = DriveNum%
 CALL INTERRUPT(&H21, REGS, REGS)
 IF REGS.AX = -1 THEN    '** -1 = &HFFFF
    PRINT
    PRINT "ERROR: Invalid Drive Specification"
    PRINT
    END
 END IF

 REM ** TEMP = [ Sectors per cluster ] TIMES [ Bytes per Sector ]    **
 Temp& = REGS.AX * REGS.CX

 REM ** CAPACITY  = [ TEMP ] TIMES [ Clusters per Drive ]            **
 Capacity& = Temp& * REGS.DX

 REM ** AVAILABLE = [ TEMP ] TIMES [ Number of Available Clusters ]  **
 Available& = Temp& * REGS.BX

 REM ** INUSE     = [ CAPACITY ] TIMES [ AVAILABLE ]                 **
 InUse& = Capacity& - Available&

 PRINT
 PRINT "Drive Number = "; DriveNum%
 IF DriveNum% = 0 THEN
    PRINT "** Default drive number used **"
 ELSE
    PRINT "      Letter =  "; CHR$(64 + DriveNum%)
 END IF
 PRINT
 PRINT USING "Capacity  = ###,###,###"; Capacity&
 PRINT USING "In Use    = ###,###,###"; InUse&
 PRINT "            ==========="
 PRINT USING "Available = ###,###,###"; Available&
 END


 716. Example of Passing a Variable-Length String to Assembly

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q47122

 The program shown below demonstrates how to pass a variable-length
 string by far reference to an assembly language routine.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
 OS/2, and to near variable-length strings in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 The following program is PSTRING.BAS, which passes a string to an
 assembly language routine using the VARSEG and SADD functions. SADD
 gives the actual address of the string, whereas VARPTR gives the
 address of the string descriptor.

 This example cannot be used in BASIC PDS 7.00 or 7.10 with far strings
 (BC /Fs) or with QBX.EXE (which always uses far strings). For more
 information about far strings, see Chapter 13 of "Microsoft BASIC 7.0:
 Programmer's Guide" for versions 7.00 and 7.10.

 DECLARE SUB PSTRING(BYVAL STRSEG AS INTEGER, BYVAL STROFF AS INTEGER)
 A$ = "Hello World"
 PRINT "Before call: ";
 PRINT A$
 CALL PSTRING(VARSEG(A$), SADD(A$))
 PRINT "After call : ";
 PRINT A$

 The following separately compiled routine is PSTR.ASM:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .CODE

 pstring     PROC sseg:WORD, soff:WORD
             push bx                  ; save bx register, dx, and es
             push dx
             push es

             mov ax, sseg             ; get segment of string
             mov es, ax               ; put into segment register
             mov bx, soff
                                      ; 65 is ASCII value for letter 'A'.
             mov BYTE PTR es:[bx], 65 ; Move the 'A' to the first character
                                      ;  in the string.
             pop es
             pop dx
             pop bx                   ; restore (pop) es, dx, and bx
             ret
 pstring     ENDP
             end

 Compile and link the program as follows:

    BC PSTRING;
    MASM PSTR;

    LINK PSTRING PSTR;

 When run, PSTRING should print the following:

    Before call: Hello World
    After call : Aello World


 717. Array in SUB Statement Doesn't Need Dimensions in Parentheses

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom
 Last Modified: 30-MAY-1990    ArticleIdent: Q47124

 In QuickBASIC versions 3.00 and earlier, passing an array in a SUB
 statement requires the number of array dimensions to be specified in
 parentheses, such as x(2) for an array dimensioned as DIM x(10,10).
 Empty parentheses () after the array name in a SUB statement cause a
 compile-time error in QuickBASIC 3.00 and earlier.

 However, in QuickBASIC versions 4.00 and later, empty parentheses
 after the array name in a SUB statement are actually the preferred
 syntax. They are also the preferred syntax in Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2 and in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS and MS
 OS /2.

 In fact, the QB.EXE editor in QuickBASIC versions 4.00, 4.00b, and
 4.50 and the QBX.EXE editor in BASIC PDS version 7.00 automatically
 strip out the constant (if any) in the parentheses net to the array
 name in a SUB statement.

 When using a text editor (word processor, EDLIN, etc.) and writing the
 program using the syntax for QuickBASIC versions 3.00 or earlier, you
 will get an "L1101 Invalid Object Module" error when trying to link
 the .OBJ that was created using QuickBASIC versions 4.00 or later.

 The subroutine example for the LBOUND and UBOUND functions in the
 manuals doesn't require the subscript (2) in the array in the SUB
 statement. This applies to Page 60 of the "Microsoft QuickBASIC 4.0:
 Programming in BASIC: Selected Topics" manual for QuickBASIC versions
 4.00 and 4.00b and for Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Page 53 of the "Microsoft
 QuickBASIC 4.5: Programming in BASIC" manual for QuickBASIC version
 4.50. This misleading documentation was changed in Microsoft BASIC PDS
 version 7.00.

 The first line of the subroutine example shows the following, which is
 allowed but may be a little misleading, since QB.EXE and QBX.EXE strip
 out the "2":

    SUB PrintOut(A(2)) STATIC

 No number of dimensions (2) is required for the A array. This line
 converts to the following preferred syntax when entered in the QB.EXE
 and QBX.EXE editor:

    SUB PrintOut(A()) STATIC


 718. IBM PS/2 Video Problems with QuickBASIC 4.50 Under DOS 4.00

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 B_BasicCom
 Last Modified: 30-JAN-1990    ArticleIdent: Q47346

 If you are using MS-DOS or PC-DOS Version 4.00, operating QuickBASIC
 4.50 on an IBM PS/2 Model 50 or 60 can lead to video problems (such as
 a garbled or rolling display) when you switch between 25-line and
 43-line screen modes. This also applies to a PS/2 Model 30 (286) with
 a VGA under MS-DOS 4.00. This problem does not occur in versions of DOS
 earlier than 4.00. Note that QuickBASIC Version 4.50 was released
 before DOS Version 4.00, and thus, was not tested under DOS 4.00.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50 running under MS-DOS Version 4.00 and in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS
 (buglist7.00). We are researching this problem and will post new
 information here as it becomes available.

 The problems described in Examples 1 and 2 (below) also apply to
 Microsoft BASIC PDS Version 7.00 for MS-DOS. The same problems occur
 with the QBX.EXE editor and programs compiled with BC.EXE in 7.00.

 Example 1
 ---------

 The following steps reproduce this behavior:

 1. Boot under DOS 4.00 on an IBM PS/2 Model 50 or 60.

 2. Use the DOS MODE command to put the screen into 43-line mode (PS/2
    Models 50 and 60 have VGA graphics), as follows:

       MODE CO80,43

 3. Execute a compiled QuickBASIC Version 4.50 program that uses a
    WIDTH statement to change the screen to 25-line mode, such as the
    following one-line program:

       WIDTH 80,25

 When the program terminates, the display will start rolling
 uncontrollably. You must reboot the computer to regain control.

 The same problem occurs if you start the QuickBASIC environment in
 43-line mode, and then change to 25-line mode using a WIDTH statement
 in the immediate window in the QB.EXE editor.

 Example 2
 ---------

 If you start in DOS 4.00 with the default screen mode (MODE CO80,25),
 invoke the QB.EXE editor, and then invoke the WIDTH 80,43 statement to
 change to 43-line mode, the program printout rolls on the screen.
 However, you can recover from this problem by either ending the
 program, returning to the editor, or making the program reinvoke the
 default screen mode with the WIDTH 80,25 statement.


 719. The Number of SUBprograms Per Module Affects .EXE Size

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 20-DEC-1989    ArticleIdent: Q47347

 Linking many separate object (.OBJ) modules carries a small size
 penalty per module that can be alleviated by combining SUBprograms
 into fewer modules. For the smallest executable (.EXE) program size,
 you should compile together (into one module) the SUBprograms that are
 most often called together. However, SUBprograms that are not usually
 called together (from most of your .EXE programs) should be placed
 into separate modules so that unused procedures are not linked in.

 You can optionally use the Microsoft Library Manager (LIB.EXE) program
 to group multiple separate .OBJ modules into a .LIB library file for
 more convenient linking. (There is no size difference if you compare
 linking to a .LIB library file versus linking to an equivalent list of
 .OBJ object modules.)

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 Example
 -------

 It might be inefficient to put a sorting routine into a .OBJ module
 that also contains unrelated windowing routines. In this situation,
 the linker would include all the windowing routines (even if some are
 not called) in your executable when the sort routine is called. The
 executable size could be reduced if you put the sorting routine in one
 module and the windowing routines in one or more separate modules.

 If your program calls most of the windowing routines, you may want to
 put the windowing routines in as few separate modules as possible. If
 your program calls only a few windowing routines, then multiple
 separate windowing modules are appropriate. Multiple modules can be
 grouped into a .LIB library file for linking convenience.

 Detailed Illustration
 ---------------------

 The size overhead per module can be illustrated using two extreme
 cases:

 1. Compiling each SUBprogram into a separate module.

 2. Compiling all SUBprograms into one module.

 Ten SUBprograms were used in the experiment below. These SUBprograms
 were placed into libraries in accordance with the two extremes. Each
 extreme produces smaller executables depending upon whether all the
 SUBprograms were called or only one SUBprogram was called out of the
 ten found in the library.

 All modules were compiled with the BC /O (stand-alone executable)
 option, but a similar size impact occurs when compiling with the
 run-time library option. The .EXE size results of the experiment below
 were obtained from QuickBASIC Version 4.50.

 Extreme 1: Compile each SUBprogram into a separate object file,
            combine all into one library, and link the library
            to a main program that calls as follows:

    Scenario                   | Resulting .EXE size
    ------------------------------------------------
    Main program calls only    |     26,424
    1 of the 10 SUBprograms    |
                               |
    Main program calls all     |     29,084
    of the 10 SUBprograms      |
    ------------------------------------------------

 Extreme 2: Compile all SUBprograms into one object file, and link
            to a main program that calls as follows:

    ------------------------------------------------
    Main program calls only    |     28,008
    1 of the 10 SUBprograms    |
                               |
    Main program calls all     |     28,056
    of the 10 SUBprograms      |
    ------------------------------------------------

 Explanation of Resulting .EXE Sizes
 -----------------------------------

 When the linker resolves externals, it does not attempt to granulate
 the SUBprograms past the module level. In other words, the linker will
 look for a SUBprogram's module within the library and load every
 SUBprogram in that module into the final executable (.EXE) file. This
 means that you could take advantage of the linker's ability to
 discriminate against a library's unused object modules by compiling
 each SUBprogram into a different module. The separate modules can be
 placed into one library. The above results show that this helps reduce
 program size in situations where only a few of the SUBprograms are
 needed from the library. However, as you call a greater number of
 SUBprograms, this becomes inefficient due to the padding added when
 the linker incorporates several object modules into the executable.

 The most efficient method for building modules is to place into one
 module the SUBprograms that share variables and are most often called
 together. SUBprograms that are not often called together in the same
 program can be placed into separate modules. The separate modules can
 be placed into a library for linking convenience.


 720. Example of Passing Fixed-Length Strings from C to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890711-46 B_BasicCom S_C S_QuickC
 Last Modified: 28-DEC-1989    ArticleIdent: Q47348

 To pass a string from Microsoft C to compiled BASIC, the string must
 originate in BASIC. A fixed-length string works best for this purpose.
 In the C module, you can modify the string, and BASIC will recognize
 this modification because BASIC is referencing the address of the
 string.

 This information about interlanguage calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 The following program is an example of passing a fixed-length string
 from C to BASIC (where the string is first allocated in BASIC). Please
 note that the C module needs to use the medium memory model.

 Compile Steps
 -------------

    BC callc.bas /o;

    cl /c /AM stringf.c

 Link Step
 ---------

    LINK callc+stringf /nod /noe ,,,bcom45+mlibce;

 For BASIC PDS 7.00, use the following link step:

    LINK callc+stringf /nod /noe ,,,bcl70enr.lib+mlibce.lib;

 BASIC Program
 -------------

 'CALLC.BAS
 DECLARE SUB StringFar CDECL (_
             BYVAL p1o AS INTEGER,_
             BYVAL p1s AS INTEGER,_
             SEG p3 AS INTEGER)
 CLS
 DIM array AS STRING * 15
 array = "This is a test" + CHR$(0)
 CALL StringFar(VARPTR(array), VARSEG(array), LEN(array))
 LOCATE 20,20
 PRINT array
 END

 C Program
 ---------

 /* stringf.c */
 #include <stdio.h>
 void StringFar(a,len)
    char far *a;
     int *len;
  {
     int i;
     printf("The string is : %s \n\n",a);
     printf(" Index       Value       Character\n");
     for (i=0;i < *len; i++)
      {
          printf("  %2d       %3d      %c\n",i,a[i],a[i]);
      };

     /* This loop shows that the string can be modified.
        It fills the string with the '@' character.
     */
     for (i=10;i < *len; i++)
       {
          a[i]=64;
       }
  }


 721. Displaying Inverse Video Text in Hercules SCREEN 3

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890717-67 SR# S890522-4 B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q47490

 The QuickBASIC program in this article contains a routine that
 demonstrates how to display text in inverse video on a Hercules
 monochrome graphics card in SCREEN 3.

 The program runs correctly if compiled using QuickBASIC version 4.00,
 4.00b, or 4.50, Microsoft BASIC Compiler version 6.00 or 6.00b for
 MS-DOS, or Microsoft BASIC PDS version 7.00 or 7.10 for MS-DOS.

 The general procedure is as follows:

 1. Draw a box on the screen with the LINE statement using the BF (Box
    Fill) argument. The filled-in box will act as the background on
    which the text will appear. The box should be of the same height
    and width as the line of text to be displayed.

 2. Use the graphics GET statement to store the background block in an
    array.

 3. Print the line of text to be displayed.

 4. Use the graphics PUT statement with the XOR argument to place the
    block of background color over the text.

 The result is a black foreground with a highlighted background (in
 other words, inverse video).

 Note: The resulting display is all foreground. What appears to be the
 background is actually foreground color. The above steps construct a
 character that is a solid block with the outline of the character cut
 out of the middle.

 For more information about performing a similar operation on a color
 graphics adapter, search in this Knowledge Base on the following
 words:

    foreground and background and GET and PUT and 16 and simultaneously

 This separate article explains how you can use as many background
 colors as foreground colors in SCREEN 9.

 Code Example
 ------------

 The InversePrint SUBprogram below takes only one parameter, the STRING
 to be displayed. The parameter can be a simple STRING literal or a
 STRING expression. No special formatting characters are supported, but
 they could easily be added.

 Following is the code for the module IPRINT.BAS, which contains the
 InversePrint SUBprogram:

 '* Module name:        IPRINT.BAS                          *
 '* Global variables:                                       *
 DIM SHARED bgblock%(2242)  'holds background block         *

 '***********************************************************
 '*                                                         *
 '* InversePrint:                                           *
 '*           This routine will not wrap around if the      *
 '*           string exceeds column 80. It truncates        *
 '*           whatever text is being printed at column 80.  *
 '*                                                         *
 '*           The string length in pixels is first calcu-   *
 '*           lated. A LINE statement with the BF option    *
 '*           (Box Fill) using the amber background color   *
 '*           is executed. The resulting block of color is  *
 '*           saved with a GET statement. The string is     *
 '*           then printed. The saved block of background   *
 '*           is then PUT over the text with XOR option,    *
 '*           thus the text appears in inverse video.       *
 '*                                                         *
 '***********************************************************
 SUB InversePrint (text$)
   'get cursor position and determine size of text
   tx% = POS(0)
   ty% = CSRLIN
   col% = (tx% - 1) * 9
   row% = (ty% - 1) * 14
   maxpix% = 719 - col%
   maxlength% = 81 - tx%
   tlength% = LEN(text$) * 9

   'truncate text if longer than 80 columns
   IF tlength% > maxpix% THEN
     text$ = LEFT$(text$, maxlength%)
     tlength% = maxpix%
   END IF

   'draw background box and GET it into an array
   LINE (col%, row%)-STEP(tlength%, 13), 7, BF
   GET (col%, row%)-STEP(tlength%, 13), bgblock%(0)
   PRINT text$;

   'XOR background box with text on screen
   LOCATE ty%, tx%
   PUT (col%, row%), bgblock%(0), XOR
 END SUB

 The following demonstrates how to compile InversePrint and how to call
 it from another module (IPDEMO.BAS):

 1. To create IPRINT.OBJ:  BC IPRINT;
    To create IPLIB.LIB:   LIB IPLIB IPRINT;

 2. If using IPRINT.OBJ:   BC IPDEMO;
                           LINK IPDEMO IPRINT;

    If using IPLIB.LIB:    BC IPDEMO;
                           LINK IPDEMO,,,IPLIB;

 The following is the code for IPDEMO.BAS, which makes calls to
 InversePrint:

 '* Module:       IPDEMO.BAS
 '* Description:  This program demonstrates how to call InversePrint.
 '* Note:         InversePrint prints the text at the current cursor
 '*               position.
 DECLARE SUB InversePrint (test$)
 SCREEN 3
 CLS
 A$ = "A$ +"
 B$ = "B$"
 LOCATE 1
 InversePrint "This is the text to be printed"
 LOCATE 2
 InversePrint A$ + B$
 LOCATE 3
 InversePrint STRING$(50, "X")
 LOCATE 4
 CALL InversePrint("CALL statement used")
 WHILE INKEY$ = "": WEND


 722. How SUB and FUNCTION Windows Inherit DEFtype in QB.EXE Editor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-SEP-1990    ArticleIdent: Q47491

 The following information applies to the QB.EXE editor in QuickBASIC
 versions 4.00, 4.00b, and 4.50; to the QB.EXE editor in Microsoft
 BASIC Compiler versions 6.00 and 6.00b; and to the QBX.EXE editor in
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10.

 When creating SUB or FUNCTION procedures in the QB.EXE or QBX.EXE
 editor, the procedures inherit the DEFtype statement shown in the
 window in which they were first created. "DEFtype" refers to the
 following statements: DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR, and
 DEFCUR. (DEFCUR, which is a declaration for the CURRENCY data type, is
 supported only in BASIC PDS 7.00 and 7.10.)

 If no DEFtype statement is visible in a window, the default DEFSNG A-Z
 applies. If a certain range of letters is not covered by a DEFtype
 statement in the current window, then that range of letters is covered
 by DEFSNG (since single precision is the default data type).

 For more information in a related article, search for the following
 words:

    DEFLNG and MISMATCH and $DYNAMIC

 If the module-level code for the current module contains a DEFINT A-Z
 statement, any SUB or FUNCTION created in that module automatically
 has a DEFINT A-Z statement placed just above the SUB or FUNCTION line.

 If a SUB or FUNCTION is created and moved to a module (source file)
 with a different DEFtype than the module it was created in, the
 SUBprogram and its new module have different default variable types,
 and SHARED or passed variables may not be recognized in the
 SUBprogram. In this case, the variables that were intended to be
 SHARED may have the same name in both the SUBprogram and the module,
 but the variables are of different types and, thus, are considered
 different variables. You may encounter this same situation if you
 create a SUBprogram (which "inherits" the module-level DEFtype) and
 then change the DEFtype at the module level.

 To avoid problems accessing SHARED or passed variables, you can either
 append the appropriate type-specifier character (%, &, !, #, or $) to
 the variable name, or make sure that all your SUBprograms have the
 same DEFtype as the module that calls them.

 Code Example
 ------------

 Executing the following code prints the values 0 and 10, whereas you
 may have wanted 10 and 10. The reason for the difference is that while
 Y% is always an integer variable (the "%" type specifier ensures this)
 and, thus, is recognized as the COMMON SHARED variable Y% in the
 subprogram, "X" is an integer (because of the DEFINT) at the module
 level, and a double-precision variable (because of the DEFDBL before
 the SUB) in the SUBprogram. Thus, Y% is recognized as SHARED and
 changed correctly, while X is considered a local variable in the
 SUBprogram and the COMMON SHARED variable X remains unaltered.

    'Module-level code:
    DEFINT A-Z
    COMMON SHARED X, Y%
    CALL thesub
    PRINT X, Y%
    END

    'SUBprogram level in same module -- different DEFtype statement:
    DEFDBL A-Z
    SUB thesub
      X = 5
      Y% = 10
    END SUB


 723. Watch Value and Watchpoint Ignored During Event or ERROR Trap

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q47510

 When using ON ERROR GOTO or any of the ON event GOSUB statements
 (where event includes KEY, TIMER, COM, PEN, PLAY, and STRIG),
 watchpoints or watch values will not function while you are in the ON
 ERROR GOTO or ON <event> GOSUB subroutine. Watch values will show the
 default value for the type of variable (either 0 or a null string),
 and watchpoints will not halt the program.

 This behavior occurs in the QB.EXE editor for QuickBASIC Versions
 4.00, 4.00b, 4.50 and the QB.EXE editor for Microsoft BASIC Compiler
 Versions 6.00 and 6.00b. This behavior is a known design limitation of
 these versions of QuickBASIC and is not an error.

 The QBX.EXE editor for Microsoft BASIC PDS 7.00 has been enhanced
 so that you may now use watchpoints and watch values in ON ERROR GOTO
 and ON <event> GOSUB subroutines.

 The following example demonstrates the limitation:

 ON TIMER (5) GOSUB 1000
 TIMER ON
 WHILE INKEY$ = "" : WEND
 END

 1000 PRINT "In routine"
      FOR x = 1 TO 10
        PRINT x
      NEXT x
      RETURN

 Execute the program with a watchpoint or watch value for the variable
 "x". The watchpoint will not halt the program in the FOR NEXT loop as
 you would expect. If you set a breakpoint inside the FOR NEXT loop,
 you will also see that a watch value on "x" will always report a value
 of 0.


 724. QuickBASIC Must Be Main Program in Mixed-Language Calling

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890720-118
 Last Modified: 20-DEC-1989    ArticleIdent: Q47511

 When writing a mixed-language program utilizing modules written in
 either Microsoft QuickBASIC or Microsoft BASIC Compiler, BASIC must be
 the start-up controlling language. This step is necessary to activate
 the BASIC language run-time support code.

 For example, if a mixed-language program uses both C and QuickBASIC
 modules, then QuickBASIC must be the controlling language. Thus, C
 cannot call QuickBASIC without QuickBASIC first calling C.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.


 725. CTRL+A and CTRL+B Bytes Stripped from String Constants in .EXE

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890721-81 B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q47563

 BC.EXE in QuickBASIC version 4.50 strips out the characters CTRL+A and
 CTRL+B (ASCII 1 and 2) from quoted strings at compile time, whereas
 QB.EXE allows these characters. Inside QB.EXE, a CONST or a variable
 assigned a value of a literal STRING consisting of the CTRL+A or
 CTRL+B characters correctly has both a length and a graphics
 representation. In an .EXE program compiled with BC.EXE, neither one
 has a length or a graphics representation. This is a limitation with
 BC.EXE in QuickBASIC version 4.50, but not with earlier versions.

 This design limitation also applies to BC.EXE in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2. QBX.EXE 7.00 and 7.10 allows ASCII 1 and 2 values
 in quoted strings.

 BC.EXE reserves the ASCII 1 and 2 bytes to internally represent
 end-of-statement and end-of-line. QB.EXE and QBX.EXE are more lenient
 in allowing ASCII 1 and 2 bytes to be used in strings.

 Code Example
 ------------

 To enter the ASCII character 01 or 02 (smiley or inverse smiley face)
 into a quoted string within the QB.EXE or QBX.EXE environment, you
 must press CTRL+P followed by CTRL+A or CTRL+B. In the following
 program, the caret symbol (^) represents holding down the CTRL key
 while pressing the next key:

    CONST a = "^P^A"    ' Smiley face representation of CTRL+A
    CONST b = "^P^B"    ' Inverse smiley face representation of CTRL+B

    a1$ = "^P^A"
    b1$ = "^P^B"

    PRINT a, a1$, CHR$(1), LEN(a1$)
    PRINT b, b1$, CHR$(2), LEN(b1$)

 Note that the functions CHR$(1) and CHR$(2) return the same ASCII
 values (01 and 02) at run time as pressing CTRL+A and CTRL+B at edit
 time. The problem does not occur if you print the function CHR$(1) or
 CHR$(2), or assign either to a string variable. To work around the
 problem, assign CHR$(1) and CHR$(2) to a string variable (but not to a
 CONST constant). For example:

    a1$ = CHR$(1)
    b1$ = CHR$(2)
    PRINT a1$, CHR$(1), LEN(a1$)   ' Works fine in .EXE
    PRINT b1$, CHR$(2), LEN(b1$)   ' Works fine in .EXE


 726. Using Named COMMON /SYMBOL/ May Cause "String Space Corrupt"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 SR# S890710-48
 Last Modified: 26-FEB-1990    ArticleIdent: Q47565

 When running a program from the QuickBASIC QB.EXE environment Version
 4.50, 4.00b, or 4.00, a "string space corrupt" error message can
 occur, dumping you back to DOS, when all of the following conditions
 occur together:

 1. The program contains a named COMMON block with the name of
    /SYMBOL/.

 2. The named COMMON block contains a variable-length STRING.

 3. Any Quick library has been loaded.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50. We are researching this problem and will
 post new information here as it becomes available.

 This problem does not occur in the Microsoft BASIC Professional
 Development System (PDS) Version 7.00 QBX.EXE environment.

 This problem can be corrected by any of the following methods:

 1. Rename the COMMON block to anything but /SYMBOL/.

 2. Remove all variable-length STRINGs from the COMMON block.

 3. Changed the variable-length STRINGs to fixed-length STRINGs.

 4. Invoke QuickBASIC without loading a Quick library.

 Code Example
 ------------

 The following sample program generates a "String space corrupt" error
 message and then drops you out to DOS if run from within the
 environment with a Quick library loaded:

    COMMON /SYMBOL/ Astring$
    Print "Hello"
    END

 Additional reference word: B_BasicCom


 727. SHARED Dynamic Array Element Passed as Parameter Aliases to 0

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 14-NOV-1990    ArticleIdent: Q47566

 If you attempt to alter an element of a SHARED or COMMON SHARED
 $DYNAMIC array while inside a SUBprogram and that element has also
 been passed as a parameter to the SUBprogram, the value returned in
 the parameter will be the value assigned to the array element upon
 exit from the SUBprogram, and will replace whatever value may have
 been assigned directly to the array in the SUBprogram.

 This behavior occurs in Microsoft QuickBASIC versions 4.00, 4.00b, and
 4.50, Microsoft BASIC Compiler 6.00 and 6.00b for MS-DOS and MS OS/2,
 and Microsoft BASIC PDS 7.00 for MS-DOS and MS OS/2.

 This is a form of variable aliasing, which is a programming practice
 not recommended by Microsoft. A variable passed in an argument list to
 a procedure should not also be shared by means of the SHARED statement
 or the SHARED attribute (of the DIM or COMMON statement) in that
 procedure's module.

 Similarly, a variable should not be passed twice in the list of
 arguments passed to a procedure, or else variable aliasing problems
 occur. This information can be found under "The Problem of Variable
 Aliasing" section, on Page 64 in the "Microsoft BASIC 7.0:
 Programmer's Guide" for BASIC PDS versions 7.00 and 7.10, on Page 68
 of the "Microsoft QuickBASIC 4.5: Programming in BASIC" manual, and on
 Page 78 of "Microsoft QuickBASIC 4.0: Programming in BASIC: Selected
 Topics" manual for versions 4.00 and 4.00b.

 The behavior in the first example above results from the way
 QuickBASIC accesses $DYNAMIC arrays. Since access to these arrays
 requires a far pointer, and all parameters use near pointers, a
 temporary location is set aside for the parameter before and during
 the CALL, and the value in this location is assigned to the actual
 array element following the return from the CALL. Thus, whatever value
 you assign to the array element inside the SUBprogram using the SHARED
 array name will be replaced with the value of the parameter when the
 SUBprogram ends.

 Note that when inside the QuickBASIC environment, virtually all arrays
 are treated as $DYNAMIC. It is only at compile time that $STATIC
 arrays are actually made $STATIC by allocation in the data segment.
 Since the QuickBASIC editor treats most arrays as $DYNAMIC, this
 behavior can be observed in the editor even for arrays declared
 $STATIC. Please see Pages 32-33 in the "Microsoft QuickBASIC 4.0:
 BASIC Language Reference" manual for versions 4.00 and 4.00b, and
 Pages 719-721 in the "Microsoft BASIC 7.0: Programmer's Guide" for
 BASIC PDS Version 7.00, for a complete description of where arrays are
 stored.

 The following example demonstrates this behavior:

 DECLARE SUB test (a!)
 CLS
 ' *** The DYNAMIC metacommand is not required to reproduce
 '     this behavior inside the QuickBASIC environment.
 '$DYNAMIC
 DIM SHARED b(20)        'Step 1. b(20) initially is 0.
 CALL test(b(20))
 PRINT b(20)             'Step 3. PRINTs 0 -- global has been
 END                     '        replaced by returned value.

 SUB test (a!)
   b(20) = 10
   PRINT b(20)           'Step 2. PRINTs 10 -- Global value is
 END SUB                 '        changed. Parameter a! is still 0.


 728. Correction for BASIC Calling POWER2, "Mixed-Language": Page 81

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom S_C H_MASM S_PasCal
 Last Modified:  7-FEB-1990    ArticleIdent: Q48479

 The following correction applies to Page 81 of the "Microsoft
 Mixed-Language Programming Guide," which is provided with C Versions
 5.00 and 5.10, Macro Assembler Versions 5.00 and 5.10, and Pascal
 Version 4.00 (but is NOT provided with QuickBASIC Version 4.00, 4.00b,
 or 4.50, Microsoft BASIC Compiler Version 6.00 or 6.00b, or Microsoft
 BASIC Professional Development System (PDS) Version 7.00).

 On Page 81 of the "Microsoft Mixed-Language Programming Guide," the
 BASIC program example is incomplete. The structure of the code as
 shown incorrectly returns a value of 0 (zero) for the POWER2 assembler
 function. This error occurs because POWER2(3,5) is interpreted by
 BASIC to be an array as opposed to a FUNCTION as it was intended to
 be.

 To correct the program, add the following line after the DEFINT A-Z
 statement:

    DECLARE FUNCTION Power2 (x, y)

 The program in its entirety should read:

    DEFINT A-Z
    DECLARE FUNCTION Power2 (x, y)
    PRINT "3 times 2 to the power of 5 is ";
    PRINT Power2(3,5)
    END

 This BASIC program can be compiled with Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions
 6.00 and 6.00b for MS-DOS and MS OS/2, or Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 The assembly language routine on Page 82 is correct and returns the
 expected values when you add the above DECLARE in the BASIC code.


 729. Improper IF Statement Syntax Can Hang QB.EXE 4.00 Environment

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50 SR# S890614-
 Last Modified: 28-FEB-1990    ArticleIdent: Q47643

 An illegally formed IF statement may hang the QuickBASIC environment
 during the binding stage. When you move the cursor to the IF
 statement, the reserved words will not be converted to uppercase
 letters, and there will be no syntactic error message generated.

 The computer hangs only when the program is executed inside the
 QuickBASIC environment. The compiler correctly generates several error
 messages for the illegally formed IF statement.

 Microsoft has confirmed this to be a problem in the QB.EXE editor in
 QuickBASIC Versions 4.00, 4.00b, and 4.50, and in the QB.EXE editor
 that comes with Microsoft BASIC Compiler Versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b). This problem was corrected in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00). QBX.EXE correctly
 identifies that the syntax is in error.

 Code Example
 ------------

 The following code sample reproduces the problem:

    REM *** SAMPLE PROGRAM

    if a$ = "1" goto d$ = "larry"

 When you type this program in the QB.EXE editor and press the ENTER
 key, reserved words stay as entered and fail to automatically shift to
 uppercase letters. Running the program hangs the computer.

 If you attempt to enter the above code in the QBX.EXE environment of
 BASIC PDS 7.00, the environment correctly highlights the second string
 variable and reports "Expected: Label or Line-number".


 730. List of Run-Time Error Numbers and Messages for QuickBASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S890720-59
 Last Modified: 18-DEC-1989    ArticleIdent: Q47753

 This article contains a complete list of run-time errors and their
 corresponding numbers (returned by the ERR function). These errors can
 be trapped with the ON ERROR GOTO statement.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

    Error                              Error
    Code   Description                 Code   Description
    -----  -----------                 -----  -----------

     1*    NEXT without FOR            37*    Argument-count mismatch
     2*    SYNTAX error                38*    Array not defined
     3     RETURN without GOSUB        39**   CASE ELSE expected
     4     Out of DATA                 40     Variable required
     5     Illegal function call       50     Field Overflow
     6     Overflow                    51     Internal Error
     7     Out of memory               52     Bad file name or number
     8     Label not defined           53     File not found
     9     Subscript out of range      54     Bad file mode
    10     Duplicate definition        55     File already open
    11     Division by zero            56     FIELD statement active
    12*    Illegal in direct mode      57     Device I/O error
    13*    Type mismatch               58     File already exists
    14     Out of string space         59     Bad record length
    16*    String formula too complex  61     Disk Full
    17*    Cannot continue             62     Input past end-of-file
    18     Function not defined        63     Bad record number
    19     No RESUME                   64     Bad file name
    20     RESUME without error        67     Too many files
    24     Device timeout              68     Device Unavailable
    25     Device Fault                69     Communications-buffer overflow
    26*    FOR without NEXT            70     Permission denied
    27     Out of paper                71     Disk not ready
    29*    WHILE without WEND          72     Disk-media error
    30*    WEND without WHILE          73     Advanced feature unavailable
    33*    Duplicate LABEL             74     Rename across disks
    35*    Subprogram not defined      75     Path/file access error
                                       76     Path not found

    *   Denotes errors that usually occur at COMPILE TIME, but may
        occur and be trapped during RUN TIME under special circumstances

    **  Denotes that the error number was removed in BASIC PDS 7.00

 The following errors appear in Microsoft BASIC PDS Version 7.00 only:

    80     Feature removed
    81     Invalid name
    82     Table not found
    83     Index not found
    84     Invalid column
    85     No current record
    86     Duplicate value for unique index
    87     Invalid operation on null index
    88     Database needs repair

 The following undefined error numbers produce an "Unprintable error"
 message if they are not trapped with the ON ERROR GOTO statement:

    15, 21, 22, 23, 28, 31, 32, 34, 41-49, 60, 65, 66, 77, and upwards

 For Microsoft BASIC PDS 7.00, the numbers that generate the
 "Unprintable error" message are as follows:

    15 ,21, 22, 23, 28, 31, 32, 34, 39, 41-49, 60, 65, 66, 77-79, 89
    and upwards

 For a more detailed explanation of the above errors, please consult
 your language reference manual for BASIC or QuickBASIC, or your
 "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for Version
 4.50, Appendix I, or the QB Advisor on-line Help system for QuickBASIC
 Version 4.50, or your "Microsoft BASIC 7.0: Language Reference" manual
 for BASIC PDS 7.00, Appendix D, or the Microsoft Advisor on-line Help
 system for BASIC PDS Version 7.00.

 You can invoke any error in the QB.EXE or QBX.EXE environment with the
 ERROR statement. In QB.EXE 4.50 or QBX.EXE 7.00, the ERROR statement
 displays the error message with the choice to receive Help on the
 error. Choosing Help gives a brief explanation and some key points to
 consider when tracking down the cause of the error.


 731. Can't Trap "String Input When a Numeric Value Is Expected"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom SR# S890711-21
 Last Modified: 18-DEC-1989    ArticleIdent: Q47754

 The documentation incorrectly states that you can "...safeguard your
 program from user errors such as string input when a numeric value is
 expected..." in the following manuals:

 1. "Microsoft QuickBASIC 4.0: Programming in BASIC: Selected Topics"
    manual for Versions 4.00 and 4.00b, Page 279

 2. "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for Version
    4.50, Page 225

 3. "Microsoft BASIC Compiler 6.0: Programming in BASIC: Selected
    Topics" for Microsoft BASIC Compiler Versions 6.00 and 6.00b, Page
    279

 This documentation error is not present in Microsoft BASIC PDS Version
 7.00.

 It is not possible to use the ON ERROR GOTO statement to trap the
 "Redo from Start" error that occurs for the INPUT statement when a
 string is entered and a numeric value is required. To avoid the "Redo
 from Start" error message, you must use a different form of input,
 such as the LINE INPUT statement or the INKEY$ function.

 Because LINE INPUT accepts all characters until it encounters a
 carriage return, you must parse the input string yourself using string
 manipulation (e.g. MID$, INSTR) and type conversion (e.g. VAL).

 For a code example of a line-input routine using the INKEY$ statement,
 query on the following words:

    INKEY$ and CTRL+BREAK and DEBUG and GOSUB


 732. Example of C Function Returning a String to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  5-SEP-1990    ArticleIdent: Q47756

 The two programs shown below demonstrate how a C function can return a
 string to a compiled BASIC program.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For Microsoft BASIC PDS 7.00 and 7.10, this example applies only to
 near strings. If you are using far strings (BC /Fs on compile or when
 using QBX.EXE), you must use the string-manipulation routines supplied
 with BASIC PDS 7.00 and 7.10 (StringAssign, StringRelease,
 StringAddress, and StringLength). For more information about far
 strings, see Chapter 13 of "Microsoft BASIC 7.0: Programmer's Guide"
 for versions 7.00 and 7.10.

 For more information about passing other types of parameters between
 BASIC and C and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library on the following
 word:

    BAS2C

 Code Example
 ------------

 The following BASIC program is BSTRF.BAS, which calls the C function
 and prints out the returned string and its length:

    DECLARE FUNCTION CFUNC$ CDECL ()
    a$ = CFUNC$
    PRINT a$
    PRINT len(a$)

 The following program is CSTRF.C, which builds a string descriptor
 that is passed back to the calling BASIC program:

 #include <string.h>
 struct stringdesc
        {
         int length;        /* length of the string */
         char *string;      /* near pointer to the string */
        };
 struct stringdesc *std;
 char thestring[18];      /* In the medium memory model this  */
                          /* string will be in DGROUP - which */
                          /* is required for BASIC    */
 struct stringdesc *cfunc()
 {
   std->length = 18;      /* length of the string */
   strcpy(thestring, "This is the string");
   std->string = thestring;
   return(std);           /* return pointer to string descriptor */
 }

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTRF.BAS;
    CL /c /AM CSTRF.C;
    LINK /NOE BSTRF CSTRF;

 BSTRF.EXE produces the following output:

    This is the string
    18


 733. SETMEM(0) Returns Total Heap, FRE(-1) Returns Available Heap

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q47758

 The program shown below demonstrates the difference between the
 SETMEM(0) and FRE(-1) functions. SETMEM(0) returns the TOTAL possible
 amount of far heap space, while FRE(-1) returns the far heap space
 minus any data (in DGROUP or far heap) that is currently allocated.
 For Microsoft BASIC PDS Version 7.00, FRE(-1) refers only to far heap;
 to get available expanded memory you must use FRE(-3).

 This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The following program is MEMSIZE.BAS, which invokes SETMEM(0) and
 FRE(-1) before and after allocating a data string:

 CLS
 PRINT "Setmem                        : "; SETMEM(0)
 PRINT "Nonstring array             -1: "; FRE(-1)
 a$ = SPACE$(200)
 PRINT
 PRINT "      --- After Allocation ---"
 PRINT "Setmem                        : "; SETMEM(0)
 PRINT "Nonstring array             -1: "; FRE(-1)

 After the string is allocated, SETMEM(0) returns the same value as it
 did before the call. FRE(-1), however, is decreased by the size of the
 string (200 bytes for the string plus 2 bytes for the string
 descriptor).


 734. How to Print BASIC Video Screens to Epson Printers

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom BQ0085
 Last Modified: 18-OCT-1990    ArticleIdent: Q57354

 This document explains how Microsoft BASIC programs can print video
 screen images to Epson-compatible printers. If you have a printer
 other than an Epson, you must change the printer control codes used in
 the following programs for setting line spacing and graphics mode.
 Control codes can be found in your printer's manual.

 This document is also available in four shorter, separate
 articles that can be found by querying on the following words:

    Epson and print and screen and QuickBASIC

 These examples apply to Microsoft QuickBASIC versions 4.00, 4.00b, and
 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b; and to
 Microsoft BASIC PDS (Professional Development System) versions 7.00
 and 7.10 for MS-DOS. The CGA method can be adapted for QuickBASIC
 versions 2.00, 2.01, and 3.00.

           How to Print BASIC Video Screens to Epson Printers
           --------------------------------------------------

 Introduction
 ------------

 This document explains how Microsoft BASIC programs can print video
 screen images to Epson-compatible printers. If you have a printer
 other than an Epson, you must change the printer control codes used in
 the following programs for setting line spacing and graphics mode.
 Control codes can be found in your printer's manual.

 The routines presented below are divided based on SCREEN modes. SCREEN
 modes 0 through 2 use one method of printing, SCREEN 3 uses another,
 SCREEN modes 7 through 12 are all combined into one routine, and
 SCREEN 13 is another separate routine.

 The routines for printing EGA and VGA SCREEN modes 7 through 13 are
 required only if you aren't running under MS-DOS version 4.00 or
 later. In MS-DOS 4.00 and later, the program GRAPHICS.COM supports all
 standard EGA and VGA SCREEN modes. Thus, the routine given below for
 printing CGA SCREEN modes can be used to print EGA and VGA SCREENs in
 MS-DOS 4.00 and later.

 Each of these groups of SCREEN modes uses different methods of storing
 graphics information in video memory. A brief explanation of this is
 given before each program. If you want further information about
 graphics memory and the various graphics modes, please refer to the
 following book, which is available in bookstores or by calling
 Microsoft Press at (800) 888-3303 or (206) 882-8661:

     "Programmer's Guide to PC and PS/2 Video Systems," by Richard
     Wilton (published by Microsoft Press, 1987)

 These examples apply to Microsoft QuickBASIC versions 4.00, 4.00b, and
 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b; and to
 Microsoft BASIC PDS (Professional Development System) versions 7.00
 and 7.10 for MS-DOS. The CGA method can be adapted for QuickBASIC
 versions 2.00, 2.01, and 3.00.

 Printing CGA Screen Modes 0 Through 2
 -------------------------------------

 The following are two methods of performing a CGA screen dump to a
 graphics printer:

   Note: These methods will also support all standard EGA and VGA
   SCREEN modes (SCREENs 7 through 13) if you are using
   GRAPHICS.COM provided in MS-DOS 4.00 or later.

 1. You can manually execute a screen dump to a graphics printer of a
    CGA SCREEN 0, 1, or 2 in BASIC by doing the following:

    a. Run GRAPHICS.COM, which is a terminate-and-stay resident (TSR)
       program located on the DOS disk (run GRAPHICS.COM only once per
       boot session).

    b. Press SHIFT+PRINT SCREEN (that is, press the PRINT SCREEN key
       while holding down the SHIFT key).

       The above SHIFT+PRINT SCREEN screen dump also can print the
       screen in GW-BASIC, in IBM BASICA, or in most programs that use
       CGA text or graphics.

 2. A hardware interrupt 5 also can be invoked to perform a CGA screen
    dump to a graphics printer from a Microsoft BASIC program run on an
    IBM PC. To perform the screen dump, do the following:

    a. Run the GRAPHICS.COM program provided with the DOS disk (run
       GRAPHICS.COM only once per boot session).

    b. Once GRAPHICS.COM is resident in memory, using SHIFT+PRINT
       SCREEN or hardware interrupt 5 will print screens displayed by
       the IBM CGA card. In versions of MS-DOS earlier than 4.00, the
       IBM GRAPHICS.COM program does not support the printing of EGA or
       VGA screens, and only BASIC SCREENs 0, 1, and 2 can be printed.

 The following program, DUMP.BAS, shows the preferred method to CALL
 hardware interrupt 5 to perform a screen dump (this program can be
 compiled in QuickBASIC 4.00, 4.00b, or 4.50; in BASIC compiler 6.00 or
 6.00b; or in BASIC PDS 7.00 or 7.10 for MS-DOS):

    ' Dump.Bas
    TYPE Regtype
      AX AS INTEGER
      BX AS INTEGER
      CX AS INTEGER
      DX AS INTEGER
      BP AS INTEGER
      SI AS INTEGER
      DI AS INTEGER
      FLAGS AS INTEGER
      DS AS INTEGER
      ES AS INTEGER
    END TYPE
    DIM inary AS RegType
    DIM outary AS RegType
    CLS
    SCREEN 1
    PRINT "This goes to the printer"
    LINE (1,1)-(100,100)
    CALL interrupt (&H5, inary, outary)      ' Performs screen dump

 The program below, DUMP2.BAS, can be used with Microsoft QuickBASIC
 versions 2.00, 2.01, and 3.00 if you change CALL INT86OLD to CALL
 INT86. Otherwise, if you don't change CALL INT86OLD to CALL INT86,
 this program can be compiled as is in QuickBASIC 4.00, 4.00b, or 4.50;
 in BASIC compiler 6.00 or 6.00b; or in BASIC PDS 7.00 or 7.10:

    ' DUMP2.BAS
    DIM inary%(7), outary%(7)
    SCREEN 1
    PRINT "This goes to the printer"
    LINE (1,1)-(100,100)
    CALL int86old ( &H5, VARPTR(inary%(0)), VARPTR(outary%(0)) )

    ' The following syntax, which leaves out the VARPTR function,
    ' is also supported in QuickBASIC 4.00, 4.00b, 4.50, in BASIC
    ' compiler 6.00 and 6.00b, and in BASIC PDS 7.00 and 7.10:
    '         CALL int86old ( &H5, inary%(), outary%() )
    ' This INT86OLD syntax is given on Pages 86-88 of the "QuickBASIC
    ' 4.0: Language Reference" for 4.00 and 4.00b and on Pages 86-88 of
    '"BASIC Compiler 6.0: Language Reference" for 6.00 and 6.00b.

    'NOTE: The following syntax is ILLEGAL for CALL INT86 in
    'QuickBASIC 2.00, 2.01, or 3.00:
    '           CALL int86 ( &H5, inary%(), outary%() )

 To run the above DUMP.BAS or DUMP2.BAS program within the QB.EXE
 version 4.00, 4.00b, or 4.50 editor (or within QB.EXE from BASIC
 compiler 6.00 or 6.00b), you must invoke the editor with the QB.QLB
 Quick library, as follows:

    QB DUMP.BAS /L QB.QLB

 To make an EXE program from one of the above programs, you must LINK
 with QB.LIB as follows:

    BC DUMP.BAS;
    LINK DUMP.OBJ,DUMP.EXE,,QB.LIB;

 The above LINK creates DUMP.EXE, which is a program that can be
 executed from DOS by typing "DUMP".

 For BASIC PDS version 7.00 or 7.10, you must use QBX.EXE, QBX.QLB, and
 QBX.LIB (instead of QB.EXE, QB.QLB, and QB.LIB) in the above steps.

 DUMP.BAS cannot run in QuickBASIC version 2.00, 2.01, or 3.00;
 instead, you must use DUMP2.BAS. To run DUMP2.BAS in QB.EXE version
 2.00, 2.01, or 3.00, do the following:

 1. Make a USERLIB.EXE that contains INT86, as follows:

    a. In version 2.00 or 2.01, type the following at the DOS command
       line:

          BUILDLIB USERLIB.OBJ,userlib.EXE;

    b. In version 3.00, type the following at the DOS command line:

          BUILDLIB INT86.OBJ,userlib.EXE;

 2. Run GRAPHICS.COM (only once per boot session) if you will be
    printing graphics.

 3. Invoke QB.EXE as follows:

       QB DUMP2.BAS /L userlib.EXE

 4. Change INT86OLD to INT86 in DUMP2.BAS (since there is no INT86OLD
    in version 2.00, 2.01, or 3.00).

 5. Press CTRL+R to run the program in QB.EXE.

 To make DUMP2.BAS into DUMP2.EXE using QuickBASIC version 2.00, 2.01,
 or 3.00, do the following:

 1. Do ONE of the following:

    a. Create DUMP2.OBJ using the Compile command from the Run menu in
       the QB.EXE editor.

    b. You can also create DUMP2.OBJ using the separate compilation
       method, where you must end the QB command line with a semicolon
       (;), as follows:

          QB DUMP2;

 2. Do one of the following, depending on which version of QuickBASIC
    you are using:

    a. In 2.00 or 2.01, type the following at the DOS command line:

          LINK DUMP2+USERLIB.OBJ;

    b. In 3.00, type the following at the DOS command line:

          LINK DUMP2+INT86.OBJ;

 Printing Hercules Screen Mode 3
 -------------------------------

 Understanding how to print graphics screens generated by Hercules and
 Hercules-compatible graphics adapters requires familiarity with how
 Hercules graphics memory is set up.

 Hercules memory starts at hex-paragraph B000 (decimal 45056). Graphics
 memory starts with Page 0 at hex-paragraph B000 (decimal 45056), and
 Page 1 at hex-paragraph B800 (decimal 47104). (Paragraphs mark
 segment boundaries, and there are 16 bytes per paragraph.)

 However, graphics memory is interleaved, and is not contiguous. Each
 line of pixels in SCREEN mode 3 consists of 90 bytes. Thus, the top
 line of pixels (line 0) on Page 0 will start at hex-paragraph B000 at
 offset 0 and go for 90 bytes.

 To draw a line of pixels at the top of the screen (in line 0 of Page
 0), POKE 255 into positions 0 through 89 (where 255 means all 8 bits
 per byte being "on"), as follows:

    SCREEN 3
    DEF SEG = &HB000
    FOR x = 0 TO 89    ' B000:0000 hex to B000:0059 hex (in
       POKE x, 255     ' segment:offset notation)
    NEXT x

 To perform this procedure on Page 1, change the value of the DEF SEG
 statement to hex-paragraph &HB800.

 Because graphics memory is interleaved and not contiguous, if you
 continue to POKE at an offset 90 bytes after hex-paragraph B000, the
 next line will appear on the screen at the fourth line down. To draw a
 line just one line down (on line 1), add 2000 Hex (8192 decimal) to
 the offset of the first byte on line 0, then POKE as follows:

    DEF SEG = &HB000
    FOR x = 8192 TO 8281     ' or B000:2000 hex to B000:2059 hex (in
       POKE x, 255           ' segment:offset notation)
    NEXT x

 This procedure must also be performed for line 2 and line 3. (Note
 that line numbering starts at 0.) As a result, the first byte of line
 2 will be B000:4000 hex, and the first byte of line 3 will be
 B000:6000 hex. The interleaving cycles every four lines, thus the first
 byte of line 4 will be B000:005A hex (45056:0090 decimal), and
 subsequent lines will follow the previous pattern, at offset intervals
 of 2000 hex (8192 decimal).

 The following diagram shows how the scan lines relate to the
 interleaved video buffer:

                Video Buffer                    Display

       B000:0000 +---------+                       +-------------
                 |         |<----------Scan Line 0 | ............
            005A |---------|       +---Scan Line 1 | ............
                 |         |<---+  |  *Scan Line 2 | ............
            00B4 |---------|    |  |  *Scan Line 3 | ............
                 .         .    +------Scan Line 4 | ............
                 .         .       |               |
       B000:2000 |---------|       |
                 |         |<------+
            205A |---------|          * NOTE:
                 .         .            Scan line 2 is at B000:4000 hex
                 .         .            Scan line 3 is at B000:6000 hex

 This same interleaving is used in video Page 1, which begins at hex-
 paragraph B800. Please see the figure on Page 89 of the "Programmer's
 Guide to PC and PS/2 Video Systems" for a more complete diagram of the
 display memory for Hercules graphics mode.

 The following subprogram prints SCREEN Page 0 of a Hercules graphics
 screen to an Epson or Epson-compatible printer. To print SCREEN Page
 1, use a DEF SEG = &HB800 statement (instead of &HB000 for Page 0).

    DECLARE SUB HerculesPrintScreen ()
    ' Before using Hercules SCREEN 3, you must run QBHERC.COM (included
    ' with QuickBASIC 4.00 or 4.00b, and BASIC compiler 6.00 or 6.00b)
    ' or MSHERC.COM (included with QuickBASIC 4.50).
    SCREEN 3
    ' Put your screen graphics commands here - and take out commands
    ' between these markers:
    ' --------------------------------------------------------------
      FOR i% = 1 TO 719 STEP 10
        LINE (1, 1)-(i%, 348)
        LINE (1, 348)-(i%, 1)
      NEXT i%
    ' --------------------------------------------------------------
    CALL HerculesPrintScreen

    SUB HerculesPrintScreen STATIC
       DEF SEG = &HB000  'Set segment to SCREEN 3, video Page 0
       OPEN "LPT1" FOR BINARY AS #1  'Open printer port in binary mode
       WIDTH #1, 255                 'Set print width to 256 bytes wide
       adv872$ = CHR$(27) + "A" + CHR$(8)
       dots408$ = CHR$(27) + "K" + CHR$(92) + CHR$(1)
       linefeed$ = CHR$(10)

       PUT #1, , adv872$        'Set printer linefeed to 8/72"
       FOR x = 0 TO 89
          PUT #1, , dots408$    'Set printer for bit image graphic mode
          FOR y = 7740 + x TO x STEP -90
             FOR z = 24576 + y TO y STEP -8192
                image$ = CHR$(PEEK(z))
                PUT #1, , image$  'Send bit-image graphics to printer
             NEXT z
          NEXT y
          PUT #1, , linefeed$   'Send a linefeed to the printer
       NEXT x

       ResetPrn$ = CHR$(27) + "@"
       PUT #1, , ResetPrn$      'Reset the printer to default settings
       CLOSE #1
    END SUB

 Printing EGA or VGA Screen Modes 7 Through 12
 ---------------------------------------------

 Because EGA and VGA memory are stored in contiguous blocks per
 "plane," printing the screen to a printer can be a fairly simple
 operation. The method used in the program below prints the image
 sideways, which avoids the need to do any bit-shifting and uses a
 simple two-dots-per-pixel shading pattern to represent different
 colors.

 To produce different patterns for different colors, each color plane
 must be analyzed. In SCREEN modes with four video planes (7, 8, 9, and
 12), each of the four different base EGA/VGA colors --  blue, green,
 red, and intensity -- is represented in a separate memory bank or
 plane of EGA/VGA memory. Each bit in a color plane represents a pixel
 on the screen; thus, each pixel on the screen has a color attribute
 depicted by four bits, one in each color plane.

 Each plane is addressed for reading/writing by selecting the bank of
 memory to access with an OUT instruction. This program logically OR's
 the blue and red planes together and does the same with the green and
 intensity planes. This effectively reduces the number of pattern
 (color) combinations from 16 to 4. Therefore, some colors that appear
 to be different on the screen have the same appearance on paper.

 SCREEN modes 10 and 11 are almost identical, except that there are
 only two color planes; thus, each pixel on the screen has a color
 attribute depicted by two bits, one in each of the two color planes.
 Because there are only two bits per pixel and two pins are being
 fired, no OR'ing of the color planes needs to be done.

 The Epson printer can fire up to eight pins per graphics byte sent.
 Thus, moving from left to right, a loop that reads screen data from
 the bottom of the screen upward can access eight vertical columns at a
 time. This behavior coincides with the printer firing eight pins at a
 time and creates eight horizontal columns on the page, turning the
 printout sideways.

    DECLARE SUB ScreenParams (scrn%, ScreenWidth%, ScreenLength%, NP%)
    DECLARE SUB DRAWPIC (scrn%)
    DECLARE SUB VGAtoEpson (scrn%, f$, flip%, border%)
    ' Demonstrates the use of VGAtoEpson, a subprogram that dumps
    ' a SCREEN 7, 8, 9, 10, 11 or 12 image to an Epson printer.

    CLS : scrn% = 0
    WHILE (scrn% < 7) OR (scrn% > 12)
       INPUT "Enter Screen Mode: (7, 8, 9, 10, 11 or 12)"; scrn%
    WEND

    SCREEN scrn% : CALL DRAWPIC(scrn%)      ' Draw the picture
    CALL VGAtoEpson(scrn%, "LPT1", 0, 255)  ' Do the VGA screen print
    END

    SUB DRAWPIC (scrn%)                     ' Draw picture on screen
      CALL ScreenParams(scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)
      IF NumPlanes% = 2 THEN ci% = 0 ELSE ci% = 1  ' Color increment
      xmax% = ScreenWidth% : ymax% = ScreenLength%
      halfx% = xmax% / 2 : halfy% = ymax% / 2
      x% = halfx% : c% = 1
       FOR y% = ymax% TO halfy% STEP -5
          deltax% = xmax% - x% : deltay% = ymax% - y%
          LINE (halfx%, y%)-(x%, halfy%), c%
          LINE (x%, ymax%)-(xmax%, y%), c% + ci%
          LINE (halfx%, deltay%)-(x%, halfy%), c% + 2 * ci%
          LINE (x%, 0)-(xmax%, deltay%), c% + 3 * ci%
          LINE (halfx% + 1, y%)-(deltax%, halfy%), c% + 4 * ci%
          LINE (deltax%, ymax%)-(0, y%), c% + 5 * ci%
          LINE (halfx%, deltay%)-(deltax%, halfy% + 1), c% + 6 * ci%
          LINE (deltax%, 0)-(0, deltay%), c% + 7 * ci%
          x% = x% + (((xmax% + 1) / (ymax% + 1)) * 5)
       NEXT y%
    END SUB

    SUB ScreenParams (scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)
      ' Return the screen dimensions in pixels
      ' and the number of planes.
      NumPlanes% = 4          ' Set default values for SCREEN 12
      ScreenWidth% = 640 : ScreenLength% = 480
      SELECT CASE scrn%       ' Change values for other SCREEN modes
         CASE 7
            ScreenWidth% = 320 : ScreenLength% = 200
         CASE 8
            ScreenLength% = 200
         CASE 9
            ScreenLength% = 350
         CASE 10
            NumPlanes% = 2 : ScreenLength% = 350
         CASE 11
            NumPlanes% = 2
      END SELECT
    END SUB

    SUB VGAtoEpson (scrn%, fileN$, flip%, border%) STATIC
    ' Sends the image on SCREEN 7, 8, 9, 10, 11 or 12
    ' to an Epson printer.
    ' Parameters:
    '    scrn%   - SCREEN video mode of screen to print (7 through 12)
    '    fileN$  - Name of file or device to send image to
    '    flip%   - Invert flag (0 = normal, not 0 = invert)
    '    border% - Character to use for border drawing on screens
    '              9 and 10 (0 = none, 255 = solid, etc.)
      OPEN fileN$ FOR BINARY AS 1            'Open the output file
      WIDTH #1, 255
      esc$ = CHR$(27) : crlf$ = CHR$(13) + CHR$(10)
      line$ = esc$ + "A" + CHR$(8)           'Set printer to 8/72 lpi"
      PUT #1, , line$
      CALL ScreenParams(scrn%, ScreenWidth%, ScreenLength%, NumPlanes%)

      IF ScreenLength% < 480 THEN       ' Figure how many bytes to send
         numbyte% = ScreenLength% * 2 + 16   ' to printer for one
         maxy% = ScreenLength% - 1           '  line of graphics.
      ELSE
         numbyte% = 960 : maxy% = 479
      END IF

      DEF SEG = &HA000               'Start of EGA/VGA screen memory
      BorderOffset% = (960 - numbyte%) / (2 * 8)
      IF ScreenLength% < 480 THEN
         ' Print top line for border on screens where border will fit
         line$ = SPACE$(BorderOffset%)           '(for margin)
         PUT #1, , line$
         line$ = esc$ + "L" + MKI$(numbyte%)
         line$ = line$ + STRING$(numbyte%, border%) + crlf$
         PUT #1, , line$
      END IF

      ' This loop is the horizontal byte location
      colend% = (ScreenWidth% / 8) - 1
      FOR col% = 0 TO colend%
        ' Set the printer up to receive 716 or 960 bytes
        ' of graphics data
        IF ScreenLength% < 480 THEN
           line$ = SPACE$(BorderOffset%)
           PUT #1, , line$  '(for border)
        END IF

        line$ = esc$ + "L" + MKI$(numbyte%)  '(for init)
        PUT #1, , line$
        IF ScreenLength% < 480 THEN
           line$ = STRING$(8, border%)
           PUT #1, , line$    '(for border)
        END IF

        '--- This loop is the vertical byte position
        FOR row% = maxy% TO 0 STEP -1
          ' For 4 plane screens (7, 8, 9 and 12) logically OR the blue
          ' plane with the red plane, send that byte, then OR the green
          ' plane with the intensity plane and send that byte.

          ' For screens 10 and 11, the video planes are sent directly
          ' to the printer.
          FOR plane% = 0 TO 1                'Plane (* 2) set
            OUT &H3CE, 4 : OUT &H3CF, plane%
            place& = row%                   'Figure out screen memory
            place& = place& * (colend% + 1) ' location to read - use
            place& = place& + col%          ' a long to avoid overflow.
            mem% = PEEK(place&)

            IF NumPlanes% = 4 THEN ' OR color planes together
               OUT &H3CE, 4 : OUT &H3CF, plane% + 2
               mem% = mem% OR PEEK(place&)
            END IF

            '--- Flip the byte if need be (inverses printed picture)
            IF flip% <> 0 THEN mem% = 255 - mem%
            line$ = CHR$(mem%) : PUT #1, , line$
          NEXT plane%
        NEXT row%

        line$ = crlf$    ' Default for no border
        IF ScreenLength% < 480 THEN
           line$ = STRING$(8, border%) + crlf$   ' Righthand border
        END IF
        PUT #1, , line$
      NEXT col%

      IF ScreenLength% < 480 THEN     '--- Print bottom line for border
         line$ = SPACE$(BorderOffset%)       '(for margin)
         PUT #1, , line$
         line$ = esc$ + "L" + MKI$(numbyte%)
         line$ = line$ + STRING$(numbyte%, border%) + crlf$
         PUT #1, , line$
      END IF
      ResetPrn$ = esc$ + "@"
      PUT #1, , ResetPrn$                 ' Reset printer
      line$ = CHR$(12) : PUT #1, , line$  ' Send formfeed (page eject)
      CLOSE 1                             ' All done
    END SUB

 Printing VGA Screen Mode 13
 ---------------------------

 Printing SCREEN mode 13 can also be fairly simple. The method used in
 the program below prints the image sideways, which avoids the need to
 do any bit-shifting and uses a simple eight-dots-per-pixel shading
 pattern to represent different colors.

 To produce different patterns for different colors, each byte of pixel
 information must be analyzed. In SCREEN 13, each pixel is represented
 by 1 contiguous byte of information, thus allowing 256 colors per
 pixel. Since 8 printer pins are fired for each pixel, a direct mapping
 of the pixel byte to the printer pins to be fired is done.

 As stated before, 8 pins are fired for each pixel; the pins are fired
 in a 2 by 4 pattern. Since this is not square, some slight image
 distortion does occur.

 The Epson printer can fire up to eight pins per graphics byte sent.
 Thus, moving from left to right, a loop that reads screen data from
 the bottom of the screen upward can access eight vertical columns at a
 time. This behavior coincides with the printer firing eight pins at a
 time and creates eight horizontal columns on the page, turning the
 printout sideways.

    DECLARE SUB VGAtoEpson (f$, flip%)

    '--- VGAEPSON.BAS
    '--- Demonstrates the use of VGAtoEpson, a subprogram that
    '--- dumps a SCREEN 13 image to an Epson printer.
    '--- Copyright (c) 1988 Microsoft Corp.
    REM $INCLUDE: 'QB.BI'

    DIM SHARED inregs AS regtype
    DIM SHARED outregs AS regtype

    SCREEN 13
    '--- Draw picture on screen
    xmax% = 319
    ymax% = 199
    halfx% = xmax% / 2
    halfy% = ymax% / 2
    x% = halfx%
    c% = 1
    FOR y% = ymax% TO halfy% STEP -2
      LINE (halfx%, y%)-(x%, halfy%), c%
      LINE (x%, ymax%)-(xmax%, y%), c% + 20
      LINE (halfx%, (ymax% - y%))-(x%, halfy%), c% + 40
      LINE (x%, 0)-(xmax%, (ymax% - y%)), c% + 60
      LINE (halfx% + 1, y%)-((xmax% - x%), halfy%), c% + 80
      LINE ((xmax% - x%), ymax%)-(0, y%), c% + 100
      LINE (halfx%, (ymax% - y%))-((xmax% - x%), halfy% + 1), c% + 120
      LINE ((xmax% - x%), 0)-(0, (ymax% - y%)), c% + 140
      x% = x% + (((xmax% + 1) / (ymax% + 1)) * 5)
      c% = c% + 1
    NEXT y%

    CALL VGAtoEpson("LPT1", 1)
    SCREEN 0
    END

    SUB VGAtoEpson (f$, flip%) STATIC
    '--- Sends the image on SCREEN 13 to an Epson graphics printer
    '--- Parameters:
    '         f$    -   Name of file or device to send image to
    '         flip% -   Invert flag (0 = normal, not 0 = invert)

      OPEN f$ FOR BINARY AS 1         'Open the output file
      WIDTH #1, 255
      esc$ = CHR$(27)
      line$ = esc$ + "A" + CHR$(8)
      PUT #1, , line$   'set printer to 8/72 lpi
      DEF SEG = &HA000                'Start of VGA screen memory
      '--- This loop is the horizontal byte location
      FOR Col% = 0 TO 79
         '--- Set the printer to receive 800 bytes of graphics data
         line$ = esc$ + "L" + MKI$(800)
         PUT #1, , line$  '(for init)

         '--- This loop is the vertical byte position
         FOR row% = 199 TO 0 STEP -1

            place& = row% * 320&
            place& = place& + Col% * 4
            ' 4 bytes of pixel information are read in. Each
            '  of these bytes is broken up across 4 variables
            '  that are used to fire the printer pins. 2 bits
            '  from each pixel byte are stored to each of the
            '  variables.
            mem1% = 0           ' Initialize storage bytes for
            mem2% = 0           '   color information.
            mem3% = 0
            mem4% = 0
            FOR byte% = 0 TO 3
               newplace& = place& + byte%
               shift% = 2 ^ ((7 - 2 * byte%) - 1)
               mem% = PEEK(newplace&)
               mem% = mem% AND 3
               mem% = mem% * shift%
               mem1% = mem1% OR mem%

               mem% = PEEK(newplace&)
               mem% = (mem% AND 12) / 4
               mem% = mem% * shift%
               mem2% = mem2% OR mem%

               mem% = PEEK(newplace&)
               mem% = (mem% AND 48) / 16
               mem% = mem% * shift%
               mem3% = mem3% OR mem%

               mem% = PEEK(newplace&)
               mem% = (mem% AND 192) / 64
               mem% = mem% * shift%
               mem4% = mem4% OR mem%
            NEXT

            '--- Flip the byte, if called from
            IF flip% <> 0 THEN
               mem1% = 255 - mem1%
               mem2% = 255 - mem2%
               mem3% = 255 - mem3%
               mem4% = 255 - mem4%
            END IF

            '--- Send bytes to device
            line$ = CHR$(mem1%) + CHR$(mem2%)

            line$ = line$ + CHR$(mem3%) + CHR$(mem4%)
            PUT #1, , line$
         NEXT
         line$ = CHR$(13) + CHR$(10)
         PUT #1, , line$
      NEXT
      ResetPrn$ = esc$ + "@"
      PUT #1, , ResetPrn$  ' Reset printer
      line$ = CHR$(12)
      PUT #1, , line$      ' Send formfeed (page eject)
      CLOSE 1              ' All done
    END SUB


 735. L2029: "Unresolved Externals"; FORTRAN Variable Name Limit

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890811-30 B_BasicCom H_Fortran
 Last Modified: 21-DEC-1989    ArticleIdent: Q48056

 When LINKing inter-language object modules between QuickBASIC and
 FORTRAN, the error message L2029 "Unresolved Externals" may be
 displayed because of lengthy variable names. QuickBASIC allows
 variable names to extend to 40 characters, all of which are
 significant; however, depending on the version of FORTRAN, either 6 or
 31 characters are significant.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS,
 and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 When linking QuickBASIC and FORTRAN object files, be careful of which
 version of FORTRAN is being used and with what directives. When long
 SUBroutine or FUNCTION names are used, FORTRAN may truncate the name
 depending on the version and therefore cause the linker error message
 L2029 "Unresolved Externals."

 Microsoft FORTRAN Version 4.10 allows for variable names to be up to
 31 characters, all of which are considered significant. However, the
 default option for Version 4.10 is to truncate at the standard six (6)
 characters. This can cause problems when BASIC is calling a SUB or
 FUNCTION name that is greater than six characters in length.

 Microsoft FORTRAN Version 5.00 also allows variable names to be up to
 31 characters, all of which are considered significant. This is the
 default option, unlike FORTRAN Version 4.10. No variables are
 truncated unless they extend beyond the 31-character limit.

 FORTRAN offers the following three methods for alleviating this
 variable truncation and allows the programmer to easily change the way
 the FORTRAN compiler interprets the variable names.

 1. The compiler directive /4{Y|N}t allows you to change the
    translation method on the command line. /4Yt causes the FORTRAN 77
    defaults to be in effect. Variable names are truncated at 6
    characters in length. This is the default for FORTRAN Version 4.10.
    /4Nt allows the compiler to use Microsoft's 31 significant character
    variable names. This is the default for FORTRAN Version 5.00.

 2. The metacommand $STRICT can be placed directly into the FORTRAN
    code to allow different interpretations of the variable names. When
    the $STRICT metacommand is applied, FORTRAN 77 standards will be
    assumed. For FORTRAN Version 4.10 this is the default, but for
    FORTRAN Version 5.00, $NOSTRICT is the default.

 3. The metacommand $TRUNCATE can be placed directly in the FORTRAN
    code to force whether variable names are truncated at the 6
    character limit or $NOTRUNCATE can be used to force 31 character
    variable names. $TRUNCATE is the default for FORTRAN Version 4.10,
    and $NOTRUNCATE is the default for FORTRAN Version 5.00.


 736. Graphics Algorithm Different in QuickBASIC Versus GW-BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890811-64  B_BasicCom B_GWBasicI
 Last Modified: 15-DEC-1989    ArticleIdent: Q48058

 When constructing an image with multiple-line statements, the image
 may not appear as fully symmetrical as the x and y coordinates
 indicate. The algorithm used by QuickBASIC to draw the various graphic
 images executes the starting and ending coordinates in a specific
 order to produce the fastest results. This algorithm is different than
 that of GW-BASIC, where each line is drawn literally.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, to Microsoft BASIC
 PDS Version 7.00, and to Microsoft GW-BASIC Versions 3.20, 3.22, and
 3.23 for MS-DOS.

 The algorithm used by QuickBASIC to draw the various graphic images
 determines the fastest way to draw the image and then constructs that
 image on the screen. The LINE statement is the best example, with the
 following syntax:

    LINE (50,0) - (100,200)
    LINE (150,0) - (100,200)

 Under QuickBASIC, the algorithm draws the initial line, from (50,0) to
 (100,200), then evaluates the next statement and draws the next line
 from (100,200) to (150,0). GW-BASIC draws the first line similar to
 QuickBASIC, but then draws the next line from (150,0) to (100,200).

 This is not considered a problem, but is a feature of the QuickBASIC
 graphics algorithm that makes it faster and more efficient than the
 interpreted sequential method of graphics. This difference is
 illustrated when using a medium to low resolution graphics screen, as
 in the following code example. The two lines drawn do not look
 symmetrical under QuickBASIC, but are drawn identically under
 GW-BASIC. The two lines are exactly the same, but one is inverted from
 the other.

 Code Example
 ------------

 10 SCREEN 1
 20 LINE (160, 90)-(140, 1), 1
 30 LINE (162, 90)-(182, 1), 1


 737. "String Space Corrupt" If BSAVE Variable-Length-String Array

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890724-71 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q48059

 If you want to use BSAVE and BLOAD with string arrays, you must use an
 array of fixed-length strings. Fixed-length strings are available in
 Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS, in
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and in
 Microsoft BASIC PDS Version 7.00, but not in earlier versions.

 Arrays of variable-length strings CANNOT be BSAVEd to a file, nor can
 a file that was BSAVEd from a variable-length-string array be BLOADed
 into another variable-length-string array. A "String space corrupt"
 error message can display if you attempt to BLOAD a file into a
 variable-length-string array, because the pointers in the BSAVEd
 string descriptors will overlay and tangle existing pointers to string
 space. This is the same mistake as POKEing a spurious value into a
 string descriptor, which can corrupt the integrity of string space.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2.

 Each element of variable-length-string array has a 4-byte string
 descriptor composed of an offset (a 2-byte pointer) and length field
 (2 bytes). The array of string descriptors is stored sequentially, but
 the actual contents of the strings are stored separately in the
 dynamic string space. Each 2-byte offset points to a location in the
 string space. The string space memory is very dynamic, and strings are
 given new offsets whenever new string values are reassigned. The
 string contents of an array are not usually adjacent, especially if
 they have been reassigned values. As a result, BSAVEing a certain
 number of bytes does not mean that you've BSAVEd the contents of the
 variable-length-string array.

 The following code example attempts to BSAVE a variable-length-string
 array, but generates the error "String Space Corrupt" when run within
 the QuickBASIC QB.EXE Version 4.00, 4.00b, or 4.50 environment.

 To work around this situation, create fixed-length-string arrays and
 BSAVE that information. Fixed-length-string space is allocated
 statically and sequentially in memory, and can be BSAVEd and BLOADed.

 Code Example
 ------------

 This example requires Microsoft QuickBASIC Version 4.00, 4.00b, or
 4.50 for MS-DOS, Microsoft BASIC Compiler Version 6.00 or 6.00b for
 MS-DOS, or Microsoft BASIC PDS Version 7.00 for MS-DOS.

 To alter this program to work correctly, change the DIMension
 statements to create a fixed-length-string array and BSAVE just that
 many bytes.

 OPTION BASE 1
 DIM Arr1$(10)   ' Instead, use DIM Arr1(10) AS STRING*20
 DIM Arr2$(10)   ' Instead, use DIM Arr2(10) AS STRING*20
 StrDesc% = 4
 ArrayLength% = 0
 PRINT "This is the BSAVE array:"
 PRINT
 FOR I = 1 TO 10
    Arr1$(I) = "TEST" + STR$(I)
    ArrayLength% = ArrayLength% + LEN(Arr1$(I))
    PRINT Arr1$(I)
 NEXT I

 DEF SEG = VARSEG(Arr1$(1))
 ' In BC.EXE and QBX.EXE for BASIC 7.00 use SSEG for far variable
 ' length strings.

 BSAVE "Test.Dat", VARPTR(Arr1$(1)), ArrayLength% + StrDesc%
 DEF SEG
 PRINT
 PRINT "Hit a Key"
 PRINT
 SLEEP
 DEF SEG = VARSEG(Arr2$(1))
 ' In BC.EXE and QBX.EXE for BASIC 7.00 use SSEG for far variable
 ' length strings.

 BLOAD "Test.Dat", VARPTR(Arr2$(1))
 DEF SEG
 PRINT "This is the BLOADed array:"
 PRINT
 FOR I = 1 TO 10
    PRINT Arr2$(I)
 NEXT I


 738. Example of BASIC Function Returning a String to C

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified: 10-AUG-1990    ArticleIdent: Q48205

 The two programs below demonstrate how a Microsoft BASIC function can
 return a string to C.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For BASIC PDS 7.00 and 7.10, this example applies to near strings
 only. If you are using far strings (/Fs during compile or in the
 QBX.EXE environment), you must use the string-manipulation routines
 supplied with BASIC PDS 7.00 and 7.10 (StringAssign, StringRelease,
 StringAddress, and StringLength). For more information about using far
 strings, see Chapter 13 of the "Microsoft BASIC 7.0: Programmer's
 Guide" for versions 7.00 and 7.10.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, search in the Software/Data Library for the following
 word:

    BAS2C

 Code Example
 ------------

 The following BASIC program is BSTRF.BAS, which contains a function
 that returns a string to a calling C routine:

    DECLARE SUB CSUB CDECL ()
    CALL CSUB
    END

    FUNCTION basvarfunc$(dummy%)
       basvarfunc$ = "This is the string"
    END FUNCTION

 The following program is CSTRF.C, which calls a BASIC routine that
 returns a string. A string descriptor is created to receive the data
 returned by the BASIC function.

 #include <stdio.h>
 struct stringdesc
        {
         int length;       /* string length */
         char *string;     /* string address */
        };
 extern struct stringdesc * pascal basvarfunc(int *dummy);
 struct stringdesc *std;
 void csub()
 {
    int i;

    std = basvarfunc(0);

    printf("Length of string: %2d\r\n", std->length);

    for(i = 0; i < std->length; i++)
       printf("%c", std->string[i]);

    printf("\r\n");

 }

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTRF.BAS;
    CL /c /AM CSTRF.C;
    LINK /NOE BSTRF CSTRF;

 BSTRF.EXE produces the following output:

    Length of String: 18
    This is the string


 739. Example of C Functions Returning Numeric Types to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified: 20-DEC-1989    ArticleIdent: Q48206

 The two programs shown below demonstrate how Microsoft C functions can
 return common numeric types to BASIC.

 This information about inter-language calling applies to QuickBASIC
 Versions 4.00, 4.00b, 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library for the following
 word:

    BAS2C

 Code Example
 ------------

 The following BASIC program is BFUNC.BAS, which invokes several C
 functions, and prints out the values returned by the functions:

 DECLARE FUNCTION cintfunc% CDECL ()
 DECLARE FUNCTION clongfunc& CDECL ()
 DECLARE FUNCTION cdoublefunc# CDECL ()
 PRINT "Integer: "; cintfunc
 PRINT "Long   : "; clongfunc
 PRINT "Double : "; cdoublefunc

 The following program is CFUNC.C, which contains several functions
 called from BASIC. These functions return standard numeric types to
 the calling BASIC program.

 int cintfunc(void)        /* BASIC INTEGER */
 {
    int theint = 32767;
    return(theint);
 }

 long clongfunc(void)      /* BASIC LONG */
 {
    long thelong = 32769;

    return(thelong);
 }

 double cdoublefunc(void)  /* BASIC DOUBLE */
 {
    double thedouble = 129381.123;
    return(thedouble);
 }

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BFUNC.BAS;
    CL /c /AM CFUNC.C;
    LINK /NOE BFUNC CFUNC;

 BFUNC.EXE produces the following output:

    Integer:  32767
    Long   :  32769
    Double :  129381.123


 740. Example of Passing Strings from C to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified: 10-AUG-1990    ArticleIdent: Q48207

 The two programs below demonstrate how Microsoft C can create and pass
 both fixed-length and variable-length strings to Microsoft BASIC.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For BASIC PDS 7.00 and 7.10, this example works only with near
 strings. If you are using far strings (BC /Fs compile switch or in
 QBX.EXE), you must use the string-manipulation routines provided with
 BASIC PDS 7.00 and 7.10 to change variable-length strings
 (StringAssign, StringRelease, StringAddress, and StringLength). For
 more information about using far strings, see Chapter 13 of the
 "Microsoft BASIC 7.0: Programmer's Guide" for versions 7.00 and 7.10.

 For more information about passing other types of parameters between
 BASIC and C and a list of which BASIC and C versions are compatible
 with each other, search in the Software/Data Library for the following
 word:

    BAS2C

 Code Example
 ------------

 The following BASIC program is BSUB.BAS, which invokes a C routine
 that creates two strings and passes them to a BASIC subroutine. The
 BASIC subroutine prints out the string (and the string's length)
 received from the C routine.

    DECLARE SUB CSUB CDECL()
    TYPE fixstringtype        ' Must use type to pass fixed-length string
       B AS STRING * 26       '  in parameter list.
    END TYPE
    CALL CSUB
    END

    SUB BASSUB(A$, B AS fixstringtype)  ' Subroutine called from C
       PRINT A$
       PRINT LEN(A$)
       PRINT B.B
       PRINT LEN(B.B)
    END SUB

 The following program is CSUB.C, which builds a string descriptor that
 is passed to a called BASIC subroutine:

 #include <string.h>
 struct stringdesc
        {
         int length;       /* string length */
         char *string;     /* near address of the string */
        };
 extern void pascal bassub(struct stringdesc *basstring,
                           char *basfixstring);
 struct stringdesc *std;
 char thesecondstring[26];

 void csub()
 {                                         /* create the strings */
    std->length = 18;
    strcpy(std->string, "This is the string");
    strcpy(thesecondstring, "This is the second string");
    bassub(std, thesecondstring);          /* call BASIC subroutine */
 }

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSUB.BAS;
    CL /c /AM CSUB.C;
    LINK /NOE BSUB CSUB;

 BSUB.EXE produces the following output:

    This is the string
    18
    This is the second string
    26


 741. Example Passing char from C to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified:  7-FEB-1990    ArticleIdent: Q48208

 The two programs shown below demonstrate how a Microsoft C routine can
 pass a char to BASIC.

 This information about interlanguage calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library for the following
 word:

    BAS2C

 Code Example
 ------------

 The following BASIC program is BSUB.BAS, which invokes a C routine
 that passes a char to a BASIC subroutine, which then prints out the
 received character (and its length):

 DECLARE SUB CSUB CDECL()
 TYPE char                  ' must declare user-defined TYPE to hold
    character AS STRING *1  '  char, as there are no single-byte
 END TYPE                   '  TYPEs in BASIC
 CALL CSUB
 END

 SUB BASSUB(cchar AS char) ' subroutine called by C routine
    PRINT cchar.character
    PRINT LEN(cchar.character)
 END SUB

 The following program is CSUB.C, which passes a char to a BASIC
 subroutine:

 #include <stdio.h>
 struct character         /* must declare as struct so type casting */
        {                 /* won't affect value */
           char thechar;
        };
 extern void pascal bassub(struct character *baschar);
 struct character *c_char;

 void csub()
 {
    c_char->thechar = 'A';
    bassub(c_char);

 }

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSUB.BAS;
    CL /c /AM CSUB.C;
    LINK /NOE BSUB CSUB;

 BSUB.EXE produces the following output:

    A
    1


 742. Using RUN with No Argument Inside SUB Should Cause Error

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 docerr
 Last Modified:  8-NOV-1990    ArticleIdent: Q48398

 In the QB.EXE or QBX.EXE environment, a RUN statement with no
 <filename> argument fails to give a "Subprogram Error" and may hang
 under certain conditions (see Program #3 below) when invoked inside a
 SUBprogram (SUB .. END SUB). This improper use of RUN correctly
 produces a "Subprogram Error" when compiled with BC.EXE in QuickBASIC
 versions 4.00, 4.00b, and 4.50 and in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of QuickBASIC versions 4.00, 4.00b, and 4.50 for MS-DOS; in the QB.EXE
 environment of Microsoft BASIC Compiler versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b) for MS-DOS; and in the QBX.EXE environment
 of Microsoft BASIC PDS versions 7.00 and 7.10 (buglist7.00,
 buglist7.10) for MS-DOS. We are researching this problem and will post
 new information here as it becomes available.

 Normally, the RUN statement with no argument restarts the current
 program. However, using RUN with no argument to restart a program is
 allowed only in the module-level code of a program, not in a
 SUBprogram or FUNCTION procedure. In a SUBprogram or FUNCTION
 procedure, you must use RUN <filename>, since RUN <linenumber> and RUN
 with no argument are not allowed in SUBprograms. However, you can use
 RUN <filename> to have a program run itself from within a SUBprogram
 or FUNCTION.

 The appropriate use of RUN is correctly documented on Page 367 of the
 "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual:

    Because a line number in a RUN statement must refer to a line in
    the module-level code, only the RUN "filespec" form of the
    statement is allowed in a SUB or FUNCTION.

 The above correct statement should replace the incorrect statements
 described further below.

 Documentation Error
 -------------------

 The RUN <linenumber> option is incorrectly documented on Page 317 of
 the "Microsoft QuickBASIC 4.5: BASIC Language Reference" manual for
 version 4.50 and on Page 303 of the "Microsoft BASIC 7.0: Language
 Reference" manual for BASIC PDS versions 7.00 and 7.10. These pages
 give the following incorrect statements:

    Therefore, a RUN statement in a SUB or FUNCTION procedure must
    point to labels at module level. If no line label is given,
    execution always starts with the first executable line of the
    main module.

 This same documentation error occurs in the QB Advisor online Help
 system for QuickBASIC 4.50 and in the Microsoft Advisor online Help
 system for BASIC PDS 7.00 and 7.10 and can be found as follows from
 within the QB.EXE environment or QBX.EXE environment:

 1. Press SHIFT+F1.

 2. Select Index.

 3. Type "R".

 4. Double-click the left mouse button on "RUN statement" or position
    the cursor on "RUN" and press ENTER.

 5. Select Details.

 Program #1
 ----------

 Program #1 below correctly causes a "Subprogram Error" during
 compilation with BC.EXE 4.00, 4.00b, and 4.50, but the QB.EXE or
 QBX.EXE editor fails to give you an error message, and the RUN
 executes:

    ' **** PROGRAM #1: Test.Bas
    ' Main level (module level):
    PRINT "Inside Main Level"
    CALL Test
    ' Subprogram level:
    SUB Test
    PRINT "Inside Test"
    RUN
    END SUB

 Program #2
 ----------

 Program #2 below is the correct method for using RUN (with a
 <filename> argument) in a SUBprogram, and it works when the program is
 either compiled with BC.EXE or run in the QB.EXE or QBX.EXE editor:

    ' **** Program #2: Test.Bas
    ' Main level (module level):
    PRINT "Inside Main Level"
    CALL Test
    ' Subprogram level:
    SUB Test
    PRINT "Inside Test"
    RUN "Test"   ' This is legal for both QB.EXE/QBX.EXE and BC.EXE
    END SUB

 Program #3
 ----------

 In QB.EXE or QBX.EXE, your program may hang if the RUN statement is
 invoked with no parameters (or with a line number) in a non-STATIC SUB
 or FUNCTION procedure, and the SUB or FUNCTION procedure uses DIM or
 REDIM to dimension a dynamic array local to that procedure:

    'Warning!!!!! This program is going to hang your machine.
    DECLARE SUB sub1 ()
    sub1
    END
    SUB sub1
       DIM y(1)
       y(1) = 1
       PRINT y(1);
       ' Note: Invoking ERASE Y before the RUN will prevent the hang.
       ' Must then press CTRL+BREAK to stop the program, since it keeps
       ' running itself.
       RUN
    END SUB

 You can change Program #3 to run successfully without hanging in
 QB.EXE/QBX.EXE if you do one of the following:

 1. ERASE the local dynamic array(s) before the RUN.

 2. Make the SUB STATIC.

 3. Make the array global by dimensioning it with DIM SHARED or COMMON
    SHARED at the module level of the program.

 4. Pass the array as a parameter to the SUBprogram.

 Additional reference words: B_BasicCom SR# S900919-42 SR# S890801-4


 743. Why QuickBASIC Is Incompatible with Many TSR Programs

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890801-3 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q48399

 This article summarizes Microsoft's response to the question of why
 many TSR (terminate and stay resident) programs are incompatible with
 Microsoft QuickBASIC for the IBM Personal Computers and compatibles.

 For similar information regarding hardware incompatibility, query
 on the following words:

    incompatible and video and hardware and QuickBASIC

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS and to Microsoft BASIC Compiler 6.00, and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC PDS 7.00 for MS-DOS and
 OS/2.

 The QuickBASIC environment is a highly sophisticated development tool
 tuned for simultaneous usability, speedy performance, and efficient
 size, insuring a maximally responsive environment while retaining
 capacity. One technique used to achieve this goal was to hand code the
 majority of the speed-critical areas in assembly language, including
 all parts of the language engine and I/O support. Our constant aim is
 to create program development environments that are unmatched in the
 areas of responsiveness and programmer productivity. The alternative
 is to have a text editor environment capable of spawning off what are
 fundamentally command-line tools.

 The result of this challenging objective is a dynamic technical
 accomplishment -- the QuickBASIC environment allows you to climb
 inside the language "engine" and vary the execution paths, manipulate
 your data, and edit and test your source code all without recompiling.
 If QuickBASIC is ill-behaved when TSR software is also present, it's
 the sort of behavior that hundreds of thousands of QuickBASIC
 programmers have decided is well worth the cost for the benefits it
 delivers.

 The conflict with TSR software is difficult to avoid in the
 ultrasophisticated low-level technology of QuickBASIC's magnitude.
 While we make every effort to retain TSR and hardware compatibility,
 we are faced with the challenge of identifying those configurations
 that are important enough to support with added code (thus sacrificing
 environment capacity), while trying to retain the maximum speed and
 work space that the majority of users, not using that specific
 configuration, not only appreciate but demand.

 The alternative for people who want environments that do not take over
 the machine is the more traditional and less responsive text editor or
 command-line compiler programming technique, which is certainly
 available to all QuickBASIC owners. But for those who appreciate the
 unique advantages of BASIC in its instant environment and do not want
 to trade productivity for low-level machine control, QuickBASIC is
 available for them. And for many people, this is a very reasonable and
 acceptable trade-off.


 744. Multi-DIMensioned Arrays Are in Column Order; BC /R Row Order

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890801-7 B_BasicCom
 Last Modified: 28-DEC-1989    ArticleIdent: Q48401

 By default, multidimensional arrays are stored in contiguous columns
 in memory (that is, column-major order) in compiled BASIC. With
 column-major order, the leftmost subscript (the row dimension)
 changes the fastest.

 You can force executable .EXE programs to store arrays in rows by
 using the BC /R option. However, the /R option (for row-major order)
 is not available in the QB.EXE or the QBX.EXE editor environment. With
 row-major order, the rightmost subscript (the column dimension)
 changes the fastest.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS.

 In the DIM X(row,column) statement, arrays are stored by default in
 column order in memory. When looking at a contiguous block of memory
 that is storing a two-dimensional array, you'll find one column stored
 after another. For example, for DIM X(2,2), the array elements are
 stored by default in the following column-major order:

    X(0,0), X(1,0), X(2,0), X(0,1), X(1,1), X(2,1), X(0,2), X(1,2), X(2,2)

 If you compile the program with BC /R, you get row-major order, as
 follows:

    X(0,0), X(0,1), X(0,2), X(1,0), X(1,1), X(1,2), X(2,0), X(2,1), X(2,2)

 An easy way to demonstrate the storage order is to BSAVE a two-
 dimensional array and then BLOAD the same data into a one-dimensional
 array. You then have a firsthand view of how the array is stored.

 Unlike BASIC, Microsoft C defaults to row-major order.

 This array-order information is taken from Page 313 of the "Microsoft
 QuickBASIC 4.0: Learning and Using" manual for QuickBASIC Versions
 4.00 and 4.00b, from Page 313 of the "Microsoft BASIC Compiler 6.0:
 Learning and Using Microsoft QuickBASIC" manual for Versions 6.00 and
 6.00b, and from Page 560 of the "Microsoft BASIC 7.0: Programmer's
 Guide" for BASIC PDS Version 7.00.


 745. QB 4.50 .EXE Program Might Print DYNAMIC Arrays Incorrectly

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890809-44 buglist4.50
 Last Modified: 17-JAN-1991    ArticleIdent: Q48669

 DYNAMIC arrays might not PRINT correctly when using the PRINT TAB(nn),
 SPC(nn), or SPACE$(nn) statement in .EXE programs compiled with BC.EXE
 in Microsoft QuickBASIC version 4.50. The problem does not occur in
 the QB.EXE editor environment.

 This problem can occur when PRINTing any DYNAMIC array, and compiling
 the program without the /D (DEBUG), /X (RESUME), or /AH (HUGE ARRAYS)
 switch. STATIC arrays print correctly regardless of the compiler
 switches used.

 Microsoft has confirmed this to be a problem in version 4.50. This
 problem is corrected in Microsoft BASIC Professional Development
 System (PDS) version 7.00 (fixlist7.00).

 This problem does not occur in Microsoft QuickBASIC version 4.00 or
 4.00b or in Microsoft BASIC Compiler version 6.00 or 6.00b.

 To work around the problem in 4.50, compile with one or all of the
 following compiler switches: /d /x /ah. For example:

    BC filename /d /x /ah;

 The problem can also be corrected by using STATIC arrays rather than
 DYNAMIC arrays.

 Code Example
 ------------

 ' $STATIC

 DIM SVarStr$(3)
 DIM SFixStr(3) AS STRING * 4
 DIM SInt%(3)
 DIM SSgl!(3)

 ' $DYNAMIC

 DIM DVarStr$(3)
 DIM DFixStr(3) AS STRING * 4
 DIM DInt%(3)
 DIM DSgl!(3)

 CLS

 FOR A% = 1 TO 3
     SVarStr$(A%) = STR$(A%)
     DVarStr$(A%) = STR$(A%)

     SFixStr(A%) = STR$(A%)
     DFixStr(A%) = STR$(A%)

     SInt%(A%) = A%
     DInt%(A%) = A%

     SSgl!(A%) = A%
     DSgl!(A%) = A%
 NEXT A%

 PRINT "STATIC AND DYNAMIC ARRAYS USING TAB(nn)"
 PRINT
 PRINT TAB(5); SVarStr$(1); TAB(12); SVarStr$(2); TAB(18); SVarStr$(3)
 PRINT TAB(5); DVarStr$(1); TAB(12); DVarStr$(2); TAB(18); DVarStr$(3)
 PRINT
 PRINT TAB(5); SFixStr(1); TAB(12); SFixStr(2); TAB(18); SFixStr(3)
 PRINT TAB(5); DFixStr(1); TAB(12); DFixStr(2); TAB(18); DFixStr(3)
 PRINT
 PRINT TAB(5); SInt%(1); TAB(12); SInt%(2); TAB(18); SInt%(3)
 PRINT TAB(5); DInt%(1); TAB(12); DInt%(2); TAB(18); SInt%(3)
 PRINT
 PRINT TAB(5); SSgl!(1); TAB(12); SSgl!(2); TAB(18); SSgl!(3)
 PRINT TAB(5); DSgl!(1); TAB(12); DSgl!(2); TAB(18); SSgl!(3)
 PRINT
 PRINT "STATIC AND DYNAMIC ARRAYS USING SPACE(nn)"
 PRINT
 PRINT SPACE$(5); SVarStr$(1); SPACE$(5); SVarStr$(2);
 PRINT SPACE$(5); SVarStr$(3)
 PRINT SPACE$(5); DVarStr$(1); SPACE$(5); DVarStr$(2);
 PRINT SPACE$(5); DVarStr$(3)
 PRINT
 PRINT SPACE$(5); SFixStr(1); SPACE$(5); SFixStr(2);
 PRINT SPACE$(5); SFixStr(3)
 PRINT SPACE$(5); DFixStr(1); SPACE$(5); DFixStr(2);
 PRINT SPACE$(5); DFixStr(3)
 PRINT
 PRINT SPACE$(5); SInt%(1); SPACE$(5); SInt%(2); SPACE$(5); SInt%(3)
 PRINT SPACE$(5); DInt%(1); SPACE$(5); DInt%(2); SPACE$(5); DInt%(3)
 PRINT
 PRINT SPACE$(5); SSgl!(1); SPACE$(5); SSgl!(2); SPACE$(5); SSgl!(3)
 PRINT SPACE$(5); DSgl!(1); SPACE$(5); DSgl!(2); SPACE$(5); DSgl!(3)
 PRINT
 PRINT "STATIC AND DYNAMIC ARRAYS USING SPC(nn)"
 PRINT
 PRINT SPC(5); SVarStr$(1); SPC(5); SVarStr$(2); SPC(5); SVarStr$(3)
 PRINT SPC(5); DVarStr$(1); SPC(5); DVarStr$(2); SPC(5); DVarStr$(3)
 PRINT
 PRINT SPC(5); SFixStr(1); SPC(5); SFixStr(2); SPC(5); SFixStr(3)
 PRINT SPC(5); DFixStr(1); SPC(5); DFixStr(2); SPC(5); DFixStr(3)
 PRINT
 PRINT SPC(5); SInt%(1); SPC(5); SInt%(2); SPC(5); SInt%(3)
 PRINT SPC(5); DInt%(1); SPC(5); DInt%(2); SPC(5); DInt%(3)
 PRINT
 PRINT SPC(5); SSgl!(1); SPC(5); SSgl!(2); SPC(5); SSgl!(3)
 PRINT SPC(5); DSgl!(1); SPC(5); DSgl!(2); SPC(5); DSgl!(3)
 PRINT
 END

 The values in the DYNAMIC arrays in the above program will PRINT
 unpredictably on all machines -- the values can vary depending on the
 hardware configuration.


 746. "SELECT Without END SELECT" Flagged in Wrong Place by QB 4.00

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 27-FEB-1990    ArticleIdent: Q49130

 The QB.EXE editor in QuickBASIC Versions 4.00, 4.00b, and 4.50 flags
 the error "SELECT without END SELECT." However, the editor does not
 correctly locate and highlight the area of the code where the error
 occurs. The editor incorrectly places the cursor (or highlighting) at
 the top right corner or "home" of the current window, even though the
 error may have occurred several pages down.

 Microsoft has confirmed this to be a problem in QB.EXE in QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS. This problem was corrected
 in the QBX.EXE environment supplied with Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2
 (fixlist7.00).

 Whenever a mismatch occurs with two paired statements, the editor
 should highlight the other member of the pair when it reports an error
 message. For example, if a program contains a multiple-line IF
 statement but fails to include the END IF statement, the editor should
 locate the error, highlight the IF keyword, and then display the error
 message in a dialog box. However, for the error "SELECT without END
 SELECT," the editor incorrectly fails to highlight the SELECT
 statement that is missing a matching END SELECT phrase.

 Code Example
 ------------

 The following code example demonstrates the problem:

 REM <-- The QB.EXE editor misleadingly highlights this topmost REM
 REM     statement when the "SELECT without END SELECT" error
 REM     occurs, no matter where the SELECT error is located in
 REM     this window.
 SELECT CASE x%
 CASE 1
 CASE 2
    ' END SELECT  ' Adding this END SELECT corrects the syntax error.

 The error-flagging location problem does not occur for IF statements,
 as in the following example:

 REM  QB.EXE correctly highlights "IF" for the following
 REM  "Block IF Without END IF" error:
 IF x% THEN
    PRINT "hello"
       ' END IF ' Adding this END IF corrects the syntax error.


 747. "Subscript Out of Range" Using ERASEd Array in a SUB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 27-FEB-1990    ArticleIdent: Q49210

 In the QuickBASIC editor, the ERASE statement frees the memory for an
 array DIMensioned in a non-STATIC SUBprogram, even if the $STATIC
 metacommand is used. Because the memory for the array has been
 deallocated, a "Subscript out of range" error results the next time an
 attempt is made to access the array beyond element 10.

 Microsoft has confirmed this to be a problem in QB.EXE in QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS. This problem was corrected
 in the QBX.EXE environment of Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 This behavior does not occur in a compiled .EXE program. In an .EXE
 program, a $STATIC array DIMensioned in a SUBprogram that is ERASEd
 remains allocated, and the ERASE initializes all elements to their
 default value (0 or "").

 Workarounds
 -----------

 The best workaround is to reinitialize the array without using the
 ERASE statement. Alternatively, you can DIM the array at the main
 module level and share it with the SUBprogram with the SHARED
 statement. Both methods ensure that memory for the array is not freed
 by ERASE.

 Another possible workaround for this problem is to make the SUBprogram
 STATIC by placing the STATIC clause on the SUB or FUNCTION statement.
 This method should be used with caution. Normally, BASIC allocates
 memory for variables in SUBprograms on the stack, and the memory is
 released when the SUB is exited. Making the SUBprogram STATIC causes
 all variables in the SUBprogram to be permanently allocated, which
 permanently reduces the space available for other variables and
 strings. A STATIC SUBprogram also has to initialize its own variables,
 and a STATIC SUBprogram cannot be recursive.

 Code Example
 ------------

 The following program demonstrates the "Subscript out of range" error
 caused by erasing an array that was DIMensioned in a non-STATIC
 SUBprogram in the QuickBASIC QB.EXE environment:

 DECLARE SUB Test ()
 CALL Test
 END

 SUB Test
   DIM A$(100)
   ERASE A$
   PRINT A$(80)           ' "Subscript Out of Range" occurs.
 END SUB

 Workaround 1
 ------------

 Initialize the array without ERASE, as follows:

 DECLARE SUB Test ()
 CALL Test
 END

 SUB Test
   DIM A$(100)
   FOR I = 1 TO 100
       A$(I) = ""
   NEXT
   PRINT A$(80)
 END SUB

 Workaround 2
 ------------

 DIM the array in the main level of the module and SHARE it in the SUB,
 as follows:

 DECLARE SUB Test ()
 DIM A$(100)
 CALL Test
 END

 SUB Test
   SHARED A$()
   ERASE A$
   PRINT A$(80)
 END SUB

 Workaround 3
 ------------

 Use a STATIC SUBprogram, as follows:

 DECLARE SUB Test ()
 CALL Test
 END

 SUB Test STATIC          'Added STATIC
   DIM A$(100)
   ERASE A$
   PRINT A$(80)
 END SUB


 748. How to Save and Restore the VGA Palette Registers in BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891017-45 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q50000

 In Microsoft QuickBASIC, a program can save and restore the VGA
 PALETTE registers using the CALL INTERRUPT statement. This can be
 useful when SHELLing to other programs that might change the PALETTE
 registers.

 This can also be used along with BSAVE and BLOAD to save graphic
 images. BLOAD and BSAVE save the binary image of the graphic image,
 but not the color PALETTE. The INTERRUPT can be used to read the
 PALETTE registers into an array, which can then be saved along with
 the graphic image.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The BASIC program below is SAVPAL.BAS, which displays a multicolored
 image and then restores the palette registers after setting all of the
 palette registers to black.

 To demonstrate this program from an .EXE program, compile and link as
 follows:

    BC SAVEPAL.BAS;
    LINK SAVEPAL;

 If running the program from the QuickBASIC editor environment, the
 Quick library QB.QLB must be loaded in. This can be done with the
 following command line:

    QB SAVPAL /L

 If running in the BASIC Compiler 7.00 QuickBASIC Extended environment,
 the Quick library QBX.LIB must be loaded in. This can be done with
 the following command line:

    QBX SAVEPAL /L

 Code Example
 ------------

 TYPE colortype           ' structure to hold RGB color palette
    red AS STRING * 1
    green AS STRING * 1
    blue AS STRING * 1
 END TYPE

 REM $INCLUDE: 'qb.bi'    ' defines for CALL INTERRUPTX
 ' For QBX.EXE environment use the include file 'QBX.BI'

 DIM inregsx AS RegTypeX
 DIM outregsx AS RegTypeX
 DIM colorbuf(255) AS colortype
 SCREEN 13

 inregsx.ax = &H1017      ' BIOS interrupt to save palette registers
 inregsx.bx = 0
 inregsx.cx = 256         ' save all 256 color registers
 inregsx.es = VARSEG(colorbuf(0))  ' address of array holding palette
 inregsx.dx = VARPTR(colorbuf(0))

 CALL INTERRUPTX(&H10, inregsx, outregsx)  ' save palette registers

 FOR i% = 2 TO 255      ' display colorful pattern
    LINE (i%, 10)-(i%, 199), i%
 NEXT

 LOCATE 1, 1
 COLOR 1
 PRINT "press any key to blank palette"
 WHILE INKEY$ = "": WEND

 FOR i% = 2 TO 255  ' set all but first palette register to black
         PALETTE i%, 0
 NEXT

 LOCATE 1, 1
 PRINT "press any key to restore palette"

 WHILE INKEY$ = "": WEND

 inregsx.ax = &H1012      ' BIOS interrupt to restore palette registers
 inregsx.bx = 0
 inregsx.cx = 256         ' restore all 256 color registers
 inregsx.es = VARSEG(colorbuf(0))  ' address of array holding palette
 inregsx.dx = VARPTR(colorbuf(0))

 CALL INTERRUPTX(&H10, inregsx, outregsx)  ' restore palette registers


 749. No Watch in Debug Menu of QBI.EXE Interpreter Academic Edition

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S890906-36
 Last Modified: 18-OCT-1989    ArticleIdent: Q49258

 Microsoft QuickBASIC Interpreter (QBI) Academic Edition Version 1.00
 was shipped in a box that mistakenly shows a picture of Microsoft
 QuickBASIC Version 4.50 screen menus. The Debug menu in QuickBASIC
 4.50 has Watch... features that are not available in the QuickBASIC
 Academic Edition Interpreter (QBI.EXE) Version 1.00.

 The Watch... features shown on the Academic Edition (QBI.EXE) 1.00
 package are available in QuickBASIC 4.50, which is a more complete and
 powerful product.

 The QuickBASIC Academic Edition Interpreter (QBI.EXE) Version 1.00
 doesn't have any of the following Debug menu features, but QuickBASIC
 (QB.EXE) Version 4.50 does have them:

    Add Watch...
    Instant Watch...
    Delete Watch...

 Where these menu items appear in the Debug menu on the package
 picture, QBI.EXE actually has Step and Procedure Step options. The
 Debug menu in QBI.EXE actually displays as follows:

    Step                    F8
    Procedure Step          F10
    Trace On
    Toggle Breakpoint       F9
    Clear All Breakpoints
    Set Next Statement


 750. Example of Passing BASIC String Descriptor to MASM (Far)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49382

 The two programs shown below demonstrate how a Microsoft BASIC program
 passes a string descriptor to assembly language by far reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BSTRF.BAS, which passes a string
 descriptor (of a variable-length string) to assembly language by far
 reference:

    A$ = "This is the String" + "$"    ' "$" terminates the string for
                                       ' INT call
    CALLS RString(A$)   ' CALLS passes far address
    END

 The following program is ASTRF.ASM, which gets a BASIC string
 descriptor, then prints the string:

 ; The following handy .MODEL directive is found in MASM 5.10 but not
 ; in earlier versions:
 .MODEL MEDIUM, BASIC
 .CODE
         PUBLIC RString
 RString PROC
         push bp
         mov bp, sp       ; set stack frame
         push ds
         mov ds, [bp+8]   ; segment of descriptor
         mov bx, [bp+6]   ; offset of descriptor
         mov dx, [bx+2]   ; address of actual string
         mov ah, 9        ; DOS interrupt to print string
         int 21h
         pop ds
         pop bp
         ret 4
 RString ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTRF.BAS;
    MASM ASTRF.ASM;
    LINK BSTRF ASTRF;

 BSTRF.EXE produces the following output:

    This is the string


 751. Example Passing Numerics from BASIC to MASM by Near Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49383

 The two programs shown below demonstrate how a Microsoft BASIC program
 can pass standard numeric types to assembly language routines.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BNUMNEAR.BAS, which passes standard
 numeric types (by near reference) to assembly language routines:

    DECLARE SUB Numint(i%)
    DECLARE SUB Numlong(l&)
    DECLARE SUB Numsng(s!)
    DECLARE SUB Numdbl(d#)
    i% = 2                   ' Initialize values
    l& = 4
    s! = 3.4
    d# = 5.6
    CLS
    PRINT "         BEFORE","AFTER"
    PRINT "Integer: ";i%,,
    CALL Numint(i%)
    PRINT i%

    PRINT "Long   : ";HEX$(l&),,
    CALL Numlong(l&)
    PRINT HEX$(l&)

    PRINT "Single : ";s!,
    CALL Numsng(s!)
    PRINT s!

    PRINT USING "Double : ##.####            ";d#,
    CALL Numdbl(d#)
    PRINT USING "##.####"; d#

    END

 The following assembler program is ANUMNEAR.ASM, which accepts
 standard numerics by near reference and alters their values:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .CODE
         PUBLIC Numint, Numlong, Numsng, Numdbl
 Numint  PROC
         push bp
         mov bp, sp        ; set stack frame
         mov bx, [bp+6]
         mov ax, [bx]   ; get integer
         shl ax, 1         ; multiply by 2
         mov [bx], ax   ; put new value back
         pop bp
         ret 2
 Numint  ENDP

 Numlong PROC
         push bp
         mov bp, sp        ; set stack frame
         mov bx, [bp+6]
         mov cx, [bx]   ; get long
         mov ax, [bx+2] ; switch high and low words
         mov [bx+2], cx ; put new value back
         mov [bx], ax
         pop bp
         ret 2
 Numlong ENDP

 Numsng  PROC
         push bp
         mov bp, sp        ; set stack frame
         mov bx, [bp+6]
         or byte ptr [bx+2],80h   ; Set sign bit
         pop bp
         ret 2
 Numsng  ENDP

 Numdbl  PROC
         push bp
         mov bp, sp         ; set stack frame
         mov bx, [bp+6]
         or byte ptr [bx+6],80h  ; Set sign bit
         pop bp
         ret 2
 Numdbl  ENDP

         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC /O BNUMNEAR.BAS;
    MASM ANUMNEAR.ASM;
    LINK BNUMNEAR ANUMNEAR;

 BNUMNEAR.EXE produces the following output:

            BEFORE     AFTER
    Integer:  2          4
    Long   :  4          40000
    Single :  3.4       -3.4
    Double :  5.6000    -5.6000


 752. Example of Passing BASIC String Descriptor to MASM (Near)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 10-AUG-1990    ArticleIdent: Q49384

 The two programs below demonstrate how a Microsoft BASIC program
 passes a BASIC string descriptor to assembly language by near
 reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library or the Microsoft
 Knowledge Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BSTRN.BAS, which passes a string
 descriptor to assembly language by near reference:

    DECLARE SUB RString(A AS STRING)
    A$ = "This is the String" + "$"  ' "$" terminates the string
                                     '     for INT call
    CALL RString(A$)
    END

 The following program is ASTRN.ASM, which gets a string descriptor
 from BASIC by near reference and prints the string out:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .CODE
         PUBLIC RString
 RString PROC
         push bp
         mov bp, sp
         mov bx, [bp+6]     ; get offset of string descriptor
         mov dx, [bx+2]     ; get address of string
         mov ah, 9          ; int call to print string
         int 21h
         pop bp

         ret 2
 RString ENDP

         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTRN.BAS;
    MASM ASTRN.ASM;
    LINK BSTRN ASTRN;

 BSTRN.EXE produces the following output:

    This is the string


 753. Example Passing Numerics from BASIC to MASM by Far Reference

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 10-AUG-1990    ArticleIdent: Q49385

 The two programs below demonstrate how a Microsoft BASIC program can
 pass standard numeric types to assembly language routines.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library or the Microsoft
 Knowledge Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BNUMFAR.BAS, which passes standard
 numeric types to assembly language routines:

    DECLARE SUB Numint(SEG i%)
    DECLARE SUB Numlong(SEG l&)
    DECLARE SUB Numsng(SEG s!)
    DECLARE SUB Numdbl(SEG d#)
    i% = 2
    l& = 4
    s! = 3.4
    d# = 5.6
    CLS

    PRINT "         BEFORE","AFTER"
    PRINT "Integer: ";i%,,
    CALL Numint(i%)
    PRINT i%

    PRINT "Long   : ";HEX$(l&),,
    CALL Numlong(l&)
    PRINT HEX$(l&)

    PRINT "Single : ";s!,
    CALL Numsng(s!)
    PRINT s!

    PRINT USING "Double : ##.####            ";d#,
    CALL Numdbl(d#)
    PRINT USING "##.####"; d#

    END

 The following program is ANUMFAR.ASM, which accepts standard numerics
 by far reference and alters their values:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .CODE
         PUBLIC Numint, Numlong, Numsng, Numdbl
 Numint  PROC
         push bp
         mov bp, sp        ; set stack frame
         push es
         mov es, [bp+8]    ; get seg
         mov bx, [bp+6]    ; get offset
         mov ax, es:[bx]   ; get actual integer
         shl ax, 1         ; multiply by 2
         mov es:[bx], ax   ; put back new value
         pop es
         pop bp
         ret 4
 Numint  ENDP

 Numlong PROC
         push bp
         mov bp, sp        ; set stack frame
         push es
         mov es, [bp+8]    ; get seg
         mov bx, [bp+6]    ; get offset
         mov cx, es:[bx]   ; get actual long
         mov ax, es:[bx+2] ; switch high and low words
         mov es:[bx+2], cx ; put back new value
         mov es:[bx], ax
         pop es
         pop bp
         ret 4
 Numlong ENDP

 Numsng  PROC
         push bp
         mov bp, sp        ; set stack frame
         push es
         mov es, [bp+8]    ; get seg
         mov bx, [bp+6]    ; get offset
         mov ax, es:[bx+2] ; get actual single
         or ah, 80h        ; set sign bit
         mov es:[bx+2], ax ; put back new value
         pop es
         pop bp
         ret 4
 Numsng  ENDP

 Numdbl  PROC
         push bp
         mov bp, sp         ; set stack frame
         push es
         mov es, [bp+8]     ; get seg
         mov bx, [bp+6]     ; get offset
         mov ax, es:[bx+6]  ; get actual double
         or ah, 80h         ; set sign bit
         mov es:[bx+6], ax  ; put back new value
         pop es
         pop bp
         ret 4
 Numdbl  ENDP

         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC /O BNUMFAR.BAS;
    MASM ANUMFAR.ASM;
    LINK BNUMFAR ANUMFAR;

 BNUMFAR.EXE produces the following output:

             BEFORE     AFTER
    Integer:  2          4
    Long   :  4          40000
    Single :  3.4       -3.4
    Double :  5.6000    -5.6000


 754. Example of Passing Array of Long Integers from BASIC to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49386

 The two programs shown below demonstrate how a Microsoft BASIC program
 passes an array of long (4-byte) integers to assembly language.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library or the Microsoft
 Knowledge Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BLONG.BAS, which creates an array of
 long integers and passes it to assembly language by far reference:

    DEFINT A-Z
    DECLARE SUB MasmSub (BYVAL segment, BYVAL offset, BYVAL number)

    'REM $DYNAMIC     'Can be either STATIC (the default) or DYNAMIC
    DIM l&(1 TO 10)   'Remove comment to define array DYNAMICally

    CLS
    PRINT "Calling assembly routine to fill array elements..."
    CALL MasmSub(VARSEG(l&(1)), VARPTR(l&(1)), 10)
    PRINT "Values in array:"
    FOR i% = 1 TO 10
        PRINT l&(i);
    NEXT
    END

 The following program is ALONG.ASM, which receives an array of long
 integers and fills each array element with a 1:

 .MODEL MEDIUM
 .CODE
         PUBLIC MasmSub
 MasmSub PROC
         push bp
         mov bp,sp
         mov es,[bp+10]   ; get segment of array
         mov bx,[bp+8]    ; get offset of array
         mov cx,[bp+6]    ; get length of array
         mov al,1
 next:   mov es:[bx], al  ; put one in the array element
         add bx, 4        ; increment counter to next array element
         loop next        ; loop to assign next array element
         pop bp
         ret 6
 MasmSub ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BLONG.BAS;
    MASM ALONG.ASM;
    LINK BLONG ALONG;

 BLONG.EXE produces the following output:

    Calling assembly routine to fill array elements...
    Values in array: 1 1 1 1 1 1 1 1 1 1


 755. Example of Passing Array of Singles from BASIC to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 10-AUG-1990    ArticleIdent: Q49387

 The two programs below demonstrate how a Microsoft BASIC program
 passes an array of single precision numbers to assembly language by
 far reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00 4.00b and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BSINGLE.BAS, which creates an array of
 single-precision numbers, then passes the array to assembly language
 by far reference:

    DEFINT A-Z
    DECLARE SUB MasmSub (BYVAL segment, BYVAL offset, BYVAL number)

    'REM $DYNAMIC     'Can be either STATIC (the default) or DYNAMIC
    DIM s!(1 TO 10)   'Remove comment to define array DYNAMICally
    FOR i% = 1 to 10
       s!(i%) = i%
    NEXT
    CLS
    PRINT "Calling assembly routine to fill array elements..."
    CALL MasmSub(VARSEG(s!(1)), VARPTR(s!(1)), 10)
    PRINT "Values in array:"
    FOR i% = 1 TO 10
        PRINT s!(i);
    NEXT
    END

 The following program is ASINGLE.ASM, which gets an array of
 single-precision numbers by far reference, then makes each number
 negative:

 .MODEL MEDIUM
 .CODE
         PUBLIC MasmSub
 MasmSub PROC
         push bp
         mov bp, sp

         mov es, [bp+10]  ; get segment of array
         mov bx, [bp+8]   ; get offset of array
         add bx, 3        ; offset to byte holding sign bit
         mov cx, [bp+6]   ; get length of array
         mov al, 1

 next:   or BYTE PTR es:[bx], 80h     ; set sign bit
         add bx, 4        ; increment counter to next array element
         loop next        ; loop to assign next array element
         pop bp
         ret 6
 MasmSub ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSINGLE.BAS;
    MASM ASINGLE.ASM;
    LINK BSINGLE ASINGLE;

 BSTRF.EXE produces the following output:

    Calling assembly routine to fill array elements...
    Values in array:  -1 -2 -3 -4 -5 -6 -7 -8 -9 -10


 756. Example of Passing Fixed-Length String Between BASIC and MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 10-AUG-1990    ArticleIdent: Q49388

 The two programs below demonstrate how Microsoft BASIC and assembly
 language pass fixed-length strings by near reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BFSTRN.BAS, which creates a
 fixed-length string that is passed to assembly language to print and
 receives a fixed-length string from assembly:

    DECLARE SUB RString(BYVAL offs AS INTEGER)
    TYPE fixstring
       s AS STRING * 20
    END TYPE
    DIM a AS STRING * 20
    CLS
    a = "BASIC String$"      ' "$" terminates string for assembly
    CALL RString(VARPTR(a))
    END
    SUB BasicSub(a AS fixstring)
       LOCATE 2, 1    ' Must LOCATE because print in assembly won't move
       PRINT a.s      '   BASIC's screen position
    END SUB

 The following program is AFSTRN.ASM, which gets a fixed-length string
 by near reference, prints the string, then passes a string to a BASIC
 subprogram:

 ; The following handy .MODEL directive is found in MASM 5.10 but not
 ; in earlier versions:
 .MODEL MEDIUM, BASIC
 EXTRN BasicSub:PROC
 .DATA
   astr  DB 'Assembly String      '

 .CODE

         PUBLIC RString
 RString PROC
         push bp
         mov bp, sp           ; set stack frame
         mov dx, [bp+6]       ; address of string
         mov ah, 9            ; DOS interrupt to print string
         int 21h

         mov ax, OFFSET astr  ; address of assembly string
         push ax              ; pass it to BASIC
         call BasicSub

         pop bp
         ret 2
 RString ENDP

         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BFSTRN.BAS;
    MASM AFSTRN.ASM;
    LINK BFSTRN AFSTRN;

 BFSTRN.EXE produces the following output:

    BASIC String
    Assembly String


 757. Example Passing Fixed-Length String from BASIC to MASM (Far)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49389

 The two programs shown below demonstrate how Microsoft BASIC passes a
 fixed-length string to assembly language by far reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BFSTRF.BAS, which creates a
 fixed-length string and passes it to assembly language to be printed:

    DECLARE SUB RString(BYVAL sseg AS INTEGER, BYVAL soff AS INTEGER)

    DIM a AS STRING * 20

    CLS
    a = "BASIC String$" ' "$" terminates string for assembly
    CALL RString(VARSEG(a), VARPTR(a))
    END

 The following program is AFSTRF.ASM, which gets a fixed-length string
 from BASIC and prints it:

 .MODEL MEDIUM, BASIC
 .CODE
         PUBLIC RString
 RString PROC
         push bp
         mov bp, sp       ; set stack frame
         push ds
         mov ds, [bp+8]   ; segment of string
         mov dx, [bp+6]   ; offset of string
         mov ah, 9        ; DOS interrupt to print string
         int 21h
         pop ds
         pop bp
         ret 4
 RString ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BFSTRF.BAS;
    MASM AFSTRF.ASM;
    LINK BFSTRF AFSTRF;

 BFSTRF.EXE produces the following output:

    BASIC String


 758. Example of Passing Numerics from MASM to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49390

 The two programs shown below demonstrate how Microsoft assembly
 language can pass common numeric types to BASIC subprograms.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BNUM.BAS, which contains subprograms
 that receive common numeric types passed from assembly language:

    DECLARE SUB AssemSub(dummy AS INTEGER)

    CALL AssemSub(dummy%)
    END

    SUB NumInt(i AS INTEGER)
       PRINT "Integer : "; i
    END SUB

    SUB NumLong(l AS LONG)
       PRINT "Long    : "; l
    END SUB

    SUB NumSingle(s AS SINGLE)
       PRINT "Single  : "; s
    END SUB

    SUB NumDouble(d AS DOUBLE)
       PRINT "Double  : "; d
    END SUB

 The following program is ANUM.ASM, which passes common numeric types
 to BASIC subprograms:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 EXTRN NumInt:PROC        ; declare BASIC procedures
 EXTRN NumLong:PROC
 EXTRN NumSingle:PROC
 EXTRN NumDouble:PROC
 .DATA
   intnum    DW 32767              ; initialize data
   Longnum   DD 37999
   Singlenum DD 123.45
   Doublenum DQ 1234.14159
 .CODE
          PUBLIC AssemSub
 AssemSub PROC
          push bp
          mov bp, sp

          mov ax, OFFSET intnum    ; get address of integer
          push ax
          call NumInt

          mov ax, OFFSET Longnum   ; get address of long
          push ax
          call NumLong

          mov ax, OFFSET Singlenum ; get address of single
          push ax
          call NumSingle

          mov ax, OFFSET Doublenum ; get address of double
          push ax
          call NumDouble

          pop bp
          ret 2
 AssemSub ENDP
          END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BNUM.BAS;
    MASM ANUM.ASM;
    LINK BNUM ANUM;

 BNUM.EXE produces the following output:

    Integer : 32767
    Long    : 37999
    Single  : 123.45
    Double  : 1234.14159


 759. Example of Passing Array of BASIC String Descriptors to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49391

 The two programs shown below demonstrate how a Microsoft BASIC program
 can pass an array of string descriptors to assembly language.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) version 7.00 and 7.10 for MS-DOS
 and MS OS/2.

 For Microsoft BASIC PDS versions 7.00 or 7.10, this example works
 only with near strings. If using far strings (BC /Fs or in QBX.EXE),
 you must use SSEG and SADD to gain access to the location of strings.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library or the Microsoft
 Knowledge Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BSTR.BAS, which gets an array of
 strings from the user and calls an assembly language program that
 capitalizes the strings:

 ' This program demonstrates passing an array of strings
 ' to an assembly language routine. The assembly language
 ' routine then receives the address of the array and
 ' interprets the array as an array of string descriptors.
 ' It then uses the descriptors to get the length and address
 ' of the strings. It uses these two values to capitalize all of
 ' the lowercase alphabetic characters in any of the strings, and
 ' to skip all others.
 ' It is very important to pass the assembly routine the number
 ' of elements in the array.

 OPTION BASE 0
 DECLARE SUB UpCaseArray (BYVAL ArrayAddress%, arraylen%)
 ' BYVAL is necessary because we want to pass the VALUE of
 ' the address, not a pointer to the address.
 DIM Num%, Array1$(20)
 CLS

 WHILE NOT a$ = "quit"
    INPUT "Enter a string ('quit' to end): ", a$
    Array1$(Num%) = a$
    Num% = Num% + 1
 WEND

 CALL UpCaseArray(VARPTR(Array1$(0)), Num%)
 CLS
 FOR i% = 0 TO (Num% - 1)
    PRINT Array1$(i%)
 NEXT
 END

 The following program is ASTR.ASM. It accepts an array of BASIC string
 descriptors. ASTR.ASM goes through each of the strings in the array
 and capitalizes all of the letters.

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM,BASIC
 .CODE
         PUBLIC UpCaseArray
 UpCaseArray PROC FAR
         push bp
         mov  bp,sp
         push di
         mov bx,[bp+6]    ; Argument #2: Number of array elements.
         mov cx,[bx]      ; Get the actual number of array elements.
         jcxz EndOutLoop  ; If the array has 0 elements, then quit.
         mov bx,[bp+8]    ; Argument #1: Which is a pointer to an
                          ; array of descriptors.
 OutLoop:                 ; CX is the outer-OutLoop counter.
         push cx          ; Save the outer loop counter.
         mov cx,[bx]      ; Get the first 2 bytes of the current
                          ; descriptor which is the string length.
         jcxz EndInLoop   ; If zero length, end the inner loop.
         mov di,[bx+2]    ; The second 2 bytes is the address.
                          ; DI = pointer to current string.
 InLoop:                  ; Check if the char needs to be capitalized.
         cmp byte ptr [di],'a'  ; Is it < a ?
         jb I1                  ; If so, then move to the next char.
         cmp byte ptr [di],'z'  ; Is is > z ?
         ja I1                  ; If so, then move on to the next char.
         and byte ptr [di],05Fh ; Make uppercase. Mask -> (0101 1111).
 I1:     inc di                 ; Move on to next character in the
                                ;    string.
         loop InLoop            ; Do it for all characters
                                ;    (until CX = 0).
                                ; Note: 'loop' decrements CX.
 EndInLoop:
         add bx,4               ; Move on to next descriptor.
         pop cx                 ; Restore the outer loop counter.
         loop OutLoop           ; Do for all descriptors
                                ;    (until CX = 0).
 EndOutLoop:
         pop di
         pop bp
         ret 4
 UpCaseArray ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTR.BAS;
    MASM ASTR.ASM;
    LINK BSTR ASTR;

 BSTRF.EXE produces the following output:

    Enter a string ('quit' to end): First String
    Enter a string ('quit' to end): Second String
    Enter a string ('quit' to end): quit

    FIRST STRING
    SECOND STRING


 760. Example of Passing User-Defined Type from BASIC to MASM (Far)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49392

 The two programs shown below demonstrate how a Microsoft BASIC program
 passes a user-defined type to assembly language by far reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for MS-DOS
 and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is UFAR.BAS, which passes a user-defined
 type to assembly language by far reference:

    DEFINT A-Z
    DECLARE SUB MasmSub (BYVAL segment, BYVAL offset)
    TYPE mixed
       i AS INTEGER
       l AS LONG
       s AS SINGLE
       d AS DOUBLE
       fx AS STRING * 19
    END TYPE
    DIM dummy AS mixed
    CLS
    PRINT "Calling assembly routine to fill the user-defined type."
    CALL MasmSub(VARSEG(dummy), VARPTR(dummy))
    PRINT "Values in user-defined type:"
    PRINT "Integer: ", dummy.i
    PRINT "Long: ", dummy.l
    PRINT "Single: ", dummy.s
    PRINT "Double: ", dummy.d
    PRINT "fixed-length String: ", dummy.fx
    END

 The following program is UAFAR.ASM, which gets a user-defined type by
 far reference and copies data into it:

 .MODEL MEDIUM
           usrdefType   STRUC
                        iAsm       DW 10
                        lAsm       DD 43210
                        sAsm       DD 32.10
                        dAsm       DQ 12345.67
                        fxAsm      DB 'Fixed-length string'
           usrdefType   ENDS
 .DATA
           AsmRec usrdefType <>

           PUBLIC MasmSub
 MasmSub   PROC FAR
           push bp
           mov  bp,sp
           push es
           push di
           push si
           push cx

           mov es,[bp+8]         ; get segment of user-defined type
           mov di,[bp+6]         ; get offset of user-defined type
           mov si,OFFSET AsmRec
           mov cx,37             ; size of structure
           rep movsb             ; copy values to BASIC variable

           pop cx
           pop si
           pop di
           pop es
           pop bp
           ret 4
 MasmSub   ENDP
           END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

      BC /O UFAR.BAS;
      MASM UAFAR.ASM;
      LINK UFAR UAFAR;

 UFAR.EXE produces the following output:

      Integer:   10
      Long:      43210
      Single:    32.10
      Double     12345.67
      fixed-length String:  Fixed-length string


 761. Example of Passing User-Defined Type from BASIC to MASM (Near)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49393

 The two programs shown below demonstrate how a Microsoft BASIC program
 passes a user-defined type to assembly language by near reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is UNEAR.BAS, which passes a user-defined
 type to assembly language by near reference:

    DEFINT A-Z
    TYPE mixed
       i AS INTEGER
       l AS LONG
       s AS SINGLE
       d AS DOUBLE
       fx AS STRING * 19
    END TYPE
    DECLARE SUB MasmSub (dummy AS mixed)
    DIM dummy AS mixed
    CLS
    PRINT "Calling assembly routine to fill the user-defined type."
    CALL MasmSub(dummy)
    PRINT "Values in user-defined type:"
    PRINT "Integer: ", dummy.i
    PRINT "Long: ", dummy.l
    PRINT "Single: ", dummy.s
    PRINT "Double: ", dummy.d
    PRINT "fixed-length String: ", dummy.fx
    END

 The following program is AUNEAR.ASM, which gets a BASIC user-defined
 type by near reference and copies data into it:

 .MODEL MEDIUM
           usrdefType   STRUC
                        iAsm       DW 10
                        lAsm       DD 43210
                        sAsm       DD 32.10
                        dAsm       DQ 12345.67
                        fxAsm      DB 'Fixed-length string'
           usrdefType   ENDS
 .DATA
           AsmRec usrdefType <>

           PUBLIC MasmSub
 MasmSub   PROC
           push bp
           mov  bp,sp            ; set stack frame
           push es
           push di
           push si
           push cx
           push ds
           pop  es

           mov di,[bp+6]         ; get offset of user-defined type
           mov si,OFFSET AsmRec  ; set up for copy
           mov cx,37             ; size of structure
           rep movsb             ; copy values to BASIC variable

           pop cx
           pop si
           pop di
           pop es
           pop bp
           ret 2
 MasmSub   ENDP
           END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC UNEAR.BAS;
    MASM UANEAR.ASM;
    LINK UNEAR UANEAR;

 UNEAR.EXE produces the following output:

    Integer:   10
    Long:      43210
    Single:    32.10
    Double:    12345.67
    fixed-length String:  Fixed-length string


 762. Example of Passing User-Defined Type from MASM to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49394

 The two programs below demonstrate how Microsoft assembly language can
 pass a user-defined type to BASIC.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BUTYPE.BAS, which receives a
 user-defined type from an assembly language program and prints it out:

 DEFINT A-Z
 DECLARE SUB MasmSub
 TYPE mixed
    i AS INTEGER
    l AS LONG
    s AS SINGLE
    d AS DOUBLE
    fx AS STRING * 19
 END TYPE
 DIM dummy AS mixed
 CLS
 PRINT "Calling assembly routine which will fill the";
 PRINT " user-defined type."
 CALL MasmSub
 END

 SUB BASICSub (dummy AS mixed)
    PRINT "Values in user-defined type:"
    PRINT
    PRINT "Integer: ", dummy.i
    PRINT "Long: ", dummy.l
    PRINT "Single: ", dummy.s
    PRINT "Double: ", dummy.d
    PRINT "fixed-length String: ", dummy.f
 END SUB

 The following program is AUTYPE.ASM, which builds a user-defined type
 and passes it to BASIC:

 .MODEL MEDIUM
           usrdefType   STRUC
                        iAsm       DW 10
                        lAsm       DD 43210
                        sAsm       DD 32.10
                        dAsm       DQ 12345.67
                        fxAsm      DB 'Fixed-length string'
           usrdefType   ENDS
 EXTRN BASICSub:PROC
 .DATA
           BASICRec usrdefType <>
 .CODE

           PUBLIC MasmSub
 MasmSub   PROC                     ; no stack frame is needed
                                    ;   because no arguments are
                                    ;   passed to assembly
           mov ax, OFFSET BASICRec  ; get address of structure
           push ax                  ; pass it as argument to BASIC
           CALL BASICSUb
           ret
 MasmSub   ENDP
           END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BUTYPE.BAS;
    MASM AUTYPE.ASM;
    LINK BUTYPE AUTYPE;

 BUTYPE.EXE produces the following output:

    Integer:   10
    Long:      43210
    Single:    32.10
    Double:    12345.67
    fixed-length String:  Fixed-length string


 763. Example of Passing Numerics from BASIC to MASM by Value

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 10-AUG-1990    ArticleIdent: Q49395

 The two programs below demonstrate how a Microsoft BASIC program
 passes standard numeric types to assembly language by value.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BNUMVAL.BAS, which passes two standard
 numeric types to assembly language by value:

    DECLARE SUB ValInt(BYVAL i%)
    DECLARE SUB ValLong(BYVAL l&)
    i% = ASC("A")
    l& = ASC("B") * 65536 + ASC("C")
    CLS
    CALL ValInt(i%)
    CALL ValLong(l&)
    END

 The following program is ANUMVAL.ASM, which gets two standard numeric
 types by value and prints them out:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .CODE
         PUBLIC ValInt, ValLong
 ValInt  PROC
         push bp
         mov bp, sp            ; set stack frame
         mov dx, [bp+6]        ; get integer
         mov ah, 02            ; DOS interrupt to print character
         int 21h
         pop bp
         ret 2
 ValInt  ENDP

 ValLong PROC
         push bp
         mov bp, sp            ; set stack frame
         mov dx, [bp+6]        ; get first part of long
         mov ah, 02            ; DOS interrupt to print character
         int 21h
         mov dx, [bp+8]        ; get second part of long
         int 21h               ; print it
         pop bp
         ret 4
 ValLong ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BNUMVAL.BAS;
    MASM ANUMVAL.ASM;
    LINK BNUMVAL ANUMVAL;

 BNUMVAL.EXE produces the following output:

    ABC


 764. Example of Passing Variable-Length String from BASIC to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 10-AUG-1990    ArticleIdent: Q49396

 The two programs below demonstrate how a Microsoft BASIC program
 passes a variable-length string to assembly language by near
 reference.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BSTR.BAS, which passes the offset of a
 variable-length string to assembly language:

    DECLARE SUB RString(BYVAL soff AS INTEGER)
    A$ = "This is the string" + "$"  ' "$" terminates string for INT call
    CALL RString(SADD(A$))
    END

 The following program is ASTR.ASM, which gets the address of a
 variable-length string and prints the string out:

 .MODEL MEDIUM
 .CODE
         PUBLIC RString
 RString PROC
         push bp
         mov bp, sp           ; set stack frame
         mov dx, [bp+6]       ; get offset to string
         mov ah, 9            ; DOS interrupt to print string
         int 21h
         pop bp
         ret 2
 RString ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTR.BAS;
    MASM ASTR.ASM;
    LINK BSTR ASTR;

 BSTR.EXE produces the following output:

    This is the string


 765. Example of Passing a String Descriptor from MASM to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49397

 The two programs shown below demonstrate how Microsoft assembly
 language can create a BASIC string descriptor and pass it to BASIC.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library or the Microsoft
 Knowledge Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BSTRDESC.BAS, which is passed a string
 created in assembly language and prints the string out:

    DECLARE SUB MkString
    CALL MkString
    END
    SUB BasicSub(TheString AS STRING)
       PRINT LEN(TheString)
       PRINT TheString
    END SUB

 The following program is ASTRDESC.ASM, which builds a string
 descriptor that is passed back to the calling BASIC program:

 .MODEL MEDIUM
         SType   STRUC
                 SLength DW 18
                 Soff    DW ?
         SType   ENDS
 .DATA
         StringDesc  SType <>
         TheString   DB 'This is the string'

 .CODE
             EXTRN BasicSub:PROC

             PUBLIC MkString
 MkString    PROC
             mov ax, OFFSET TheString       ; set up string descriptor
             mov bx, OFFSET StringDesc.Soff
             mov [bx], ax
             mov ax, OFFSET StringDesc.SLength
             push ax           ; pass address of descriptor to BASIC
             CALL BasicSub
             ret
 MkString    ENDP
             END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BSTRDESC.BAS;
    MASM ASTRDESC.ASM;
    LINK BSTRDESC ASTRDESC;

 BSTRDESC.EXE produces the following output:

    This is the string


 766. Example of Passing BASIC Two-Dimensional Integer Array to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified: 13-AUG-1990    ArticleIdent: Q49398

 The two programs shown below demonstrate how a Microsoft BASIC program
 can pass a two-dimensional integer array to assembly language.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BTWODIMI.BAS, which passes an
 uninitialized two-dimensional integer array to an assembly routine
 that initializes the array:

    DECLARE SUB TwoInt(BYVAL ASeg AS INTEGER, BYVAL AOff AS INTEGER)
    DIM IntArray(1 TO 2, 1 TO 3) AS INTEGER
    CALL TwoInt(VARSEG(IntArray(1, 1)), VARPTR(IntArray(1, 1)))
    FOR row% = 1 TO 2
       FOR col% = 1 TO 3
          PRINT IntArray(row%, col%)
       NEXT
    NEXT
    END

 The following program is ATWODIMI.ASM, which initializes a
 two-dimensional integer array passed from BASIC:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         i11 DW 11
         i21 DW 21
         i12 DW 12
         i22 DW 22
         i13 DW 13
         i23 DW 23
 .CODE
         PUBLIC TwoInt
 TwoInt  PROC
         push bp
         mov bp, sp             ; set stack frame
         push es
         push si
         push di
         mov es, [bp+8]         ; segment of array
         mov di, [bp+6]         ; offset of array
         mov si, OFFSET i11
         mov cx, 6              ; number of items to copy
         rep movsw              ; copy data to array
         pop di
         pop si
         pop es
         pop bp
         ret 4
 TwoInt  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BTWODIMI.BAS;
    MASM ATWODIMI.ASM;
    LINK BTWODIMI ATWODIMI;

 BTWODIMI.EXE produces the following output:

    11
    12
    13
    21
    22
    23


 767. Example Allocating Memory in MASM Released by BASIC's SETMEM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49399

 The two programs shown below demonstrate how a BASIC program can use
 SETMEM to free memory for an assembly routine to get dynamic memory.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about interlanguage calling between BASIC and
 MASM, search in the Software/Data Library or the Microsoft Knowledge
 Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BMEMSET.BAS, which uses SETMEM to free
 a block of memory for an assembly routine that uses a DOS interrupt to
 get dynamic memory:

    DECLARE SUB AMem(BYVAL AllocSize AS INTEGER)
    CLS
    ' Decrease the size of the far heap so AMem can use a DOS
    ' interrupt to get dynamic memory
    BeforeCall% = SETMEM(-2048)
    CALL AMem(1024%)
    ' Return the memory to the far heap; use a larger value so
    ' all space goes back into the heap.
    AfterCall% = SETMEM(3500)
    LOCATE 2, 1
    IF AfterCall% <= BeforeCall% THEN
       PRINT "Memory not reallocated"
    ELSE
       PRINT "Memory was successfully reallocated"
    END IF
    END

 The following program is AMEMSET.ASM, which allocates and deallocates
 a block of memory freed by BASIC:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in
 ; MASM 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         Fail    DB 'Failed to allocate memory$'
         Success DB 'Successfully allocated memory$'
 .CODE
         PUBLIC AMem
 AMem    PROC
         push bp
         mov bp, sp                ; set stack frame
         push cx
         push es

         mov ax, [bp+6]            ; get number of bytes freed
         mov cl, 4                 ; divide by 16 to get number of
         shr ax, cl                ;  paragraphs of memory
         mov bx, ax
         mov ah, 48h               ; DOS interrupt to allocate block
         int 21h                   ;  of memory
         mov es, ax
         mov ah, 9
         jnc NoFail                ; carry flag clear if successful
         mov dx, OFFSET Fail       ; display failed message
         int 21h
         jmp Exit                  ; go back to BASIC

 NoFail: mov dx, OFFSET Success    ; display success message
         int 21h
         mov ah, 49h
         int 21h

 Exit:   pop es
         pop cx
         pop bp
         ret 2
 AMem    ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BMEMSET.BAS;
    MASM AMEMSET.ASM;
    LINK BMEMSET AMEMSET;

 BMEMSET.EXE produces the following output:

    Successfully allocated memory
    Memory was successfully reallocated


 768. Example of Passing Two-Dimensional Fixed-String Array to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49400

 The two programs shown below demonstrate how a Microsoft BASIC program
 can pass a two-dimensional fixed-length string array to assembly
 language.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2 and to Microsoft BASIC
 PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BTWOFIX.BAS, which passes an
 uninitialized two-dimensional array of fixed-length strings to an
 assembly routine that initializes the array:

    DECLARE SUB TwoFix(BYVAL ASeg AS INTEGER, BYVAL AOff AS INTEGER)
    DIM FixArray(1 TO 2, 1 TO 3) AS STRING * 9
    CALL TwoFix(VARSEG(FixArray(1, 1)), VARPTR(FixArray(1, 1)))
    FOR row% = 1 TO 2
       FOR col% = 1 TO 3
          PRINT FixArray(row%, col%)
       NEXT
    NEXT
    END

 The following program is ATWOFIX.ASM, which initializes a
 two-dimensional array of fixed-length strings passed from BASIC:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         Fix11 DB 'String 11'     ; allocate string data
         Fix21 DB 'String 21'
         Fix12 DB 'String 12'
         Fix22 DB 'String 22'
         Fix13 DB 'String 13'
         Fix23 DB 'String 23'
 .CODE
         PUBLIC TwoFix
 TwoFix  PROC
         push bp
         mov bp, sp               ; set stack frame
         push es
         mov es, [bp+8]           ; segment of string array
         mov di, [bp+6]           ; offset of string array
         mov si, OFFSET Fix11     ; get offset to string data
         mov cx, 54               ; length of all string data
         rep movsb                ; copy string data to array
         pop es
         pop bp
         ret 4
 TwoFix  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

      BC BTWOFIX.BAS;
      MASM ATWOFIX.ASM;
      LINK BTWOFIX ATWOFIX;

 BTWOFIX.EXE produces the following output:

      String 11
      String 12
      String 13
      String 21
      String 22
      String 23


 769. Example of Passing Array of Doubles from BASIC to MASM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QuickASM
 Last Modified:  5-SEP-1990    ArticleIdent: Q49401

 The two programs shown below demonstrate how a Microsoft BASIC program
 can pass an array of double-precision variables to assembly language.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is BDBL.BAS, which passes an uninitialized
 array of double precision numbers to an assembly routine that
 initializes the array:

    DECLARE SUB FillDbl(BYVAL ASeg AS INTEGER, BYVAL AOff AS INTEGER)

    DIM DblArray(1 TO 5) AS DOUBLE
    CALL FillDbl(VARSEG(DblArray(1)), VARPTR(DblArray(1)))
    FOR i% = 1 TO 5
       PRINT DblArray(i%)
    NEXT
    END

 The following program is ADBL.ASM, which initializes an array of
 double-precision numbers passed from BASIC:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         Dbl1 DQ 123.45           ; initialize data table
         Dbl2 DQ 456.78
         Dbl3 DQ 98765.432
         Dbl4 DQ 12345.678
         Dbl5 DQ 777.888
 .CODE
         PUBLIC FillDbl
 FillDbl PROC
         push bp
         mov bp, sp               ; set stack frame
         push es                  ; Preserve (push) es, di, si
         push di
         push si
         mov es, [bp+8]           ; segment of array
         mov di, [bp+6]           ; offset of array
         mov si, OFFSET Dbl1      ; get offset of data table
         mov cx, 40               ; length of data in table
         rep movsb                ; copy data table to array
         pop si                   ; Restore (pop) si, di, es
         pop di
         pop es
         pop bp
         ret 4
 FillDbl ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC BDBL.BAS;
    MASM ADBL.ASM;
    LINK BDBL ATWODBL;

 BDBL.EXE produces the following output:

    123.45
    456.78
    98765.432
    12345.678
    777.888


 770. VAL Function Concatenates Digits That Have Embedded Spaces

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890829-89 B_GWBasicI B_BasicCom B_BasicInt B_MQuickB
 Last Modified:  1-JAN-1990    ArticleIdent: Q49709

 The VAL function concatenates all digits that are separated by a
 space, a tab, or a linefeed character in the string argument.

 In other words, VAL ignores space, tab, and linefeed characters that
 are embedded (leading or trailing) in the string argument. For
 example, the following code prints a value of 345678 (not 34):

    a$ = "  34  56  78"
    PRINT VAL(a$)

 This behavior applies to Microsoft BASIC on most operating systems,
 including the following products:

 1. Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for the IBM PC

 2. Microsoft BASIC Compiler Versions 6.0, and 6.00b for MS-DOS
    and MS OS/2

 3. Microsoft BASIC Profesional Development System 7.00 for MS-DOS.

 4. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 5. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 6. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh

 7. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 8. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh

 The following code prints a value of 123.45 (not just 12) because
 spaces are ignored. The first decimal point is treated as part of the
 number, and the second decimal point acts as a delimiter:

    a$ = "12  3.4  5.6"
    PRINT VAL(a$)

 The following examples also print 123.45, thus showing that tab and
 linefeed characters, as well as spaces, are ignored by the VAL
 function:

    a$="12"+CHR$(9)+" 3.4  5.6")    ' CHR$(9) is a tab character.
    PRINT VAL(a$)    ' PRINTs 123.45
    a$="12"+CHR$(10)+" 3.4  5.6")   ' CHR$(10) is linefeed character.
    PRINT VAL(a$)    ' PRINTs 123.45

 To work around this behavior, make sure to separate with commas the
 numbers passed to VAL in a string. You can also parse the string into
 a new string before invoking VAL, such as in the following workaround.

 Workaround Example
 ------------------

 This program parses a string a$ such that the first trailing blank
 delimits the end of a number.

 PRINT "Enter the numeric string to parse ";
 LINE INPUT a$
 x = 1
 b$ = ""
 c$ = ""
 DO UNTIL x > LEN(a$)
    c$ = MID$(a$, x, 1)    ' Puts character at column x into c$
    IF c$ <> CHR$(32) THEN
       b$ = b$ + c$        ' Build a string with no spaces.
    ELSEIF LEN(b$) > 0 THEN
       PRINT VAL(b$)
       EXIT DO             ' Stop parsing if trailing blank is found.
    END IF
    x = x + 1
 LOOP

 Programming note: The above example uses the DO...LOOP statement,
 which requires QuickBASIC 3.00 or later. For other products, use a
 different looping structure.


 771. SUB Not Defined; Change CALL MOUSE to MOUSES in MS Press Book

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891002-77 docerr B_BasicCom H_DriverPR H_Mouse
 Last Modified: 13-DEC-1989    ArticleIdent: Q49711

 As specified in the README.TXT file on Disk 2 of the companion disks
 to the "Microsoft Mouse Programmer's Reference" (a Microsoft Press
 release, 1989), the MOUSE routine in MOUSE.LIB has been changed to
 MOUSES (and to MOUSEL, which is not mentioned in the README.TXT).
 MOUSES and MOUSEL are the small- and large-model implementations of
 mouse calls, respectively, and are contained in MOUSE.LIB, which comes
 on the companion disks.

 The change of MOUSE to MOUSES affects QuickBASIC Versions 4.00, 4.00b,
 and 4.50 examples in the "Microsoft Mouse Programmer's Reference" that
 call MOUSE through building the QBMOUSE.QLB file (using MOUSE.LIB).
 After creating the QBMOUSE.QLB and trying to execute QBMOU.BAS,
 MOUSE.BAS, PENCIL.BAS, or QBTEST.BAS (from the disk or book), the
 following QuickBASIC error occurs on reference to MOUSE:

    "Subprogram not defined"

 This error occurs because there is no routine named MOUSE in
 MOUSE.LIB. To work around this problem, change the CALL (or implied
 CALL) and DECLARE statements from MOUSE to MOUSES or MOUSEL.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and to Microsoft BASIC Compiler 6.00, and 6.00b for MS-DOS, and
 Microsoft BASIC PDS 7.00 for MS-DOS.

 The following specific corrections apply to "Microsoft Mouse
 Programmer's Reference" (published by Microsoft Press, 1989):

 1. On Pages 220, 222, 223, and in MOUSE.BAS on the companion disk,
    change all occurrences of

       CALL MOUSE(m1%, m2%, m3%, m4%)   ' Gives "Subprogram not defined"

    to the following:

       CALL MOUSES(m1%, m2%, m3%, m4%)  ' Small-model mouse CALL works OK
    or
       CALL MOUSEL(m1%, m2%, m3%, m4%)  ' Large-model mouse CALL works OK

 2. On Pages 212, 213, 214, and in QBMOU.BAS, QBTEST.BAS, and
    PENCIL.BAS on the companion disk, change all occurrences of

       MOUSE m1, m2, m3, m4         ' Gives "Subprogram not defined"

    to the following:

       MOUSES m1, m2, m3, m4        ' Implicit CALL OK
    or
       MOUSEL m1, m2, m3, m4        ' Implicit CALL OK

 3. On Pages 214 and 221, and in the QBMOU.BAS, MOUSE.BAS, PENCIL.BAS,
    and QBTEST.BAS programs on the companion disk, change the DECLARE
    SUB MOUSE statements to DECLARE SUB MOUSES or DECLARE SUB MOUSEL.

 Recommended Method to Call Mouse Functions
 ------------------------------------------

 As an alternative to linking with the MOUSE.LIB library that is
 provided with the "Microsoft Mouse Programmer's Reference," Microsoft
 recommends the BASIC procedure below to provide the mouse interface.
 This routine uses the CALL INTERRUPT statement to access the mouse via
 interrupt 51.

 DEFINT A-Z
 REM $INCLUDE: 'QB.BI'
 REM When using this code in BASIC PDS 7.00, it is necessary
 REM to include the 'QBX.BI' file instead of QB.BI.
 SUB mouse (m0, m1, m2, m3) STATIC
 DIM inregs AS RegType, outregs AS RegType
     inregs.ax = m0    'Load the registers
     inregs.bx = m1
     inregs.cx = m2
     inregs.dx = m3
     CALL INTERRUPT(51, inregs, outregs)
     m0 = outregs.ax
     m1 = outregs.bx   'Return values from driver
     m2 = outregs.cx
     m3 = outregs.dx
 END SUB


 772. PUTting a CONST to a RANDOM File Hangs QB.EXE 4.50 Editor

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 B_BasicCom
 Last Modified: 27-FEB-1990    ArticleIdent: Q49889

 Using a CONSTant as the third argument of a PUT statement when writing
 to a RANDOM file hangs QB.EXE at run time and during the Make EXE File
 command, leaving the word "Binding..." in the lower-left corner of the
 screen. This problem occurs only within the QuickBASIC Version 4.50
 editor.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50 for MS-DOS. We are researching this problem and will post new
 information here as it becomes available.

 When compiled outside the environment, BC.EXE correctly flags the
 error with the message "Variable required," displaying the PUT
 statement with a caret pointing to the offending CONSTant. The third
 argument of the PUT statement requires a variable, and CONSTants are
 not allowed.

 This problem does not occur in the QBX.EXE environment of Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS-DOS
 and MS OS/2. Within QBX.EXE, the error "Variable required" is flagged
 and the offending constant is highlighted.

 Code Example
 ------------

 The QuickBASIC editor hangs, displaying the message "Binding..." in
 the lower-left corner of the screen, when you run (by pressing
 SHIFT+F5) or compile (by using the Make EXE File command on the Run
 menu) the following program:

    CONST a = 1
    OPEN "test.dat" FOR RANDOM AS #1
    PUT #1, 1, a


 773. Logitech Bus Mouse Can Use Microsoft Mouse Drivers

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890501-141 B_BasicCom H_Mouse H_DriverPR
 Last Modified: 18-OCT-1989    ArticleIdent: Q49892

 Logitech bus mice can use all versions of the Microsoft Mouse driver
 earlier than Version 7.00. This does not apply to Logitech serial
 mice. Logitech serial mice must use the Logitech mouse driver.

 Versions of the Logitech mouse driver released before QuickBASIC
 Version 4.50 (before September 29, 1988) might not work correctly with
 QuickBASIC 4.50. To use the Logitech bus mouse, the Microsoft Mouse
 driver should be installed.

 Logitech technical support has confirmed that all of their bus mice
 have been tested with the Microsoft Mouse drivers up to, but not
 including, Version 7.00. Version 7.00 of the Microsoft Mouse driver is
 shipped with the new high-resolution 400 ppi (pixels per inch)
 Microsoft Mouse and has not been tested with the Logitech bus mice.


 774. CHAIN or RUN from Quick Library Can Hang QuickBASIC Editor

 Product Version(s): 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 20-SEP-1990    ArticleIdent: Q49925

 When executing a program within the QB.EXE or QBX.EXE (QuickBASIC
 Extended) environment that CALLs a Quick library routine that executes
 a RUN or CHAIN command, the system can hang under either of the
 following two specific conditions:

 1. If the program to be CHAINed or RUN does not exist in the current
    directory, the QuickBASIC editor will hang.

 2. If the first program has been changed since being loaded, the
    QuickBASIC environment will ask if you want to save the current
    program before loading the program named in the CHAIN or RUN
    statement. An "OK" or "No" response allows QuickBASIC to load and
    execute the CHAIN or RUN program correctly. A "Cancel" response
    causes QuickBASIC to drop to DOS. Attempting to rerun QuickBASIC
    after the drop to DOS will hang the machine.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00b and 4.50 and in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 (buglist7.00, buglist7.10). We are researching
 this problem and will post new information here as it becomes
 available.

 These errors occur with the CHAIN or RUN statement only if it is
 invoked from a Quick library routine. CHAIN and RUN work normally from
 a source program in the QuickBASIC editor or from a compiled EXE
 program.

 For information about a separate hanging problem specific only to
 QuickBASIC version 4.00 when executing ANY CHAIN or RUN from a Quick
 library, query in this Knowledge Base on the following words:

    4.00 and CHAIN and Quick and library and hangs

 The following set of programs reproduce the problem. QLBERR.BAS should
 be compiled and made into a Quick library, while PROG1.BAS and
 PROG2.BAS should be left as uncompiled source.

 To reproduce the first error detailed above, do not create PROG2.BAS
 at all. Instead, create and load the QLBERR.QLB Quick library and
 create and save PROG1.BAS. Executing PROG1.BAS at this point will hang
 QuickBASIC.

 To reproduce the second error, start QuickBASIC using the QLBERR.QLB
 Quick library, then load, modify, and execute PROG1. When the dialog
 box asks if you want to save PROG1 before loading and running PROG2,
 select Cancel. QuickBASIC will then drop to DOS.

 Code Examples
 -------------

    '               *** QLBERR.BAS ***
    '       ** Make this into a Quick library **
    SUB QLBErrSub
      RUN "PROG2"     'Can also be CHAIN "PROG2"
    END SUB

    '               *** PROG1.BAS ***
    '       ** Leave this as source code **
    PRINT "In program1"
    CALL QLBErrSub
    END

    '               *** PROG2.BAS ***
    '       ** Leave this as source code **
    PRINT "In Program 2"
    END


 775. Reasons for "File Not Found" Error Using $INCLUDE Metacommand

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  7-FEB-1990    ArticleIdent: Q50219

 The text file specified in a $INCLUDE metacommand must exist on disk,
 or the message "File not found" appears.

 You get the "File not found" message unless you do one of the following:

 1. Qualify the filename with an explicit directory path in the
    $INCLUDE statement.

 2. If an unqualified filename is specified in the $INCLUDE statement,
    the file must be in the current directory or the root directory. In
    addition, QuickBASIC Version 4.50 and Microsoft BASIC Professional
    Development System (PDS) Version 7.00 are enhanced to recognize the
    DOS INCLUDE environment variable (for both QB.EXE, QBX.EXE and
    BC.EXE) for unqualified $INCLUDE filenames. Both of these versions
    also let you set additional $INCLUDE file paths in the Options
    menu.

    The following products DON'T recognize the DOS INCLUDE environment
    variable to search for unqualified $INCLUDE filenames: Microsoft
    QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, and
    4.00b for MS-DOS, and Microsoft BASIC Compiler Versions 6.00 and
    6.00b for MS-DOS and MS OS/2.

 If the file isn't found, a "File not Found" error is flagged on the
 REM in the REM $INCLUDE: 'filename' statement (instead of on the
 filename in the single quotation marks in QuickBASIC 4.00, 4.00b, and
 4.50 and in QuickBASIC extended shipped with Microsoft BASIC PDS
 Version 7.00).

 To create an include file while in the QuickBASIC QB.EXE 4.00, 4.00b,
 or 4.50 editor, or the QBX.EXE editor, use the Create File command on
 the File menu and select Include. Then when you try to execute the
 program in the editor, it will inform you to save the Include file
 before execution can occur, preventing the "File not Found" error.


 776. The Width of Text Is Carried between BASIC SCREENs If Possible

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891008-1 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q50001

 When switching from one SCREEN mode to another, the height and width
 of the text in the first SCREEN mode will be maintained in the second
 SCREEN mode if the height and width is supported by the second mode.

 If the second SCREEN mode does not support the height and width of the
 text used in the first SCREEN mode, then the height and width will
 change to the default of the second.

 Although the height and width of the text characters are maintained
 across SCREEN modes when possible, the text itself is cleared.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
 for MS-DOS and MS OS/2.

 The following sample program exhibits this behavior:

 SCREEN 0
 PRINT "80 X 25"        '80 X 25 is the default for screen mode 0.
 SLEEP

 SCREEN 1
 PRINT "40 X 25"        'SCREEN 1 does not support the 80 X 25 text
 SLEEP                  'format, so the format will be changed to
                        'SCREEN 1's default of 40 X 25.

 SCREEN 0
 PRINT "40 x 25"        'SCREEN 0 does support the 40 X 25 text
 SLEEP                  'format, so the format that was used in
                        'SCREEN 1 is maintained when switching to
                        'SCREEN 0.


 777. Bits Per Pixel Per Plane for Graphics GET for SCREEN 3 and 4

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891016-54 B_BasicCom docerr
 Last Modified: 13-DEC-1989    ArticleIdent: Q50003

 The bits-per-pixel-per-plane values and the number of planes for
 SCREEN 3 and SCREEN 4 were omitted and must be added under the
 graphics GET statement in the following sources:

 1. Page 207 of "Microsoft QuickBASIC 4.0: BASIC Language Reference"
    manual for Versions 4.00 and 4.00b

 2. Page 207 of "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" manual for Versions 6.00 and 6.00b for MS-DOS

 3. Page 151 of "Microsoft BASIC Version 7.00: BASIC Language
    Reference" manual for Version 7.00 for MS-DOS

 4. The QuickBASIC Advisor on-line help screen for QuickBASIC 4.50
    under "HELP: GET (Graphics) Statement Details"

 5. The QuickBASIC Extended Advisor on-line help screen for BASIC
    Compiler 7.00 under "HELP: GET (Graphics) Statement Details"

 Below is a table that contains the complete values for bits per pixel
 per plane and the number of planes used by the GET (Graphics)
 statement.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 and to Microsoft BASIC Compiler Versions 6.00, and 6.00b for
 MS-DOS and to Microsoft BASIC PDS 7.00 for MS-DOS.

 The following complete table provides values necessary to calculate
 the array size required by the graphics GET Statement:

                 Bits
                 Per Pixel
    Mode         Per Plane     Planes
    ----         ---------     ------
    SCREEN 1     2             1
    SCREEN 2     1             1
    SCREEN 3     1             1   <<-- (Add to manual)
    SCREEN 4     1             1   <<-- (Add to manual)
    SCREEN 7     1             4
    SCREEN 8     1             4
    SCREEN 9     1             2 (if 64K of EGA memory)
                               4 (if more than 64K of EGA memory)
    SCREEN 10    1             2
    SCREEN 11    1             1
    SCREEN 12    1             4
    SCREEN 13    8             1

 The GET statement transfers a screen image into an array. The PUT
 statement, associated with GET, transfers the image stored in the
 array onto the screen.

 For the statement

    GET (x1,y1)-(x2,y2),arrayname

 the following formula gives the required size of the array in bytes:

    4+INT(((x2-x1+1)*(bits-per-pixel-per-plane)+7)/8)*planes*((y2-y1)+1)


 778. Example of Saving Numeric Array to Disk Using BLOAD and BSAVE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891017-63  B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q50004

 The program below demonstrates how to BSAVE a numeric array as a
 memory image file to disk and how to BLOAD the array from disk into a
 new array in memory.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft PDS Version 7.00 for MS-DOS.

 The BSAVE statement allows you to copy the contents of a memory
 location to a memory-image file on disk. A memory-image file is a
 byte-for-byte copy of what is in memory along with control information
 used by BLOAD to load the file. The program below initializes an
 array, transfers the contents of it to an output file using BSAVE,
 erases that array from memory, and then loads the saved array into a
 new array in memory using BLOAD.

 Code Example
 ------------

 REM $DYNAMIC
 DIM array%(8, 8)       ' 9 elements per dimension.
 FOR i% = 0 TO 8        ' Initialize the array with desired values.
     FOR j% = 0 TO 8
         array%(i%, j%) = i% + j%   ' Arbitrary values assigned.
     NEXT j%
 NEXT i%
 ' Set DEF SEG at the segment (paragraph address) of the array:
 DEF SEG = VARSEG(array%(0, 0))
 ' Specify the output disk file name (JUNK.DAT), the offset of the
 ' starting address of the area in memory to be saved, and the number
 ' of bytes to save (9*9*2 is 162 bytes):
 BSAVE "Junk.dat", VARPTR(array%(0, 0)), 162
 DEF SEG                'Restore BASIC segment to default
 PRINT "After save"
 ERASE array%
 DIM array2%(8, 8)      ' Dimension new array.
 DEF SEG = VARSEG(array2%(0, 0))   ' Set DEF SEG for subsequent BLOAD.
 BLOAD "Junk.dat", VARPTR(array2%(0, 0))   ' Reloads the array.
 FOR j% = 0 TO 8
     FOR i% = 0 TO 8
         PRINT array2%(i%, j%);   ' Confirms array is reloaded.
     NEXT i%
     PRINT
 NEXT j%

 The following is the output for this program:

 After save
  0  1  2  3  4  5  6  7  8
  1  2  3  4  5  6  7  8  9
  2  3  4  5  6  7  8  9  10
  3  4  5  6  7  8  9  10  11
  4  5  6  7  8  9  10  11  12
  5  6  7  8  9  10  11  12  13
  6  7  8  9  10  11  12  13  14
  7  8  9  10  11  12  13  14  15
  8  9  10  11  12  13  14  15  16


 779. QB.EXE 4.50 "String Space Corrupt" Passing Function to .QLB

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891006-116 buglist4.50 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q50220

 There is a problem in the QuickBASIC Version 4.50 environment with
 passing a FUNCTION procedure as a parameter to a user-defined function
 that calls a SUBprogram when the FUNCTION and SUBprogram procedures
 are located in a Quick library. A "String space corrupt" error
 displays, and the program returns to DOS. This problem occurs only
 when running the program a second time [using any combination of the
 ALT+R+R (Restart), F8, F5 (ALT+R+N), or SHIFT+F5 (ALT+R+S) (Start)
 keys]. The problem doesn't occur in compiled .EXE programs.

 Microsoft has confirmed this to be a problem in the QuickBASIC
 environment (QB.EXE) in Version 4.50. This problem was corrected in
 the QBX.EXE environment of Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2 (fixlist7.00).

 You can work around this problem by assigning the value returned by
 the BN$ FUNCTION to a temporary value and passing this temporary value
 when you invoke the FNOPEN% user-defined function (as demonstrated in
 MAIN.BAS below).

 The "String space corrupt" error is not generated in any of the
 following cases:

 1. If QLIB.BAS (shown below) is loaded as a secondary module instead
    of as a .QLB (Quick library)

 2. When the two modules (shown below) are compiled into an .EXE (using
    QLIB.LIB or QLIB.OBJ) and run as an .EXE

 3. When QuickBASIC Version 4.00 or 4.00b is used

 The following programs, MAIN.BAS and QLIB.BAS, demonstrate the
 problem. MAIN.BAS is the module loaded into the environment, and
 QLIB.BAS is the Quick library, which is loaded in with the /L
 invocation switch (for example, QB MAIN /L QLIB).

 MAIN.BAS
 --------

 DECLARE FUNCTION BN$ (X$)
 DECLARE SUB SOPEN (KAN%, K$, BEST$, RECL%)

 DEF FNOPEN% (KAN%, K$, BEST$, RECL%)
      CALL SOPEN(KAN%, K$, BEST$, RECL%)
 END DEF

 CLS : LOCATE 21, 1

 'Statement that causes the "String space corrupt" error:
 FS% = FNOPEN%(2, "S", BN$("XXXXACTR"), 256)

 'Workaround to eliminate the "String space corrupt" error:
 'TEMP$ = BN$("XXXXACTR")
 'FS% = FNOPEN%(2, "S", TEMP$, 256)

 QLIB.BAS
 --------

 DECLARE FUNCTION BN$ (X$)
 DECLARE SUB SOPEN (KAN%, K$, BEST$, RECL%)
 FUNCTION BN$ (X$)
      BN$ = "C:0001" + MID$(X$, 5)
 END FUNCTION
 SUB SOPEN (KAN%, K$, BEST$, RECL%)
      PRINT BEST$
 END SUB


 780. How to Resize and Turn On/Off the Text Mode (SCREEN 0) Cursor

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891018-112 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q50221

 This article demonstrates how to control the text mode cursor by
 directly accessing the BIOS with CALL INTERRUPT. There are two ways to
 control the text mode cursor. The BASIC LOCATE statement enables a
 program to position the cursor, size the cursor, and turn the cursor
 on and off. This article describes how this can be done by CALLing the
 BIOS INTERRUPT 10 hex, with function 12 hex, with subfunction 34 hex,
 which allows a program to turn the cursor on or off. BIOS INTERRUPT 10
 hex with function 1 allows a program to set the cursor size.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and 4.50
 for MS-DOS and to Microsoft BASIC Compiler 6.00, and 6.00b for MS-DOS
 and Microsoft BASIC PDS 7.00 for MS-DOS.

 The text mode cursor and its size, blinking, and position are all
 controlled by the video hardware. The text mode cursor is not created
 by the QuickBASIC editor, compiler, or its applications. Because the
 hardware supports cursor emulation only in text mode (that is, SCREEN
 0 in BASIC) there is no graphics mode cursor. This is not a problem or
 limitation of QuickBASIC.

 Even though there is no hardware-generated blinking cursor in a
 graphics mode, the BIOS does keep track of the current text position.
 The program can call BIOS INTERRUPT &H10 functions &H2 and &H3 to get
 and set the current position of the cursor. If desired, a graphics
 mode cursor can be placed on the screen by the program itself. BASIC
 uses a solid, nonblinking block cursor in graphics mode. This graphics
 mode cursor is placed there by the QuickBASIC editor and compiler.

 The cursor is controlled by CALLing BIOS service routines that allow
 the cursor to be enabled, disabled, and resized. The largest possible
 cursor fills one entire character box. Depending on the graphics
 adapter, one character box can have a different number of scan lines.
 For the BIOS routines to work regardless of the video adapter, the
 BIOS routines assume that there is an 8-pixel by 8-scan-line format
 for the cursor. This means that you can set the cursor to eight
 different sizes by CALLing the BIOS.

 For more information on CALLing both BIOS and DOS INTERRUPTs query
 on the word QB4INT.

 The following code example demonstrates how to use the BIOS service
 routines to turn the cursor off, turn it back on, and how to resize
 the cursor to each of the possible sizes.

 Code Example
 ------------

 REM $INCLUDE: 'qb.bi'
 ' FOR QBX.EXE editor the include file is 'QBX.BI'

 DIM inregs AS regtype, outregs AS regtype
 CLS
 ' Set up the parameters to disable the cursor emulation.
 inregs.ax = &H1201  ' AH = 12H for function 12H
                     ' AL = 1 to disable the cursor.
 inregs.bx = &H34    ' Subfunction 34
 ' Disable the cursor:
 ' For QB.EXE : run QB /L QB.QLB, or LINK to QB.LIB, to enable
 '    CALL INTERRUPT.
 ' For QBX.EXE: run QBX/L QBX.QLB, or LINK to QBX.LIB, to enable
 '    CALL INTERRUPT.
 CALL interrupt(&H10, inregs, outregs)
 PRINT "The cursor should be off. Hit ENTER to bring it back "
 WHILE INKEY$ = "": WEND

 ' Set up parameters to enable cursor emulation.
 inregs.ax = &H1200 ' AH = 12H for function 12H
                    ' AL = 0 to enable the cursor.
 inregs.bx = &H34   ' BX = 34H for subfunction 34H.

 'Enable cursor emulation.
 CALL interrupt(&H10, inregs, outregs)

 ' Even though the cursor has been enabled, it will not show.
 ' This is because we need to set the size.  The following
 ' loop cycles through the sizes.

 FOR i = 1 TO 8 ' 0 - 8 is the maximum size.

    inregs.ax = &H100 ' AH = 1 for function 1.
    inregs.cx = i     ' CH = 0 for starting line.
                      ' CL = ending line.
    CALL interrupt(&H10, inregs, outregs)
    PRINT "Hit return to increase the cursor size: "
    WHILE INKEY$ = "": WEND
 NEXT
 END


 781. How to Convert VGA Colors to Their Equivalent Gray Scale

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891010-159 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q50225

 In Microsoft QuickBASIC, VGA colors can be converted to their
 equivalent gray scale values using the CALL INTERRUPT statement. This
 can be useful when printing an image or having the image scanned by
 devices that do not support color.

 This procedure can be used to convert a color image to a monochrome
 equivalent before printing out the image on a dot-matrix printer.

 Once the color registers are converted to their gray scale
 equivalents, the original red, green, and blue values are lost. If
 this information needs to be restored, the VGA color registers should
 be saved before doing the gray scale summing, and then restored
 afterward.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS and to Microsoft BASIC Compiler Versions 6.00,
 and 6.00b for MS-DOS, and Microsoft BASIC PDS 7.00 for MS-DOS.

 The following BASIC program is GRAY.BAS, which displays a multicolored
 image in VGA SCREEN 13, then converts all of the colors to their
 equivalent gray scale values:

 REM $INCLUDE: 'qb.bi'  ' defines for CALL INTERRUPT
 ' For BC.EXE and QBX.EXE in BASIC PDS 7.00 the include file is 'QBX.BI'

 DIM inregs AS RegType
 DIM outregs AS RegType
 SCREEN 13

 FOR i% = 2 TO 255      ' display colorful pattern
         LINE (i%, 10)-(i%, 199), i%
 NEXT

 LOCATE 1, 1
 COLOR 7
 PRINT "press any key to convert to gray scale"
 WHILE INKEY$ = "": WEND

 inregs.ax = &H101B     ' BIOS call to set gray scale values
 inregs.bx = 0          ' start at color register 0
 inregs.cx = 256        ' convert all 256 color registers
 CALL INTERRUPT(&H10, inregs, outregs)

 LOCATE 1, 1
 PRINT "press any key to end                   "
 WHILE INKEY$ = "": WEND
 END

 To demonstrate this program from an .EXE program, compile and link as
 follows:

    BC GRAY.BAS;
    LINK GRAY,,,QB.LIB;

 For BASIC compiler 7.00, compile and link as follows:

    BC GRAY.BAS;
    LINK GRAY,,,QBX.LIB;

 If you are running the program from the QuickBASIC QB.EXE editor, the
 Quick library QB.QLB must be loaded in as follows:

    QB GRAY /L QB.QLB

 For QBX.EXE in BASIC compiler 7.00, the Quick library QBX.QLB must be
 loaded as follows:

    QBX GRAY /L QBX.QLB


 782. How to Use CALL INTERRUPTX to Get Name of Current Directory

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891018-85 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q50228

 This article gives an explanation and code example for how CALL
 INTERRUPTX can be used to get the name of the current directory on a
 specified drive using Microsoft QuickBASIC.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC PDS Version 7.00.

 MS-DOS interrupt 21 hex function 47 hex returns an ASCIIZ string that
 describes the name of the current directory and the path from the root
 to the current directory. An ASCIIZ string is a series of ASCII
 characters terminated by a null byte. A null byte or null character is
 a 1-byte data item (a char in C) that has the value zero. It is the
 first character on any ASCII chart.

 The "current directory" is the subdirectory that you are currently
 working in. The MS-DOS CHDIR (CD) command is used to change the
 current directory.

 Note: It is necessary to use the CALL INTERRUPTX statement to call
 this DOS function. This is not possible with the CALL INTERRUPT
 statement. CALL INTERRUPT does not allow a program to change the value
 of the DS or ES registers. CALL INTERRUPTX allows both DS and ES to be
 set.

 Code Example
 ------------

 REM $INCLUDE: 'qb.bi'
 ' For BASIC PDS 7.00 and QBX.EXE the include file is 'QBX.BI'

 DIM InRegs AS RegTypeX
 DIM OutRegs AS RegTypeX
 DIM CurrentDirectory AS STRING * 64

 CurrentDirectory = STRING$(64, CHR$(32))   '32 is ASCII for SPACE
 InRegs.Ax = &H4700                       'Function Number     in AH
 InRegs.Si = VARPTR(CurrentDirectory)     'Offset of Variable  in SI
 InRegs.Ds = VARSEG(CurrentDirectory)     'Segment of Variable in DS
 InRegs.Dx=0                              'Drive Number        in DX
                                          '(0=default, 1=A, etc.)
 CALL INTERRUPTX(&H21, InRegs, OutRegs)
 CLS
 PRINT "Current Directory = " + RTRIM$(CurrentDirectory)
 END


 783. BASIC Can't Use Microsoft Windows SDK to Make Applications

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | H_MASM B_BasicCom P_WinSDK P_WinSDK1 S_Pascal S_C
 Last Modified: 18-OCT-1990    ArticleIdent: Q50229

 You cannot create Microsoft Windows programs using Microsoft BASIC.
 The Microsoft Windows Software Development Kit (SDK) for MS-DOS is
 compatible with Microsoft C and Microsoft Macro Assembler (MASM), but
 it is not compatible with Microsoft QuickBASIC versions 4.00, 4.00b,
 or 4.50 (or earlier versions) for MS-DOS, Microsoft BASIC Compiler
 versions 6.00 and 6.00b (or earlier) for MS-DOS, or Microsoft BASIC
 Professional Development System (PDS) version 7.00 or 7.10 for MS-DOS.

 The programs created by the above BASIC versions can run in Microsoft
 Windows only by taking complete control of the screen and computer.
 When the BASIC program terminates, control is released back to
 Windows.

 In programs written for Microsoft Windows, the usual start-up code for
 a language is not called. Instead, special start-up code for Microsoft
 Windows is called. This start-up code in turn calls the function
 "WinMain" in the program. There is no main-line code in a Microsoft
 Windows program, such as the "main module level code" in BASIC or the
 main() function in C. Instead the Windows start-up code takes the
 place of the main-line code and in turn directly calls WinMain.

 The Microsoft Windows start-up code is compatible with the C start-up
 code, but compiled BASIC must be the initial program and must be run
 through its own start-up code to initialize its memory management
 routines. Because there is no way to run the Windows start-up code and
 then call the BASIC start-up code, you can't create Microsoft Windows
 programs using Microsoft BASIC.

 Note that Microsoft Pascal 4.00 can use the Microsoft Windows Software
 Development Kit (SDK) for MS-DOS to develop programs for Microsoft
 Windows versions 2.x, but CANNOT develop programs for Microsoft
 Windows version 3.00. Microsoft recommends using C or assembler
 instead of Pascal for Windows programming for MS-DOS.

 Although you can't program under Microsoft Windows for MS-DOS using
 Microsoft BASIC, you can program MS OS/2 Presentation Manager (PM)
 applications using Microsoft BASIC Compiler versions 6.00 and 6.00b
 and Microsoft BASIC PDS versions 7.00 and 7.10. This is detailed in a
 separate article, which can be found by querying in this Knowledge
 Base using the following words:

    OS/2 and presentation and manager and BASIC and 6.00b


 784. COLOR Statement in SCREEN 11 Gives "Illegal Function Call"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891027-16 B_BasicCom docerr
 Last Modified: 15-JAN-1990    ArticleIdent: Q50461

 The COLOR statement correctly returns an "Illegal Function Call" if
 used in SCREEN 11. The only way to change the color in SCREEN 11 is to
 use the PALETTE statement. However, note that the PALETTE statement
 may not work with a video card that is not 100-percent compatible with
 the IBM standard VGA or MCGA. (SCREEN 11 requires VGA or MCGA.)

 The following resources incorrectly state that the COLOR statement is
 valid in SCREEN modes 11-13; they should instead say SCREEN modes
 12-13:

 1. Two occurrences, on Page 109 of the "Microsoft QuickBASIC 4.0: BASIC
    Language Reference" manual for QuickBASIC Versions 4.00 and 4.00b

 2. Two occurrences, on Page 109 of the "Microsoft BASIC Compiler 6.0:
    BASIC Language Reference" manual for Versions 6.00 and 6.00b

 3. One occurrence, under the COLOR statement in the QB Advisor online
    Help system for QuickBASIC Version 4.50

 This documentation error was corrected in the "Microsoft QuickBASIC
 4.5: BASIC Language Reference" manual for QuickBASIC Version 4.50, in
 the Microsoft BASIC Professional Development System (PDS) 7.00 "BASIC
 Language Reference," and in the Microsoft Advisor online Help system
 in the QuickBASIC Extended editor (QBX.EXE) shipped with BASIC PDS
 Version 7.00.

 The PALETTE statement can be used instead of the COLOR statement in
 SCREEN 11 to set the foreground and background colors. Note that the
 foreground color can only be set for graphics statements; text will
 always be blue.

 To change the foreground color in SCREEN 11, the following PALETTE
 statement must be used:

    PALETTE 1, color

 To change the background color in SCREEN 11, the following PALETTE
 statement must be used:

    PALETTE 0, color

 Below is another code example demonstrating how to set the foreground
 and background colors in SCREEN 11 using the PALETTE statement:

 ' VGA color equation: COLOR number = 65536 * blue + 256 * green + red
 '   where red, blue, and green are numbers between 0 and 63
 CLS
 SCREEN 11
 background& = 256 * 63   'bright green
 foreground& = 63         'bright red
 PALETTE 0, background&
 PALETTE 1, foreground&
 LINE (10, 240)-(630, 240)
 WHILE INKEY$ = "": WEND


 785. QB.EXE 4.50 May Lose SUB During SUB Move If "Out of Memory"

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891026-32 buglist4.50 B_BasicCom
 Last Modified: 15-DEC-1989    ArticleIdent: Q50466

 If an "OUT OF MEMORY" error message results from moving a SUBprogram
 via the Move button in the SUBS... option (F2 hotkey) from the View
 menu in the QB.EXE editor in QuickBASIC Version 4.50, the SUBprogram
 may be lost.

 This problem occurs only with very large, multiple-module programs
 that are running out of available memory. Any program that is large
 enough to create this problem is usually too large to effectively run
 in QB.EXE. To avoid this problem, use programs that do not approach
 the memory limitations of your machine.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50 for MS-DOS. This problem was corrected in QBX.EXE of Microsoft
 BASIC PDS Version 7.00 (fixlist7.00).

 To reproduce this problem, perform the following steps:

 1. Use a large multiple-module program.

 2. Load all the modules into QB.EXE.

 3. Choose the SUBS... option from the View menu (or press F2).

 4. Highlight a SUBprogram or FUNCTION.

 5. Choose the Move option.

 6. Pick a destination module.

 7. To duplicate the problem, you must receive an "OUT OF MEMORY"
    message at this point. If you View that SUBprogram, it will have
    lost its contents.

 8. If you were not able to reproduce the problem, increase the size of
    one or more of the modules and repeat from Step 3.


 786. .BAS in Set Paths for Include Files in QB 4.50 Options Menu

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891026-52
 Last Modified: 12-DEC-1989    ArticleIdent: Q50470

 In the QB.EXE editor in Microsoft QuickBASIC Version 4.50, and the
 QBX.EXE editor in Microsoft BASIC PDS 7.00, there is a box for
 "Include Files (.BI, .BAS):" in the Set Paths command on the Options
 menu. The ".BAS" and ".BI" in the parentheses are only examples of the
 three-character name extensions possible for Include files. The (.BI,
 .BAS) box refers ONLY to the path to find Include files and does NOT
 relate to any other feature.

 All filename extensions will be searched for in the specified
 directory, not just Include files with the extensions .BI and .BAS.

 This information applies to QuickBASIC 4.50 and QBX.EXE for BASIC PDS
 7.00. (Versions of the QB.EXE editor earlier than 4.50 don't have a
 Set Paths command or an Options menu.)

 The "Include Files (.BI, .BAS):" option refers to which directory will
 be searched for Include files at compile time when the REM $INCLUDE
 metacommand is used in the source code.

 If no explicit path qualifies the filename in the REM $INCLUDE:
 'filename' statement, QuickBASIC will search for the file in the
 following directories in exactly the following order:

 1. The current directory

 2. The directory specified by the "SET INCLUDE=" environment variable
    (set with the MS-DOS SET command in the AUTOEXEC.BAT file.)

 3. The directory specified in the "Include Files (.BI, .BAS):" box in
    the Set Paths command of the Options menu.

 In the following example, the file BOB.INC will be searched for in the
 current directory, the directory specified by "SET INCLUDE=", then in
 the Set Paths directory:

    REM $INCLUDE: 'BOB.INC'


 787. QB.EXE Hangs If BACKSPACE after IF GOTO Syntax (with No THEN)

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 16-DEC-1989    ArticleIdent: Q50552

 When editing a legal IF GOTO syntax that has no THEN word, if you
 press the BACKSPACE key in the column beneath the "I" in the "IF"
 statement, the computer hangs.

 This problem occurs in the QB.EXE editor in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and in QB.EXE in Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS (buglist6.00,
 buglist6.00b). This problem was corrected in QBX.EXE in Microsoft
 BASIC PDS (Professional Development System) Version 7.00
 (fixlist7.00).

 The hanging problem does not occur when you use the THEN word in the
 IF <condition> THEN GOTO syntax.

 The following is a code example:

    IF x=0 GOTO label

 While the cursor is in the column beneath the "I" in the "IF"
 statement (the first column), press the BACKSPACE key to hang the
 machine.


 788. PRINT # to "CONS:" and PRINT Can Use > for DOS Redirection

 Product Version(s): 4.50 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891103-4 B_BasicCom
 Last Modified: 13-DEC-1989    ArticleIdent: Q50637

 In a Microsoft QuickBASIC program, the output from either a compiled
 or interpreted program can be redirected from the SCREEN to a file by
 using the redirection ">" operator in MS-DOS. This will also redirect
 stream devices, such as the LPT1 printer, to MS-DOS.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft QuickBASIC Interpreter (Academic
 Edition) Version 1.00, and to Microsoft BASIC Compiler Versions 6.00,
 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version
 7.00 for MS-DOS and MS OS/2.

 ----------------

 The following are the only two forms of output from BASIC that can be
 redirected to a file:

 1. Output from the standard PRINT statement

 2. Output from the PRINT #Num, statement, where #Num is the "CONS:"
    device OPENed for output (OPEN "CONS:" FOR OUTPUT AS #Num)

 Also, if you are testing a program inside the editor environment in
 QB.EXE from QuickBASIC Version 4.00, 4.00b, or 4.50, QBX.EXE from
 BASIC PDS 7.00, or in QBI.EXE from QuickBASIC Interpreter (Academic Edition)
 Version 1.00, you can redirect the output of all programs run in the
 environment, as follows:

    QB  > LPT1
    QBX > LPT1
 or
    QBI > LPT1

 The QB, QBX, or QBI editor environment will behave normally, but
 output from the BASIC program running in the environment will be
 redirected to the printer. You can also redirect to a file on disk
 as follows:

    QB  > myfile.dat
    QBX > myfile.dat
 or
    QBI > myfile.dat

 The screen output obtained by opening the "SCRN:" FOR OUTPUT AS #Num2,
 and executing the statement PRINT #Num2 can't be redirected to a file.

 The following is an example of redirecting the output of a QuickBASIC
 program to a file:

 Code Example
 ------------

 OPEN "CONS:" FOR OUTPUT AS #1
 OPEN "SCRN:" FOR OUTPUT AS #2

 PRINT "This is a regular print"
 PRINT #2, "This is a print to scrn:"
 PRINT "This is a regular print"
 PRINT #1, "This is a print to cons:"

 CLOSE #1
 CLOSE #2
 END

 Once the program is compiled, you can redirect the output to a file by
 executing the following line at the DOS prompt:

    EXEName > OutputFileName

 When this is executed, the OutputFileName will contain the following:

    This is a regular print
    This is a regular print
    This is a print to cons:

 And the screen will contain the following:

    This is a print to scrn:


 789. "Subscript Out Of Range" If REDIM Long Integer Array in SUB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom SR# S891016-
 Last Modified: 15-DEC-1989    ArticleIdent: Q50638

 REDIMing (redimensioning with REDIM) a dynamic long integer array that
 was passed to a SUBprogram generates a "Subscript Out Of Range" error
 at run time.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS and in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in Microsoft BASIC PDS
 Version 7.00 (fixlist7.00).

 The "Subscript Out Of Range" occurs whether the SUBprogram is compiled
 as part of the main program or it is compiled in a separate module.

 You can work around this problem by using an array type other than
 long integer, or by passing the array through a COMMON SHARED block.

 The following code demonstrates the problem passing a dynamic array of
 long integers to a SUBprogram and REDIMing it in the SUBprogram.

 REM $DYNAMIC
 DIM arrayb&(50)
 CALL Test(arrayb&())
 END

 SUB Test(arrayc&())
    REDIM arrayc&(100)
 END SUB


 790. Linking QuickBASIC 4.50 with QuickC 2.00, 2.01 Font Library

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC
 Last Modified: 27-DEC-1989    ArticleIdent: Q50735

 QuickBASIC Version 4.50 and Microsoft BASIC PDS Version 7.00 can call
 routines contained in the QuickC Version 2.00 or 2.01 font library.
 One restriction is that the QuickBASIC program must be compiled with
 the BRUNxx.EXE option, or it will not link with the C program. BASIC
 PDS 7.00 is also restricted and must be linked with the BRT70xxx.EXE
 option. Note also that the QuickBASIC program must make a call to
 SETMEM to release far memory that the C routine will need to use for
 its workspace.

 This information about interlanguage calling applies to QuickBASIC
 Versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS Version 7.00 for MS-DOS and MS OS/2.

 The following is a sample program that demonstrates calling a C
 routine to display text in the Times Roman Bold font. This sample is
 based on the sample program given on Page 268 of the "Microsoft C for
 Yourself Version 2.0" manual that comes with QuickC Versions 2.00 and
 2.01.

 Code Example
 ------------

 The following BASIC program is CFONT.BAS, which calls a C routine to
 display text on the screen in the Times Roman Bold font:

 DECLARE SUB WriteTMSRB CDECL ()
 ' Release the available far memory for the C routine:
 ' Note: This releases the entire far heap. This probably should
 ' not be done with programs that use $DYNAMIC arrays.
 X = SETMEM(-FRE(-1))
 CALL WriteTMSRB
 END

 The following C routine is TMSRB.C, which calls the Font library
 routines to display text on the screen in the Times Roman Bold font:

 #include <stdio.h>
 #include <graph.h>

 void WriteTMSRB()
 {
   int mode = _VRES16COLOR;

   /* Read header info from .FON file */
   if (_registerfonts("TMSRB.FON") < 0)
   {
     _outtext("ERROR: can't register fonts");
     exit (0);
   }

   /* Set highest available video mode */
   while(!_setvideomode(mode))
     mode--;
   if (mode == _TEXTMONO)
     exit(0);

   /* Set font and display text */
   if (!_setfont ("t'helv'h30w24b"))
   {
     _moveto(10,10);
     _outgtext("THIS IS IN TIMES ROMAN BOLD");
     getch();
   }
   else
   {
     _setvideomode(_DEFAULTMODE);
     _outtext("ERROR: can't set font");
     exit(0);
   }

   _setvideomode(_DEFAULTMODE);
   _unregisterfonts();
 }

 For QuickBASIC, the steps to compile and link are as follows:

    BC CFONT.BAS;
    QCL /c /AM TMSRB.C
    LINK /noe /nod CFONT+TMSRB,,,BRUN45.LIB+MLIBCE.LIB+GRAPHICS.LIB;

 For BASIC PDS 7.00, the steps to compile and link are as follows:

    BC CFONT.BAS;
    QCL /c /AM TMSRB.C
    LINK /noe /nod CFONT+TMSRB,,,BRT70ENR.LIB+MLIBCE.LIB+GRAPHICS.LIB;


 791. How to Enter Extended ASCII Characters in QB.EXE Using ALT Key

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890925-102 B_BasicCom
 Last Modified: 13-MAR-1990    ArticleIdent: Q50736

 To enter most ASCII character byte values in the QB.EXE editor,
 including characters without their own keys, you can hold down the ALT
 key while typing in the numeric value for the character on the numeric
 keypad and then releasing the ALT key. The character with that code
 will be inserted at the current cursor position. For example,
 ALT+1+7+2 is the symbol for one-fourth (1/4).

 Extended ASCII characters (values 128 to 255) are useful for typing
 line-drawing characters, foreign alphabet characters, or other special
 symbols into quoted strings or comments (REM or ') in your code. For
 example, QCARDS.BAS for QuickBASIC 4.50 uses extended ASCII characters
 to make attractive screen boxes.

 This information applies to QB.EXE in Microsoft QuickBASIC Versions
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to QB.EXE in
 Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and to
 QBX.EXE in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS.

 Most of the ASCII characters (32 through 255) can be entered using the
 ALT key, including the normal alphabetic characters. For example, if
 the ALT key is held down while the number 65 is typed on the numeric
 keypad (with NUM LOCK active) and then ALT is released, "A" is
 inserted at the current cursor position, since the ASCII code for "A"
 is 65 (decimal). This ALT key technique also works at the MS-DOS
 command line and in many other programs in MS-DOS.

 How to Handle ASCII 0-31 Control Codes
 --------------------------------------

 Note that you cannot use the above ALT key method to embed ASCII
 character codes 0 through 31 into your source code. (ASCII characters
 0 through 31, which are often called control characters, have special
 program-specific meanings.) You also cannot type ASCII 240 using the
 ALT key in QB.EXE or QBX.EXE (ALT+2+4+0). If you want to use a
 character with ASCII value 0-31 or 240 as output from your BASIC
 program, you can use the CHR$() function to generate the character.
 The CHR$() function can be used to generate any ASCII (0-127) or
 extended-ASCII (128-255) character for output from a BASIC program.

 However, in QuickBASIC 4.00, 4.00b, and 4.50, and in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b, the PRINT statement does not display
 any character for control codes 7, 9-13, and 28-31 at run time
 (whether the character is embedded in a string with CTRL+P or created
 with the CHR$() function). For more information, query on the
 following words:

    ASCII and PRINT and SCRN and CONS

 NOTE: In QB.EXE 4.00 and later and in QBX.EXE 7.00, you can use the
 CTRL+P key to enter some of the control codes from 1 through 31. As an
 example, for 1 press CTRL+P+A, for 2 press CTRL+P+B, for 3 press
 CTRL+P+C, ..., and for 31 press CTRL+P+_ (CTRL+P+underscore).
 Many of these control codes can be typed into string constants or
 comments in your source code. WARNING: BC.EXE may not accept some
 control codes embedded in your source file. Also, the QBX.EXE editor
 does not let you enter the following CTRL+P sequences: CTRL+P+@ (0),
 CTRL+P+J (10), CTRL+P+M (13), CTRL+P+\ (28), or CTRL+P+^ (30).
 Microsoft recommends using the CHR$() function to generate the control
 characters you need instead of typing control characters directly into
 the source file.

 References for ASCII Symbols 0-255
 ----------------------------------

 The numeric character codes 0-255 are documented in the following
 ASCII and extended-ASCII tables:

 1. In the QuickBASIC 4.50 QB Advisor online Help system under
    Contents, "ASCII Character Codes"

 2. In the Microsoft Advisor online Help system for BASIC PDS 7.00
    under Contents, "ASCII Character Codes"

 3. Pages 464-465 of "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" manual for Versions 4.00 and 4.00b

 4. Pages 464-465 of "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" for Versions 6.00 and 6.00b for MS OS/2 and MS-DOS

 5. Pages 602-603 of "Microsoft BASIC 7.0: Language Reference"


 792. If WIDTH 80,60 in SCREEN 12 Then PALETTE Can Give Wrong Color

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 B_BasicCom
 Last Modified: 21-SEP-1990    ArticleIdent: Q50896

 In SCREEN 12, if the WIDTH 80, 60 statement is used to set the screen
 to 60-line mode and then the PALETTE statement is used to set
 attributes and colors, the palette can give erroneous colors. The
 problem can be worked around by changing the WIDTH statement to
 WIDTH , 30 to set the screen to 30-line mode instead of 60.

 The code fragment given below demonstrates the problem in QuickBASIC
 version 4.50. The same code fragment runs correctly in QuickBASIC
 versions 4.00 and 4.00b.

 Microsoft has confirmed this to be a problem in QuickBASIC version
 4.50 and in Microsoft BASIC Professional Development System (PDS)
 version 7.00 (buglist7.00). This problem was corrected in BASIC PDS
 version 7.10 (fixlist7.10).

 The program below reproduces the problem on SCREEN 12, which requires
 a VGA. It should produce bands of shades of gray going from black to
 white across the screen. Instead, it produces bands of the same set of
 incorrect colors each time it is run.

    SCREEN 12
    WIDTH 80, 60            'WIDTH 80, 30 gives correct results
    FOR X = 4 TO 60 STEP 4
        A& = 65536 * X + 256 * X + X
        B = X / 4
        PALETTE B, A&
    NEXT
    FOR X = 1 TO 16
        LINE (X * 10, 0)-(X * 10 + 20, 350), X, BF
    NEXT


 793. Using CALL INTERRUPT to Get Current SCREEN Video Mode

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891113-112 B_BasicCom
 Last Modified: 14-DEC-1989    ArticleIdent: Q50943

 It is possible to get the current SCREEN mode using the CALL INTERRUPT
 statement in compiled BASIC. This is useful if the program does not
 keep track of the current SCREEN mode, and the current video state
 needs to be saved.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00, and 6.00b
 for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The following BASIC program allows you to change the video mode, then
 uses CALL INTERRUPT to return the current video mode. The return
 values from the CALL INTERRUPT are not the same as the BASIC SCREEN
 modes, so the program creates an array that is used to translate the
 returned values back to BASIC SCREEN modes.

 Code Example: SCRMODE.BAS
 -------------------------

 REM $INCLUDE: 'qb.bi'   ' defines for CALL INTERRUPT
 ' For BC.EXE and QBX.EXE for BASIC 7.00, use the include file 'QBX.BI'
 ' and the Quick library  QBX.QLB.
 DIM inregs AS regtype
 DIM outregs AS regtype
 DIM screenarray(19) AS INTEGER
 FOR i% = 0 TO 19
         READ screenarray(i%)
 NEXT
 INPUT "enter screen mode: "; smode%
 inregs.ax = &HF00       ' BIOS interrupt to return video mode
 CALL interrupt(&H10, inregs, outregs)
 smode% = outregs.ax AND &HFF   ' mask off contents of AL register
 PRINT "Current screen mode = "; screenarray(smode%)
 ' Define conversion array for SCREEN modes
 DATA 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 7, 8, 10, 9, 11, 12, 12
 END

 To demonstrate this program from an .EXE program, compile and link as
 follows:

    BC SCRMODE.BAS;
    LINK SCRMODE,,,QB.LIB;

 For BASIC PDS 7.00, use QBX.LIB instead of QB.LIB.

 If you run the program within the QuickBASIC QB.EXE editor, the
 default Quick library QB.QLB must be loaded in, as follows:

    QB SCRMODE /L

 For QBX.EXE 7.00, the default Quick library QBX.QLB must be loaded in,
 as follows:

    QBX SCRMODE /L


 794. Using CALL INTERRUPT to Push Characters into Keyboard Buffer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891113-111 B_BasicCom
 Last Modified: 21-FEB-1991    ArticleIdent: Q50944

 It is possible in compiled BASIC to push keys into the keyboard buffer
 on IBM AT and PS/2 class computers using the CALL INTERRUPT statement.
 (This technique will not work on IBM PC class computers.) This can
 allow you to create keyboard macros, such as for training and
 demonstration sequences in a program. Therefore, if you were to write
 a program that required a lot of input from and interaction with a
 user, you could also write a training or demonstration sequence that
 would show the user what kind of input your program required, using
 the method demonstrated below. This would require filling in the
 required responses for the user by pushing the keystrokes into the
 keyboard buffer.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC PDS versions 7.00 and 7.10
 for MS-DOS.

 The interrupt for the key push routine requires both the scan code for
 the key and the ASCII value of the character to be pushed. A maximum
 of 15 characters can be pushed into the keyboard buffer at one time.

 The program shown below, KEYPSH.BAS, sets up a table containing all of
 the scan codes for ASCII character values 32 (a space) through 126
 (~), and defines the routine PUSHSTRING that will push the passed
 string of characters into the keyboard buffer.

 Code Example: KEYPSH.BAS
 ------------------------

 ' This program works on IBM AT and PS/2 class computers, but not on
 ' IBM PC class computers.
 DECLARE SUB pushstring (thestring$)
 REM $INCLUDE: 'qb.bi'   ' User-defined TYPEs for CALL INTERRUPT
 ' For BC.EXE and QBX.EXE in BASIC 7.00, use the include file 'QBX.BI'
 DIM SHARED scanarray(1 TO 93) AS INTEGER
 FOR i% = 1 TO 93  ' initialize scan code array
         READ scanarray(i%)
 NEXT
 CALL pushstring("<Key Push!>")
 INPUT a$
 PRINT a$
 ' Define Scan Codes for ASCII characters 32 (space) through 126 (~):

 REM      !   "  #  $  %  &   '   (   )  *   +   ,   -   .   /
 DATA 57, 2, 40, 4, 5, 6, 8, 40, 10, 11, 9, 13, 51, 12, 52, 53

 REM    0  1  2  3  4  5  6  7  8   9
 DATA  11, 2, 3, 4, 5, 6, 7, 8, 9, 10

 REM   :   ;   <   =   >   ?  @
 DATA 39, 39, 51, 13, 52, 53, 3

 REM   A   B   C   D   E   F   G   H   I   J   K   L   M
 DATA 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50

 REM   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
 DATA 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44

 REM   [   \   ]  ^   _   `
 DATA 26, 43, 27, 7, 12, 41

 REM   a   b   c   d   e   f   g   h   i   j   k   l   m
 DATA 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50

 REM   n   o   p   q   r   s   t   u   v   w   x   y   z
 DATA 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44

 REM   {   |   }   ~
 DATA 26, 43, 27, 41

 SUB pushstring (thestring$)   ' pushes string into keyboard buffer
    DIM inregs AS regtype
    DIM outregs AS regtype
    stringlen = LEN(thestring$)
    IF stringlen > 15 THEN stringlen = 15  ' max buffer size = 15
    FOR i% = 1 TO stringlen
       inregs.ax = &H500    ' subfunction to push character
       ascvalue = ASC(MID$(thestring$, i%, 1))
       IF ascvalue >= 32 AND ascvalue <= 126 THEN
          'assign scan code to high byte
          inregs.cx = scanarray(ascvalue - 31) * 256
          inregs.cx = inregs.cx + ascvalue   ' add ASCII code
          CALL interrupt(&H16, inregs, outregs) ' keyboard interrupt
       END IF
    NEXT
 END SUB

 To compile and link with Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, or with Microsoft BASIC Compiler versions 6.00 and 6.00b,
 perform the following:

    BC KeyPSH.bas;
    LINK KeyPSH.bas,,,BRUNxx.Lib+QB.Lib;

 The "xx" in the library name is for the current version of the product
 you are using (40, 41, 45, 60, or 61). For BASIC compiler 6.00 and
 6.00b, use BRUNxxER.LIB (emulation math package) or BRUNxxAR.LIB
 (alternate math package). For the alternate math library, you must
 compile with the BC /FPa switch. If you compile with BC /O, link with
 BCOMxx.LIB instead of BRUNxx.LIB.

 To run this program in the QB.EXE environment, you must load the Quick
 library QB.QLB as follows:

    QB /L QB.QLB

 For BASIC PDS 7.00, compile and link as follows:

    BC KeyPSH.bas;
    LINK KeyPSH.bas,,,BRT70ENR.Lib+QBX.Lib;

 The above example is for the math emulation, near strings, and real
 mode run-time library. The other possible run-time libraries and their
 corresponding compiler switches are as follows:

    Library Name   Compiler Switches    Comments
    ------------   -----------------    --------

    BRT70ENR.LIB   [default in MS-DOS]   Emulation math, near strings
    BRT70ANR.LIB   /FPa                  Alternate math, near strings
    BRT70EFR.LIB   /Fs                   Emulation math, far strings
    BRT70AFR.LIB   /FPa /Fs              Alternate math, far strings

 To use stand-alone libraries, use BCL70xxx.LIB instead of BRT70xxx.LIB
 and add the compiler switch BC /O.

 For the QBX.EXE 7.00 environment, use QBX.QLB as follows:

    QBX /L QBX.QLB

 References:

 For more articles about reading from and writing to the keyboard
 buffer, query on the following words:

    interrupt and keyboard and buffer

 Keyboard scan codes and ASCII codes are documented in Appendix D of
 "Microsoft QuickBASIC 4.5: Programming in BASIC"; in Appendix A of
 "Microsoft QuickBASIC 4.0: Language Reference" for 4.00 and 4.00b; in
 Appendix A of "Microsoft BASIC Compiler 6.0: Language Reference" for
 6.00 and 6.00b; and in Appendix A of "Microsoft BASIC 7.0: Language
 Reference" manual for BASIC PDS versions 7.00 and 7.10.


 795. How to Get Blinking Text in BASIC SCREEN Modes 7, 8, 9, 12, 13

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891113-97 B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q50945

 The program example below demonstrates how to use the CALL INTERRUPT
 statement to enable blinking text in screen modes 7, 8, 9, 12, and 13.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Interrupt 10 hex, with function 10 hex and subfunction 03 hex, can be
 used to toggle the blink/intensity bit on the video card. This
 determines whether the most-significant bit of the character attribute
 selects a blinking or intensified display. The default is for this bit
 to signify intensified display.

 After this interrupt has been called, anything displayed in colors 0
 through 7 is displayed normally, but anything displayed in colors 8
 through 15 is displayed blinking. This is because colors 8 through 15
 have the most-significant bit of the character attribute set.

 The registers to load for the interrupt call are as follows:

    Interrupt 10 hex
    AH = 10 hex
    AL = 03 hex
    BL = 0 = enable intensity (turns off blinking)
         1 = enable blinking  (turns off intensity)

 Running the following program, BLINK.BAS, enables and disables
 blinking characters:

 REM $INCLUDE: 'qb.bi'
 ' For BC.EXE and QBX.EXE in PDS 7.00 or 7.10, use the include file 'QBX.BI'

 DIM inregs AS regtype
 DIM outregs AS regtype
 SCREEN 9
 FOR x% = 1 TO 15
    COLOR x%
    PRINT "this is color: "; x%
 NEXT
 COLOR 7
 LOCATE 24, 1
 PRINT "Press any key to enable blinking";
 WHILE INKEY$ = "": WEND
 inregs.ax = &H1003
 inregs.bx = 1
 CALL interrupt(&H10, inregs, outregs)
 LOCATE 24, 1
 PRINT "Press any key to turn off blinking";
 WHILE INKEY$ = "": WEND
 inregs.ax = &H1003
 inregs.bx = 0
 CALL interrupt(&H10, inregs, outregs)

 Compile and link with Microsoft QuickBASIC 4.00, 4.00b, and 4.50 or
 with Microsoft BASIC Compiler 6.00 and 6.00b as follows:

    BC Blink.bas;
    LINK Blink.bas,,,BRUNxx.Lib+QB.Lib;

 The "xx" in the library name is for the current version of the product
 you are using (40, 41, 45, 60, or 61). For Microsoft BASIC Compiler
 6.00 and 6.00b, use BRUNxxER.Lib (emulation math package) or
 BRUNxxAR.Lib (alternate math package). For the alternate math library,
 you must compile with the BC /FPa switch. If you compile with BC /O,
 link with BCOMxx.LIB instead of BRUNxx.LIB.

 To run this program in the QB.EXE environment, you must load the Quick
 library QB.QLB: QB /L QB.QLB.

 For BASIC PDS 7.00 or 7.10, compile and link as follows:

    BC Blink.bas;
    LINK Blink.bas,,,BRT70ENR.Lib+QBX.Lib;

 The above example is for the math emulation, near strings, and real
 mode run-time library. The other possible run-time libraries and their
 corresponding compiler switches are as follows:

    Library Name   Compiler Switches     Comments
    ------------   -----------------     --------

    BRT70ENR.LIB   [The default mode]    Emulation math, near strings
    BRT70ANR.LIB   /FPa                  Alternate math, near strings
    BRT70EFR.LIB        /Fs              Emulation math, far strings
    BRT70AFR.LIB   /FPa /Fs              Alternate math, far strings

 To use stand-alone libraries, use BCL70xxx.Lib instead of
 BRT70xxx.Lib and add the compiler switch BC /O.

 For the QBX.EXE 7.00 or 7.10 environment, use QBX.QLB: QBX /L QBX.QLB.

 Note: This interrupt can be used to accomplish the same effect in
 SCREEN 0. Usually this in not needed because the COLOR statement can
 be used to control the intensity and blinking. However, if a program
 is directly accessing the hardware (through POKE, for example), this
 interrupt might be needed. This will have no effect for video cards
 that are NOT in a color mode (for example, MODE CO80). For example, if
 a program is running on a dual-monitor system (Hercules and VGA) and
 the current mode is monochrome, this interrupt will not affect the
 color card.


 796. Can't Directly Delete a Record from a BASIC Random Access File

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891113-44 B_BasicCom B_GWBasicI B_BasicInt
 Last Modified: 14-DEC-1989    ArticleIdent: Q50946

 You cannot directly delete a record from a BASIC random access file to
 make the file size decrease. This is a DOS and OS/2 operating system
 limitation for the random access method. You can, however, work around
 this in several different ways as explained below.

 This information applies to GW-BASIC Versions 3.20, 3.22, and 3.23 for
 MS-DOS; to Microsoft BASIC Interpreter Version 5.28 for MS-DOS; to
 Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler Versions
 5.35 and 5.36 for MS-DOS and Versions 6.00, and 6.00b for MS-DOS and
 MS OS/2; and to Microsoft BASIC PDS 7.00 for MS-DOS and MS OS/2.

 Both DOS and OS/2 support operating system calls that allow
 applications to create and manipulate files with random and sequential
 access. However, neither DOS nor OS/2 offers a record-deleting
 feature, such as a feature that reduces a file's size when a record is
 deleted. This limitation can be worked around in several different
 ways:

 1. The individual elements in a data record can be cleared by setting
    all strings to NULL ("") and all numeric items to zero (0). The
    record will still take up space on the disk. The program can be
    written to detect and skip the record when it is processing the
    data file.

 OR

 2. All of the records of the old data file can be copied to a new data
    file. As the program is copying the file, it can skip any records
    that were "marked" for deletion, as in step 1 above. The old data
    file can then be deleted, and the new file renamed to the original
    data file name.

 OR

 3. A separate index file can be created that can be used to track
    deleted records. All processing of the file will use the index file
    to skip the deleted records, and when new records are added, the
    key file can be used to insert new records into the location that
    the deleted records used to occupy.

 Microsoft BASIC PDS 7.00 has ISAM file support that does support
 DELETE for records of ISAM files. Since ISAM files are allocated in
 32K chunks, new space will only be gained if a block of 32K can be
 removed. To gain this space you must run ISAMPACK.EXE. ISAM file
 support is available for MS-DOS only.


 797. How to Get Extended Error in QuickBASIC Like EXTERR in GWBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891107-92 B_BasicCom B_GWBasicI
 Last Modified: 14-DEC-1989    ArticleIdent: Q50947

 The EXTERR function found in GW-BASIC Versions 3.20, 3.22, and 3.23 is
 not built into QuickBASIC Versions 4.00, 4,00b, 4.50, or earlier, but
 below is a code example calling a DOS interrupt that returns the same
 information (concerning extended errors in MS-DOS 3.00 and later).

 This code example applies to Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00,
 and 6.00b for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for
 MS-DOS.

 The EXTERR function found in GW-BASIC takes a value of n as an
 argument and returns a different set of values, depending on the value
 of n. This return value gives detailed information on the most recent
 DOS error. For all values of n, EXTERR returns 0 (zero) if there was
 no previous DOS error, or if the version of DOS is earlier than 3.00.

    Value of n        EXTERR(n) Return Value
    ----------        ----------------------
    0                 Extended error code
    1                 Extended error class
    2                 Extended error suggested action
    3                 Extended error locus

 To find what the error codes returned by EXTERR mean, look up the
 values in "Advanced MS-DOS Programming, 2nd Edition" by Ray Duncan
 (published by Microsoft Press, 1988) on Pages 145 and 146. This book
 also documents the interrupt used below, along with the extended error
 codes on Pages 453 through 456.

 Compile and link with Microsoft QuickBASIC 4.00, 4.00b. and 4.50, or
 with Microsoft BASIC Compiler 6.00 and 6.00b as follows:

    BC Test.bas;
    LINK Test.bas,,,BRUNxx.Lib+QB.Lib;

 The "xx" in the library name is for the current version of the product
 you are using (40, 41, 45, 60, or 61). For BASIC compiler 6.00 and
 6.00b, use BRUNxxER.LIB (emulation math package) or BRUNxxAR.LIB
 (alternate math package). For the alternate math library, you must
 compile with the BC /FPa switch. If you compile with BC /O, link with
 BCOMxx.LIB instead of BRUNxx.LIB.

 Also, if you run this program in the QB.EXE environment, you must load
 the Quick library QB.QLB as follows:

    QB /L QB.QLB

 For BASIC PDS 7.00, compile and link as follows:

    BC Test.bas;
    LINK Test.bas,,,BRT70ENR.Lib+QBX.Lib;

 The above example is for the math emulation, near strings, and real
 mode run-time library. The other posible run-time libraries and their
 corresponding compiler switches are as follows:

 Library Name   Compiler Switches     Comments
 ------------   -----------------     --------

 BRT70ENR.LIB                         Emulation math, near strings
 BRT70ANR.LIB        /FPa             Alternate math, near strings
 BRT70EFR.LIB        /Fs              Emulation math, far strings
 BRT70AFR.LIB        /FPa /Fs         Alternate math, far strings

 To use stand-alone libraries, use BCL70xxx.LIB instead of
 BRT70xxx.LIB, and you must add the compiler switch BC /O.

 For the QBX.EXE 7.00 environment, use QBX.QLB as follows:

    QBX /L QBX.QLB

 Code Example
 ------------

 REM $INCLUDE: 'QB.BI'
 ' For BC.EXE and QBX.EXE in BASIC 7.00, use the include file 'QBX.BI'

 DIM Inregs AS RegTypeX, Outregs AS RegTypeX
 CLS
 INPUT "Enter the filename "; test$
 test$ = test$ + CHR$(0)
 Inregs.ax = &H3D00
 Inregs.ds = VARSEG(test$)
 ' For BASIC Compiler 7.00 and QBX.EXE use SSEG(test$)
 '     instead of VARSEG(test$)

 Inregs.dx = SADD(test$)
 CALL INTERRUPTX(&H21, inregs, outregs)
 check = outregs.flags AND &H1
 IF check = 1 THEN
    PRINT "The file was not found"
    Inregs.ax = &H5900
    Inregs.bx = inregs.bx AND &HFF
    CALL INTERRUPTX(&H21, Inregs, Outregs)
    PRINT "This is the error number"; Outregs.ax
 ELSE
   PRINT "Your file was found, no extended error information is needed"
 END IF
 END



 798. May Be LINK Error If Separate Source Files Have Same Root Name

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 15-MAR-1990    ArticleIdent: Q51074

 LINK.EXE puts the code of separate BASIC OBJect files into the same
 code segment when the base filenames of the source code are the same
 but the filename extensions are different. This procedure will lead to
 the normal code-size-limitation linker error messages, such as the
 following, if the resulting code segment becomes too large:

    L1070      "SEGMENT SIZE EXCEEDS 64K"
    L2002      "FIXUP OVERFLOW NEAR ..."

 If the combined code segment is smaller than the 64K limit, then no
 LINK error occurs and the program should run correctly.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS 7.00 for
 MS-DOS and MS OS/2.

 A related issue in QBX.EXE which is supplied with BASIC PDS 7.00 is if
 a module and an $INCLUDE file are loaded into QBX.EXE at the same time
 and have the same base name, QBX.EXE will not let you run the program
 and gives the message "Duplicate module base name loaded. Can't
 compile." To work around this problem, unload the include file or use
 a different base name for your include file.

 Code Example
 ------------

 The two modules (MAIN.BAS and MAIN.1) in the following example
 generate object files (MAIN.OBJ and MAIN1.OBJ), which are small enough
 to link successfully, but they show that the LINKer combines them into
 one code segment, MAIN_CODE.

 Compile two programs, MAIN.BAS and MAIN.1, where MAIN.BAS is the main
 module and MAIN.1 is a module of subroutines.

 The following is MAIN.BAS:

    DECLARE SUS SUB1()
    CALL SUB1
    PRINT "I'M BACK"

 The following is MAIN.1:

    SUB SUB1()
       PRINT "IN SUB"
    END SUB

 Compile as follows, renaming the object file for MAIN.1 to MAIN1.OBJ
 to distinguish it from the other module, MAIN.OBJ:

    BC MAIN.BAS;
    BC MAIN.1,MAIN1.OBJ;

 Then LINK and create a LINKer .MAP file:

    LINK MAIN MAIN1,,MAIN.MAP;

 If the subroutine module MAIN.1 is named MAIN1.BAS, the resulting
 .EXE file will have two code segments (two BC_CODE entries listed
 under "Class" in the LINKer .MAP file). But the .EXE program resulting
 from the above instructions will have only one code segment, as shown
 in the following link map (from MAIN.1 and MAIN.BAS compiled in
 QuickBASIC 4.50):

  Start  Stop   Length Name                   Class
  00000H 000A0H 000A1H MAIN_CODE              BC_CODE
  000B0H 002F5H 00246H _TEXT                  CODE
  002F6H 00977H 00682H LOADRTM                CODE
  00980H 0173FH 00DC0H BR_DATA                BLANK
  01740H 01740H 00000H BR_SKYS                BLANK
  01740H 01740H 00000H COMMON                 BLANK
  01740H 0174BH 0000CH BC_DATA                BC_VARS
  0174CH 01751H 00006H NMALLOC                BC_VARS
  01752H 01752H 00000H ENMALLOC               BC_VARS
  01752H 01752H 00000H BC_FT                  BC_SEGS
  01760H 01779H 0001AH BC_CN                  BC_SEGS
  01780H 01792H 00013H BC_DS                  BC_SEGS
  01794H 01794H 00000H BC_SAB                 BC_SEGS
  01794H 0179FH 0000CH BC_SA                  BC_SEGS
  017A0H 017A0H 00000H _DATA                  DATA
  017A0H 017BBH 0001CH CDATA                  DATA
  017BCH 017BCH 00000H XCB                    DATA
  017BCH 017BFH 00004H XC                     DATA
  017C0H 017C0H 00000H XCE                    DATA
  017C0H 017C0H 00000H XIFB                   DATA
  017C0H 017C0H 00000H XIF                    DATA
  017C0H 017C0H 00000H XIFE                   DATA
  017C0H 017C0H 00000H XIB                    DATA
  017C0H 017C0H 00000H XI                     DATA
  017C0H 017C0H 00000H XIE                    DATA
  017C0H 017C0H 00000H XPB                    DATA
  017C0H 017C0H 00000H XP                     DATA
  017C0H 017C0H 00000H XPE                    DATA
  017C0H 017C0H 00000H XCFB                   DATA
  017C0H 017C0H 00000H XCF                    DATA
  017C0H 017C0H 00000H XCFE                   DATA
  017C0H 017CBH 0000CH DBDATA                 DATA
  017CCH 017CCH 00000H XOB                    BSS
  017CCH 017CCH 00000H XO                     BSS
  017CCH 017CCH 00000H XOE                    BSS
  017D0H 01FCFH 00800H STACK                  STACK

  Origin   Group
  0098:0   DGROUP

 Program entry point at 002F:00CE


 799. QB 4.x Editor Does Not Flag VARPTR$ Error, but BC.EXE Does

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom
 Last Modified: 30-NOV-1989    ArticleIdent: Q51075

 VARPTR$ can be used only with simple variables and with arrays of
 variable-length strings. Attempting to use the VARPTR$ function on a
 $DYNAMIC array is a programming error. However, the QB.EXE versions
 4.00, 4.00b, and 4.50 editors will not flag this as an error and will
 interpret and run programs that use VARPTR$ on $DYNAMIC arrays. The
 BC.EXE compiler Versions 4.00, 4.00b, and 4.50 correctly flag this as
 an error and give the error message "Dynamic array element illegal."

 This problem has been corrected in QBX.EXE, which comes with Microsoft
 BASIC Compiler Version 7.00 (fixlist7.00).

 The VARPTR$ function is used with both the PLAY and the DRAW
 statements to return the string representation of the address of a
 variable. The following code example demonstrates the problem in the
 QuickBASIC editor.

 Code Example
 ------------

      REM $DYNAMIC
      CLS
      TYPE aa
           a AS INTEGER
      END TYPE
      REDIM a(50) AS aa
      a(1).a = 10
      PRINT VARPTR$(a(1).a)
      END


 800. PE Option in OPEN COM Statement Enables Parity Checking

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891114-52 docerr B_BasicCom
 Last Modified: 15-MAR-1990    ArticleIdent: Q51076

 When opening a communications port (COM1 or COM2) in Microsoft
 QuickBASIC or Microsoft BASIC Compiler, the parity is not checked
 unless the PE option is specified in the OPEN COM statement.

 The PE option must be added under the OPEN COM statement (listed
 alphabetically under OPEN) in the following BASIC language references:

 1. The QB Advisor on-line Help system for QuickBASIC Version 4.50,
    under the OPEN COM statement

 2. Page 297 of "Microsoft QuickBASIC 4.0: BASIC Language Reference"
    manual for Versions 4.00 and 4.00b

 3. Page 297 of "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" for Versions 6.00 and 6.00b for MS OS/2 and MS-DOS

 4. Page 241 of "Microsoft BASIC 7.0: BASIC Language Reference" for
    Microsoft PDS Version 7.00 for MS OS/2 and MS-DOS

 5. The Microsoft Advisor on-line Help system for QuickBASIC Extended
    Version 7.00, under the OPEN COM statement.

 6. Page 375 of "Microsoft QuickBASIC Compiler" Versions 2.0x and 3.00
    manual

 The PE option is documented in the "Microsoft GW-BASIC Interpreter:
 User's Reference" for Versions 3.20, 3.22, and 3.23, under the OPEN
 COM statement.

 The PE option enables parity checking during communications. A "Device
 I/O error" occurs if the two communicating programs have two different
 parities. (Parity can be even, odd, none, space, or mark). For
 example, a "Device I/O error" occurs when two programs try to talk to
 each other across a serial line using the following two different OPEN
 COM statements:

    OPEN "COM1:1200,O,7,2,PE" FOR RANDOM AS #1
 and
    OPEN "COM2:1200,E,7,2,PE" FOR RANDOM AS #2

 If the PE option is removed from the OPEN COM statements above, no
 error occurs.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS, and to Microsoft BASIC PDS Version
 7.00 for MS-DOS.


 801. "Argument Count Mismatch" If CALL ABSOLUTE DECLARE Not Changed

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891113-110 B_BasicCom
 Last Modified: 12-DEC-1989    ArticleIdent: Q51077

 When using CALL ABSOLUTE in a Microsoft BASIC program, the error
 message "Argument Count Mismatch" occurs if parameters are passed to
 the CALLed routine and the DECLARE for CALL ABSOLUTE in QB.BI is not
 changed.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC PDS Version 7.00 for MS-DOS.

 The following lines appear in the include file QB.BI shipped with
 QuickBASIC Versions 4.00, 4.00b, and 4.50 and Microsoft BASIC Compiler
 Versions 6.00 and 6.00b, and in QBX.BI shipped with Microsoft BASIC
 PDS Version 7.00:

    'Call a routine at an absolute address.
    'NOTE: If the routine called takes parameters, then they will have to
    '      be added to this declare statement before the parameter given.
    DECLARE SUB ABSOLUTE (address AS INTEGER)

 This DECLARE statement must be changed if any parameters are passed to
 the CALLed routine. For example, if the CALLed routine was passed two
 parameters as follows

    CALL ABSOLUTE(FirstNumber!, SecondNumber%, VARPTR(AsmProg(1)))

 then the DECLARE statement in QB.BI or QBX.BI should be changed to the
 following:

    DECLARE SUB ABSOLUTE(A AS SINGLE, B AS INTEGER, address AS INTEGER)


 802. PRINT SPC(n) USING on Array Element, Bad Results

 Product Version(s): 4.00 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891110-96 buglist4.00 buglist4.50 fixlist4.00b
 Last Modified: 13-DEC-1989    ArticleIdent: Q51292

 The following code example demonstrates that using the SPC(n) function
 with the PRINT USING statement on an element of an array ($DYNAMIC or
 $STATIC) produces incorrect results with BC.EXE compiler Versions 4.00
 and 4.50. This problem does not occur in BC.EXE provided with
 QuickBASIC 4.00b or with the BASIC compiler 6.00 or 6.00b. This
 problem does not occur in the QB.EXE 4.00, 4.00b, and 4.50 editors.
 This problem does not occur in BC.EXE or QBX.EXE provided with
 Microsoft BASIC PDS Version 7.00 (fixlist7.00).

 The code example produces incorrect output when compiled with BC.EXE
 Version 4.50. Compiled with BC.EXE Version 4.00, it produces the error
 "Type mismatch in line 40 of module <filename> at address xxxx:xxxx".

 This problem occurs with either dynamic or static arrays. Compiling
 with the /AH switch does NOT correct the problem in either Version
 4.00 or 4.50.

 There are several workarounds to this problem. The easiest workaround
 is to use a literal such as " " or to use a function such as
 STRING(n, " "), which produces the same results as using the SPC(n)
 function. For example,

     PRINT ; STRING$(1, " ") ; USING ........

 is the equivalent of

     PRINT ; SPC(1) ; USING .......

 The above workaround will work in Version 4.00 or 4.50. However, in
 Version 4.50 the problem also does not occur if you compile with
 either the /d or /x options as follows:

 1. In the QB.EXE editor, choose to "Produce Debug Code".

 2. On the BC.EXE compile line use /D.

 The problem also does not occur if you use error trapping. This is
 done by including an ON ERROR GOTO and RESUME in the program. On the
 BC.EXE command line, include the /X compiler option. No combination of
 compiler switches corrects the problem for Version 4.00.

 Code Example
 ------------

 ' This code example can be used to reproduce the problem.
 ' Do not include error trapping or produce debug code.
 REM $DYNAMIC
 CLS
 DEFINT A-Z
 TYPE Rec1
        F1 AS STRING * 15
        F2 AS INTEGER
        F3 AS INTEGER
        F4 AS INTEGER
        F5 AS INTEGER
        F6 AS INTEGER
        F7 AS INTEGER
        F8 AS INTEGER
 END TYPE
 DIM a1(2) AS Rec1
 FOR k = 1 TO 2
        READ a1(k).F1
        READ a1(k).F2
        READ a1(k).F3
        READ a1(k).F4
        READ a1(k).F5
        READ a1(k).F6
        READ a1(k).F8
        a1(k).F7 = a1(k).F5 - a1(k).F6
 NEXT k
 Col = 12
 LOCATE , Col
 PRINT "  PGM=M1   A           B   C   D   E    F     G    H    J"
 LOCATE , Col
 PRINT STRING$(60, 196)
 10 FOR k = 1 TO 2
 20     LOCATE , Col
 30     PRINT SPC(1); USING "###"; k;
 40     PRINT ".";
 50     PRINT ; a1(k).F1;
 60     PRINT ; SPC(1); USING "###"; a1(k).F2 + a1(k).F3 + a1(k).F4;
 70     PRINT ; SPC(1); USING "###"; a1(k).F2;
 80
 '********************************************************************
 90      PRINT ; SPC(1); USING "###"; a1(k).F3; ' Error occurs here.
 100     PRINT ; SPC(1); USING "###"; a1(k).F4; ' Error occurs here.
 110
 120
 '********************************************************************
 130     PRINT ; SPC(1); USING "####"; a1(k).F5;
 140     PRINT " :";
 150      PRINT ; SPC(1); USING "###"; a1(k).F6;
 160     PRINT ; SPC(1); USING "####"; a1(k).F7;
 170     PRINT ; SPC(1); USING "####"; a1(k).F8
 180 NEXT k
 190 END

 DATA "Club 01   ",  2, 0, 9, 33, 57,  4
 DATA "Club 02   ",  3, 2, 6, 45, 17,  4
 END


 803. BASIC INPUT and LINE INPUT Always Turn on Cursor during Input

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890919-120  B_BasicCom B_GWBasicI
 Last Modified: 19-DEC-1989    ArticleIdent: Q51322

 The INPUT and LINE INPUT statements always turn on the cursor when
 they are executed. Turning off the cursor beforehand with the LOCATE
 statement will not turn off the INPUT or LINE INPUT cursor. If the
 LOCATE statement turned off the cursor before the INPUT or LINE INPUT
 statement, the cursor will be off after input is completed. But
 during execution of INPUT or LINE INPUT, the cursor remains on.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft
 BASIC Compiler Versions 6.00, and 6.00b for MS-DOS and MS OS/2,
 Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2, and to
 Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23 for
 MS-DOS.

 If you want a form of input that has no automatic cursor, you can
 invoke the LOCATE statement to turn off the cursor and use the INKEY$
 function in a loop to accept input character by character. For an
 example of using INKEY$ to input a fixed number of characters in a
 loop, query on the following words:

    buffered and INKEY$ and keyboard and INPUT and LOCATE

 The following code example demonstrates the visibility of the cursor
 when using the INPUT statement. The results are the same for the LINE
 INPUT statement.

 Code Example
 ------------

 LOCATE 1,1,0         'Turn cursor off
 INPUT a$             'Cursor will come back on
 PRINT a$             'Cursor will be off again
 while inkey$="" : wend   ' Wait for any keystroke.


 804. How to Use SEG Keyword with Arrays in DECLARE and CALLs

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891120-129 B_BASICCOM
 Last Modified: 12-DEC-1989    ArticleIdent: Q51411

 The examples shown below demonstrate how to use the SEG keyword with
 arrays. The SEG keyword may be used in either a DECLARE statement or a
 CALL statement when calling a non-BASIC routine, and is used to pass
 both the segment and offset of a variable (which corresponds to
 passing a far address).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS and to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2.

 When using SEG in the DECLARE statement to pass the far address of an
 array to a non-BASIC routine, the array should be specified as a
 simple variable without using the array notation, as follows:

    DECLARE SUB TEST(SEG a AS INTEGER)
    DIM a(10) AS INTEGER
    TEST(a(0))

 A compilation error will occur if the array is DECLAREd using array
 notation as follows:

    DECLARE SUB TEST(SEG a() AS INTEGER)
    DIM a(10) AS INTEGER
    TEST(a(0))

 Inside the QuickBASIC QB.EXE environment, the error message "Expected:
 , or )" will be displayed for the above DECLARE statement. When
 compiled from the BC.EXE command line, the following two error
 messages display:

    "Syntax error"
    "Formal parameter specification illegal"

 When using SEG in an explicit CALL statement there should not be a
 DECLARE statement. Explicitly using the CALL keyword (instead of using
 an implied call) takes the place of the DECLARE statement. The correct
 syntax is as follows:

    DIM a(10) AS INTEGER
    CALL TEST(SEG a(0))

 If a DECLARE statement is used with an explicit CALL statement that
 uses SEG, the error "Parameter type mismatch" displays.


 805. How BASIC's Graphics GET Statement Stores Graphics in an Array

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890822-40 B_MQUICKB B_BASICCOM B_BasicInt B_GWBasicI
 Last Modified: 12-DEC-1989    ArticleIdent: Q51412

 This article describes the format with which the graphics GET
 statement stores graphics in an array.

 This article applies to Microsoft GW-BASIC Interpreter Versions 3.20,
 3.22, 3.23 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, Microsoft QuickBASIC Versions 1.00,
 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b and 4.50 for MS-DOS,
 Microsoft QuickBASIC Version 1.00 for the Apple Macintosh, Microsoft
 BASIC Compiler Version 1.00 for the Apple Macintosh, and Microsoft
 BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and 3.00  for the
 Apple Macintosh.

 This internal product information is provided as is, and may be
 subject to change or nondisclosure in future versions of BASIC.

 The graphics GET statement transfers a screen image into a specified
 array. The first 4 bytes in the array are two integers which specify
 how wide and long the stored image is in pixels, while the rest of the
 data stored in the array is a binary representation of the stored
 screen image, as shown in the following diagram:

    +------------+------------+
    | image width, in pixels  |  <-- 2-byte integer number
    +------------+------------+
    | image length, in pixels |  <-- 2-byte integer number
    +--------+--------+--------+--------+--------+--------+
    |        |        |   < binary image data >  |        |
    +--------+--------+--------+--------+--------+--------+
     byte #5   byte #6  byte #7

 The binary image data depends on the screen mode of the graphic image
 and is stored linearly in memory by pixel rows and columns. The GET
 statement scans the screen image by row from left to right and stores
 the bit representation of each pixel. Each row of the stored data will
 be padded out to an even byte boundary by NULL bytes (ASCII 0). The
 following is an example.

    Take a square box drawn on the screen and stored with the following
    program:

       SCREEN 2   ' Delete this statement for Macintosh BASICs
       DIM box%(1 to 5)
       LINE (1, 1)-(10, 3), ,B
       GET (1, 1)-(10, 3), box%

    The first 4 bytes of box% will be as follows:

       box%(1) = 10  ' The box is 10 pixels wide
       box%(2) = 3   ' The box is 3 pixels long

    The binary representation of the remaining bytes in the box% array
    is as follows:

       box%(3) = 11111111 11000000  <- Note padding of each row of bits
       box%(4) = 10000000 01000000  <- Also note how the 1's form a box.
       box%(5) = 11111111 11000000

 How GET Stores Color on an IBM PC or Compatible
 -----------------------------------------------

 On an IBM PC or compatible, the way the graphics GET statement stores
 color information depends upon the characteristics of the display
 mode. For screen modes with a single color plane (SCREENs 1, 2, 3,
 11, and 13), each pixel is represented by the number of bits per pixel
 per plane for the particular display mode. The following is an
 example.

    If the square box given above were drawn in SCREEN mode 1 (2 bits
    per pixel per plane) with the following program,

       SCREEN 1
       DIM box%(1 to 7)
       LINE (1, 1)-(10, 3), ,B
       GET (1, 1)-(10, 3), box%

    then the binary representation of the image data bytes (after the
    4-byte width and length header) would be as follows:

       11111111 11111111 11110000
       11000000 00000000 00110000   <- Notice 2 bits per pixel
       11111111 11111111 11110000

    Since no color was specified, the default color (white) was used
    (thus all of the color bits were turned on).

 For SCREEN modes with multiple color pages (SCREENs 7, 8, 9, 10, and
 12), GET stores each display page separately by screen row. GET
 stores the binary information for one row of the graphics on the first
 color page and then the same row of graphics on the next color page,
 padding each row of color page information to an even byte boundary.
 The following is an example:

    If the same square box were drawn in SCREEN mode 12 (four color
    planes) in red with the following program,

       SCREEN 12
       COLOR 4   ' select red color
       DIM box%(1 to 14)
       LINE (1, 1)-(10, 3), ,B
       GET (1, 1)-(10, 3), box%

    then the binary representation of the image data bytes (again after
    the 4-byte header) would be as follows:

       00000000 00000000 <- blue plane
       00000000 00000000 <- green plane
       11111111 11000000 <- red plane (note padding to byte boundary)
       00000000 00000000 <- intensity plane - first row finished

       00000000 00000000 <- blue
       00000000 00000000 <- green
       10000000 01000000 <- red
       00000000 00000000 < - intensity - second row

       00000000 00000000
       00000000 00000000
       11111111 11000000
       00000000 00000000 <- last row

 GET Doesn't Preserve Color in QuickBASIC for the Macintosh
 ----------------------------------------------------------

 The graphics GET statement in Microsoft QuickBASIC Version 1.00 for
 the Macintosh does not preserve the colors of graphics in its array
 argument, and a subsequent graphics PUT using that array will draw in
 monochrome, using only the current foreground and background colors.

 The following list shows how the GET statement translates pixel colors
 on the screen and stores them in the array:

 1. White (or current background color) <= yellow, magenta, cyan, white

 2. Black (or current foreground color) <= red, green, blue, black

 The GET statement captures screen information as a bitmap only. Only
 the on or off status of each pixel -- not the color information -- is
 stored in the array.

 The ForeColor and BackColor MBLC routines built into QuickBASIC let
 you change the color used by subsequent graphics statements. Invoking
 ForeColor and BackColor will cause a subsequent graphics PUT to use
 that new foreground and background for all pixels drawn.

 Note that the earlier products, Microsoft BASIC Compiler Version 1.00
 for the Apple Macintosh and Microsoft BASIC Interpreter Versions 1.00,
 1.01, 2.00, 2.10, and 3.00 for the Apple Macintosh, do not support
 ForeColor or BackColor, or any color capabilities.


 806. In .EXE, PAINT Used in a SUB Can Corrupt Passed Variables

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified:  6-DEC-1989    ArticleIdent: Q51597

 The PAINT function can corrupt variables that are passed to a SUB when
 the program is compiled using BC.EXE 4.00 4.00B or 4.50. The PAINT
 function works correctly in the QB.EXE environment, and if compiled
 using BC.EXE with the /X switch.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00, 4.00b, and 4.50 and in Microsoft BASIC Compiler Versions 6.00
 and 6.00b (buglist6.00 buglist6.00b) for MS-DOS. This problem was
 corrected in Microsoft BASIC Compiler Version 7.00 (fixlist7.00).

 The following program demonstrates this problem. The values of x and y
 will be invalid following the PAINT(x, y) statement; however, the
 values of x and y are unaffected at the module level code following
 the call to "Sub1":

 Compile with either: BC Paint; or BC Paint /O;
 Link with:           Link Paint;

 Code Example: PAINT.BAS
 -----------------------

 DECLARE SUB Sub1(x,y)
 x = 300                'Initialize x
 y = 100                'Initialize y
 CALL Sub1(x,y)
 PRINT x; y             'These values will be correct
 END
 SUB Sub1 (x, y)
 SCREEN 12              'Any graphics mode
 PRINT x; y             'These values will be correct
 CIRCLE (x, y), 50
 PAINT (x, y)            'Paint the circle
 PRINT x; y             '** These values will contain garbage
 END SUB

 Specifying a definite type for x and y (such as INTEGER, LONG, SINGLE,
 or DOUBLE) does not have any effect on the output.

 Four possible workarounds for the PAINT problem are as follows:

 1. Compile with BC /X.

 2. Copy x and y to variables that are local to the SUB.

 3. PAINT at the module level instead of at the SUB level.

 4. Make x and y SHARED or COMMON SHARED.

 This problem was corrected in Microsoft BASIC Compiler 7.00.

 Additional reference word: SR# S891128-117


 807. SCREEN Function Doesn't Give Color Attribute in Graphics Mode

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891026-104 B_BasicCom
 Last Modified: 11-DEC-1989    ArticleIdent: Q51604

 In graphics mode, the number of the color returned by the SCREEN
 function will always have a value of 0 (zero).

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS and to
 Microsoft BASIC Compiler Versions 6.00, 6.00b, and 7.00 for MS-DOS and
 MS OS/2.

 The SCREEN function has the following syntax:

    SCREEN (row,column[,colorflag])

 When colorflag is nonzero, SCREEN returns the number of the color at
 the location specified by row and column -- but only in text mode.

 When colorflag is zero or absent, the ASCII code of the character at
 the specified location is returned as an integer in both graphics and
 text modes.


 808. How to Print VGA SCREEN 13 Image to Epson Printer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom appnote BQ0085 SR# S891207-106
 Last Modified: 18-OCT-1990    ArticleIdent: Q51860

 The program listing below demonstrates one method of printing VGA
 SCREEN 13 images to an Epson (or compatible) printer with graphics
 capability.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC PDS (Professional Development
 System) versions 7.00 and 7.10 for MS-DOS. (Earlier versions do not
 support VGA SCREEN 13.)

 This article is one part of the application note titled "How to Print
 BASIC Video Screens to Epson Printers." A printed copy of this
 application note can be obtained by calling Microsoft Product Support
 Services at (206) 637-7096. This application note can also be obtained
 in separate parts in this Knowledge Base by searching for the
 following words:

    Epson and print and screen and QuickBASIC

 If you have a printer other than an Epson-compatible, you must change
 the printer control codes used in the following program for setting
 line spacing and graphics mode. Control codes can be found in your
 printer's manual.

 The routine below for printing VGA SCREEN mode 13 is required only if
 you aren't running under MS-DOS versions 4.00 or later. In MS-DOS 4.00
 and later, the program GRAPHICS.COM supports all standard EGA and VGA
 SCREEN modes. Thus, the routine given in a separate article (part of
 this application note) for printing CGA SCREEN modes can be used to
 print EGA and VGA SCREENs in MS-DOS 4.00 and later.

 If you want further information about graphics memory and the various
 graphics modes, please refer to the following book, which is available
 in bookstores or by calling Microsoft Press at (800) 888-3303 or (206)
 882-8661:

     "Programmer's Guide to PC and PS/2 Video Systems," by Richard
     Wilton (published by Microsoft Press, 1987)

 Printing VGA Screen Mode 13
 ---------------------------

 The method used in the program below prints the image sideways, which
 avoids the need to do any bit-shifting and uses a simple
 eight-dots-per-pixel shading pattern to represent different colors.

 To produce different patterns for different colors, each byte of pixel
 information must be analyzed. In SCREEN 13, each pixel is represented
 by 1 contiguous byte of information, thus allowing 256 colors per
 pixel. Since 8 printer pins are fired for each pixel, a direct mapping
 of the pixel byte to the printer pins to be fired is done.

 As stated before, 8 pins are fired for each pixel; the pins are fired
 in a 2 by 4 pattern. Since this is not square, some slight image
 distortion does occur.

 The Epson printer can fire up to eight pins per graphics byte sent.
 Thus, moving from left to right, a loop that reads screen data from
 the bottom of the screen upward can access eight vertical columns at a
 time. This behavior coincides with the printer firing eight pins at a
 time and creates eight horizontal columns on the page, turning the
 printout sideways.

    DECLARE SUB VGAtoEpson (f$, flip%)

    '--- VGAEPSON.BAS
    '--- Demonstrates the use of VGAtoEpson, a subprogram that
    '--- dumps a SCREEN 13 image to an Epson printer.
    '--- Copyright (c) 1988 Microsoft Corp.
    REM $INCLUDE: 'QB.BI'

    DIM SHARED inregs AS regtype
    DIM SHARED outregs AS regtype

    SCREEN 13
    '--- Draw picture on screen
    xmax% = 319
    ymax% = 199
    halfx% = xmax% / 2
    halfy% = ymax% / 2
    x% = halfx%
    c% = 1
    FOR y% = ymax% TO halfy% STEP -2
      LINE (halfx%, y%)-(x%, halfy%), c%
      LINE (x%, ymax%)-(xmax%, y%), c% + 20
      LINE (halfx%, (ymax% - y%))-(x%, halfy%), c% + 40
      LINE (x%, 0)-(xmax%, (ymax% - y%)), c% + 60
      LINE (halfx% + 1, y%)-((xmax% - x%), halfy%), c% + 80
      LINE ((xmax% - x%), ymax%)-(0, y%), c% + 100
      LINE (halfx%, (ymax% - y%))-((xmax% - x%), halfy% + 1), c% + 120
      LINE ((xmax% - x%), 0)-(0, (ymax% - y%)), c% + 140
      x% = x% + (((xmax% + 1) / (ymax% + 1)) * 5)
      c% = c% + 1
    NEXT y%

    CALL VGAtoEpson("LPT1", 1)
    SCREEN 0
    END

    SUB VGAtoEpson (f$, flip%) STATIC
    '--- Sends the image on SCREEN 13 to an Epson graphics printer
    '--- Parameters:
    '         f$    -   Name of file or device to send image to
    '         flip% -   Invert flag (0 = normal, not 0 = invert)

      OPEN f$ FOR BINARY AS 1         'Open the output file
      WIDTH #1, 255
      esc$ = CHR$(27)
      line$ = esc$ + "A" + CHR$(8)
      PUT #1, , line$   'set printer to 8/72 lpi
      DEF SEG = &HA000                'Start of VGA screen memory
      '--- This loop is the horizontal byte location
      FOR Col% = 0 TO 79
         '--- Set the printer to receive 800 bytes of graphics data
         line$ = esc$ + "L" + MKI$(800)
         PUT #1, , line$  '(for init)

         '--- This loop is the vertical byte position
         FOR row% = 199 TO 0 STEP -1

            place& = row% * 320&
            place& = place& + Col% * 4
            ' 4 bytes of pixel information are read in. Each
            '  of these bytes is broken up across 4 variables
            '  that are used to fire the printer pins. 2 bits
            '  from each pixel byte are stored to each of the
            '  variables.
            mem1% = 0           ' Initialize storage bytes for
            mem2% = 0           '   color information.
            mem3% = 0
            mem4% = 0
            FOR byte% = 0 TO 3
               newplace& = place& + byte%
               shift% = 2 ^ ((7 - 2 * byte%) - 1)
               mem% = PEEK(newplace&)
               mem% = mem% AND 3
               mem% = mem% * shift%
               mem1% = mem1% OR mem%

               mem% = PEEK(newplace&)
               mem% = (mem% AND 12) / 4
               mem% = mem% * shift%
               mem2% = mem2% OR mem%

               mem% = PEEK(newplace&)
               mem% = (mem% AND 48) / 16
               mem% = mem% * shift%
               mem3% = mem3% OR mem%

               mem% = PEEK(newplace&)
               mem% = (mem% AND 192) / 64
               mem% = mem% * shift%
               mem4% = mem4% OR mem%
            NEXT

            '--- Flip the byte, if called from
            IF flip% <> 0 THEN
               mem1% = 255 - mem1%
               mem2% = 255 - mem2%
               mem3% = 255 - mem3%
               mem4% = 255 - mem4%
            END IF

            '--- Send bytes to device
            line$ = CHR$(mem1%) + CHR$(mem2%)

            line$ = line$ + CHR$(mem3%) + CHR$(mem4%)
            PUT #1, , line$
         NEXT
         line$ = CHR$(13) + CHR$(10)
         PUT #1, , line$
      NEXT
      ResetPrn$ = esc$ + "@"
      PUT #1, , ResetPrn$  ' Reset printer
      line$ = CHR$(12)
      PUT #1, , line$      ' Send formfeed (page eject)
      CLOSE 1              ' All done
    END SUB


 809. Failure to Flag ELSEIF THEN <Statement> as Syntax Error

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50 SR# S890922-
 Last Modified: 20-SEP-1990    ArticleIdent: Q51863

 In the products listed below, both the compiler and editor fail to
 trap an illegal block ELSEIF THEN <statement> syntax where a statement
 improperly follows on the same line as the THEN keyword. Despite the
 failure to trap this programming error, the code in the illegal syntax
 executes successfully.

 Microsoft has confirmed this to be a problem in the QB.EXE and BC.EXE
 environments of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS; in the QB.EXE and BC.EXE environments of Microsoft BASIC
 Compiler versions 6.00 and 6.00b (buglist6.00, buglist6.00b) for
 MS-DOS and MS OS/2; and in the QBX.EXE and BC.EXE environments of
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 (buglist7.00, buglist7.10). Microsoft
 is researching this problem and will post new information here as it
 becomes available.

 Code Example
 ------------

 The following code violates the block IF...ELSEIF...END IF statement
 syntax, but fails to generate a syntax error. The program successfully
 prints both "Hello" and "Hello2", despite the untrapped syntax error:

    IF 0 THEN
    ELSEIF 1 THEN PRINT "Hello"
       PRINT "Hello2"
    END IF

 (In comparison, this code correctly generates a "Syntax Error" on the
 ELSEIF phrase in Microsoft QuickBASIC for Apple Macintosh systems.)

 As an offshoot issue, when you single-step through the above program
 in the QB.EXE or QBX.EXE editor environment with F8, the debugger
 fails to highlight the PRINT "Hello" statement but correctly
 highlights the PRINT "Hello2" statement. ("Hello" correctly prints
 despite the PRINT "Hello" not being highlighted.) When you correct the
 program by placing PRINT "Hello" on the next line, F8 in the debugger
 correctly highlights that line.

 The ELSEIF...THEN line is not supposed to allow any statement
 following the THEN on that line. The following is the correct,
 required syntax:

    IF 0 THEN
    ELSEIF 1 THEN
       PRINT "Hello"
       PRINT "Hello2"
    END IF


 810. How to Print Hercules Graphics SCREEN 3 to an Epson Printer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | appnote BQ0085 B_BasicCom
 Last Modified: 18-OCT-1990    ArticleIdent: Q51886

 Below is an example of printing Hercules graphics SCREEN 3 to an Epson
 or Epson-compatible printer.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC PDS (Professional Development
 System) versions 7.00 and 7.10 for MS-DOS. (SCREEN 3 is supported in
 MS-DOS and MS OS/2 real mode, but not in MS OS/2 protected mode.)

 If you have a printer other than Epson, you must change the printer
 control codes used in the program for setting line spacing and
 graphics mode. You must find these control codes in your printer
 manual and make the appropriate modifications to the code below.

 This article is one part of the application note titled "How to Print
 BASIC Video Screens to Epson Printers." A printed copy of this
 application note can be obtained by calling Microsoft Product Support
 Services at (206) 637-7096. This application note can also be obtained
 as separate parts in this Knowledge Base by searching for the
 following words:

    Epson and print and screen and QuickBASIC

 If you want further information about Hercules graphics memory, please
 refer to the following book, which is available from bookstores or by
 calling Microsoft Press at (800) 888-3303 or (206) 882-8661:

    "Programmer's Guide to PC and PS/2 Video Systems," by Richard
    Wilton (Microsoft Press, 1987)

 Printing Hercules Screen Mode 3
 -------------------------------

 Understanding how to print graphics screens generated by Hercules and
 Hercules-compatible graphics adapters requires familiarity with how
 Hercules graphics memory is set up.

 Hercules memory starts at hex-paragraph B000 (decimal 45056). Graphics
 memory starts with Page 0 at hex-paragraph B000 (decimal 45056), and
 Page 1 at hex-paragraph B800 (decimal 47104). (Paragraphs mark segment
 boundaries, and there are 16 bytes per paragraph.)

 However, graphics memory is interleaved, and is not contiguous. Each
 line of pixels in SCREEN mode 3 consists of 90 bytes. Thus, the top
 line of pixels (line 0) on Page 0 will start at hex-paragraph B000 at
 offset 0 and go for 90 bytes.

 To draw a line of pixels at the top of the screen (in line 0 of Page
 0), POKE 255 into positions 0 through 89 (where 255 means all 8 bits
 per byte being "on"), as follows:

    SCREEN 3
    DEF SEG = &HB000
    FOR x = 0 TO 89    ' B000:0000 hex to B000:0059 hex (in
       POKE x, 255     ' segment:offset notation)
    NEXT x

 To perform this procedure on Page 1, change the value of the DEF SEG
 statement to hex-paragraph &HB800.

 Because graphics memory is interleaved and not contiguous, if you
 continue to POKE at an offset 90 bytes after hex-paragraph B000, the
 next line will appear on the screen at the fourth line down. To draw a
 line just one line down (on line 1), add 2000 Hex (8192 decimal) to
 the offset of the first byte on line 0, then POKE as follows:

    DEF SEG = &HB000
    FOR x = 8192 TO 8281     ' or B000:2000 hex to B000:2059 hex (in
       POKE x, 255           ' segment:offset notation)
    NEXT x

 This procedure must also be performed for line 2 and line 3. (Note
 that line numbering starts at 0.) As a result, the first byte of line
 2 will be B000:4000 hex, and the first byte of line 3 will be
 B000:6000 hex. The interleaving cycles every four lines, thus the
 first byte of line 4 will be B000:005A hex (45056:0090 decimal), and
 subsequent lines will follow the previous pattern, at offset intervals
 of 2000 hex (8192 decimal).

 The following diagram shows how the scan lines relate to the
 interleaved video buffer:

                Video Buffer                    Display

       B000:0000 +---------+                       +-------------
                 |         |<----------Scan Line 0 | ............
            005A |---------|       +---Scan Line 1 | ............
                 |         |<---+  |  *Scan Line 2 | ............
            00B4 |---------|    |  |  *Scan Line 3 | ............
                 .         .    +------Scan Line 4 | ............
                 .         .       |               |
       B000:2000 |---------|       |
                 |         |<------+
            205A |---------|          * NOTE:
                 .         .            Scan line 2 is at B000:4000 hex
                 .         .            Scan line 3 is at B000:6000 hex

 This same interleaving is used in video Page 1, which begins at hex-
 paragraph B800. Please see the figure on Page 89 of the "Programmer's
 Guide to PC and PS/2 Video Systems" for a more complete diagram of the
 display memory for Hercules graphics mode.

 The following subprogram prints SCREEN Page 0 of a Hercules graphics
 screen to an Epson or Epson-compatible printer. To print SCREEN Page
 1, use a DEF SEG = &HB800 statement (instead of &HB000 for Page 0).

    DECLARE SUB HerculesPrintScreen ()
    ' Before using Hercules SCREEN 3, you must run QBHERC.COM (included
    ' with QuickBASIC 4.00 or 4.00b, and BASIC compiler 6.00 or 6.00b)
    ' or MSHERC.COM (included with QuickBASIC 4.50).
    SCREEN 3
    ' Put your screen graphics commands here - and take out commands
    ' between these markers:
    ' --------------------------------------------------------------
      FOR i% = 1 TO 719 STEP 10
        LINE (1, 1)-(i%, 348)
        LINE (1, 348)-(i%, 1)
      NEXT i%
    ' --------------------------------------------------------------
    CALL HerculesPrintScreen

    SUB HerculesPrintScreen STATIC
       DEF SEG = &HB000  'Set segment to SCREEN 3, video Page 0
       OPEN "LPT1" FOR BINARY AS #1  'Open printer port in binary mode
       WIDTH #1, 255                 'Set print width to 256 bytes wide
       adv872$ = CHR$(27) + "A" + CHR$(8)
       dots408$ = CHR$(27) + "K" + CHR$(92) + CHR$(1)
       linefeed$ = CHR$(10)

       PUT #1, , adv872$        'Set printer linefeed to 8/72"
       FOR x = 0 TO 89
          PUT #1, , dots408$    'Set printer for bit image graphic mode
          FOR y = 7740 + x TO x STEP -90
             FOR z = 24576 + y TO y STEP -8192
                image$ = CHR$(PEEK(z))
                PUT #1, , image$  'Send bit-image graphics to printer
             NEXT z
          NEXT y
          PUT #1, , linefeed$   'Send a linefeed to the printer
       NEXT x

       ResetPrn$ = CHR$(27) + "@"
       PUT #1, , ResetPrn$      'Reset the printer to default settings
       CLOSE #1
    END SUB


 811. Bad LINE Drawn Using Coordinates Far Outside WINDOW Viewport

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 20-SEP-1990    ArticleIdent: Q52170

 Using the LINE statement with coordinate values that significantly
 exceed the coordinate limits set by the WINDOW statement can produce
 unexpected results.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 3.00, 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions 6.00
 and 6.00b (buglist6.00, buglist6.00b); and in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10
 (buglist7.00, buglist7.10). This problem was partially corrected in
 Microsoft BASIC PDS versions 7.00 and 7.10 (fixlist7.00, fixlist7.10)
 as shown in Example 1. At run time, BASIC PDS 7.00 and 7.10 correctly
 flag the negative number in Example 1 as an overflow. However, BASIC
 PDS 7.00 and 7.10 incorrectly handle the overflow case in Example 2
 (buglist7.00, buglist7.10), allowing an incorrect LINE statement
 (reversed top to bottom, and incorrect coordinate values) to be drawn.

 To work around these problems, a LINE statement should not be executed
 with coordinate values that significantly exceed the logical
 dimensions of the current viewport set by the WINDOW statement. The
 amount that you must exceed the coordinate limits to get the problem
 is variable and difficult to predict.

 Code Example 1
 --------------

 The problem occurs in Example 1 under the following conditions:

 1. The Y-coordinates for the WINDOW statement have a difference of 32
    or less. For example: WINDOW (0, 1880)-(20, 1912)

 2. The parameters on the LINE statement are less than -1800 when the
    coordinates of the WINDOW statement are greater than 1850.

 The following code shows the problem in QuickBASIC 3.00, 4.00, 4.00b,
 and 4.50, but correctly gives "Overflow" error in BASIC PDS 7.00 and
 7.10:

 CLS
 xl! = 0: xu! = 20!
 yl! = 1880!: yu! = 1912!   'Values that have a difference less than 32
 SCREEN 9
 COLOR 9
 VIEW (50, 56)-(639, 336)       'Set up maximum viewport coordinates
 WINDOW (xl!, yl!)-(xu!, yu!)   'Set up window to view
 READ r!
 PSET (0, r!)
 FOR j = 2 TO 13
   READ r!
   LINE -(j * 1.5, r!)
 NEXT j
 DATA 1881,1887,1881,1840,-1881,1887,1883,-1827,1890,1882,-1807,1883,1887
           'DATA statement contains the numbers that fall within
           'the needed range for the problem.
 END

 Code Example 2
 --------------

 This code displays the LINE problem in BASIC PDS 7.00 and 7.10, as
 well as in QuickBASIC 3.00, 4.00, 4.00b, 4.50. If you use a value for
 r! a little above 1069 in the LINE statement, the line should go down,
 but instead it goes up in this example. Note that PMAP invoked on the
 integer boundaries says you can use 1066 or 1067 as a minimum
 coordinate that could be trapped, but using 1069, which is above this
 limit, still incorrectly draws the line instead of giving an
 "Overflow" error.

 ON ERROR GOTO checkerror
 CLS
 xl! = 0: xu! = 20!
 yl! = 1880!: yu! = 1890!
 SCREEN 12
 COLOR 9
 VIEW (50, 64)-(639, 463)
 WINDOW (xl!, yl!)-(xu!, yu!)
 READ r!
 PRINT r!
 PSET (0, r!)
 FOR j = 2 TO 13
    READ r!
    PRINT r!, POINT(1), POINT(3)
    LINE -(j * 1.5, r!)
 NEXT j
 DATA 1881,1887,1881,1887,1881,1887,1069
 DATA 1072,1890,1882,1840,-1887,1887
 END
 checkerror:
    yll! = PMAP(32762, 3)
    yul! = PMAP(-32762, 3)
    xll! = PMAP(-32762, 2)
    xul! = PMAP(32762, 2)
    PRINT "Axis limits "; xll!; xul!; yll!; yul!
 RESUME NEXT


 812. Light Pens Tested with Microsoft BASIC

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891206-121 B_BasicCom
 Last Modified: 22-JAN-1990    ArticleIdent: Q57342

 The following light pens by the LightPen Company were tested with
 QuickBASIC Version 4.50, Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and Microsoft BASIC Professional Development System (PDS)
 Version 7.00:

 1. Light Pen
 2. Soft Pen

 The following code example is from Page 315 of the "Microsoft
 QuickBASIC 4.0: BASIC Language Reference" manual under the example for
 the PEN function. This code example was used to test the light pen. If
 you do not have a light pen, pushing both buttons on the mouse at the
 same time simulates a light pen being on.

 The code produces an endless loop to give the current position and
 status of the pen.

 Compile and link with the following command lines:

    BC test.bas;
    LINK test.obj,,,BRUNxx.Lib;

 Code Example
 ------------

 CLS
 PEN ON
 DO
    p = PEN(3)
    LOCATE 1,1: PRINT "Pen Is ";
    IF p THEN PRINT "down" ELSE PRINT "up"
    x = PEN (4) : y = PEN(5)
    PRINT "x=" x, "y=" y
 LOOP


 813. Why QB 4.50 Language Reference Manual Is Sold Separately

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q57582

 This article explains why Microsoft doesn't put a printed copy of the
 Language Reference manual in the QuickBASIC Version 4.50 package. This
 manual has to be purchased separately.

 Microsoft QuickBASIC Versions 2.00, 2.01, 3.00, 4.00, and 4.00b are
 packaged with a printed copy of the Language Reference manual.

 QuickBASIC Version 4.50 provides the same reference manual as 4.00 and
 4.00b, but instead of packaging a printed copy, the reference manual
 is stored on disk in the QB Advisor online Help system.

 A printed copy of the "Microsoft QuickBASIC 4.5: BASIC Language
 Reference" can be purchased separately (in a three-ring binder). The
 "Manual Offer" form (in the Version 4.50 disk envelope) states the
 following:

    ...Microsoft QuickBASIC provides you with a complete set of
    programming tools, including Microsoft QB Advisor. QB Advisor
    is the most innovative and comprehensive electronic help system
    available, providing you with on-line access to the "BASIC Language
    Reference" manual.

    Microsoft QB Advisor also features hyperlinks that let you
    instantly cross-reference to related topics, a
    scrollable/searchable window that lets you access information as
    you like, and cut and paste commands that let you insert executable
    program examples into your code. You can even print out sections of
    the on-line documentation for a hard-copy reference.

    If you find, however, that you'd like to have the entire Microsoft
    QuickBASIC "BASIC Language Reference" manual in hard-copy format,
    you can order it in a three-ring binder directly from Microsoft....

 In QuickBASIC Version 4.50, our goal was to make the product
 accessible to the beginning programmer through both ease of use and
 low price. A major aspect of this product is its documentation
 strategy, where we provide all information that we've ever provided in
 the past, but we provide it only once, in its most usable format
 possible for the beginner/experimenter. For the language reference
 information, we decided that the advantages of fully context-sensitive
 help, complete with cut-and-paste examples, was the best way to speed
 the programming process.

 We opted also to put keystroke-by-keystroke tutorials both on disk and
 on paper to help the beginner past every hurdle in writing his or her
 first structured BASIC programs.

 The tradeoff of a printed reference for an online reference in Version
 4.50 unfortunately may not satisfy some users of QuickBASIC,
 especially serious developers. However, this tradeoff helps us place
 the product at a price level accessible to a wider base of customers,
 especially beginning-level customers. As stated earlier, the printed
 manual can be purchased separately for those who really want it.

 The QuickBASIC product line will continue to be marketed with goals of
 affordability, learning ease, and powerful features. The documentation
 and pricing strategy for the next potential version of QuickBASIC is
 currently being researched. We will gladly listen to your suggestions.

 BASIC Professional Development System 7.00
 ------------------------------------------

 Microsoft has listened to and gathered the suggestions from QuickBASIC
 and Microsoft BASIC Compiler customers and professional developers,
 and we have created a premium BASIC product line:

    Microsoft BASIC Professional Development System (PDS) Version 7.00

 Our design philosophy for BASIC PDS 7.00 was simple: if the
 professional programmer might want a feature, then add it. We packed
 BASIC PDS full of new features, including unprecedented amounts of
 technical documentation, both online and in print. BASIC PDS 7.00
 includes over 14 megabytes (fully installed) of software and over 2250
 pages of printed documentation. In surveys, our professional users
 told us that they were willing to pay the cost of supporting a major
 BASIC development effort and were certainly willing to pay for
 complete and thorough documentation, bound in their favorite type of
 binding (three-ring).

 Microsoft hopes you find that BASIC PDS 7.00 is a product that gives
 you all the documentation you could ever want in every format you
 could want. BASIC PDS 7.00 is marketed for professional developers who
 want the best BASIC compiler available. (QuickBASIC is a separate,
 lower-priced, powerful product for a wider audience.)


 814. Using TAB to Move Whole Blocks of Text in QB.EXE or QBX.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900102-126 B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q57601

 In the QuickBASIC environment, you can move a whole block of text
 horizontally by highlighting the block and then pressing the TAB key
 to move it. You can move it any number of spaces by changing the
 length of the tab stop in the Options menu and then highlighting the
 text and pressing TAB to move it to the new tab stop.

 If you wish to move the block to the left, press SHIFT+TAB while the
 block is highlighted.

 One limitation is that you can move only whole lines at a time. You
 cannot select a column range.

 This information applies to QB.EXE in Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50 for MS-DOS, to QB.EXE in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS, and to QBX.EXE
 (QuickBASIC Extended) in Microsoft BASIC Professional Development
 System (PDS) 7.00 for MS-DOS.

 In QB.EXE Versions 4.00, 4.00b, and 4.50, do not try to move the
 selected block of text using the SPACEBAR because this will delete the
 text. There is no way to restore this text, since these versions can
 undo only the last edit. The last edit, in this case, is the space
 entered by pressing the SPACEBAR, not the deletion of the text.
 Pressing ALT+BACKSPACE (or selecting Undo from the Edit menu) simply
 removes the space and does not bring back the deleted text.

 QBX.EXE in Microsoft BASIC PDS Version 7.00 allows you to undo the
 last 20 edits performed, so in the same situation as above, the text
 is recoverable by pressing ALT+BACKSPACE several times consecutively.


 815. CIRCLE Statement Draws Ellipses Based on Horizontal Resolution

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891227-98 B_BasicCom
 Last Modified: 12-JAN-1990    ArticleIdent: Q57649

 Circles and ellipses generated using the CIRCLE statement are based on
 the current horizontal resolution of the current coordinate system.
 This can result in what may appear to be incorrect circles or ellipses
 for the radius value given in the CIRCLE statement.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00, 6.00b for MS-DOS,
 and to Microsoft BASIC Professional Development System (PDS) Version
 7.00 for MS-DOS.

 When an ellipse is generated using the CIRCLE statement, the ellipse
 will never be wider or taller than the radius value given in the
 CIRCLE statement using the horizontal resolution of the current
 coordinate system. The following code examples demonstrate this using
 all three possibilities, using VGA SCREEN mode 12:

    X-resolution < Y-resolution: WINDOW(-320,440)-(320,440)  '640x880
    X-resolution = Y-resolution: WINDOW(-320,240)-(320,240)  '640x480
    X-resolution > Y-resolution: WINDOW(-620,240)-(620,240)  '1240x480

 Each program draws a circle using the CIRCLE statement, with a center
 at (0, 0) and a radius of 100. A box is then drawn using the LINE
 statement, with its center at (0, 0) and sides with a length of 200.
 In a coordinate system of one-to-one, the default in SCREEN 12, this
 produces a circle and a box in the center of the screen with the
 circle tangent to all four sides of the box. When the coordinate
 system is altered using a WINDOW statement, the circle always remains
 tangent to the left and right sides of the box, but either falls short
 of or exceeds the top and bottom of the box.

 Code Example 1
 --------------

 '*** X-resolution < Y-resolution ***
 SCREEN 12
 WINDOW(-320,440)-(320,440)
 CIRCLE(0, 0), 100
 LINE(-100, -100)-(100, 100),,B
 END

 Code Example 2
 --------------

 '*** X-resolution = Y-resolution ***
 SCREEN 12
 WINDOW(-320,240)-(320,240) 'Commenting this line out gives same result
 CIRCLE(0, 0), 100
 LINE(-100, -100)-(100, 100),,B
 END

 Code Example 3
 --------------

 '*** X-resolution > Y-resolution ***
 SCREEN 12
 WINDOW(-620,440)-(620,440)
 CIRCLE(0, 0), 100
 LINE(-100, -100)-(100, 100),,B
 END


 816. LOCATE Doesn't Turn Off Cursor After INTERRUPT Loads User Font

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S900102-68
 Last Modified: 15-JAN-1990    ArticleIdent: Q57670

 The LOCATE statement can be used to turn the cursor off. This is done
 by passing zero (0) as the third parameter, as in the following
 example:

    LOCATE ,,0

 However, the ability of LOCATE to turn off the cursor is disabled when
 interrupt 10 hex, function 11 hex, subfunction 0 is called. In fact,
 the interrupt routine itself turns the cursor on. This interrupt call
 (which requires an EGA card and the use of SCREEN 0) causes the video
 card to use a block of memory in RAM for generating ASCII characters,
 rather than the ROM default ASCII characters.

 To turn the cursor off in this instance, interrupt 10 hex, function 1
 must be called. The program below illustrates how this is done.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 It's not just using the RAM font instead of the ROM font that causes
 the problem. Once interrupt 10 hex, function 11 hex, subfunction 0 is
 called, the LOCATE statement cannot turn the cursor off during the
 entire execution of the program. That is, even if you load the default
 ROM font back in by calling interrupt 10 hex, function 11 hex,
 subfunction 0, the LOCATE statement still will not work properly.

 The following code example illustrates the problem. In the comments of
 this example, the word "block" refers to the block of RAM where the
 new character definition will be. Note that, for simplicity, the
 example redefines only one character and leaves the rest in their
 default state.

 'This example requires an EGA card; VGA will not work.

 ' $INCLUDE: 'qb.bi'        'Load interrupt routines and types.
 DIM Regs AS RegTypeX       'Stores values of registers.
 DIM Table AS STRING * 14   'This will hold the definition for one
                            'character (14 rows high, 8 bits wide).
 CLS
 LOCATE ,,1   'Cursor will turn on.
 LOCATE ,,0   'Cursor will turn off.

 DEF SEG = VARSEG(Table)    'Make the block's segment current.

 FOR i = 0 TO 13                  'Load definition block.
    POKE VARPTR(Table) + i, 255   'All 255s will appear as a solid
 NEXT i                           'rectangle.

 DEF SEG                     'Go back to DGROUP.

 Regs.AX = &H1100            'Function 11 hex subfunction 0.
 Regs.BX = &HE00             'There are &HE points per character.
                             'Put font at table 0.
 Regs.CX = 1                 'Block defines one character.
 Regs.DX = 0                 'First character redefined is ASCII 0.
 Regs.DS = -1                'Use old data segment.
 Regs.ES = VARSEG(Table(0))  'Segment of block.
 Regs.BP = VARPTR(Table(0))  'Offset of block.

 CALL InterruptX(&H10, Regs, Regs)  'Call interrupt &H10.
                                    'The cursor will turn on.

 LOCATE ,,0   'Cursor will not turn off.

 'The following interrupt call will cause the video card to use the
 'default ROM font but will not re-enable LOCATE's ability to turn off
 'the cursor.

 Regs.AX = &H1101   'Function &H11, subfunction 1
 CALL InterruptX(&H10, Regs, Regs)

 LOCATE ,,0   'Cursor will not turn off.

 'The following interrupt call can be used to turn the cursor off.

 Regs.AX = &H100   'Function 1.
 Regs.CX = &H2000
 CALL InterruptX(&H10, Regs, Regs)   'Cursor will turn off.


 817. PLAY and SOUND Click Speaker in QuickBASIC; OUT Clicks Less

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S900103-91
 Last Modified: 17-JAN-1990    ArticleIdent: Q57776

 In QuickBASIC, the PLAY and SOUND statements produce a click on the
 speaker noticeable at the end of a sound. Also, if an inaudible
 frequency is used with the SOUND statement, a click is heard before
 and after the PLAY or SOUND statement.

 This article shows a method using the OUT statement to produce sounds
 where the clicking is less noticeable.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 The following program produces the clicking noise and then shows an
 improvement involving programming the timer chip as explained in the
 following book:

    "The New Peter Norton Programmer's Guide to the IBM PC & PS/2," by
    Peter Norton and Richard Wilton (Microsoft Press, 1988). Pages
    148-150.

 Code Example
 ------------

 ' The following PLAY statement demonstrates the clicking sound:
 FOR i% = 1 TO 3
   PLAY "L4 C"
   SLEEP 1
 NEXT
 ' The following SOUND statement demonstrates the clicking sound:
 FOR i% = 1 TO 3
   SOUND 700, 12
   SLEEP 1
 NEXT
 ' The following OUT statements alleviate the clicking sound while
 ' generating tones:
 count1 = 1193280! / 700        ' 700 is the desired frequency
 count2 = 1193280! / 100000     ' 100,000 is the desired inaudible frequency
 lo.count1 = count1 MOD 256     ' calculate low-order byte values
 lo.count2 = count2 MOD 256
 hi.count1 = count1 / 256       ' calculate high-order byte values
 hi.count2 = count2 / 256
 OUT &H43, &HB6                 ' get timer ready
 old.port = INP(&H61)           ' read the value at port 61H
 new.port = (old.port OR &H3)   ' set bits 0 and 1
 OUT &H61, new.port             ' turn speaker on
 FOR i% = 1 TO 3
   OUT &H42, lo.count1          ' load low-order byte for first frequency
   OUT &H42, hi.count1          ' load high-order byte for first frequency
   SLEEP 1
   OUT &H42, lo.count2          ' load low-order byte for second frequency
   OUT &H42, hi.count2          ' load high-order byte for second frequency
   SLEEP 1
 NEXT
 OUT &H61, old.port             ' turn speaker off
 END


 818. CALL INTERRUPT for Small Time Increments Using BIOS Tick Count

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900111-209 B_BasicCom
 Last Modified: 25-OCT-1990    ArticleIdent: Q57851

 The TIME$ function in BASIC returns the current time in hours,
 minutes, and seconds from DOS or OS/2, but it cannot return any
 increments smaller than one second.

 However, a program can use the INTERRUPT routine to call the IBM ROM
 BIOS interrupt 1A Hex (26 decimal) with function 0. This function
 returns the number of system timer ticks since midnight. The number of
 timer ticks can then be used to calculate the number of seconds that
 have passed since midnight. You can then time to a resolution of
 18.20648 ticks per second (or .05492549 of a second).

 This information applies to Microsoft QuickBASIC versions 2.00, 3.00,
 4.00, 4.00B, and 4.50, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Here are three separate methods to get a small time interval:

 1. Use BIOS INTERRUPT 15 Hex, with function 86 hex (or, in decimal,
    INTERRUPT 21 with function 134) for a resolution at intervals of
    976 microseconds (976 millionths, or .000976 of a second).

 2. Use BIOS INTERRUPT 1A hex (26 decimal) with function 0 for a
    resolution at about 18.20648 ticks per second (or .05492549
    seconds).

 3. Use the ON PLAY statement for resolution at 30 times per second
    (or .0333333).

 This article describes method 2 above. To find two other articles,
 which explain methods 1 and 3, search in this Knowledge Base using the
 following exact words:

    BASIC and timer and increments and smaller and second

 Explanation of PC Timer Ticks
 -----------------------------

 Below is an explanation of how the PC system timer works. Also
 included is a BASIC program example that shows how to calculate the
 number of seconds since midnight to the hundredths place, with a
 resolution of .05492549 of a second.

 A timer "tick" is an interrupt that is generated by the PC's system
 timer. When this interrupt occurs, the ROM BIOS interrupt handler is
 called, and it increments a count in the ROM BIOS data area reserved
 for recording the number of ticks since midnight.

 Timer ticks work as follows. More than one system timer tick occurs
 per second. In fact, a timer tick occurs approximately 18.2 times
 every second. To be even more exact, a timer tick occurs every
 1,193,180 / 65,536 times per second, which is 18.20648 times per
 second. The first value, 1,193,180, represents the frequency at which
 the PC system timer operates, which is 1.193 MHz. This means that the
 system timer can actually recognize increments as small as 1 /
 1,193,180 seconds.

 However, since very few programs could possibly need a time increment
 this small, the system timer uses another method to determine when to
 generate a tick. The system timer maintains an internal register. The
 timer initializes the register to 65,535 and then decrements the
 register or "counts down" from 65,535 to zero. When zero occurs, the
 timer generates a tick (it actually generates an interrupt that
 increments the tick count). Note that this is where the lower half of
 the fraction 1,193,180 / 65,536 comes from. If the timer runs at 1.93
 MHz and it decrements a counter 65,536 times before it generates a
 tick, this means that dividing the timer speed by this countdown value
 gives us how many ticks occur per second.

 For more information on the PC system timer, please refer to Page 145
 of "The New Peter Norton Programmer's Guide to the IBM PC & PS/2"
 (Microsoft Press, 1988).

 The following program example shows how to use the tick count returned
 by interrupt &H1A function 0 to calculate the number of seconds since
 midnight to the hundredth place. To run this program in the QB.EXE
 editor, you must load the program with /L to load the QB.QLB Quick
 library (but for BASIC PDS 7.00 or 7.10, use QBX /L to load QBX.QLB).
 If you compile from the command line, you must link in the QB.LIB
 library (or the QBX.LIB library for BASIC PDS 7.00).

 Code Example
 ------------

 REM   TIMEINT.BAS
 DEFLNG A-Z
 ' $INCLUDE: 'QB.BI'
 ' For BASIC PDS 7.00 you must change above line to QBX.BI
 CONST tps = 18.2064819336# ' tps is ticks per second
 DIM inregs AS RegType, outregs AS RegType
 DIM flag AS INTEGER, Previous AS LONG
 CLS
 LOCATE 1, 20: PRINT "Hit any key to end"
 WHILE INKEY$ = ""
         inregs.ax = 0
         CALL INTERRUPT(&H1A, inregs, outregs)
         ' CX should never be larger than &H0017, so direct
         ' assignment is possible.
         ticks& = outregs.cx * &H10000
         ' The following IF accounts for the fact that the
         ' interrupt is using an unsigned int (register) but BASIC
         ' has only signed integers. Special action must be taken
         ' for numbers that appear to be negative.
         IF outregs.dx < 0 THEN
                 a2& = (outregs.dx AND &H7FFF&)
                 ticks& = (ticks& + a2&)
                 ticks& = (ticks& OR &H8000&)
         ELSE
                 ticks& = ticks& + outregs.dx
         END IF
         IF Previous > ticks& THEN BEEP ' It's midnight!
         Previous = ticks&

         Previous = ticks&
         seconds# = ticks& / tps 'ticks per second

         LOCATE 10, 10
         PRINT "Clock ticks since midnight: ";
         PRINT ticks&
         LOCATE 11, 10
         PRINT "Seconds since midnight: ";
         PRINT USING "######.##"; seconds#
 WEND
 END


 819. Array Elements Are Passed in Temporary Variables for BC /D

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S891229-91
 Last Modified:  8-FEB-1990    ArticleIdent: Q57925

 In a program compiled with the BC /D debug switch, array elements that
 are passed to a SUB or FUNCTION are passed using temporary variables.
 A program that is not compiled with the /D debug switch passes actual
 array elements and does not use temporary variables.

 When using the /D debug switch, taking the VARSEG and VARPTR of an
 array element in the module level code returns the address of the
 array element in memory. However, when taking the VARSEG and VARPTR of
 the array element once it has been passed as a parameter to a SUB or
 FUNCTION, VARSEG and VARPTR return the address of the temporary
 variable that the array element is stored in.

 In addition, a program that is being run in the QB.EXE or QBX.EXE
 environment passes array elements using temporary variables since
 debug mode is always on in the environment.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The following sample program demonstrates how BASIC uses temporary
 variables when passing array elements to a SUB or FUNCTION when
 compiled with the /D debug option:

    DIM A%(100)
    A%(1) = 1

    PRINT "The address of the array element before the call"
    PRINT VARSEG(A%(1)), VARPTR(A%(1))
    CALL subtest(A%(1))
    PRINT "The address of the array element after the call"
    PRINT VARSEG(A%(1)), VARPTR(A%(1))

    SUB subtest(tempvar%)
      PRINT "The address of the array element during the call"
      PRINT "This address should be different if using /D debug switch"
      PRINT VARSEG(tempvar%), VARPTR(tempvar%)
    END SUB

 Compile and link the code as follows:

    BC /d Test.bas;
    LINK Test.bas;


 820. "Subscript out of Range" Long-Integer Array in IF/THEN in 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S900117-6
 Last Modified: 31-JAN-1990    ArticleIdent: Q57926

 The QuickBASIC Version 4.50 program shown below produces a "Subscript
 out of range" error if compiled with the BC /D (debug) switch. This
 appears to be caused by a compiler optimization problem for the
 particular combination of using a long-integer variable to subscript a
 long-integer array in an IF ... THEN statement.

 If the program is run from the QB.EXE environment or is not compiled
 with the BC /D switch, the error does not occur.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Version 4.50. We are researching this problem and will post new
 information here as it becomes available.

 This problem does not occur in versions of QuickBASIC prior to
 Version 4.50, in Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, or in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The following program exhibits the behavior:

    DIM a(10) AS LONG
    a(1) = 5
    k& = 5
    i& = 1
    IF a(i&) = k&  THEN
       a(i&) = -k&       'this statement causes the error to occur
    END IF

 Compile and link the program as follows:

    BC /D TEST;
    LINK TEST;

 The "Subscript out of range" error does not occur if the IF ... THEN
 syntax is removed or if the variables i and k are of any type other
 than long integers.

 To work around the problem, replace the problem-assignment statement,
 a(i&) = -k&, with either of the following equivalent assignments:

    1. a(i&) = k&
       a(i&) = -a(i&)

    2. a(i&) = -a(i&)


 821. Named COMMON SHARED /block/ Can Be Continued onto Next Line

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S891025-45 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q57928

 Programmers may have long lists of variables that they would like to
 include in a named COMMON [SHARED] block; however, their variable
 lists are often too long to be seen on the screen all at once.
 Variables in a named COMMON [SHARED] block can be continued on the
 next line so that they can be seen without having to scroll the
 screen.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2 .

 Named COMMON (SHARED) blocks can be continued on several lines by
 giving variables on succeeding lines the same block name specified on
 the first. Block names must be specified between forward slashes (//).
 The following is an example:

    COMMON SHARED /bob/ var1, var2, var3, var4, var5, var6
    COMMON SHARED /bob/ var7, var8, var9, var10, var11, var12
    COMMON SHARED /bob/ var13, var14, var15, var16, var17, var18

 Here is an example of continuing an unnamed (blank) COMMON block,
 which is distinct in memory from any named COMMON block:

    COMMON SHARED uvar1, uvar2, uvar3, uvar4, uvar5, uvar6
    COMMON SHARED uvar7, uvar8, uvar9, uvar10, uvar11, uvar12
    COMMON SHARED uvar13, uvar14, uvar15, uvar16, uvar17, uvar18


 822. BREAK Status Always Reports OFF Using BASIC CALL INTERRUPT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900119-105 B_BasicCom
 Last Modified:  8-FEB-1990    ArticleIdent: Q57930

 The status of the BREAK flag cannot be detected from within a BASIC
 program, and a DOS interrupt from BASIC always reports that it is OFF.
 This is true even if a BREAK ON command has been issued from DOS.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 The status of the BREAK flag can be detected from some languages by
 using interrupt 21 Hex with function 33 Hex. However, when calling
 this interrupt from a BASIC program, the interrupt always reports that
 BREAK is OFF.

 During initialization, BASIC records the current setting of BREAK and
 then turns it OFF. Upon termination, BASIC restores the setting of
 BREAK to its entry value.

 This is done because when BREAK is enabled, pressing CTRL+C causes a
 ^C to be printed to the screen on the next DOS call. This is also
 printed before DOS invokes the CTRL+C handler.

 In BASICs prior to BASIC PDS Version 7.00, BREAK has to be OFF because
 these BASICs do not have a CTRL+C handler. In BASIC PDS 7.00, a CTRL+C
 handler was added to better trap CTRL+C conditions in certain
 situations (such as between resetting the BREAK state and termination,
 or during a Make EXE File command). It was decided to continue
 clearing the BREAK state to eliminate ^C on the screen.

 To demonstrate this, run the following program. (If running within the
 QuickBASIC environment, start with the /L option to load in the Quick
 library with support for the CALL INTERRUPT statement).

 Code Example
 ------------

    REM $INCLUDE: 'QB.BI'
    ' Note: Must change the above file to 'QBX.BI' in BASIC PDS 7.00

    DIM INREGS AS REGTYPE
    DIM OUTREGS AS REGTYPE

    INREGS.AX = &H3300
    CALL INTERRUPT(&H21, INREGS, OUTREGS)
    PRINT OUTREGS.DX  ' IF 0 THEN BREAK OFF

 Even if BREAK ON is previously set in DOS, the program reports that
 BREAK is OFF. After the program ends, issuing the BREAK command in DOS
 shows BREAK as still ON.


 823. QB.EXE Variable Is Wrongly Global If Name Same as COMMON Array

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b fixlist4.50 SR# S900110-109
 Last Modified:  7-FEB-1990    ArticleIdent: Q58022

 Naming a variable the same as an array in COMMON incorrectly makes the
 variable global in the following program when run in the QB.EXE
 environment of QuickBASIC Version 4.00 or 4.00b.

 Microsoft has confirmed this to be a problem in QuickBASIC Versions
 4.00 and 4.00b. This problem was corrected in QuickBASIC Version 4.50.

 To work around this problem, you can either upgrade to Version 4.50 or
 compile the program to an .EXE with BC.EXE.

 Code Example
 ------------

 The value of the variable "test2" incorrectly changes when the
 function "test" is called. This behavior is incorrect because the
 variable in the main program is not SHARED, and therefore, the test2
 variable in the function should be kept separate from the one in the
 main module. The problem is related to passing an array, test2(), in
 the COMMON SHARED statement that has the same name as the variable,
 test2.

   DEFDBL T
   DECLARE FUNCTION test (temp%)
   DIM test2(100)
   COMMON SHARED test2()
     test2 = 1.299933
     CLS
     PRINT "Before Test Test2 = "; test2
     res = test(10)
     PRINT "After Test Test2 = "; test2
  END

 FUNCTION test (temp%)
     PRINT "Test2 = "; test2
     test2 = 3.999
     PRINT "Test2 =  "; test2
     test = test2
 END FUNCTION


 824. Multidimensional Limit for Undeclared (Non-DIMmed) Arrays

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom docerr SR# S900108-52
 Last Modified:  5-MAR-1990    ArticleIdent: Q58023

 When you reference an array without first dimensioning it with the DIM
 statement, it is an undeclared array, and the highest element
 subscript in each dimension always defaults to 10.

 No errors should occur for an undeclared array that has 3 or fewer
 dimensions, as in the following example:

    X(1,1,1)=0

 However, if the undeclared (non-DIMMed) array has more than three or
 four dimensions, such as X(1,1,1,1,1), you may get one or more of the
 following error messages, depending upon the product version and the
 number of dimensions referenced:

    Subscript out of range
    Out of data space
    Out of memory
    Array not dimensioned
    Array too big

 Which error message displays depends on whether the array type is
 string or numeric, how many dimensions you give the undeclared array,
 whether the program is run in the QuickBASIC QB.EXE environment or
 compiled with BC.EXE, and which version of BASIC or QuickBASIC is
 used.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.

 You can easily test to see exactly which errors are generated for all
 combinations of the criteria above. Note that it is always safe to
 access any undeclared array as long as it does not have more than 3
 dimensions. (Note: Don't confuse dimensions with number of subscripts
 per dimension.)

 Regarding this topic, there is a difference between versions of
 QuickBASIC up to 3.00 and Versions 4.00 and later. In Versions 4.00
 and later, undeclared numeric arrays can have 4 or fewer dimensions,
 and undeclared variable-length-string arrays can have 3 or fewer
 dimensions. Versions of QuickBASIC earlier than 4.00 require all
 undeclared arrays to have 3 or fewer dimensions. The restrictions that
 apply to Versions 4.00 and later also apply to Microsoft BASIC
 Compiler Versions 6.00 and 6.00b and Microsoft BASIC Professional
 Development System (PDS) Version 7.00.

 The following code examples illustrate the minimum number of
 dimensions in the undeclared array that are needed to generate an
 error for specific versions of QuickBASIC, BASIC Compiler, and BASIC
 PDS:

 'QuickBASIC Versions 1.00, 1.01, 2.00, 2.01, and 3.00:
 PRINT a(1,2,3,4)  ' Numeric array, error for 4 or more dimensions
 PRINT a$(1,2,3,4) ' Variable-length string array, error 4 or more dims

 'QuickBASIC Versions 4.00, 4.00b, 4.50, BASIC compiler Versions 6.00
 ' and 6.00b, and BASIC PDS Version 7.00:
 PRINT a(1,2,3,4,5) ' Numeric array, error for 5 or more dimensions
 PRINT a$(1,2,3,4) ' Variable-length string array, for 4 or more dims.

 To eliminate the errors, dimension the arrays to the size(s) you want
 using the DIM statement.

 The above limitations need to be added on the page referenced in the
 Index entry under "Arrays, dimensioning" in the following manuals:

 1. "Microsoft QuickBASIC 4.5: BASIC Language Reference" for Version
    4.50

 2. "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
    Versions 4.00 and 4.00b

 3. "Microsoft QuickBASIC Compiler" Versions 2.0x and 3.00 manual

 4. "Microsoft BASIC Version 7.0: Language Reference" manual

 5. "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
    Versions 6.00 and 6.00b


 825. DRAW Statement's Scale (S) Command Has Default Scale Factor 4

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom SR# S891228-74
 Last Modified:  5-FEB-1990    ArticleIdent: Q58025

 The DRAW statement can scale the lines that it draws. The scale factor
 is specified by including the "S" command, followed by a number from 1
 to 255, before the commands that actually draw the lines.

 Certain manuals listed below fail to state that the default DRAW scale
 factor is 4, and they give the wrong formula to calculate the actual
 distance drawn.

 A scale factor of 8 must follow the "S" command to make a drawing
 twice as large. A scale factor of 2 makes a drawing half as large (4 *
 1/2 = 2).

 The following is the corrected formula for the DRAW "S n" (set Scale
 factor n) command:

    The default scale factor n is 4, which causes no scaling. The scale
    factor multiplied by movement-command arguments (U, D, L, R, or
    relative M commands) divided by 4 gives the actual distance moved.

 This correction applies to the DRAW "S n" command in the following
 manuals:

 1. Page 138 of the "Microsoft QuickBASIC 4.5: BASIC Language
    Reference" manual for Version 4.50

    Note: The QB Advisor online Help of QuickBASIC 4.50 correctly
    includes the fact that 4 is the default scale factor.

 2. Page 165 of the "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" manual for Versions 4.00 and 4.00b

 3. Page 165 of the "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" manual for Versions 6.00 and 6.00b

 4. Page 255 of the "Microsoft QuickBASIC Compiler" Version 2.0x and
    3.00 manual

 This documentation error was corrected in the "Microsoft BASIC 7.0:
 Language Reference" manual, provided with Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Knowing that the default scale factor is 4, it is easy to calculate
 the length of any line given any possible scale factor. The following
 formula can be used to do this:

    <scaled line length> = (<scale factor> / 4) * <unscaled line length>

 Here <unscaled line length> is the unscaled distance that is given
 immediately after the drawing commands.

 Code Example
 ------------

 The following program examples illustrate the correct use of the "S"
 command and how some scale factors affect what will be drawn. This
 example requires an EGA or VGA card. If you have a different card,
 change the SCREEN statement to an appropriate SCREEN mode.

 SCREEN 9
 'The "R" command of the DRAW statement draws a line to the right of
 'the current pixel position. The distance traveled is the number
 'entered after the command.
 DRAW "R10"     'No scale factor, line is 10 pixels long.
 DRAW "S1R10"   '(1/4) * 10 = 3 pixels long (rounded up).
 DRAW "S2R10"   '(2/4) * 10 = 5 pixels long.
 DRAW "S3R10"   '(3/4) * 10 = 8 pixels long (rounded up).
 DRAW "S4R10"   '(4/4) * 10 = 10 pixels long.
 DRAW "S5R10"   '(5/4) * 10 = 13 pixels long (rounded up.
 DRAW "S6R10"   '(6/4) * 10 = 15 pixels long.
 DRAW "S7R10"   '(7/4) * 10 = 18 pixels long (rounded up).
 DRAW "S8R10"   '(8/4) * 10 = 20 pixels long.


 826. No QB Error Message If File Listed in .MAK File Does Not Exist

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900119-50 B_BasicCom
 Last Modified: 31-JAN-1990    ArticleIdent: Q58026

 When a program that has a corresponding .MAK file is loaded into the
 QuickBASIC (QB.EXE) or QuickBASIC Extended (QBX.EXE) environment, all
 files listed in the .MAK file are in turn loaded into the environment.
 If a file listed in the .MAK file does not exist, an empty module is
 created with the name of that nonexistent file. There is no message
 generated informing you that a file did not exist.

 This is not a problem with the QuickBASIC environment. QuickBASIC
 reacts to nonexistent files in a .MAK file the same way it reacts if
 the environment is invoked using a nonexistent filename as a command
 line argument, for example, QB myprog. In this case, "myprog" will be
 created.

 This information applies to the QB.EXE environment in QuickBASIC
 Versions 4.00, 4.00b, and 4.50, to the QB.EXE environment included
 with Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS, and
 to the QBX.EXE environment in Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 The QuickBASIC environment automatically creates a .MAK file for
 multiple-module (multiply-loaded-source file) programs when you choose
 the Save All command from the File menu.


 827. Can't READ DATA Statements Across BASIC Modules

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr B_BasicCom SR# S900118-15
 Last Modified: 31-JAN-1990    ArticleIdent: Q58037

 The READ statement cannot read DATA statements that are in another
 module. READ statements are allowed within subprograms, but will only
 read DATA statements that are in the same module that the subprogram
 is in. DATA statements themselves cannot be included inside SUB or
 FUNCTION procedure definitions; they must be located at the module
 level code of each module.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 If a READ statement is executed and there are no DATA statements in
 that module, an "Out of data" error is generated. The READ statement
 does not look for DATA statements in other modules. This limitation of
 the READ statement is not explicitly stated in any documentation. This
 information needs to be added to the READ and DATA statements (listed
 alphabetically) in the following manuals:

 1. "Microsoft QuickBASIC 4.5: BASIC Language Reference" for Version
    4.50

 2. "Microsoft QuickBASIC 4.0: BASIC Language Reference" manual for
    Versions 4.00 and 4.00b

 3. "Microsoft QuickBASIC Compiler" Versions 2.0x and 3.00 manual

 4. "Microsoft BASIC Version 7.0: Language Reference" manual

 5. "Microsoft BASIC Compiler 6.0: BASIC Language Reference" for
    Versions 6.00 and 6.00b


 828. QCARDS Demo Program Incorrectly Searches for Zip Code

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900118-77 buglist4.50
 Last Modified: 31-JAN-1990    ArticleIdent: Q58042

 The QCARDS.BAS demo program shipped with Microsoft QuickBASIC Version
 4.50 does not search correctly for zip codes. When searching for only
 a zip code, all cards will match; when searching for zip code and some
 other field, no cards are found.

 To correct this problem, change the following lines from near the end
 of the FindCard FUNCTION in QCARDS.BAS as indicated:

         ' Test zip code.
         SELECT CASE TmpCard.Zip   '**** change to RTRIM$(UCASE$(...))
             CASE "", RTRIM$(UCASE$(Index(Card).Zip))
                 Found = Found + 1
             CASE ELSE
         END SELECT

      ' If match is found, set function value and quit, else next card.
         IF Found = NFIELDS - 1 THEN  '**** remove "- 1" after NFIELDS
             FindCard% = Card
             EXIT FUNCTION
         END IF

 The altered code is as follows:

         ' Test zip code.
         SELECT CASE RTRIM$(UCASE$(TmpCard.Zip))      '****
             CASE "", RTRIM$(UCASE$(Index(Card).Zip))
                 Found = Found + 1
             CASE ELSE
         END SELECT

      ' If match is found, set function value and quit, else next card.
         IF Found = NFIELDS THEN                      '****
             FindCard% = Card
             EXIT FUNCTION
         END IF


 829. PLAY "Illegal Function Call" for "B+","C-","E+", and "F-"

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom B_GWBasicI
 Last Modified: 20-SEP-1990    ArticleIdent: Q58043

 The PLAY statement causes an "Illegal Function Call" error when given
 any of these notes: "B+", "C-", "E+", or "F-". These are valid notes
 (since they are the equivalent of natural notes) and should not cause
 the error.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 1.00, 1.01, 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50; in
 Microsoft BASIC Compiler versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b); in Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS (buglist7.00, buglist7.10);
 and in Microsoft GW-BASIC versions 3.23, 3.22, and 3.20 (buglist3.20,
 buglist3.22, buglist3.23). We are researching this problem and will
 post new information here as it becomes available.

 To work around this problem, check for those notes and use their
 natural equivalents (listed below).

 The following table lists the errant notes and their equivalents for
 the workaround:

    Errant Note  Equivalent
    -----------  ----------

        B+           C
        C-           B
        E+           F
        F-           E

 By using the workaround listed above, the following statement would
 changed as follows:

    PLAY "B+C-E+F-"    'changed to PLAY "CBFE"

 Additional reference words: buglist1.00 buglist1.01 buglist1.02
 buglist2.00 buglist2.01 buglist3.00 SR# S900117-43


 830. How to Convert Unsigned Integer from Another Language to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900111-205 B_BasicCom S_C H_MASM S_QuickC
 Last Modified: 10-JAN-1991    ArticleIdent: Q58103

 This article describes how to convert an unsigned integer value
 (returned from another language) to a BASIC LONG integer, keeping the
 sign correct. Bit manipulation is necessary in this conversion because
 BASIC does not support an unsigned integer data type.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 BASIC does not support an unsigned integer data type. However, there
 are times when a BASIC program must accept an unsigned integer type
 returned after calling a function in languages such as C or assembly
 language.

 If your other-language routine returns an unsigned integer to a BASIC
 INTEGER data type, and if the value of the integer exceeds 32,767 (or
 7FFF hex), it will PRINT in BASIC as a negative number, even though
 the CALLed routine meant to return a positive number in the range of
 32,768 to 65,535 (passed as an unsigned integer). In such a case, your
 BASIC program must convert the number to a positive number stored in a
 BASIC long integer.

 BASIC stores both INTEGER and LONG data types as signed
 two's-complement numbers. In signed two's-complement format, the
 highest bit in the number is a a sign bit. When a BASIC program is
 passed an unsigned integer from another language, and the number is in
 the range of 32,768 to 65,535, the highest bit will be set, causing
 BASIC to treat the number as negative.

 For more information, see Pages 16-17 of "Microsoft QuickBASIC 4.0:
 BASIC Language Reference," in the "Data Types" Chapter 2; or see an
 assembly language book that discusses signed two's-complement data
 types.

 You can convert an unsigned integer to a positive BASIC LONG integer
 as follows:

 1. Check if the integer is positive or zero. If BASIC already
    recognizes the number as positive or zero, then either use it as
    is, or assign it directly to a long integer and skip the next three
    steps.

 2. Otherwise, if the number (x%) is negative, then set the high bit to
    zero, as follows:

       x% = x% AND &H7FFF&

 3. Assign the number to a long integer, as follows:

       y& = x%

 4. Then set the 15th bit (counting from bit zero) back to a one, as
    follows:

       y& = (y& OR &H8000&)

    The long integer (y&) now contains the correct positive integer
    that the other-language routine meant to pass back to BASIC.

 A simple way to do this is to use the following function:

    FUNCTION Unsigned&(param%)
       Unsigned& = &HFFFF& AND param%
    END FUNCTION

 Example 1
 ---------

 The following program converts the unsigned integer stored in x% to a
 positive LONG integer stored in y&:

 x% = -1     ' -1 in two's complement is 65535 as unsigned integer
 IF x% < 0 THEN
    ' Set the 15th bit to zero (counting from bit 0):
    x% = (x% AND &H7FFF&)
    ' Assign it to a LONG integer:
    y& = x%
    ' Set the 15th bit back to a one:
    y& = (y& OR &H8000&)
 ELSE
    y& = x%
 END IF
 PRINT y&   ' Prints 65535

 Example 2
 ---------

 The following is a BASIC code example that CALLs the INTERRUPT routine
 provided in QB.QLB or QB.LIB. This program accesses the PC system
 clock to get the number of clock ticks since midnight. It then
 calculates the number of seconds (in hundredths) since midnight.

 To run the program in the QuickBASIC editor, you must load the QB.QLB
 library, as follows:

    QB TIMEINT.BAS /L QB.QLB

 For BASIC PDS 7.00 and 7.10 do the following instead:

    QBX TIMEINT.BAS /L QBX.QLB

 To compile and LINK the program, use the following:

    BC TIMINT.BAS;
    LINK TIMINT,,,QB.LIB;

 For BASIC PDS 7.00 and 7.10 LINK as follows instead:

    LINK TIMEINT,,,QBX.LIB;

 Code Example
 ------------

 DEFLNG A-Z
 ' $INCLUDE: 'qb.bi'
 CONST tps = 18.2064699073# ' tps is ticks per second
 DIM inregs AS RegType, outregs AS RegType
 DIM flag AS INTEGER, Previous AS LONG
 CLS
 WHILE 1
      inregs.ax = 0
      CALL INTERRUPT(&H1A, inregs, outregs)
      ' CX should never be larger than &H0017, so direct
      ' assignment is possible.
      ticks& = outregs.cx * &H10000
 ' This IF statement is the part that accomplished the conversion.
      ' First, only convert if BASIC thinks it's a negative number.
      IF outregs.dx < 0 THEN
         ' Set the 15th bit to zero (counting from 0)
         a2& = (outregs.dx AND &H7FFF&)
         ' Assign it to a LONG integer.
         ticks& = (ticks& + a2&)
         ' Set the 15th bit back to a one.
         ticks& = (ticks& OR &H8000&)
      ELSE
         ' Otherwise, just assign it to a long or use it 'as is'.
         ticks& = ticks& + outregs.dx
      END IF
      IF Previous > ticks& THEN BEEP ' It's midnight!
         Previous = ticks&

      Previous = ticks&
      seconds# = ticks& / tps 'ticks per second

      LOCATE 10, 10
      PRINT "Clock ticks since midnight: ";
      PRINT ticks&
      LOCATE 11, 10
      PRINT "Seconds since midnight: ";
      ' Print out the seconds to the hundredths place.
      PRINT USING "######.##"; seconds#
 WEND
 END


 831. Explanation of Tiling in BASIC; PAINTing with Patterns

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900114-17 B_BasicCom
 Last Modified:  5-MAR-1990    ArticleIdent: Q58105

 The QuickBASIC PAINT statement can be used to paint a region of the
 screen in a particular color or pattern. PAINTing with a pattern is
 called "tiling."

 The syntax for the paint statement is as follows:

    PAINT [STEP] (x,y) [,[paint] [,[bordercolor] [,[background]]]

 The variable labeled "paint" is used to control the color of the
 painted region. If it is a numeric value, then the number must be a
 valid color attribute. The corresponding color is used to paint the
 area. If paint is left blank, then the foreground color attribute is
 used.

 However, if you use a string in this part of the PAINT statement, then
 this string is used to do "tiling." This article describes how to do
 tiling in different screen modes.

 For an in-depth explanation of tiling, please see the following
 manuals:

 1. "Microsoft QuickBASIC 4.5: Programming in BASIC," Pages 181-191

 2. "Microsoft QuickBASIC 4.0: Programming in BASIC: Selected Topics,"
    Pages 226-239

 3. "Microsoft BASIC 7.0: Programmer's Guide," Pages 179-189

 4. "Microsoft BASIC Compiler 6.0: Programming in BASIC: Selected
    Topics," Pages 226-239

 5. "Microsoft QuickBASIC Compiler" manual for Versions 2.00, 2.01, and
    3.00, Pages 380-382

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50 for MS-DOS; to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2; and to
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.

 Each tile for a pattern is composed of a rectangular grid of pixels.
 This tile grid can have up to 64 rows in all screen modes. However,
 the number of pixels in each row depends on the screen mode. This is
 because, depending on the number of color attributes per screen, each
 pixel can be represented by a varying number of bits.

 The formula for the number of bits per pixel is as follows:

    Bits-per-pixel = Log (base 2) of the number-of-attributes

 The number-of-attributes is the number of color attributes in that
 screen mode.

 The following table gives the bits-per-pixel and length-of-tile-row
 for each screen mode:

    Screen Mode      Bits-per-Pixel       Length-of-Tile-Row
    -----------      --------------       ------------------

     1                     1                     8 pixels
     2                     2                     4 pixels
     3                     1                     8 pixels
     4                     1                     8 pixels
     7                     4                     2 pixels
     8                     4                     2 pixels
     9                     2                     4 pixels
    10                     2                     4 pixels
    11                     1                     8 pixels
    12                     4                     2 pixels
    13                     8                     1 pixel

 The easiest way to define a tile row is with the CHR$() function. This
 function defines one byte (8 bits) in the tiling string. It is also
 easiest to use two hexadecimal digits per byte since they are easily
 converted to 4 bits per digit. For instance, the following line

    TILE$ = CHR$(&HF0)

 sets up a tiling string with the value 11110000. It is used in a
 PAINT statement, such as the following:

    PAINT (100,100), TILE$

 SCREENS 2, 3, 4, and 11
 -----------------------

 In screen modes with only two attributes (modes 2, 3, 4, and 11), the
 tiling string is very simple since each bit equals one pixel. A one
 (1) means that the pixel is on and a zero (0) means that the pixel is
 off.

 SCREENS 1, 9, and 10
 --------------------

 In screen modes with four attributes (modes 1, 9, and 10), the tiling
 is only a little more complicated since a pixel is represented by two
 bits. For instance, if the two bits were 01, then the pixel would be
 drawn in color 1. If they were 11, then the pixel would be color 3.
 One byte would equal 4 pixels. The byte 00011011 would draw 4 pixels
 in color 0, 1, 2, and 3 consecutively. The tiling string for 00011011
 would be the following:

    TILE$ = CHR$(&H1B)   '0001 = &H1, 1101 = &HB

 SCREENS 7, 8, and 12
 --------------------

 Tiling in EGA and VGA screen modes with more than 4 colors is a lot
 more complicated. In these modes, it takes more than one row (byte) to
 define a tiling row. This is because each pixel is represented
 three-dimensionally in a stack of "bit planes," rather than
 sequentially in a single plane.

 Below is an example of how to define a multicolored pattern consisting
 of rows of alternating yellow and magenta in a screen mode with 16
 color attributes (modes 7, 8, and 12). The following table shows how
 the colors are defined for each pixel and how to arrange them into
 CHR$() statements:

               Column
           1 2 3 4 5 6 7 8
         -------------------
 Row 1     1 1 0 0 0 0 1 1   =    CHR$(&HC3)
 Row 2     0 0 1 1 1 1 0 0   =    CHR$(&H3C)
 Row 3     1 1 1 1 1 1 1 1   =    CHR$(&HFF)
 Row 4     0 0 1 1 1 1 0 0   =    CHR$(&H3C)

      TILE$ = CHR$(&HC3)+CHR$(&H3C)+CHR$(&HFF)+CHR$(&H3C)

 The preceding line defines 8 pixels of the colors magenta, magenta,
 yellow, yellow, yellow, yellow, magenta, magenta. This combination
 results in alternating stripes of magenta and yellow. You can get the
 color by reading each column from BOTTOM to TOP. For instance, the
 first pixel is defined in column 1 by the color number 0101. This is
 color 5, which defaults to magenta. The sixth pixel is defined by the
 number 1110, or color 14, which is yellow in the default palette.

 To paint a circle with this pattern, you would do the following:

    SCREEN 12
    TILE$ = CHR$(&HC3)+CHR$(&H3C)+CHR$(&HFF)+CHR$(&H3C)
    CIRCLE (100,100),50       'a circle of radius 50
    PAINT (100,100),TILE$
    END

 SCREEN 13
 ---------

 Screen mode 13, which has 256 attributes, works differently than the
 other EGA and VGA modes. You have a lot less flexibility with screen
 13 than you do with even the two-color screens. The most that you can
 do with screen 13 tiling is to create horizontal lines of different
 colors. This is very simple since one byte is equal to one pixel
 color. Therefore, one CHR$() statement defines one line or row.

 To paint a circle with alternating lines of color 5 (magenta) and
 color 14 (yellow), you would do the following:

    SCREEN 13
    TILE$ = CHR$(&H5) + CHR$(&HE)   'colors 5 and 14
    CIRCLE (100,100),50
    PAINT (100,100),TILE$
    END


 832. CHAIN Line-Number Option Is in BASICA, Not in QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900125-125 B_BasicCom B_GWBasicI
 Last Modified: 30-JAN-1990    ArticleIdent: Q58122

 The documentation for the CHAIN statement misleadingly refers to the
 line-number option. The line-number option is supported in the BASICA
 and GW-BASIC Interpreters, but not in compiled BASICs. This fact is
 documented in the same section, "Differences from BASICA," but not in
 the same paragraph, and thus might cause confusion. References to the
 line-number option apply only to modifying BASICA and GW-BASIC code.

 This information applies to the following manuals:

 1. Page 94 of the "Microsoft QuickBASIC 4.0: BASIC Language Reference"
    manual for QuickBASIC Versions 4.00 and 4.00b for MS-DOS

 2. Page 94 of the "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" manual for Versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS

 3. Page 38 of the "Microsoft BASIC 7.0: Language Reference" manual for
    Microsoft BASIC Professional Development System (PDS) Version 7.00
    for MS-DOS and MS OS/2

 The last two paragraphs of the "Differences from BASICA" section read
 as follows:

    BASIC does not support the ALL, MERGE, or DELETE, OPTIONS available
    in BASICA, nor does it allow the specification of a line number.

    Without the line-number option, execution always starts at the
    beginning of the chained-to program. Thus, a chained-to program
    that chains back to a carelessly written chaining program can cause
    an endless loop.


 833. C Char Parameters Passed from BASIC as 2-Byte Parameters

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900126-85 B_BasicCom S_C S_QuickC BAS2C
 Last Modified:  9-FEB-1990    ArticleIdent: Q58411

 Microsoft C uses 2 bytes when passing single-byte parameters;
 therefore, to pass a single-byte data item by value between C and
 BASIC, the BASIC parameter must be DECLAREd as an INTEGER.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2, to
 Microsoft QuickC Versions 2.00 and 2.01 for MS-DOS, and to Microsoft C
 Compiler Versions 5.00 and 5.10 for MS-DOS and MS OS/2.

 The two programs below demonstrate passing a character by value from
 BASIC to C.

 To run the programs, do the following:

 1. Compile as follows, depending on which language you are using:

    a. Compile in BASIC as follows:

          BC testb ;

    b. For Microsoft C Versions 5.00 and 5.10, compile as follows:

          CL -c -AL test.c ;

    c. For Microsoft QuickC, compile as follows:

          QCL -c -AL test.c ;

 2. LINK with the following line:

       LINK /NOE testb+test ;

 The following program, TESTB.BAS, illustrates passing characters from
 BASIC to C by using the ASCII values and DECLAREing the C char
 parameter with BYVAL var AS INTEGER:

    DECLARE SUB test CDECL (BYVAL a%, BYVAL b%)
    CALL test(ASC("A"), ASC("B"))
    END

 TEST.C is as follows:

    void test(char a, char b)
      {
      printf("%c %c\n",a,b);
      }

 When compiled and run, TESTB.EXE displays the following:

    A B


 834. How to Empty (Flush) the Keyboard Buffer in BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900118-69 B_BasicCom
 Last Modified:  7-FEB-1990    ArticleIdent: Q58213

 The two programs below show two different methods of emptying the
 keyboard input buffer. The first program uses a DOS interrupt to clear
 the buffer, while the second program uses the INKEY$ function.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS.

 Code Example 1
 --------------

 The following program uses DOS interrupt 21 hex (33 decimal) with
 function 0C hex (12 decimal), which flushes the input (type-ahead)
 keyboard buffer. To run this program inside the QuickBASIC (QB.EXE)
 environment, you must load the Quick library QB.QLB with the /L
 option. To run this program inside the QuickBASIC Extended (QBX.EXE)
 environment supplied with Microsoft BASIC PDS Version 7.00, load the
 Quick library QBX.QLB with the /L option.

    'For BASIC PDS Version 7.00 you must instead use $INCLUDE: 'QBX.BI'
    REM $INCLUDE: 'qb.bi'
    DIM inregs AS regtype
    DIM outregs AS regtype
    inregs.ax = &HC00   ' 0C hex goes in AH, high byte of AX register
                        ' 00 goes in AL, the low byte of AX register
    CALL INTERRUPT(&H21, inregs, outregs)
    END

 Code Example 2
 --------------

 The following program uses the INKEY$ function to read characters from
 the keyboard buffer until no more are available. This program can also
 be used under MS OS/2 protected mode when compiled with Microsoft
 BASIC Compiler Versions 6.00 and 6.00b and Microsoft BASIC PDS Version
 7.00.

    WHILE INKEY$ <> ""
    WEND


 835. Error 53 ("File Not Found") Using FILES "filespec" Statement

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900126-95 B_BasicCom B_GWBasicI docerr
 Last Modified: 31-JAN-1990    ArticleIdent: Q58214

 The FILES "filespec" statement prints the names of the files residing
 on the specified disk. However, the manual doesn't mention that if the
 "filespec" parameter does not describe any current filenames, an error
 53 ("File Not Found") is returned. Unless this error is trapped,
 program execution is halted.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2; to
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2; and to Microsoft GW-BASIC Interpreter Versions
 3.20, 3.22, and 3.23 for MS-DOS.

 When a FILES statement is used to list the files in a specific
 directory and the pattern that FILES is searching for does not exist,
 an error 53 ("File Not Found") is returned.

 If the error is not trapped by the program, the error message "File
 Not Found" is displayed in the interpreter environment. In executable
 programs, the message displayed is "File Not Found In Module
 [Filename] at SEG:OFF," where SEG:OFF represents the segment and the
 offset from that segment of code where the error happened.

 To avoid halting the program, the program needs only to trap the error
 53 that is returned to the program. The program examples below
 demonstrate this, assuming that a file named ABC.XYZ does not exist on
 the root directory of drive C.

 Example for Compiled BASICs -- BASPROG.BAS
 ------------------------------------------

    ON ERROR GOTO ErrorHandle
    FILES "c:\abc.xyz"
    END
    ErrorHandle:
       IF ERR = 53 THEN PRINT "Error 53 was trapped. File not found."
    RESUME NEXT

 You can compile and link BASPROG.BAS as follows in QuickBASIC 4.00,
 4.00b, or 4.50, BASIC compiler 6.00 or 6.00b, or BASIC PDS 7.00:

    BC /x Basprog;
    LINK Basprog;

 Use QB /x Basprog in QuickBASIC Versions 2.00, 2.01, 3.00.

 Use BASCOM /x Basprog in QuickBASIC Versions 1.00, 1.01, 1.02.

 Example for GW-BASIC Interpreter
 --------------------------------

    10 ON ERROR GOTO 999
    20 FILES "c:\abc.xyz"
    30 END
    999  IF ERR = 53 THEN PRINT "Error 53 was trapped. File not found."
    1000 RESUME NEXT


 836. No Error in QB Using Duplicate Parameter Name in DECLARE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900126-79 B_BasicCom buglist4.00 buglist4.00b buglist4.
 Last Modified: 20-SEP-1990    ArticleIdent: Q58498

 The QuickBASIC environment fails to give an error message for a
 DECLARE statement that has several parameters with the same name. But
 when compiled with BC.EXE, the same statement correctly causes the
 following severe errors:

    Formal parameters not unique
    Formal parameter specification illegal

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; in the QB.EXE
 environment of Microsoft BASIC Compiler versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b); and in the QBX.EXE (QuickBASIC Extended)
 environment of Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 The following code example fails to produce an error inside the
 QuickBASIC QB.EXE or QBX.EXE environment:

    DECLARE SUB test (a%, a%)   'This line should cause error
    CALL test(1, 2)
    END

    SUB test (a%, b%)
    PRINT a%, b%
    END SUB

 When the above program is compiled with BC.EXE, the compiler correctly
 flags the DECLARE line as follows:

    DECLARE SUB test (a%, a%)   'This line should cause error
                          ^ Formal parameters not unique
                          ^ Formal parameter specification illegal


 837. "Overflow" with Integer Division and MOD Operator; Workaround

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900113-13 B_BasicCom
 Last Modified:  7-FEB-1990    ArticleIdent: Q58499

 The integer division operator (\) and the modulo arithmetic operator
 (MOD) correctly produce an "Overflow" error if an operand is a
 negative number less than -2,147,483,648 or a positive number greater
 than +2,147,483,647 (outside the limits for long integers).

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS)  Version 7.00 for MS-DOS and MS OS/2.

 The following program shows how to do integer division and modulo
 arithmetic when the size of an operand causes overflow:

    x# = 2147483648                ' numerator
    y# = 123                       ' denominator
    x# = INT(x# + .5)              ' round off the numerator
    y# = INT(y# + .5)              ' round off the denominator
    PRINT FIX(x# / y#)             ' Emulate integer division
    PRINT x# - ( y# * FIX(x# / y#) )  ' Emulate modulo arithmetic


 838. 4.50 Must Reset PALETTE After WIDTH 80,60 in SCREEN 12

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50 SR# S900201-95 B_BasicCom
 Last Modified: 21-SEP-1990    ArticleIdent: Q58564

 When using the WIDTH 80,60 statement in SCREEN 12 of a BASIC program,
 you must reset the palette or you cannot change attributes 8 through
 15 of the 16-attribute palette.

 The following code example demonstrates this problem when executed in
 Microsoft QuickBASIC version 4.50 or Microsoft BASIC Professional
 Development System (PDS) version 7.00 for MS-DOS.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 version 4.50 and in Microsoft BASIC Professional Development System
 (PDS) version 7.00 for MS-DOS (buglist7.00). This problem was
 corrected in BASIC PDS 7.10 (fixlist7.10).

 To change the palette in the program, you must reset the palette using
 the PALETTE statement (with no arguments) after you use the WIDTH
 80,60 statement.

 This behavior in the above product versions differs from QuickBASIC
 versions 4.00 and 4.00b and Microsoft BASIC Compiler versions 6.00 and
 6.00b, where you do not need to reset the palette after WIDTH 80,60.

 Code Example
 ------------

      SCREEN 12
      WIDTH 80, 60
      'PALETTE         'Remove the quote to make it work correctly.
      count = 0
      FOR y = 0 TO 375 STEP 25
         LINE (y + 2, y + 2)-(y + 25, y + 25), count, BF
         count = count + 1
      NEXT y
      FOR x = 1 TO 15
         PALETTE x, 63   ' Should change all boxes to same color.
      NEXT x
      END


 839. Any EGA/VGA Video RAM Above 256K Not Usable in Compiled BASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900201-17 B_BasicCom
 Last Modified: 13-FEB-1990    ArticleIdent: Q58567

 Any RAM above 256K on an EGA or VGA video card cannot be used to store
 screen pages during the execution of a compiled BASIC program.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS, and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS.

 These compilers are compatible with video cards that conform to the
 IBM standard. Accessing video RAM above 256K is not part of this
 standard.

 For example, when reading the documentation on the SCREEN statement in
 either the manuals or online Help included with the above products, it
 may appear that more than 2 pages of screen memory are available to a
 512K VGA card operating in screen mode 9. Footnote 2 on the bottom of
 Page 314 of the "Microsoft BASIC 7.0: Language Reference" manual
 states the following:

    Pages = Screen memory divided by page size. Eight page maximum,
            one page minimum.

 The page size of screen 9 for VGA is 128K. Applying the above formula,
 we get the following:

    Pages = 512K / 128K = 4 pages

 However, 4 pages is incorrect because all the memory above 256K on
 the VGA card is not usable. Therefore, the maximum number of pages is
 as follows:

    Pages = 256K / 128K = 2 pages


 840. "Selected Programs" in 4.50 Online Help Have Only 1 Example

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900131-28 docerr
 Last Modified: 26-FEB-1990    ArticleIdent: Q58607

 In the QB Advisor online Help system for Microsoft QuickBASIC Version
 4.50, several subtopics under the "HELP: Selected Programs" topic
 incorrectly claim to contain several examples, but contain only one.

 To find this error, run QB.EXE Version 4.50. Press ALT+H+C to choose
 the Contents command, which displays the "HELP: Table of Contents"
 window. Choose the Selected Programs button.

 The following "HELP: Selected Programs" subtopics contain only one
 example, contrary to a statement in each subtopic:

 1. Control Flow programs
 2. Error and Event Trapping programs
 3. Graphics programs
 4. Programs that demonstrate how to construct functions
    and procedures

 Note: To see additional QuickBASIC code examples for these topics, see
 the example programs shipped with QuickBASIC Version 4.50.


 841. ON...GOSUB Example from QB 4.50 Help Gives "Label Not Defined"

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900208-105 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q58609

 The ON...GOSUB example from the QB Advisor online Help system in
 Microsoft QuickBASIC Version 4.50 causes a "Label not defined" error
 when run without modification. This is not a documentation error,
 since the preface to the example states "the following program
 fragment...", thus implying that the code is incomplete.

 The Microsoft Advisor online Help system for QBX.EXE (QuickBASIC
 Extended) in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS has a complete working example for ON...GOSUB.

 ON...GOSUB Example from QB.EXE Version 4.50
 -------------------------------------------

 The following example, taken from the ON...GOSUB example in the
 QuickBASIC 4.50 online Help system, produces a "Label not defined"
 error on the ON...GOSUB statement:

 'The following program fragment causes program control to branch to
 'one of the four subroutines listed, depending on the value of Chval:

 DO
     CLS
     PRINT "1) Display attendance at workshops."
     PRINT "2) Calculate total registration fees paid."
     PRINT "3) Print mailing list."
     PRINT "4) End program."
     PRINT : PRINT "What is your choice?"
     DO
        Ch$ = INKEY$
     LOOP WHILE Ch$ = ""
     Chval = VAL(Ch$)
     IF Chval > 0 AND Chval < 5 THEN
         ON Chval GOSUB Shop, Fees, Mailer, Progend
     END IF
 LOOP
 END

 To use the above example, you must define the four GOSUB labels
 (Shop:, Fees:, Mailer:, and Progend:).

 ON...GOSUB Example from QBX.EXE Version 7.00
 --------------------------------------------

 The following similar example from the QBX.EXE online Help system runs
 without error:

 'This example uses the ON...GOSUB statement to cause program control to
 'branch to one of three subroutines, depending on the value of Chval.

 CLS    'Clear screen.
 Attend = 20
 Fees = 5 * Attend
 PRINT "1  Display attendance at workshops"
 PRINT "2  Calculate total registration fees paid"
 PRINT "3  End program"
 PRINT : PRINT "What is your choice?"
 Choice:
     DO
        ch$ = INKEY$
     LOOP WHILE ch$ = ""
     Chval = VAL(ch$)
     IF Chval > 0 AND Chval < 4 THEN
         ON Chval GOSUB Shop, Fees, Progend
     END IF
 END
 Shop:
     PRINT "ATTENDANCE IS", Attend
     RETURN Choice
 Fees:
     PRINT "REGISTRATION FEES ARE $"; Fees
     RETURN Choice
 Progend:
     END


 842. QB 4.50 Parameter Passed to Separate Module Shows as Garbage

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900210-1 buglist4.50
 Last Modified:  1-MAR-1990    ArticleIdent: Q58732

 A QuickBASIC 4.50 program that calls a subprogram located in a
 separate module (such as in a library or Quick library) can have a
 parameter's contents become corrupt under the specific circumstances
 described further below. After the parameter has been corrupted,
 PRINTing that parameter may display "garbage" instead of the correct
 results.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Version 4.50. We are researching this problem and will post new
 information here as it becomes available.

 This problem does NOT occur in earlier versions of QuickBASIC, in
 Microsoft BASIC Compiler Versions 6.00 or 6.00b for MS-DOS and MS
 OS/2, or in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 for MS-DOS and MS OS/2.

 The conditions under which parameters may become corrupt are as
 follows:

 1. Variables are passed using argument and parameter lists to a
    subprogram located in a separate module (a linked .OBJ, a library,
    or a Quick library). (This problem does not occur if variables are
    passed through a COMMON SHARED statement.)

 2. The second argument passed is of type SINGLE, DOUBLE, or INTEGER.
    (This problem does not occur with long integers.)

 3. In the subprogram, the variable in the first position of the
    parameter list is multiplied by the variable in the second
    position, giving the result to a third variable such as a third
    parameter or a variable local to the subroutine. The problem
    does not occur if the order of multiplication is switched.

 4. If all of the above conditions are met, the variable that is
    defined in the second position of the parameter list shows garbage
    when PRINTed even though no changes were made to this variable.
    All other variables are displayed correctly.

 The following program exhibits the problem:

 Main Level Code
 ---------------

    x = 5
    y = 6
    Print "Before Call "; x, y, z
    CALL Garbage(x, y, z)
    PRINT "After Call "; x, y, z   '--Correct values are displayed
                                   '  after exiting the sub

 Separate Module (.OBJ, Library, or Quick Library) Code
 ------------------------------------------------------

    SUB Garbage (x, y, z)
      PRINT "In sub, before multiplying "; x, y, z  '--Correct values
                                                    '  are displayed
      z = x * y                   '--Change this line to z = y * x
                                  '  and program will work correctly
      PRINT "In sub, after multiplying  "; x, y, z  '--y displays garbage
    END SUB

 Workarounds
 -----------

 One workaround to the problem is to assign the variable located in the
 second position of the parameter list to a temporary variable and work
 with that temporary variable. At the end of the procedure, assign the
 parameter variable the value of the temporary variable. For example,
 the procedure in the library or Quick library would look like the
 following:

    SUB Garbage (x, y, z)
       ytemp = y
       z = x * ytemp
       y = ytemp
       PRINT "Printing ytemp "; ytemp
       PRINT "Printing y     "; y
   END SUB

 Another workaround is to pass variables through a COMMON SHARED
 statement instead of a parameter list.


 843. "Input Run-Time Module Path:" Never Found If BRUN45.EXE Typed

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900209-125 buglist4.50 B_BasicCom
 Last Modified:  9-MAR-1990    ArticleIdent: Q58789

 An executable program that requires but cannot locate the BRUN45.EXE
 run-time module displays the prompt "Input run-time module path:". If
 you type the complete path with the BRUN45.EXE or BRUN45 filename at
 the end, the search is never satisfied and the prompt continues to
 display. You must press CTRL+C or CTRL+BREAK to abort.

 Microsoft has confirmed this to be a problem in QuickBASIC Version
 4.50 for MS-DOS. This problem was corrected in Microsoft BASIC
 Compiler Versions 6.00 and 6.00b (fixlist6.00, fixlist6.00b) and in
 Microsoft BASIC Professional Development System (PDS) Version 7.00
 (fixlist7.00).

 A QuickBASIC source file compiled without the BC /O option makes
 LINK.EXE link with the BRUN45.LIB run-time library to create an
 executable program. If the resulting code cannot locate the BRUN45.EXE
 run-time module, a prompt displays for you to enter the path to search
 for the module.

 If you provide an incorrect path, the prompt displays again. This
 process continues until one of the following two conditions occur:

 1. You stop the process with CTRL+C or CTRL+BREAK.

 2. You give the correct path WITHOUT the filename BRUN45.EXE or
    BRUN45 appended. For example, type "C:\QB45\" as a path.

 If you give the correct path plus the filename BRUN45 with or without
 the extension .EXE at the end, the prompt is never satisfied (even if
 you next give the correct path WITHOUT the filename BRUN45.EXE or
 BRUN45 appended).


 844. How BASIC Can Determine VGA Palette Colors with BIOS Interrupt

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900214-79 B_BasicCom
 Last Modified:  6-MAR-1990    ArticleIdent: Q58825

 The easiest way to determine the color value associated with a given
 VGA palette register is to use BIOS Interrupt 10 Hex, with Function 10
 Hex, and Subfunction 15 Hex. This information applies only to machines
 that have VGA adapters and return information only on the VGA palette.
 This interrupt does not supply information on the EGA or CGA palettes.

 The sample program below applies only to Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 under MS-DOS. It does not apply to earlier versions of
 QuickBASIC or BASIC compiler because they do support VGA SCREEN modes.
 (However, the information on Interrupt 10 Hex, with Function 10 Hex
 applies to any language with the ability to call BIOS routines,
 including QuickBASIC Versions 2.00, 2.01, and 3.00.)

 Interrupt 10 hex (16 decimal) contains all of the advanced video
 services available through the BIOS of the PC. Function 10 hex (16
 decimal) of interrupt 10 hex contains the color or palette services.
 These include services for setting or retrieving color information.
 Subfunction 15 hex (21 decimal) of these services returns the red,
 green, and blue intensities associated with a particular palette
 register. From this, you can determine the color number associated
 with that attribute.

 There are 16 (0-15) attributes in VGA Screen 12, and 256 (0-255)
 attributes in VGA Screen 13. Screen 11 has only 1. Each of these
 attributes has a corresponding palette register. When you do a PALETTE
 or PALETTE USING statement, you change the values in one or all of
 these registers. However, BASIC has no built-in procedure for reading
 these registers. Therefore, you must use CALL INTERRUPT.

 The sample program below uses CALL INTERRUPT to find the default
 values for all of the palette registers associated with screen mode
 12. This program can easily be modified to find all 256 registers
 available in screen mode 13 by looping 256 times instead of 16. The
 output of the program lists the register number and the red, green,
 and blue intensity values for each palette register. It also
 calculates the corresponding color number with the following formula:

    Colornumber = (65536 * Blue) + (256 * Green) + Red

 For more information about BIOS interrupts and video graphics, see the
 following books:

 1. "Advanced MS-DOS Programming, 2nd Edition," by Ray Duncan
    (Microsoft Press, 1988)

 2. "Programmer's Guide to PC & PS/2 Video Systems," by Richard Wilton
    (Microsoft Press, 1987)

 Code Example
 ------------

 The following program can be run in the QuickBASIC 4.00, 4.00b, or
 4.50 environment and in the QuickBASIC environment included with
 Microsoft BASIC Compiler Versions 6.00 and 6.00b by loading QB.EXE
 with the QB.QLB Quick library. In the BASIC PDS 7.00 environment, load
 QBX.EXE with the QBX.QLB Quick library. If the program is compiled, it
 must be linked with either QB.LIB or QBX.LIB, respectively.

 'PALINFO.BAS
 '*** You must load QB.QLB or link with QB.LIB for QuickBASIC 4.x ***
 '*** You must load QBX.QLB or link with QBX.LIB for BASIC 7.00 ***

 REM $INCLUDE: 'qb.bi'   'qbx.bi for BASIC 7.00 and QBX
 DIM inregs AS regtype, outregs AS regtype

 SCREEN 12
 PRINT "Palette Information"
 PRINT "Register #", "Green", "Blue", "Red", "Color Number"
 PRINT "----------", "-----", "----", "---", "-------------"

 FOR i = 0 TO 15             '0 to 255 for screen 13
   inregs.ax = &H1015          'AH = 10H,   AL=15H
   inregs.bx = i               'BL = register #
   CALL interrupt(&H10, inregs, outregs)

 'The following lines mask off the high/low bites of the registers
 'CH = green, CL = blue, DH = red

   a% = (outregs.cx AND &HFF00) / &HFF
   b% = (outregs.cx AND &HFF)
   c% = (outregs.dx AND &HFF00) / &HFF

   d& = 65536 * b% + 256 * a% + c%
   PRINT i, a%, b%, c%, d&
 NEXT i

 END  ' End of example code.

 Additional reference words: &H10 10H &H15 15H


 845. RUN Inside ON ERROR Handler Causes "Press Any Key" in EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900201-75 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 26-FEB-1990    ArticleIdent: Q58924

 Using a RUN statement to run a file from inside an error-handling
 routine causes the message "press any key to return to system" to be
 displayed before passing control to the new program. This problem
 occurs in compiled EXE files only; the QuickBASIC QB.EXE environment
 transfers control without any message.

 Use one of the following to work around the problem:

 1. Use CHAIN instead of RUN.
 2. To restart the same program, use RUN without a filename.
 3. RESUME to a line that executes the RUN statement.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Versions 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) Version 7.00 (fixlist7.00).

 The following code example displays the "press any key..." message
 when run in EXE form. The three workarounds mentioned above are each
 listed in comments.

    'A.BAS  compile and link commands:
    '   BC   /E A;
    '   LINK    A;
    ON ERROR GOTO handle:
    PRINT "Before error"
    IF INKEY$ <> CHR$(27) THEN ERROR 100
    END

    handle:
    PRINT "In error"
    'CHAIN "a"                       'Workaround #1
    'RUN                             'Workaround #2
    'RESUME 110                      'Workaround #3
    110 RUN "a"


 846. Array Storage DGROUP vs. Far Heap Differs in .EXE vs. QB.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900112-152 B_BasicCom
 Last Modified: 27-FEB-1990    ArticleIdent: Q58926

 Arrays can be stored in different places depending on array type and
 on whether the program is run from an .EXE file or the QB.EXE
 environment. All nonarray (scalar) variables are always stored in
 DGROUP.

 In the QuickBASIC QB.EXE environment, a static array of numeric type
 or fixed-length-string type must be in a COMMON or COMMON SHARED
 statement to be allocated in the DGROUP memory area; otherwise it will
 be stored in the far heap.

 In an executable file (.EXE), all types of static arrays are always
 stored in the DGROUP area (which can be referenced with a near
 address).

 Dynamic or static arrays of variable-length strings are always stored
 in DGROUP in both QB.EXE and .EXE programs.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, and to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2.

 For a complete description of variable storage allocation, please read
 Pages 32 and 33 of the "Microsoft QuickBASIC 4.0: BASIC Language
 Reference," or Pages 32 and 33 of the "Microsoft BASIC Compiler 6.0:
 BASIC Language Reference."

 DGROUP is also known as the default data segment, or the near data
 storage area.

 In summary, array storage in QB.EXE adheres to the following three
 rules:

 1. All $STATIC arrays in COMMON or COMMON SHARED are stored in DGROUP.

 2. All arrays of type variable-length string are stored in DGROUP.

 3. All other arrays are stored in far addresses.

 Array storage in .EXE programs adheres to the following three rules:

 1. All $STATIC arrays are stored in DGROUP.

 2. All $DYNAMIC arrays of variable-length strings are stored in
    DGROUP.

 3. All other $DYNAMIC arrays are stored as far objects in the far heap.

 Program Example
 ---------------

 The program below illustrates the preceding information.

 DIM ar1(100) AS INTEGER      ' REM $STATIC is the default for arrays
 DIM ar2(100) AS INTEGER      ' REM $STATIC is the default for arrays
 COMMON SHARED ar2() AS INTEGER
 ' Must be in COMMON in QB.EXE environment to be placed in DGROUP.
 s$ = "hello"    ' this is put into the DGROUP
 REM $DYNAMIC
 DIM ar3(100) AS INTEGER
 PRINT VARSEG(s$), VARSEG(ar1(0)), VARSEG(ar2(0)), VARSEG(ar3(0))


 847. You Cannot Decompile .EXE or .OBJ Files Back to BASIC Source

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890926-125 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q58956

 Microsoft does not currently offer any product capable of
 "decompiling" an object (.OBJ) or executable (.EXE) file back to the
 original source code (.BAS). The following are several reasons for
 this:

 1. No decompiler could exactly reproduce the original source code.

    When a program is compiled to an object and linked to produce an
    executable, most of the "names" used in the original program are
    converted to addresses. This loss of names means that a decompiler
    would have to create unique names for all the variables,
    procedures, and labels, and these names would not be meaningful in
    the context of the program.

    Obviously, source language syntax no longer exists in the compiled
    object file or executable. It would be very difficult for a
    decompiler to interpret the series of machine language instructions
    that exist in an object or executable file and decide what the
    original source language instruction was.

 2. If such a decompiler did exist and was available, anyone could use
    it to decompile any executable program produced in the language the
    decompiler was designed for.

    For instance, if a Microsoft BASIC decompiler existed, anyone with
    that decompiler could use it on an executable that you had
    produced and from that executable obtain a copy of your source
    code. The source code to any program you wrote in Microsoft BASIC
    would be available to anyone with the decompiler. Few developers of
    commercial software would want to use a language product that could
    be deciphered, thus allowing others to obtain their source code.

 This information applies to Microsoft QuickBASIC Versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50 for MS-DOS, to Microsoft
 BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS and MS OS/2.


 848. DEF SEG from POKE Help Shows DEF FN Help in 4.50 Online Help

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900221-73 docerr
 Last Modified: 26-FEB-1990    ArticleIdent: Q58965

 In the QB Advisor online Help system in Microsoft QuickBASIC Version
 4.50 for MS-DOS, the hyperlink to the DEF SEG statement from the POKE
 statement Help screen incorrectly displays help for the DEF FN
 statement. (The hyperlinks to DEF SEG from PEEK, BLOAD, and BSAVE all
 correctly display the DEF SEG help.)

 This hyperlink works correctly in the Microsoft Advisor online Help
 system in the QuickBASIC Extended (QBX.EXE) environment that comes
 with Microsoft BASIC Professional Development System (PDS) Version
 7.00 for MS-DOS.


 849. How to Distinguish Between a Standard and Enhanced Keyboard

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q59006

 The following code example demonstrates calling interrupts to
 determine whether an enhanced or standard keyboard is connected to
 your machine. This example applies to Microsoft QuickBASIC Versions
 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b, and to Microsoft BASIC Professional Development System (PDS)
 Version 7.00 under MS-DOS. (The information about the interrupt 16
 Hex, with Functions 2 and 12 Hex, also applies to any language that
 can call BIOS interrupts.)

 The information for the interrupts was taken from Pages 581-586 of the
 book "Advanced MS-DOS Programming, Second Edition," by Ray Duncan,
 (Microsoft Press, 1988). This information can also be found on Pages
 105-112 of the "Programmer's Quick Reference Series: IBM ROM BIOS," by
 Ray Duncan (Microsoft Press, 1988).

 The information about the address for the PEEK statement was taken
 from Pages 137 and 138 of the book "The New Peter Norton Programmer's
 Guide to the IBM PC and PS/2," by Peter Norton and Richard Wilton,
 (Microsoft Press, 1988).

 To compile and link the program in QuickBASIC 4.50, do the following:

    BC Keytest.bas ;
    LINK Keytest,,,BRUN45.LIB+QB.LIB ;

 Code Example
 ------------

 REM $INCLUDE: 'qb.bi'   ' Change to qbx.bi for BASIC PDS Version 7.00
 DIM inregs AS regtype, outregs AS regtype
 CLS
 inregs.ax = &H1200
 CALL interrupt(&H16, inregs, outregs)
 key2% = outregs.ax
 DEF SEG = &H40
 test% = PEEK(&H17)
 DEF SEG
 LOCATE 13, 23
 IF key2% <> test% THEN PRINT "You have a Standard Keyboard"
 IF key2% = test% THEN PRINT "You have an Enhanced Keyboard"
 LOCATE 25, 20
 PRINT "Hit a key to end test"
 SLEEP
 CLS
 END


 850. How BASIC Can Display Multiple Text Colors at Once on SCREEN 1

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900202-98 B_BasicCom
 Last Modified: 26-FEB-1990    ArticleIdent: Q59007

 In SCREEN 1, the COLOR statement cannot be used to put text of more
 than one color on the screen at one time. However, this can be done by
 using the ROM BIOS INTERRUPT hex 10, function 9, which displays a
 character with a specified attribute at the current cursor position.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2.

 The specified attribute of a character can be 0, 1, 2, or 3. This
 attribute and the COLOR statement determine the color of the
 character. When an even expression (0 to 254) is the value for the
 palette in the COLOR statement, the default colors are 1 (green), 2
 (red), and 3 (yellow on CGA, or brown on EGA). When an odd expression
 (1 to 255) is the value for the palette in the COLOR statement, the
 default colors are 1 (cyan), 2 (magenta), and 3 (white). When the
 attribute is 0, the character is the background color specified by the
 COLOR statement. Attribute 0 can be used to erase a character. If no
 COLOR statement is used, the default is COLOR 0,1.

 The following program CALLs INTERRUPT 10 Hex (16 decimal), with
 function 9, to display a character of a certain color on the screen.
 To use this program, do the following:

 1. Invoke QuickBASIC by typing the following:

       QB /L QB.QLB       [for QuickBASIC 4.00, 4.00b, or 4.50]
    or
       QBX /L QBX.QLB     [for BASIC PDS Version 7.00]

    (The /L option above loads the QB.QLB or QBX.QLB Quick library,
    which contains the CALL INTERRUPT routine.)

 2. QB.BI must be used in the $INCLUDE metacommand (see below). QB.BI
    contains the user-defined TYPEs RegTypeX and RegType. Refer to the
    QB.BI text file for more information. For BASIC PDS 7.00, this file
    is called QBX.BI.

 3. If you are compiling and linking outside the environment, QB.LIB
    must be linked in. For BASIC PDS 7.00, you must link in QBX.LIB.

 This program allows text to be printed to the screen at the location
 of the cursor by CALLing a subprogram named PrintColors. The text,
 attribute, and row and column position of the cursor are passed.

 DECLARE SUB PrintColors (text$, attribute, col, row)
 ' $INCLUDE: 'qb.bi'
 ' For BASIC PDS you must include 'qbx.bi'
 DIM SHARED inregs AS RegType, outregs AS RegType
 CLS
 SCREEN 1
 COLOR 0, 0                   'black background and even palette
 col = 1: row = 1             'current position of the cursor
 attribute = 1
 CALL PrintColors("green text ", attribute, col, row)
 attribute = 2

 CALL PrintColors("red text ", attribute, col, row)
 attribute = 3

 CALL PrintColors("yellow/brown text", attribute, col, row)
 PRINT "Default is yellow on CGA, brown on EGA"
 END

 REM Subprogram PrintColors prints text to the screen at position col
 REM and row in a color determined by the attribute passed and the
 REM palette selected by the COLOR statement. The cursor is updated.

 SUB PrintColors (text$, attribute, col, row)
   FOR i = 1 TO LEN(text$)
     inregs.ax = &H900 + ASC(MID$(text$, i, 1)) 'function 09 in the
                               'high part of the register and the ASCII
                               'code of a character in the low part
     inregs.bx = attribute 'display page (0 is the current page) in the
                           'high part and the attribute in the low part
     inregs.cx = &H1         'number of times to display the character
     CALL Interrupt(&H10, inregs, outregs)
     col = col + 1        'relocate the cursor one place to the right
     LOCATE row, col      'for every character written to the screen
   NEXT
 END SUB


 851. WHEREIS.BAS Correction in "4.5: Programming in BASIC" Manual

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 28-FEB-1990    ArticleIdent: Q59130

 The following statement in the program example WHEREIS.BAS on Page
 78 of the "Microsoft QuickBASIC 4.5: Programming in BASIC" manual for
 Version 4.50 is incorrect. The last line on the page incorrectly
 states the following:

    OPEN TempSpec$ FOR INPUT AS #FileNu

 This statement should be corrected as follows:

    OPEN TempSpec$ FOR INPUT AS #FileNum

 The WHEREIS.BAS example program is also included in the \EXAMPLES
 subdirectory on the "Setup/Microsoft QB Express" disk for QuickBASIC
 Version 4.50. The example provided on disk does not contain the error
 and executes properly in the QB.EXE environment or as an .EXE program.

 This documentation error has been corrected in the manuals for
 Microsoft BASIC Professional Development System 7.00 for MS-DOS and MS
 OS/2.


 852. How to Trap CTRL, ALT, and SHIFT Keys Alone in BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900223-10 B_BasicCom
 Last Modified: 28-FEB-1990    ArticleIdent: Q59131

 Normally, to trap CTRL (CONTROL), ALT, and SHIFT in combination with
 other keys, you would set the bits for these keys in the first byte
 (keyboard flag) of the two CHR$() bytes in the KEY statement.

 However, to trap the CTRL, ALT, and SHIFT keys alone (not in
 combination with other keys), the keyboard flag in the KEY statement
 should be CHR$(0) for the standard keyboard or CHR$(&H80) for keys
 specific to an extended keyboard.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 The syntax of the KEY statement (where n=15 through 25 can be
 user-defined keys) is as follows:

    KEY n, CHR$(keyboardflag) + CHR$(scancode)

 The following table lists the scan codes for the CTRL, ALT and SHIFT
 keys:

    Key           Scan Code
    ---           ---------
    CTRL          &H1D
    ALT           &H38
    LEFT SHIFT    &H2A
    RIGHT SHIFT   &H36

 NOTE: To trap the RIGHT CTRL or RIGHT ALT key (found only on an
 extended 101 keyboard), the extended keyboard flag (&H80) must be used
 in the keyboard flag byte.

 Code Example
 ------------

 The following code example traps the CTRL, ALT, and SHIFT keys
 alone:

 'NOTE:  This program requires NUM LOCK and CAPS LOCK to be off.
 KEY 15, CHR$(&H0) + CHR$(&H1D)      'LEFT CTRL (on
 ON KEY(15) GOSUB Ctrl               'Standard or Extended keyboard)
 KEY(15) ON

 KEY 16, CHR$(&H80) + CHR$(&H1D)     'RIGHT CTRL (on Extended keyboard)
 ON KEY(16) GOSUB Ctrl
 KEY(16) ON

 KEY 17, CHR$(&H0) + CHR$(&H38)      'LEFT ALT (on
 ON KEY(17) GOSUB alt                'Standard or Extended keyboard)
 KEY(17) ON

 KEY 18, CHR$(&H80) + CHR$(&H38)     'RIGHT ALT (on Extended keyboard)
 ON KEY(18) GOSUB Alt
 KEY(18) ON

 KEY 19, CHR$(&H0) + CHR$(&H2A)      'LEFT SHIFT (on
 ON KEY(19) GOSUB Shift              'Standard or Extended keyboard)
 KEY(19) ON

 KEY 20, CHR$(&H0) + CHR$(&H36)      'RIGHT SHIFT (on
 ON KEY(20) GOSUB Shift              'Standard or Extended keyboard)
 KEY(20) ON

 WHILE INKEY$ <> CHR$(27): WEND      'Press ESC to end
 END

 Ctrl: PRINT "CTRL"
 RETURN

 Alt:  PRINT "ALT"
 RETURN

 Shift:  PRINT "SHIFT"
 RETURN


 853. How to Disable Toggle for NUM/CAPS/SCROLL LOCK with Key Trap

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900222-212 B_BasicCom SCROLLLOCK NUMLOCK CAPSLOCK
 Last Modified: 26-MAR-1990    ArticleIdent: Q59132

 By setting up key traps for the NUM LOCK, CAPS LOCK, and SCROLL LOCK
 keys, a BASIC program can prevent the toggling of each of these key
 states. This is extremely useful for trapping other keys because the
 program can limit the number of keys to be defined.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) Version 7.00.

 The syntax of the KEY statement (where n=15 through 25 can be
 user-defined keys) is as follows:

    KEY n, CHR$(keyboardflag) + CHR$(scancode)

 The following are the scan codes are for the CAPS LOCK, NUM LOCK, and
 SCROLL LOCK keys:

    Key           Scan Code
    ---           ---------
    CAPS LOCK     &H3A
    NUM LOCK      &H45
    SCROLL LOCK   &H46

 By defining traps for NUM LOCK and CAPS LOCK, your program can
 effectively reduce (by a factor of four) the number of keys needed to
 be defined. For example, to trap both the CTRL+ALT+DEL and CTRL+BREAK
 combinations, 16 keys must be created to handle all the different
 combinations. This is more than the maximum number of user-defined
 keys (11). By defining CAPS and NUM LOCK traps, only 4 additional keys
 must be defined.

 To see how to programmatically (without pressing the key) force the
 NUM LOCK, CAPS LOCK, or SCROLL LOCK state on or off, query on the
 following words to find a separate article in this Knowledge Base:

    KEY and POKE and CAPS

 Code Example
 ------------

 The following code example disables the toggles for the CAPS LOCK,
 NUM LOCK, and SCROLL LOCK keys:

 'NOTE: This program assumes NUM LOCK and CAPS LOCK are off at the
 '      beginning. See the article referenced above for how to set
 '      the NUM and CAPS LOCK off.
 KEY 15, CHR$(&H0) + CHR$(&H3A)       'CAPS LOCK
 ON KEY(15) GOSUB caps
 KEY(15) ON

 KEY 16, CHR$(&H0) + CHR$(&H45)       'NUM LOCK
 ON KEY(16) GOSUB num
 KEY(16) ON

 KEY 17, CHR$(&H0) + CHR$(&H46)       'SCROLL LOCK
 ON KEY(17) GOSUB scroll
 KEY(17) ON

 WHILE INKEY$ <> CHR$(27): WEND
 END

 caps: PRINT "NO CAPS LOCK TOGGLE!"
 RETURN

 num:  PRINT "NO NUM LOCK TOGGLE!"
 RETURN

 scroll:  PRINT "NO SCROLL LOCK TOGGLE!"
 RETURN


 854. How to Trap PRINT SCREEN Key on an Extended (101-Key) Keyboard

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900222-147 B_BasicCom
 Last Modified:  2-MAR-1990    ArticleIdent: Q59133

 It is possible to detect (trap) the PRINT SCREEN (or SHIFT+PRINT
 SCREEN, PRT SCR, etc.) key with Microsoft QuickBASIC Versions 4.00,
 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and Microsoft BASIC Professional
 Development System (PDS) Version 7.00 for MS-DOS and MS OS/2.

 Although BASIC can detect the key press with the ON KEY GOSUB
 statement, the PRINT SCREEN action is controlled through the ROM BIOS
 interrupt table and cannot be disabled directly with BASIC. To disable
 the print screen utility, the interrupt vector must be remapped with a
 C or assembly routine.

 Here is the syntax of the KEY statement, where n=15 through 25 can be
 user-defined key combinations to trap:

    KEY n, CHR$(keyboardflag) + CHR$(scancode)

 The following chart shows the keyboard flags and scan codes for PRINT
 SCREEN and SHIFT+PRINT SCREEN for standard and extended keyboards:

                           Standard   Extended
                           --------   --------
    Keyboard flag for:

       No    SHIFT         &H00       &H80
       LEFT  SHIFT         &H02       &H82
       RIGHT SHIFT         &H01       &H81

    Scan Code for:

       PRINT SCREEN        &H37       &H2A

 NOTE: The keyboard flags are affected by CAPS LOCK and NUM LOCK. The
 above values assume that CAPS LOCK and NUM LOCK are off. Add &H40 to
 the keyboard flag for CAPS LOCK, and add &H20 for NUM LOCK.

 Code Example
 ------------

 The following code example detects each of the PRINT SCREEN and
 SHIFT+PRINT SCREEN combinations listed above:

 'NOTE: This program detects PRINT SCREEN and SHIFT+PRINT SCREEN key
 '      combinations on standard and extended keyboards with CAPS LOCK
 '      and NUM LOCK off.
 '
 'ALSO NOTE: This program does NOT disable the PRINT SCREEN action
 '           (that is, the screen is still printed). See the explanation
 '           in the text of the above article.
 KEY 15, CHR$(&H00) + CHR$(37)        'Standard no SHIFTs
 KEY 16, CHR$(&H02) + CHR$(37)        'Standard LEFT SHIFT
 KEY 17, CHR$(&H01) + CHR$(37)        'Standard RIGHT SHIFT
 KEY 18, CHR$(&H80) + CHR$(2A)        'Extended no SHIFTs
 KEY 19, CHR$(&H82) + CHR$(2A)        'Extended LEFT SHIFT
 KEY 20, CHR$(&H81) + CHR$(2A)        'Extended RIGHT SHIFT
 FOR i%=15 TO 20
   ON KEY(i%) GOSUB Handle:
   KEY(i%) ON
 NEXT
 WHILE INKEY$<>CHR$(27) : WEND        'Press ESC to end
 END

 Handle: PRINT "Trapped PRINT SCREEN keystroke"
         PRINT "Screen will still print unless"
         PRINT "Interrupt vector changed with"
         PRINT "C or Assembly routine."
         RETURN


 855. Designer Quickwindows Is Alternative Graphics User Interface

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  9-MAR-1990    ArticleIdent: Q59401

 This article describes Designer Quickwindows (from Software
 Interphase, Inc.), an add-on product for Microsoft QuickBASIC Version
 4.50 and Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS.
 This product provides an alternative method of producing a Graphical
 User Interface (GUI) in a BASIC program. It can be used instead of
 hand coding your own interface or instead of using the User Interface
 (UI) Toolbox routines provided with Microsoft BASIC Professional
 Development System (PDS) Version 7.00. The product described here is
 manufactured by a vendor independent of Microsoft; we make no
 warranty, implied or otherwise, regarding this product's performance
 or reliability.

 Software Interphase, Inc. provides a product called "Designer
 Quickwindows," which is a mouse-driven design interface that generates
 BASIC code. This code can then be enhanced with other BASIC code to
 create a full BASIC program. The code generated creates the GUI by
 making calls into the "Quick Windows Advanced Library." This library
 is another product available from Software Interphase.

 At the present time, Designer Quickwindows works under Microsoft
 QuickBASIC Versions 4.50 and earlier and under Microsoft BASIC
 Compiler Versions 6.00b and earlier. In the near future, Designer
 Quickwindows should have a version that supports far strings with
 Microsoft BASIC PDS 7.00. You can obtain a sample program by calling
 Software Interphase (see below).

 The following information was taken from Page 15 of the "Language
 Support Directory for Microsoft QuickBASIC and Microsoft BASIC
 Compiler":

    Software Interphase
    5 Bradley Street, Suite 102
    Providence, RI 02908-2304
    (401) 274-5465

 [The "Language Support Directory for Microsoft QuickBASIC and BASIC
 Compiler" is a pamphlet distributed with Microsoft BASIC Compiler
 Versions 6.00 and 6.00b, but not with QuickBASIC packages. QuickBASIC
 owners can order it (free) from Microsoft Sales/Consumer Response by
 calling (800) 426-9400 or (206) 882-8088.]


 856. BASIC &num Constant Defaults to &Onum (Octal), Not &Hnum (Hex)

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_GWBasicC B_MQuickB B_BasicInt
 Last Modified: 15-MAR-1990    ArticleIdent: Q59403

 In all versions of Microsoft BASIC products, the base for a literal
 constant that begins with an ampersand (&) alone (not &H, &h, &O, or
 &o) defaults to octal (equivalent to &O or &o). Thus, if you type a
 literal such as the following

    &700

 then all versions of Microsoft BASIC will assume that this is an octal
 literal equivalent to &o700.

 In fact, many Microsoft BASIC Interpreters (such as GW-BASIC Versions
 3.20 and later for MS-DOS; QuickBASIC Versions 4.00 and later for
 MS-DOS; Microsoft BASIC Interpreter Versions 2.00, 2.10, and 3.00 for
 the Apple Macintosh; and QuickBASIC Version 1.00 for the Apple
 Macintosh) actually alter the literal to &o700 to show they are
 making this assumption.

 The octal default for a literal constant that begins with a lone
 ampersand (&) occurs in the following products:

 1. Microsoft QuickBASIC Version 1.00 for the Apple Macintosh

 2. Microsoft BASIC Compiler Version 1.00 for the Apple Macintosh

 3. Microsoft BASIC Interpreter Versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for the Apple Macintosh

 4. Microsoft QuickBASIC Versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, 4.50 for MS-DOS

 5. Microsoft BASIC Compiler Versions 5.35 and 5.36 for MS-DOS

 6. Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS

 7. Microsoft BASIC Professional Development System (PDS) Version 7.00
    for MS-DOS and MS OS/2

 8. Microsoft GW-BASIC Interpreter Versions 3.20, 3.22, and 3.23

 To demonstrate this feature of BASIC, enter the following code into
 the environment one of the BASIC interpreters, such as GW-BASIC or
 Microsoft QuickBASIC:

    40 CLS
    50 PRINT &700    ' This will print out as 448 (decimal value)
    55 PRINT &o700   ' This will print out as 448 (decimal value)
    60 PRINT &H700   ' This will print out as 1792 (decimal value)
    70 END

 In many Microsoft BASIC interpreters (such as GW-BASIC 3.20 or later
 for MS-DOS; QuickBASIC 4.00 and later for MS-DOS; BASIC interpreter
 2.00, 2.10, and 3.00 for the Apple Macintosh; or QuickBASIC 1.00 for
 the Apple Macintosh), the editor automatically changes lines 50
 and 55 to the following:

    50 PRINT &O700
    55 PRINT &O700

 If you want a hexadecimal number, the & (ampersand sign) must be
 followed with H, as in line 60 above.


 857. Bad EXE Result, Expression Indexing Dynamic Long Integer Array

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified:  4-SEP-1990    ArticleIdent: Q59428

 Subscripting $DYNAMIC long-integer arrays with expressions can give
 incorrect results in a compiled .EXE program, as shown in the code
 example further below. (The example below works correctly when run in
 the QB.EXE editor.)

 To work around this problem, do not use an expression in the
 subscript. Instead, store the result of the expression in a temporary
 variable and use that variable to subscript the array.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
 buglist6.00b). This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) version 7.00 (fixlist7.00).

 Technical Note
 --------------

 You can view the cause of this problem by examining the assembly code
 generated by your program. To do this, generate an assembly listing or
 use Microsoft CodeView. This problem occurs because of an error in the
 way that the array is referenced. Since the array is $DYNAMIC, the
 address is a far address and should be referenced with ES:[BX] and
 ES:[BX+02]. Instead, the array is referenced with [SI] and [SI+2].
 This is not the correct address for the array and will yield incorrect
 results.

 Without the $DYNAMIC metacommand, the specific code below works
 correctly, but a related example can cause the "Internal Error Near
 xxxx" compiler error. A separate article, which describes the
 circumstances for that error, can be found by querying on the
 following words:

    internal and error and long and integer and array and subtraction
    and division

 Code Example
 ------------

 ' LONGINT.BAS
 ' The following code example prints incorrect results when compiled and
 ' linked as specified:
 '
 '    Compile line: BC /D LONGINT;
 '    LINK line:    LINK LONGINT;
 '
 'NOTE: The behavior of this program varies, depending on which BC
 '      compile options (/O, /D, etc.) are used. Most combinations of
 '      compiler options result in problems for this program. The problem
 '      does not occur if you compile the example below with BC /O,
 '      but similar examples give a problem even when compiled with /O.
 '      The surest workaround, which works for all compiler options, is
 '      to use temporary variables as shown below.
 REM $DYNAMIC
 DIM X&(1, 1)
 ' Note that a FOR...NEXT loop index variable (j%) is required to show
 ' the problem:
 FOR j% = 1 TO 1
    ' The heart of the problem lies in lines A and B (marked below).
    ' You can partially solve the problem by modifying lines A and B
    ' in either one of the following two ways:
    '
    ' 1. Remove either line A or line B (corrects the problem in the
         remaining line B or A).
    ' 2. Reverse the order of lines A and B (corrects the problem in
    '    line A but moves the problem to line B).

    ' To completely solve the problem, you must use temporary
    ' (intermediate) variables (X1& and X2&) as shown in the following
    ' comments:
    '
    '  WORKAROUND: Add the next 4 lines, and remove lines A and B:
    '    X1& = X&(j%, 1 - j%)    ' Assign to temporary variable X1&.
    '    X2& = X&(j%, 2 - j%)    ' Assign to temporary variable X2&.
    '    Fail& = X1& + X2&       ' Use the temporary variables.
    '    Work& = X2& + X1&       ' Use the temporary variables.

 ' The heart of the problem lies in the following lines, marked A and B:
    Fail& = X&(j%, 1 - j%) + X&(j%, 2 - j%)   ' Consider this as line A
    Work& = X&(j%, 2 - j%) + X&(j%, 1 - j%)   ' Consider this as line B
    PRINT "Fail=", Fail&, "Work=", Work&      'Should print two 0's, but
                                              'Fail& gives garbage.
 NEXT j%


 858. Open and Save in QB/QBX Editor Treat Filenames as Directories

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900227-113 B_BasicCom
 Last Modified: 26-MAR-1990    ArticleIdent: Q59722

 When opening or saving a file in the QuickBASIC (QB) or QuickBASIC
 Extended (QBX) editor, the name of the file can be entered in an edit
 field titled "File Name :". If the filename is entered without an
 extension, the editor assumes that the extension is ".BAS". However,
 if the name entered is also the name of a subdirectory within the
 current directory, the editor (depending on the version) may change to
 that directory and no file will be opened or saved. In such a
 situation, you must enter the extension to tell the editor you are
 referring to the file, not the directory.

 This information applies to QB.EXE in Microsoft QuickBASIC Versions
 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS and to QBX.EXE in
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS.

 What the QB.EXE or QBX.EXE editor will do in the above situation
 depends on which version you use.

 The following table describes the behavior of different versions of
 the QB.EXE and QBX.EXE editors in this situation. There is also a
 difference that depends on whether a file is being opened (or loaded)
 or saved. In the table below, the "Open" column lists the behavior of
 the editor when a file is being opened, while the "Save" column lists
 the editor's behavior when a file is being saved.

    Editor     Open                       Save
    ------     ----                       ----

    QB 2.00    Treats the name entered    "Invalid file specification"
    QB 2.01    as a directory and         error, then it changes to that
    QB 3.00    changes to it.             directory.

               Treats the name entered    Treats the name entered as a
    QB 4.00    as a directory and         file.
    QB 4.00b   changes to it.

               Treats the name entered    Treats the name entered as a
    QB 4.50    as a directory and         directory and changes to it.
               changes to it.

               Treats the name entered    Treats the name entered as a
    QBX 7.00   as a directory and         directory and changes to it.
               changes to it.


 859. INTERRUPT for Clock Tick Counter Returns Negative Value

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900222-218 B_BasicCom
 Last Modified: 26-MAR-1990    ArticleIdent: Q59725

 Interrupt 1A Hex, with Function 0, returns the current value of the
 clock tick counter in registers CX and DX. When the low-order portion
 of the clock tick counter (returned in DX) exceeds 32,767, it becomes
 negative when stored as an integer in BASIC, because 32,767 is the
 maximum value for a 2-byte signed integer. Below is an example to
 convert the negative value to the equivalent unsigned long integer
 value.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) Version 7.00 for
 MS-DOS.

 For a more complete description of converting negative signed integers
 to unsigned integers, query on the following words:

    CALL and INTERRUPT and negative and signed and integer

 The following QuickBASIC program outputs only positive values by
 removing the sign bit and adding the remaining number plus 1 to
 32,767:

 ' $INCLUDE: 'qb.bi'
 REM  In BASIC 7.00, use $INCLUDE: 'qbx.bi' instead of 'qb.bi'.
 REM  To use CALL INTERRUPT in this program, you must do the following:
 REM  If you run this program in QB.EXE, use QB /L QB.QLB.
 REM  If you run this program in QBX.EXE, use QBX /L QBX.QLB.
 REM  LINK with QB.LIB (or QBX.LIB for BASIC 7.00).

 DIM inregs AS regtype, outregs AS regtype
 LOCATE 23, 1: PRINT "Push any key to end program."
 DO
 inregs.ax = 0
 CALL interrupt(&H1A, inregs, outregs)
 high& = outregs.cx
 low& = outregs.dx
 IF low& < 0 THEN              'if the low-order portion is negative:
   low& = low& AND &H7FFF      'remove sign bit
   low& = low& + &H7FFF + 1    'add remaining number plus 1 to 32,767
 END IF
 LOCATE 24, 1: PRINT high&; ":"; low&; "   ";
 LOOP UNTIL INKEY$ <> ""
 END


 860. Legal Data Delimiters When Using INPUT #n Statement

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900312-105 B_BasicCom docerr
 Last Modified: 10-AUG-1990    ArticleIdent: Q59727

 This article corrects several documentation errors concerning how to
 delimit data in a sequential file that is to be read by the INPUT#
 statement.

 The INPUT# statement reads data items from a sequential device or file
 and assigns them to variables. If the data items in the file are
 numeric values, they should be separated with a space, carriage return
 (CR), or comma. Strings should be separated with a carriage return or
 a comma, or enclosed in double quotation marks. A linefeed (LF) by
 itself should not be used as a file delimiter in either case.

 The following references incorrectly state that a linefeed may be used
 as a delimiter between data items in a file. These references also
 omit the fact that string data may be delimited by a comma.

 1. Page 304 of the "Microsoft QuickBASIC Compiler" manual for versions
    2.00, 2.01, and 3.00

 2. Page 225 of the "Microsoft QuickBASIC 4.0: BASIC Language
    Reference" manual for QuickBASIC versions 4.00 and 4.00b

 3. Page 225 of the "Microsoft BASIC Compiler 6.0: BASIC Language
    Reference" manual for versions 6.00 and 6.00b

 4. Page 167 of the "Microsoft BASIC 7.0: Language Reference" manual
    for Microsoft BASIC Professional Development System (PDS)
    versions 7.00 and 7.10

 5. Under the INPUT# statement in the QB Advisor online Help system
    for QuickBASIC version 4.50

 In addition, all the above references (except #4) incorrectly state
 that string data items may be delimited with spaces. Only numeric data
 items may be delimited with spaces. String data items must be
 delimited by a comma or a carriage return, or enclosed in double
 quotation marks.

 If you need some other character, such as a linefeed by itself, to act
 as a delimiter, then a file may be read in BINARY mode. When a file is
 opened in BINARY mode, the data is not interpreted and the program
 must be written to interpret or "filter" each character as needed.

 The following is a description of how the INPUT# statement handles a
 linefeed, carriage return, space, and comma if one of these characters
 is used as a delimiter between data items. Also, the program below
 exhibits the behavior of these characters when used as delimiters.

 Numeric Input Syntax: INPUT #n, <numeric variable>
 --------------------------------------------------

 This reads a linefeed in as a numeric value instead of a delimiter.
 Each time a linefeed is encountered, the linefeed character is treated
 as a data item and a value of 0 is returned for the input.

 A carriage return, space, or comma functions correctly as a delimiter
 for numeric input.

 String Input Syntax:  INPUT #n, <string variable>
 -------------------------------------------------

 This ignores the linefeed character completely. If two data items are
 separated by a linefeed and read in as strings, the two data items are
 read in as one string that is a concatenation of the two data items.

 A space between two data items causes the two data items to be read in
 as one string, and the space is an actual character in that string.

 A carriage return or comma functions correctly as a delimiter. If a
 comma appears between a pair of double quotation marks, the comma is
 treated as part of the string. A carriage return always acts as a
 delimiter, terminating any string delimited by a beginning double
 quotation mark.

 Sample Code
 -----------

 CLS
 INPUT "Enter 'q' to quit.  Enter 'c' to continue==> ", start$

 WHILE start$ <> "q"
  CLS

  OPEN "numeric.dat" FOR OUTPUT AS #1
  OPEN "string.dat" FOR OUTPUT AS #2

  PRINT "Input the ASCII code for the delimiter you wish to attempt:"
  PRINT "   10 = line feed"
  PRINT "   13 = carriage return"
  PRINT "   32 = space"
  INPUT "   44 = comma =============>", delimit%

  num1% = 5: num2% = 10        'define data to be put in numeric file
  str1$ = "hi": str2$ = "mom"  'define data to be put in string file

  PRINT #1, num1%; CHR$(delimit%); num2%  'write data separated by
  PRINT #2, str1$; CHR$(delimit%); str2$  'chosen delimiter to file

  CLOSE

  OPEN "numeric.dat" FOR INPUT AS #1
  OPEN "string.dat" FOR INPUT AS #2

  PRINT
  count% = 0
  PRINT "This file contains the numeric values 5 and 10."
  PRINT "==============================================="
  DO UNTIL EOF(1)
      count% = count% + 1
      INPUT #1, inp1%
      PRINT "Value read in after"; count%; "input(s):"; inp1%
  LOOP

  PRINT
  count% = 0
  PRINT "This file contains the string values 'hi' and 'mom'."
  PRINT "===================================================="
  DO UNTIL EOF(2)
      count% = count% + 1
      INPUT #2, inp2$
      PRINT "Value read in after"; count%; "input(s): "; inp2$
  LOOP

  CLOSE

  PRINT : PRINT
  INPUT "Press 'q' to quit.  Press 'c' to continue==> ", start$
 WEND
 END


 861. QB 4.50 Learning to Use Correction; MBF Used Prior to QB 4.00

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900304-1 docerr
 Last Modified: 26-MAR-1990    ArticleIdent: Q59728

 This article corrects a documentation error on Page 285 of the
 "Microsoft QuickBASIC 4.5: Learning to Use" manual for Version 4.50.

 The following statement in the middle of Page 285 is incorrect:

    Microsoft Binary Format is used by versions of QuickBASIC prior
    to Version 3.0.

 Microsoft Binary Format (MBF) is actually used by versions of
 QuickBASIC prior to 4.00, except for QB87.EXE in QuickBASIC Version
 3.00, which uses IEEE floating-point format. QB.EXE in QuickBASIC 3.00
 uses MBF.


 862. QB 4.5 Learning to Use Correction; Preserving COMMON in CHAIN

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900304-1 docerr
 Last Modified: 26-MAR-1990    ArticleIdent: Q59729

 This article corrects a documentation error on Page 237 of the
 "Microsoft QuickBASIC 4.5: Learning to Use" manual for Version 4.50.

 The following statement on Page 237 near the middle of the page is
 incorrect:

    Also, files created with the EXE requiring BRUN45.EXE option do
    not preserve open files or variables listed in COMMON statements
    when a CHAIN statement transfers control to another program.

 This statement should be changed to the following:

    Also, files compiled with /O, which uses the BCOM45.LIB library
    to create a stand-alone .EXE application, do not preserve open
    files or variables listed in COMMON statements when a CHAIN
    statement transfers control to another program.


 863. Single-Line IF...THEN Label, "Syntax Error"; Requires GOTO

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900313-116 B_BasicCom B_MQuickB
 Last Modified: 26-MAR-1990    ArticleIdent: Q59758

 A single-line IF statement of the form IF <cond> THEN <label> causes a
 "Syntax Error." In a single-line IF statement, you must use the GOTO
 statement to branch to a line label. This is different from the
 branching rule for line numbers, where the GOTO is optional.

 This information applies to Microsoft QuickBASIC Versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS and OS/2, and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2.

 The following is the single-line IF statement syntax. (It is taken
 from the QuickBASIC 4.50 QB Advisor online Help system):

       IF booleanexpression THEN thenpart [ELSE elsepart]

    The thenpart and the elsepart both have the following syntax:

       {statements | [GOTO]linenumber | GOTO linelabel }

    The following list describes the parts of the thenpart and
    elsepart syntax:

       Part         Description
       ----         -----------

       statements   One or more BASIC statements, separated by colons

       linenumber   A valid BASIC program line number

       linelabel    A valid BASIC line label

    Note that GOTO is optional with a line number but is required
    with a line label.

 A Related Issue in QuickBASIC for the Apple Macintosh
 -----------------------------------------------------

 Note that QuickBASIC for the Apple Macintosh does not require the GOTO
 for a label in an IF statement. This prevents making an implicit CALL,
 as in the IF...THEN subname statement. For more information, query on
 the following words:

    Macintosh and QuickBASIC and GOTO and implicit and subprogram
              and explicit

 Code Example
 ------------

 The following code example causes a syntax error on the IF statement:

    IF 1 = 1 THEN Label      'Should be: IF 1 = 1 THEN GOTO Label
    Label: PRINT "Made it!"


 864. "Permission Denied" with > 20 LOCKs with SHARE Loaded

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900221-77 B_GWBasicI B_BasicCom
 Last Modified: 26-MAR-1990    ArticleIdent: Q59761

 With the DOS SHARE utility loaded, the error message, "Permission
 Denied" occurs when a program attempts to LOCK more than the available
 number of LOCKs. The number of LOCKs is specified with the /L:n option
 for the SHARE command. The default number of LOCKs is 20.

 This information applies to Microsoft GW-BASIC Versions 3.23, 3.22,
 and 3.20, to Microsoft QuickBASIC Versions 4.00, 4.00b, and 4.50, to
 Microsoft BASIC Compiler Versions 6.00 and 6.00b, and to Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS-DOS.

 Without SHARE loaded, GW-BASIC gives "Permission Denied" on the first
 LOCK statement. With QuickBASIC and the BASIC compilers (listed
 above), 3120 LOCKs can be performed without SHARE loaded before the
 "Permission Denied" error occurs.

 For more information about the SHARE statement, please see the MS-DOS
 reference manual.

 Code Example
 ------------

 The following code example tests the number of LOCKs available on a
 system:

    10  ON ERROR GOTO 100
    20  REM Note: File does not need to exist before run to LOCK records.
    30  OPEN "xxxx.xxx" FOR RANDOM AS #1
    40  FOR i%=1 TO 32767
    50    LOCK #1,i%
    60  NEXT
    70  PRINT "More than 32767 LOCKs available!"
    80  END
    100 PRINT "Permission Denied (";ERR;")"
    110 PRINT "Number of locks = ";i%-1
    120 END


 865. QB 4.00 "String Space Corrupt" F8/F10 Step on CALL Breakpoint

 Product Version(s): 4.00 4.00b
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890919-123 buglist4.00 buglist4.00b fixlist4.50 B_Basic
 Last Modified: 26-MAR-1990    ArticleIdent: Q59762

 A "String Space Corrupt" error occurs in QuickBASIC Versions 4.00 and
 4.00b when the code sample listed below is run using the steps
 described below. The general background on the problem is as follows.
 If a program is STOPped during the execution of a procedure, a
 breakpoint is set on a subsequent CALL to the same procedure that is
 currently executing, and execution of the program is continued, then a
 "String space corrupt" error occurs. However, this problem occurs only
 under very specific conditions which are described in comments in the
 code below.

 Microsoft has confirmed this to be a problem in QB.EXE in Microsoft
 QuickBASIC Versions 4.00 and 4.00b and Microsoft BASIC Compiler
 Versions 6.00 and 6.00b for MS-DOS (buglist6.00, buglist6.00b). This
 problem was corrected in QB.EXE in Microsoft QuickBASIC Version 4.50
 and QBX.EXE in Microsoft BASIC Professional Development System (PDS)
 Version 7.00 (fixlist7.00).

 Use the following steps to produce a "String Space Corrupt" error in
 QuickBASIC 4.00 and 4.00b with the code listed below:

 1. Press SHIFT+F5 to run the program.

    The program stops on the STOP statement in ASub.

 2. Set a breakpoint (press F9) on the second CALL statement in the
    module-level code.

 3. Press F5 to continue.

    The program breaks on the second CALL.

 4. Press F8 or F10 to step and produce the "String Space Corrupt"
    error.

 Code Example
 ------------

 The following code example causes a "String Space Corrupt" error in
 QB.EXE in QuickBASIC 4.00 and 4.00b and exits back to DOS when the
 above steps are followed:

 'NOTE: Parameter must be a nonzero length literal string.
 '      If you use a variable, the problem will not occur.
 CALL ASub("X")

 'NOTE: The parameter can be any length or can be a variable.
 'Set breakpoint (F9) & Press F8 or F10 to cause "String Space Corrupt"
 CALL ASub("")
 END

 SUB ASub (s$)
 'Now, go back and set a breakpoint on second CALL at module-level code
 '(press F2 followed by RETURN). After setting the breakpoint, continue
 'executing (press F5).
 STOP
 END SUB


 866. 9th Pixel of 9x16 VGA Fonts Mimics 8th Pixel for ASCII 192-223

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900206-119 B_BasicCom
 Last Modified: 26-MAR-1990    ArticleIdent: Q59953

 The width of CGA, EGA, MCGA, and VGA text characters is 8 pixels. In
 the case of VGA however, 9 pixels are actually used for displaying the
 characters. The 9th pixel is appended to the right end of each pixel
 row. If the character being displayed has an ASCII code ranging from
 192 to 223 and the 8th pixel in a given pixel row is on, the 9th pixel
 in that row will be on also. If the 8th pixel in the row is off or the
 ASCII code for the character is not in the range 192 to 223, the 9th
 pixel will not be turned on.

 This hardware information may be of interest to users of Microsoft
 QuickBASIC Versions 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft BASIC
 Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and Microsoft
 BASIC Professional Development System (PDS) Version 7.00 for MS-DOS
 and MS OS/2.

 The following diagram shows the pixel make-up of a sample VGA
 character and how it would be displayed on the screen if it had an
 ASCII code within the range 192 to 223, and if its ASCII code was also
 outside that range:

    * = lit pixel
    O = unlit pixel

    Pixel make-up        ASCII 192             ASCII 255
    -------------        ---------             ---------

    OO****OO             OO****OOO             OO****OOO
    O******O             O******OO             O******OO
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    ********             *********             ********O
    O******O             O******OO             O******OO
    OO****OO             OO****OOO             OO****OOO

 Note how the 9th pixel mimics the status of the 8th pixel preceding it
 when the ASCII code is 192. When the ASCII code is 255 (outside the
 range 192 to 223), the 9th pixel is always off, regardless of the
 status of the 8th pixel. This behavior is limited to VGA text mode and
 is not found in CGA, EGA, or MCGA.


 867. Description of How LOCATE Can Change the Cursor Size

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S890714-76 B_BasicCom
 Last Modified:  3-APR-1990    ArticleIdent: Q60133

 The LOCATE statement provides the ability to change the cursor size in
 text mode (SCREEN 0). The number of scan lines varies depending on the
 video system and the operating system.

 This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b
 and 4.50 for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b
 for MS-DOS and OS/2, and Microsoft BASIC Professional Development
 System (PDS) Version 7.00 for MS-DOS and OS/2.

 The following table shows the valid settings for most video systems:

    Video System | Op Sys | Scan lines
    -------------+--------+-----------
    Hercules     |  DOS   |    12
    CGA/EGA/VGA  |  DOS   |     8
    Any          |  OS/2  |    16

 The cursor is a text mode feature and is not available for use with
 the LOCATE statement in graphics modes. INPUT is the only statement
 that automatically uses a cursor in graphics modes.

 The following information, taken from the QBX.EXE online help from
 BASIC PDS 7.00, is the description of the usage of the start and stop
 lines in the LOCATE statement:

 The start and stop lines are the CRT scan lines that specify the
 following:

 1. Which pixels on the screen are lit.

    A wider range between the start and stop lines produces a taller
    cursor, such as one that occupies an entire character block.

    In OS/2 real mode and under DOS, LOCATE assumes there are eight
    lines (numbered 0 to 7) in the cursor. In OS/2 protected mode, there
    are 16 lines (numbered 0 to 15).

 2. When start% is greater than stop%, LOCATE produces a two-part
    cursor.

    If the start line is given, but the stop line is omitted, stop%
    assumes the same value as start%.

    A value of 8 for both start% and stop% produces the underline
    cursor.

    The maximum cursor size is determined by the character block size
    of the screen mode in use.

    Setting start% greater than stop% displays a full-height cursor on
    VGA-equipped systems.

 Code Example
 ------------

 The following code example prompts you for start and stop scan lines
 and displays the cursor:

 SCREEN 0
 CLS
 LOCATE 8, 10

 DO
   INPUT "Start line: ",StartLine%
   IF StartLine% = -1 THEN END       'Enter -1 to end
   LOCATE 9, 10
   INPUT "Stop  line: ",StopLine%
   CLS
   LOCATE 10, 10, 1, StartLine%, StopLine%
 LOOP


 868. Location of Keyboard Buffer Area in MS-DOS; BASIC PEEK, POKE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900326-109 b_basiccom pss
 Last Modified: 12-NOV-1990    ArticleIdent: Q60140

 The actual location of the keyboard buffer on the IBM PC or PS/2 is
 variable, but by default, the buffer is a 32-byte area located at
 segment 0, offset 1054 (41E hex). Because many applications assume
 that this is the default location, please be careful if you change its
 address or size.

 The buffer is composed of 16 2-byte entries. It holds up to 16
 keystrokes until they are read via the BIOS services through interrupt
 22 (16 hex). Because this is a circular queue buffer, two pointers
 indicate the head and tail of the queue. It is usually best to
 manipulate the pointers rather than the actual data.

 This information is taken from "The New Peter Norton Programmer's
 Guide To The IBM PC and PS/2" on pages 56-60, published by Microsoft
 Press (1988).

 There are other adjacent memory locations that are used in conjunction
 with the keyboard buffer. The most important of these are listed
 below. All of these addresses are in segment 0.

 Offset 1050 (41A hex)
 ---------------------

 A 2-byte address that points to the current head of the BIOS keyboard
 buffer at offset 1054.

 Offset 1052 (41C hex)
 ---------------------

 A 2-byte address that points to the current tail of the BIOS keyboard
 buffer at offset 1054.

 Note: One interesting way to clear the keyboard buffer is to set the
 head of the queue equal to the tail. To do this in BASIC, simply PEEK
 the two bytes at 1052 and POKE them into location 1050.

 Offset 1152 (480 hex)
 ---------------------

 A 2-byte word pointing to the start of the keyboard buffer area.

 Offset 1154 (482 hex)
 ---------------------

 A 2-byte word pointing to the end of the keyboard buffer area.

 Note: Be careful if you choose to change the addresses at 1152 or 1154
 because many applications may not check these memory locations to
 determine the keyboard buffer area. These applications will assume the
 default configuration.

 References:

 For more articles about reading from and writing to the keyboard
 buffer, search in this Knowledge Base for the following words:

    interrupt AND keyboard AND buffer

 Keyboard scan codes are documented in Appendix D of "Microsoft
 QuickBASIC 4.5: Programming in BASIC"; in Appendix A of "Microsoft
 QuickBASIC 4.0: Language Reference" for 4.00 and 4.00b; in Appendix A
 of "Microsoft BASIC Compiler 6.0: Language Reference" for 6.00 and
 6.00b; and in Appendix A of "Microsoft BASIC 7.0: Language Reference"
 manual for BASIC PDS versions 7.00 and 7.10.


 869. "The QuickBASIC Journal" Magazine Available for BASIC Users

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900402-110
 Last Modified: 11-APR-1990    ArticleIdent: Q60424

 A magazine titled "The QuickBASIC Journal" premiered in January 1990.
 This magazine is dedicated to providing information relating to
 Microsoft QuickBASIC Compiler for MS-DOS and to Microsoft BASIC
 Professional Development System (PDS) Version 7.00 for MS-DOS and MS
 OS/2. The topics discussed vary; the magazine includes tutorials for
 beginners, advanced programming tips, reports on BASIC's future
 development, and advertisements for third-party add-on products. Some
 of the programming articles contain code listings that can be
 downloaded via the Syslink Bulletin Board System at (401) 272-1138.
 The magazine's circulation is quarterly and the cost is $19.95. To
 order, contact:

    Northeast Publishing
    126 Wellington Avenue
    Warwick, RI  02886
    (401) 274-5492


 870. NO87 Environment Variable Echoed to Screen When Run

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900406-108 B_BasicCom
 Last Modified: 14-MAY-1990    ArticleIdent: Q60964

 The QB.EXE and QBX.EXE environments echo to the screen the string
 stored in the environment variable NO87. This is to notify you
 whether or not the math coprocessor (if one exists) will be used by
 these environments in floating-point calculations. NO87 must be set to
 null if the coprocessor is to be used; any other string value turns it
 off. To set the NO87 environment variable, execute the following
 statement from the DOS command line:

    SET NO87=[string-expression]

 Note: <string-expression> would be entered only if the coprocessor
 were not to be used.

 This information applies to Microsoft QuickBASIC Compiler versions
 4.00, 4.00b, 4.50 for MS-DOS, and to Microsoft BASIC Professional
 Development System (PDS) version 7.00 for MS-DOS. Furthermore, EXE
 files compiled in all Microsoft languages that use an IEEE emulation
 math package (BASIC, C, Pascal, FORTRAN) will exhibit the same
 behavior when run.

 For example, enter the following at the DOS command line:

    SET NO87=OFF

 Then run QB (or QBX). The word "OFF" will be displayed on the next
 line.


 871. QB.EXE and QBX.EXE Erase Line If You Type STRIG ON

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom SR# S900410-80
 Last Modified: 30-MAY-1990    ArticleIdent: Q60966

 If the following code example is typed into the Microsoft QuickBASIC
 (QB.EXE) or QuickBASIC extended (QBX.EXE) editors, the line "STRIG ON"
 will disappear when you either move the cursor off that line, press
 RETURN, or try to run the program.

 This is not considered a problem with QB.EXE or QBX.EXE. Page 411 of
 the "Microsoft QuickBASIC 4.0: BASIC Language Reference," Page 411 of
 the "Microsoft BASIC Compiler 6.0: BASIC Language Reference," and Page
 361 of the "Microsoft BASIC 7.0: Language Reference" state that the
 STRIG ON and STRIG OFF statements are ignored. These statements are
 provided for compatibility with earlier versions of BASIC.

 Code Example
 ------------

    PRINT "Before Line"
    STRIG ON                 'This line will disappear if entered
                             'in CAPS or not
    PRINT "After Line"

 Output
 ------

    Before Line
    After Line


 872. Dynamic Arrays, Far Strings Overwrite COMMAND.COM

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900228-4 B_BasicCom
 Last Modified: 14-MAY-1990    ArticleIdent: Q60967

 If the far heap is used for any reason during the execution of a BASIC
 program, the transient part of COMMAND.COM may have to be reloaded
 after its execution. COMMAND.COM occupies an area of the far heap that
 some features of Microsoft's BASIC compilers use. If COMMAND.COM does
 need to be reloaded and cannot be found in the current path, the
 system prompts you to insert a disk containing it.

 This information applies to Microsoft QuickBASIC Compiler versions
 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler versions 6.00 and
 6.00b, and to Microsoft BASIC Professional Development System (PDS)
 version 7.00.

 Page 14 of "Advanced MS-DOS Programming, Second Edition" by Ray Duncan
 (Microsoft Press, 1988) explains this behavior of COMMAND.COM, which
 applies not only to BASIC, but all applications:

    When an application program terminates, the resident portion of
    COMMAND.COM does a checksum of the transient module to determine
    whether it has been destroyed and fetches a fresh copy from the
    disk if necessary.

 Many features of Microsoft's BASIC compilers require use of the far
 heap, and thus are common destroyers of COMMAND.COM. The most common
 is when an executable file uses a run-time module, BRUN45.EXE for
 example. Another is the use of dynamic arrays, which are stored in the
 far heap, although using small enough arrays will not overwrite
 COMMAND.COM. In BASIC PDS 7.00, the far strings option (/Fs) also uses
 the far heap, even if no strings are used in the program.

 Consider this sample program:

    'NOCODE.BAS
    'This program contains no code

 If NOCODE.BAS is compiled without the /o switch (specifying use of the
 run-time library) or compiled with the /Fs switch under BASIC PDS
 7.00, COMMAND.COM has to be reloaded after execution, even though no
 code or data is actually present.

 Consider another example:

    'HUGEARAY.BAS
    REM $DYNAMIC
    DIM Array(1 TO 200, 1 TO 200) AS INTEGER

 Since HUGEARAY.BAS dimensions a huge, dynamic array, it  overwrites
 COMMAND.COM. If the array were much smaller, COMMAND.COM would remain
 intact. Note that even larger dynamic arrays that aren't huge (over
 64K) can cause COMMAND.COM to be overwritten.


 873. Storage Format for MKI$, MKL$, MKS$, MKD$ Same as Variable

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900403-6 B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q61332

 The MKS$, MKI$, MKL$, and MKD$ functions are used in Microsoft
 QuickBASIC to convert numeric data to strings for use in random access
 files. The actual conversion of the numbers to strings is just a
 transfer of the binary representation of the number. If you look at a
 binary representation of both a numeric variable and the string
 equivalent made with the MKS$, MKI$, MKL$, or MKD$ function, you will
 see that they are exactly the same (with the exception of MKS$ and
 MKD$ when compiling with the /MBF option).

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10. Note that BASIC PDS also provides MKC$, for the CURRENCY
 data type.

 The binary numeric format stored in numeric variables versus MKS$ or
 MKD$ strings differs if you invoke the QuickBASIC environment (QB.EXE
 or QBX.EXE) or the BC.EXE compiler with the /MBF option (which makes
 MKS$ and MKD$ behave just like the MKSMBF$ and MKDMBF$ functions). The
 /MBF (Microsoft Binary Format) option makes MKS$ and MKD$ return MBF
 strings instead of IEEE format strings.

 Code Sample
 -----------

 Both the integer and the string equivalent in the following program
 are stored in 2 bytes in memory. This program prints out the numeric
 value of the binary content of the locations that A% and A$ are kept
 in. As the output of this program demonstrates, the binary
 representation of the two values is the same.

 This program prints a series of numbers both as decimal numbers and as
 their MKI$ equivalent. Then it prints out the information stored in
 the 2-byte locations in memory for both the numeric and string data.
 When you run the program, note the difference in the binary storage of
 the numbers when the value increments from 255 to 256 (requiring a bit
 in the higher byte).

 CLS
 FOR a% = 252 TO 259
   a$ = MKI$(a%)
   PRINT "Number:"; a%, "String: "; a$
   aseg = VARSEG(a%)
   aptr = VARPTR(a%)
   asseg = VARSEG(a$)
   asptr = SADD(a$)
   DEF SEG = aseg
   aval1 = PEEK(aptr): aval2 = PEEK(aptr + 1)
   DEF SEG = asseg
   asval1 = PEEK(asptr): asval2 = PEEK(asptr + 1)
   PRINT aval1, aval2, , asval1, asval2
 NEXT a%


 874. Explanation of Compiler Workspace and What Affects It

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900415-7 B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q61336

 The information below shows what items affect compiler workspace, and
 some practices that can be used when compiler workspace must be
 increased.

 The compiler workspace is displayed by the "Bytes Available" and
 "Bytes Free" lines given at the end of compilation. For more
 information on these lines, query on the following words:

    BASIC and bytes available and free and symbol table and workspace

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The compiler workspace is made up of the line-number table, symbol
 table, and working storage for compiler code generation and
 optimization. Because of this, the compiler workspace is affected by
 such things as the length of variable, procedure, and line label
 names, and the number of lines in the program. The following
 paragraphs detail some of the things that affect the compiler
 workspace:

    Variable SUB,    Because variables go into the symbol table, they
    and FUNCTION     have a direct effect on compiler workspace.
    names
                     Each new variable has some initial overhead plus
                     additional overhead for each character in the
                     variable name. Once a variable is defined, it
                     has no extra effect on the compiler workspace no
                     matter how many times it is used again.

    Line numbers     Every line number decreases the compiler
                     workspace. Unlike variable and procedure names,
                     however, it does not matter how big a line
                     number is. The line number 10 takes just as
                     much compiler workspace as does the line number
                     10,000.

    Program lines    Each line in the program takes up some compiler
                     workspace. Two PRINT statements put on the same
                     line, such as

                        PRINT : PRINT

                     take up less compiler workspace than when the
                     statements are put on two separate lines, as in:

                        PRINT
                        PRINT

                     Extra blank lines between code have no effect on
                     compiler workspace. Therefore, the following
                     three lines of code take just as much compiler
                     workspace as do the previous two lines of code:

                        PRINT

                        PRINT

 If a program is running out of compiler workspace (bytes available
 goes to zero), you can try each of the following to increase the
 workspace:

 1. Break the code into multiple modules. This is the best solution
    from a structured programming point of view. Each module has the
    full compiler workspace available to it, and because code is taken
    out of the original program, compiler workspace will be used
    regained.

 2. Put multiple statements on each line. Although not recommended for
    structured programming, moving multiple source lines onto a single
    line separated by a colon (:) will decrease the amount of compiler
    workspace being used.

 3. Decrease the size of SUB, FUNCTION, and variable names. This will
    make the code less readable, but again can be used when compiler
    workspace is at a premium.


 875. Watchpoints Set at Module Level Won't Break in a SUBprogram

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900415-5 B_BasicCom
 Last Modified:  2-MAY-1990    ArticleIdent: Q61340

 Watchpoints put on variables (which are set in QuickBASIC's Debug
 menu) have a local scope. That is, you must reset the watchpoint on a
 variable in each SUBprogram or FUNCTION, even if the variable is in a
 SHARED or COMMON SHARED statement. This is by design.

 If you add a watchpoint in the module-level code of a shared variable,
 and a SUBprogram or FUNCTION changes the variable so the watchpoint
 should break, the program will not break until the SUBprogram or
 FUNCTION returns to the module-level code.

 This information applies to the QB.EXE environment in QuickBASIC
 versions 4.00, 4.00b, and 4.50, and to the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) version 7.00.

 The following program, when run in the QuickBASIC or QuickBASIC
 Extended environment, demonstrates that watchpoints are local:

    DECLARE SUB test ()
    COMMON SHARED a
    a = 0
    CALL test
    PRINT "After call"
    END

    SUB test
       a = 3
       PRINT "in sub - does not break"
    END SUB

 To demonstrate this, set a watchpoint on "a<>0" (to break when the
 variable "a" changes from being zero). When the program is run, the
 watchpoint will not activate until control is returned to the
 module-level code. The program will break on the line "PRINT 'After
 call'," even though the value of variable "a," was changed in the
 SUBprogram.


 876. Why a Program Might Hang with BLOAD/BSAVE

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900305-58 B_BasicCom
 Last Modified:  2-MAY-1990    ArticleIdent: Q61344

 There are two reasons a program might hang when using the BLOAD
 statement in Microsoft QuickBASIC. First, it is possible to hang your
 computer by BLOADing to the incorrect area in memory. Second, if the
 array you are BLOADing into is not large enough, the computer might
 hang or data and code might become corrupt.

 This information applies to Microsoft QuickBASIC versions 3.00, 4.00,
 4.00b, and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b;
 and to Microsoft BASIC Professional Development System (PDS) version
 7.00.

 The most common programming error with BLOAD is to BLOAD into an array
 and only use the offset value [VARPTR()] of the array. If the array
 you BLOAD into is being stored as a far object and you only use the
 offset of the variable [VARPTR()], you will write over data in your
 DGROUP and possibly some of your code, and if you are using QB.EXE,
 you could write over the code for the editor. To avoid this problem,
 always use the VARSEG function to get the segment of the array and
 then invoke a DEF SEG beforehand to set the current segment to the one
 containing the array variable. This ensures that the data will go into
 the correct memory location, whether the array is being stored as a
 near or far object.

 The second programming error is to BLOAD into a data-item that is
 smaller than the one that was used to BSAVE the data. This is similar
 to the error above in that this might cause you to write over both
 code and data in memory.

 Both of these programming errors can cause a variety of problems, as
 follows:

 1. You might receive a "String space corrupt" error.

 2. You might receive a "Far heap corrupt" error.

 3. Data values might be corrupt or incorrect.

 4. The program could display totally erratic behavior because of
    corrupt code segments.

 5. The computer might hang.

 The following code examples demonstrate the correct and incorrect
 ways of executing a binary save.

 Code Examples
 -------------

 '***********************************************
 '*  This program creates the file to BLOAD     *
 '*                  MAKIT.BAS                  *
 '***********************************************

 REM $DYNAMIC
 DEFINT A-Z
 DIM buffer(16384)
 DEF SEG = VARSEG(buffer(0))
 BSAVE "test.bin", VARPTR(buffer(0)), 32768
 DEF SEG

 '***********************************************
 '*  Correct method for BLOAD:  CORRECT.BAS     *
 '***********************************************

 REM $DYNAMIC
 DEFINT A-Z
 DIM buffer(16384)
 ' For far data objects, you must first set the segment
 ' to the segment of that object.
 DEF SEG = VARSEG(buffer(0))
 BLOAD "test.bin", VARPTR(buffer(0))
 ' The next line is necessary because you MUST
 ' reset the segment back to the BASIC default segment.
 DEF SEG
 END

 '***********************************************
 '*  Incorrect method for BLOAD:  INCORRECT.BAS *
 '***********************************************
 ' WARNING!!!!!: This probably will hang the computer.
 ' This example is just for comparison with the one above.

 REM $DYNAMIC
 DEFINT A-Z
 DIM buffer(16384)
 BLOAD "test.bin", VARPTR(buffer(0))
 END


 877. XOR, OR, AND Convert Floating Point to Integer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900424-129 B_BasicCom
 Last Modified:  1-MAY-1990    ArticleIdent: Q61434

 The BASIC bitwise operators (AND, OR, XOR, and NOT) do not operate
 directly on floating-point numbers (SINGLE ! or DOUBLE #) or string
 variables ($). They also do not operate directly on currency data type
 numbers (@) in Microsoft BASIC Professional Development System (PDS)
 version 7.00. When a bitwise operation is attempted with a
 floating-point variable that has a value greater than the maximum LONG
 integer (2,147,483,647), an "Overflow" error occurs.

 To properly perform a bitwise operation on a floating-point variable,
 the floating-point number must be moved into a LONG using a bitwise
 move. Two functions are listed below to move between SINGLEs and LONGs
 so that bitwise operations can be used on SINGLE floating-point
 numbers.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, and Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and Microsoft BASIC PDS version 7.00 for MS-DOS
 and MS OS/2.

 When a bitwise operation is attempted on a floating point or currency
 numeric type, the fractional number is converted to its INTEGER or
 LONG equivalent and the operation is then performed using INTEGERs or
 LONGs. This can cause an "Overflow" error message if the value of the
 floating-point number exceeds the maximum value of a LONG integer.

 Another method of performing bitwise operations on a floating-point
 number is to convert the number to a LONG, manipulate the bits, and
 then convert it back to a floating-point number. The code example
 below demonstrates moving between SINGLEs and LONGs using the MKS$,
 MKL$, CVS, and CVL functions. Converting DOUBLEs is more involved
 because they are longer than any integer type. A similar operation
 could be performed to convert DOUBLEs using two LONGs and the MKD$ and
 CVD functions as well.

 Code Example
 ------------

 The following code example performs a bitwise move by using the MKS$,
 MKL$, CVS, and CVL functions using a string as an intermediary:

 'Module level demonstrates using functions
 s! = 1.0
 t! = 1.1
 l& = SingleToLong(s!)
 m& = SingleToLong(t!)
 n& = l& XOR m&                    'Bit AND (won't work with SINGLEs)
 PRINT HEX$(l&), HEX$(m&), HEX$(n&)'3F800000   3F8CCCCD   3F800000
 u! = LongToSingle(n&)             'Equivalent of bit AND of s! and
                                   't!
 PRINT u!                          '1.75495E-39
 END

 FUNCTION SingleToLong&(s!)
   SingleToLong& = CVL(MKS$(s!))
 END FUNCTION

 FUNCTION LongToSingle!(l&)
   LongToSingle! = CVS(MKL$(l&))
 END FUNCTION


 878. Problem of Testing Floating-Point Equality, IF n=VAL("n")

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900416-32 B_BasicCom
 Last Modified: 14-FEB-1991    ArticleIdent: Q61436

 A floating-point constant passed in a string to the VAL function can
 return a slightly different floating-point result compared to the same
 floating-point constant in an IF statement, resulting in an apparent
 inequality. This floating-point difference may seem like a software
 problem, but it is actually a design limitation. This behavior is
 demonstrated in the program below.

 To reliably test for floating-point equality (in any binary
 floating-point format, such as IEEE or Microsoft Binary Format), you
 must subtract the two floating-point numbers being compared and test
 whether their difference is less than a value at the limits of
 significance for single or double precision.

 The example below applies to Microsoft QuickBASIC versions 4.00,
 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 You might expect the conditions in the IF statements in the program
 below to both be true and PRINT their messages. Instead, only the
 second IF is true and PRINTs its message:

    a$ = "0.1"
    IF .1 <= VAL(a$) THEN PRINT "This is false, and does not print."
    s = VAL(a$)   ' This time use a temporary variable s.
    IF .1 <= s THEN PRINT "This is true and does print."

 There is an inequality in the first IF statement because the numeric
 constant .1 in the IF is assigned at compile time, whereas the VAL(A$)
 function is calculated at run time and different numeric storage is
 allocated internally so that a tiny difference exists between the
 numbers at the limits of single precision. In the second IF statement,
 the comparison of .1 and "s" is compiled differently than in the first
 IF, and the comparison luckily expected a "true" result. However, you
 should avoid both of the above numeric comparison techniques for
 testing the equality of floating-point numbers.

 Instead, to reliably test for floating-point equality (in any binary
 floating-point format), you must subtract the two floating-point
 numbers being compared and test whether their difference is less than
 a value that is about 7 significant digits smaller than the value
 being compared for single precision (in other words, divide by 10^7 to
 find the comparison value), or about 15 significant digits smaller
 than the value being compared for double precision (divide by 10^15).
 For example:

 A$ = ".1"
 IF .1 - VAL(A$) <= .1 / 10^7 THEN PRINT "Equal within single precision"

 B$ = ".1#"
 IF .1# - VAL(B$) <= .1# / 10^15 THEN PRINT "Equal within double precision"

 References:

 Note that many numbers in decimal (base 10) notation do not have an
 exact representation in the binary (base 2) floating-point storage
 format used in BASIC's SINGLE and DOUBLE precision data types. This
 often causes BASIC to return floating-point results different than you
 might expect, as explained in separate articles found with the
 following query:

    floating and point and format and QuickBASIC


 879. DIMension in a FOR-NEXT Loop Is Possible

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900412-54 B_BasicCom
 Last Modified: 10-MAY-1990    ArticleIdent: Q61440

 Microsoft QuickBASIC allows you to correctly DIMension a static array
 within a loop (FOR, WHILE, or DO). This is possible because a DIM of a
 static array happens as the program is being compiled (or during the
 binding phase in the interpreter). DIM on a static array is not an
 executable statement. Even though the DIM appears in a loop, it is not
 being executed over and over as the loop iterates. Each time the loop
 executes, the array is not being redimensioned. Therefore, any values
 inserted into the array are not lost.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) version 7.00.

 The situation is different for dynamic arrays. QuickBASIC will give
 you an error on a DIMension of a dynamic array in a loop. If an array
 needs to be redimensioned as a loop executes, the program should REDIM
 the array in the loop. REDIM is an executable statement, and
 therefore, will be executed over and over as the loop repeats. As the
 loop executes, REDIM will reallocate the memory for that array and
 erase its previous contents.

 The following code example demonstrates this feature of BASIC:

 c% = 100
 FOR i% = 1 TO 20
 '  DIM a%(c%)   ' will generate an error.
 '  REDIM a%(c%) ' will redim the array and erase its contents.
    DIM a%(20)
    a%(i%)=i%
    PRINT a%(i%)
 NEXT i%

 FOR j% = 1 TO 20
    PRINT a%(j%)
 NEXT j%


 880. Reference to Table 10.4 in "Programming in BASIC" Incorrect

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr SR# S900430-9
 Last Modified:  1-MAY-1990    ArticleIdent: Q61501

 On Page 118 of the "Microsoft QuickBASIC 4.5: Programming in BASIC"
 manual under Section 3.5, "Working with Devices," the third line
 refers to Table 10.4; this should be changed to Table 9.4.

 The incorrect line reads:

    Input from or output to these devices can be done with the
    statements and functions listed in Table 10.4.

 This should be changed to:

    Input from or output to these devices can be done with the
    statements and functions listed in Table 9.4.

 This information applies to Microsoft QuickBASIC version 4.50 for
 MS-DOS.


 881. Setting the Border Color in EGA and VGA with CALL INTERRUPT

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900325-26
 Last Modified:  8-MAY-1990    ArticleIdent: Q61657

 In EGA and VGA SCREEN modes, the color of the border cannot be set
 using the COLOR statement. However, the ROM BIOS interrupt 10 Hex,
 function 10 Hex, subfunction 01 can be used to control the color of
 the screen border.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS, and to Microsoft BASIC Professional Development System
 (PDS) version 7.00 for MS-DOS.

 The following program calls interrupt 10 Hex (16 decimal), with
 function 10 Hex and subfunction 1, to set the border color. The color
 value is put in register BH. To use this program, do the following:

 1. Invoke QuickBASIC by typing one of the following:

       QB /L QB.QLB       [for QuickBASIC 4.00, 4.00b, or 4.50 and
                          BASIC compiler 6.00 and 6.00b]
    or
       QBX /L QBX.QLB     [for BASIC PDS version 7.00]

    (The /L option above loads the QB.QLB or QBX.QLB Quick library,
    which contains the CALL INTERRUPT routine.)

 2. Use the QB.BI include file using the $INCLUDE metacommand. QB.BI
    contains the user-defined types RegTypeX and RegType. Refer to the
    QB.BI text file for more information. For QBX.EXE, this file is
    called QBX.BI.

 3. If you are compiling and linking outside the QB.EXE (or QBX.EXE)
    environment, QB.LIB must be linked in. For QBX.EXE, you must link
    in QBX.LIB.

 Code Example
 ------------

    REM $INCLUDE: 'qb.bi'
    DIM inregs AS RegType, outregs AS RegType
    SCREEN 12   ' Any EGA or VGA SCREEN mode can be used here
    inregs.ax = &H1001   ' Function 10 Hex and subfunction 1 are put in
                         ' AX
    inregs.bx = &H200    ' 2 representing green is put in BH
    CALL Interrupt(&H10, inregs, outregs)   ' A green border is produced


 882. "Illegal Function Call" with TAB & LOCATE in Compiled Program

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900417-103 B_BasicCom buglist4.50
 Last Modified: 11-MAY-1990    ArticleIdent: Q61673

 This article documents a special case where the TAB function placed
 between two LOCATE statements causes an "Illegal Function Call" in a
 subroutine. This problem occurs only in a compiled (.EXE) program
 using QuickBASIC version 4.50.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 version 4.50. This problem was corrected in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS
 (fixlist7.00).

 This problem does not occur in Microsoft QuickBASIC versions 4.00 or
 4.00b or in Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS.

 The problem does not occur if you do one or both of the following:

 1. Remove the TAB function from between the Locate statements. Instead
    of TAB, use a literal such as "     " with the appropriate number of
    spaces, or use the STRING$() function.

 2. Compile with /x.

 Code Example
 ------------

    ' Compile line: BC tab.bas;
    ' Link line:    LINK tab ;

    DECLARE SUB test (col)
    CALL test(20)

    SUB test (col)
        LOCATE col, 1
        PRINT TAB(2);
        LOCATE col, 1     'This line gives the "Illegal Function call"
    END SUB


 883. Expanded Memory Emulators Slow Down Floating-Point Operations

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900426-56 B_BasicCom S_C S_QuickC S_PasCal H_Fortran
 Last Modified: 11-MAY-1990    ArticleIdent: Q61676

 Floating-point mathematics in Microsoft languages may be slower when
 running with expanded memory emulators. This is a result of the
 expanded memory emulators redirecting interrupts used by the
 floating-point routines.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS, to Microsoft BASIC Professional Development System
 (PDS) version 7.00 for MS-DOS, to Microsoft QuickC versions 2.00 and
 2.01 for MS-DOS, to Microsoft C versions 5.00 and 5.10 for MS-DOS, to
 Microsoft C Professional Development System version 6.00 for MS-DOS,
 to Microsoft Pascal version 4.00, and to Microsoft FORTRAN versions
 4.00 and 4.10 for MS-DOS.

 Microsoft is researching this problem and will post new information
 here as it becomes available.

 Expanded memory managers on 80386/80486 systems generally run in a
 virtual 8086 mode that allows them to trap and handle memory access
 requests (this allows them to trap and handle all calls relating to
 expanded memory). When running in virtual 8086 mode, interrupts are
 trapped by the virtual machine manager.

 In the case of the interrupts used for floating-point emulation, the
 virtual machine manager does not handle them so it reflects the
 interrupts back to real mode where they are handled by the
 floating-point emulator.

 Instead of directly calling the floating-point routines, the processor
 must switch between protected and real modes as well as performing
 checks to see if it should handle the interrupt. This extra processing
 by the virtual machine manager is responsible for the reduced
 performance.


 884. Routine to Save and Restore a Block of Memory to a File

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900426-43 B_BasicCom
 Last Modified: 10-MAY-1990    ArticleIdent: Q61678

 The program shown below allows a block of memory to be saved and
 restored to any location in a file. This program uses DOS interrupts
 to save and restore an area of memory to/from a file.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) version 7.00 for
 MS-DOS.

 This routine can be used for several purposes:

 1. This routine can be used for saving and restoring an array quickly
    to a file. BASIC PDS 7.00 can do this by using STATIC arrays in a
    user-defined type, but earlier versions of BASIC don't have this
    ability.

       Note: Variable-length string arrays cannot use this method, as
       the string data is not contiguous in memory.

 2. This routine can be used in place of BLOAD and BSAVE to save and
    restore graphic screen images. The advantages of this routine are
    that in EGA and VGA screen modes, all of the screen planes can be
    stored to one file as opposed to four separate files.

 3. This routine can be used when debugging a program to dump an area
    of memory to a file for later viewing by a hex dump program.

 The program shown below, BUFTEST.BAS, must have the support routines
 for CALL INTERRUPT. To load the Quick library QB.QLB, start QuickBASIC
 with the following line:

    QB /l

 To load the Quick library QBX.QLB, start the QuickBASIC Extended
 (QBX.EXE) environment with the following line:

    QBX /l

 The following program is BUFTEST.BAS and demonstrates quickly saving
 and restoring an integer array to a file:

 DECLARE SUB ReadBuffer (FileName$, FileLocation&, NumBytes%,_
                         Segment%, Offset%)
 DECLARE SUB WriteBuffer (FileName$, FileLocation&, NumBytes%,_
                          Segment%, Offset%)
 ' Switch the following two lines for BASIC PDS 7.00
 ' REM $INCLUDE: 'qbx.bi'
 REM $INCLUDE: 'qb.bi'

 ' These two dimension lines need to be in the program for the
 ' Buffer subprograms. They must be dimensioned here because
 ' if they are dynamically created in the subprogram it could cause
 ' arrays and variables to move, thus invalidating the addresses
 ' passed to the subroutines.
 DIM SHARED InRegsx AS regtypex, OutRegsx AS regtypex
 DIM SHARED Filenum AS INTEGER, FileHandle AS INTEGER

 ' Dimension the test array to save and restore from the file
 DIM a(1 TO 100) AS INTEGER

 CLS

 ' Create and initialize an array
 FOR x% = 1 TO 10
    a(x%) = x%
 NEXT

 ' Write the array to the file
 CALL WriteBuffer("Test.DAT", 10, 20, VARSEG(a(1)), VARPTR(a(1)))

 ' Clear the array and display that it is zeroed
 ERASE a
 FOR x% = 1 TO 10
    PRINT a%(x%),
 NEXT

 ' Read the array back in and display that it has been restored
 CALL ReadBuffer("Test.DAT", 10, 20, VARSEG(a(1)), VARPTR(a(1)))
 FOR x% = 1 TO 10
    PRINT a%(x%),
 NEXT

 ' Read information from a file into a memory address
 ' The parameters are:
 '   FileName$     - Filename to write information to
 '   FileLocation& - Starting byte location in file
 '   NumBytes%     - Number of bytes to write (2 integers at 10 bytes
 '                   each)
 '   Segment%      - Segment address of memory location to save to
 '                   file
 '   Offset%       - Offset address of memory location to save to file
 SUB ReadBuffer (FileName$, FileLocation&, NumBytes%, Segment%,_
                 Offset%)
    Filenum = FREEFILE                            ' Get next file #
    OPEN FileName$ FOR BINARY AS #Filenum
    FileHandle = FILEATTR(Filenum, 2)             ' Get DOS file handle

    InRegsx.ax = &H4200                           ' Interrupt to SEEK
    InRegsx.bx = FileHandle                       '  to specified byte
    InRegsx.cx = PEEK(VARPTR(FileLocation&) + 2)  '  in file.
    InRegsx.dx = PEEK(VARPTR(FileLocation&))
    CALL Interruptx(&H21, InRegsx, OutRegsx)

    InRegsx.ax = &H3F00                           ' Read a block of
    InRegsx.bx = FileHandle                       '  data from the
    InRegsx.cx = NumBytes%                        '  file into memory.
    InRegsx.ds = Segment%
    InRegsx.dx = Offset%
    CALL Interruptx(&H21, InRegsx, OutRegsx)
    CLOSE #Filenum
 END SUB

 ' Write a block of memory to a file
 ' The parameters are:
 '   FileName$     - Filename to write information to
 '   FileLocation& - Starting byte location in file
 '   NumBytes%     - Number of bytes to write (2 integers at 10 bytes
 '                   each)
 '   Segment%      - Segment address of memory location to save to
 '                   file
 '   Offset%       - Offset address of memory location to save to file
 SUB WriteBuffer (FileName$, FileLocation&, NumBytes%, Segment%,_
                  Offset%)
    Filenum = FREEFILE                            ' Get next file #
    OPEN FileName$ FOR BINARY AS #Filenum
    FileHandle = FILEATTR(Filenum, 2)             ' Get DOS file handle

    InRegsx.ax = &H4200                           ' Interrupt to SEEK
    InRegsx.bx = FileHandle                       '  to specified byte
    InRegsx.cx = PEEK(VARPTR(FileLocation&) + 2)  '  in file.
    InRegsx.dx = PEEK(VARPTR(FileLocation&))
    CALL Interruptx(&H21, InRegsx, OutRegsx)

    InRegsx.ax = &H4000                           ' Write a block of
    InRegsx.bx = FileHandle                       ' memory to a file
    InRegsx.cx = NumBytes%
    InRegsx.ds = Segment%
    InRegsx.dx = Offset%
    CALL Interruptx(&H21, InRegsx, OutRegsx)
    CLOSE #Filenum
 END SUB


 885. Large COMMON in Multiple Modules Uses Up DGROUP in QB/QBX.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900504-81 B_BasicCom
 Last Modified: 19-NOV-1990    ArticleIdent: Q62054

 Using a large COMMON block with multiple modules requires much more
 static data memory (DGROUP) than a single-module program with a large
 COMMON. This article explains how the QuickBASIC environment handles
 COMMON blocks in a multiple-module program. The information below
 should be carefully considered for programs that are running out of
 room in DGROUP when running in the QB.EXE or QBX.EXE environments.
 Symptoms of this problem are error messages such as "Out of Data,"
 "Out of Memory," "Out of Stack Space," or "Out of String Space."

 This information applies to QB.EXE in Microsoft QuickBASIC versions
 4.00, 4.00b, and 4.50; to QB.EXE in Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and MS OS/2; and to QBX.EXE in Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS DOS and MS OS/2.

 In the QuickBASIC (QB.EXE) and QuickBASIC extended (QBX.EXE)
 environments, using $INCLUDE to include a COMMON block in multiple
 modules uses much more DGROUP memory than using $INCLUDE to include
 the COMMON block in a one-module program. A program that has a large
 COMMON block and has multiple modules can easily run out of space for
 static data in DGROUP. The same program, when compiled, will have much
 more available memory for static data in DGROUP.

 Each time a COMMON block is $INCLUDEd into a new module in a multiple-
 module program, the QB.EXE or QBX.EXE interpreter sets aside a
 correspondingly large block of memory. This block of memory is not a
 new COMMON block memory area, but is called a "variable table." This
 table contains information about the names of the variables and where
 they are located. Therefore, each time a new module is added to a
 program and the COMMON block is $INCLUDEd, a whole new variable table
 is created in DGROUP for that module. As the number of modules grows,
 DGROUP is used up quickly.

 Note: The graphs below do not show the actual structure of DGROUP, but
 are illustrations to show the general concept of how variable tables
 use DGROUP memory.

 For a five-module program with a 6K common block, a map of DGROUP
 might resemble the following:

             +---- "Simplified" Map of DGROUP ------+
             |                                      |
             |  10K Free static data memory         |
             |--------------------------------------|
             |  20K Other static data               |
             |--------------------------------------|
             |  5K  Variable table for Module #1    |
             |--------------------------------------|
             |  5K  Variable table for Module #2    |
             |--------------------------------------|
             |  5K  Variable table for Module #3    |
             |--------------------------------------|
             |  5K  Variable table for Module #4    |
             |--------------------------------------|
             |  5K  Variable table for Module #5    |
             |--------------------------------------|
             |  6K        THE COMMON BLOCK          |
             +--------------------------------------+

 For a one-module program with the same 6K COMMON block, a map of
 DGROUP might resemble the following:

             +--- "Simplified" Map of DGROUP -------+
             |                                      |
             |  30K    Free static data memory      |
             |--------------------------------------|
             |  20K Other static data               |
             |--------------------------------------|
             |  5K  Variable table for Module #1    |
             |--------------------------------------|
             |  6K        THE COMMON BLOCK          |
             +--------------------------------------+

 When the same program is compiled and linked into an executable
 (.EXE), it will have much more available space in DGROUP. In an .EXE
 program, all references to a variable are resolved into addresses.
 Variable tables are no longer needed to store the names of variables
 and their locations. In an .EXE, this memory in DGROUP for variable
 tables is released and is available for use by the program. In a
 multiple-module program with a large COMMON block, the difference of
 available space in DGROUP when compiled versus when running in the
 QB.EXE or QBX.EXE environment can be as much as 40K or more.

 There are two strategies for dealing with this limitation of the
 QB.EXE and QBX.EXE environments. First, the size of the COMMON block
 can be kept to a minimum. However, if a program must contain a large
 COMMON block, the number of modules must be kept to a minimum. In this
 case, a one-module program will produce the best results. The QB.EXE
 and QBX.EXE editors can handle a one-module program with more than 64K
 of code. However, if a large one-module program is compiled with
 BC.EXE, it can produce a "Program memory overflow" error. This means
 that when the program is completely coded, debugged, and a production
 version is ready to be built, the one-module program has to be broken
 up into multiple modules and separately compiled and linked.

 Note that in QB.EXE or QBX.EXE, each DECLARE statement for a SUB or
 FUNCTION procedure that is not currently loaded as a source or Quick
 library routine will take up some space in DGROUP to support the
 undefined procedure reference. However, if a procedure is currently
 loaded as a source or Quick library routine, then multiple DECLARE
 statements for that procedure name do not take up additional space in
 DGROUP.


 886. BASIC Random Files Compatible with C Random (Binary) Files

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900404-1 S_C S_QuickC B_BasicCom
 Last Modified: 10-JAN-1991    ArticleIdent: Q62057

 BASIC random access files created with either user-defined TYPE
 records or with the FIELD statement can be easily read as C random
 access files. This article gives an example of writing two random
 access files using both a TYPEd record and a FIELD statement. An
 accompanying C program shows how to read those files as C random
 access files.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b; and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2.

 Versions of QuickBASIC earlier than 4.00 use Microsoft Binary format
 (MBF) for floating-point numbers. Current versions of the C compiler
 expect floating-point numbers to be stored in IEEE format. Therefore,
 current versions of C cannot easily read random access files that are
 created with QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, and
 3.00 if those files contain single- or double-precision numbers.

 Both BASIC and C store random access file records as byte-per-byte
 copies of the record variable written to the file. No "extra"
 information about the data is stored along with the record. A direct
 image of the record variable is copied to the record on disk.
 Therefore, because BASIC and C have many data types in common, it is a
 straightforward process to create records in C that are the equivalent
 of BASIC records. The following table summarizes what C data type you
 would use in a "struct" to mirror the data type in a BASIC TYPE.

    BASIC TYPE Data Type   C struct Data Type
    --------------------   ------------------

    INTEGER                int
    LONG                   long
    SINGLE                 float
    DOUBLE                 double
    STRING * n             char array[]

 The only precaution is that all strings passed from BASIC to C in a
 TYPE should have a null character (CHR$(0)) as the last character if
 any C string-manipulation functions are going to be used.

 The following BASIC example shows writing both a TYPEd record and a
 FIELDed record to a BASIC random access file. The following C program
 can then be used to read and display the contents of the two files
 created with BASIC. The BASIC program should be compiled with
 QuickBASIC version 4.00, 4.00b, or 4.50, Microsoft BASIC Compiler
 version 6.00 or 6.00b, or BASIC PDS version 7.00 or 7.10. The C
 program should be compiled with C version 5.00 or 5.10, or with
 QuickC version 1.00, 1.01, 2.00, 2.01, 2.50, or 2.51.

 Code Example
 ------------

 '******************************  BASIC ***************************

 TYPE rec1
    s1 AS SINGLE
    d1 AS DOUBLE
    i1 AS INTEGER
    l1 AS LONG
 END TYPE

 DIM var1 AS rec1
 var1.s1 = 1.1: var1.d1 = 2.2: var1.i1 = 3: var1.l1 = 4

 OPEN "type.dat" FOR RANDOM AS #1
 PUT 1, 1, var1

 OPEN "field.dat" FOR RANDOM AS #2 LEN = LEN(var1)
 FIELD #2, 4 AS single1$, 8 AS double1$, 2 AS int1$, 4 AS long1$
 LSET single1$ = MKS$(var1.s1)
 LSET double1$ = MKD$(var1.d1)
 LSET int1$ = MKI$(var1.i1)
 LSET long1$ = MKL$(var1.l1)
 PUT 2, 1
 CLOSE
 END

 /************************************************************/
 /*                            C Program                     */
 /************************************************************/

 #include <stdio.h>
 typedef struct {
   float     float1;
   double    double1;
   int       int1;
   long int  long1;
 } RECORD;

 void printit(RECORD * rec1);

 void
 main(void)
 {

    FILE * TYPEdfile  = NULL;
    FILE * FIELDfile = NULL;
    int NumRead;
    RECORD rec1;

    TYPEdfile = fopen("TYPE.DAT","r");
    if(TYPEdfile == NULL) {
         printf("Open fail on single.dat\n");
     }
    else {
         NumRead = fread(&rec1,sizeof(rec1),1,TYPEdfile);
         if (NumRead ==  0) printf("Failed to read double.dat\n");
         printf("Contents of random file created with TYPE: \n");
         printit(&rec1);
     }

    FIELDfile = fopen("FIELD.DAT","r");
    if(FIELDfile == NULL) {
         printf("Open fail on field.dat\n");
      }
    else {
         printf("Contents of random file created with FIELD: \n");
         NumRead = fread(&rec1,sizeof(rec1),1,FIELDfile);
         printit(&rec1);
      }

    fcloseall();
 }

 void printit(RECORD * rec1)
 {
    printf("%f\n",   rec1->float1);
    printf("%lf\n",  rec1->double1);
    printf("%d\n",   rec1->int1);
    printf("%ld\n\n",rec1->long1);
 }


 887. Environment Variable Must Be Uppercase in ENVIRON$

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900507-4 B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q62208

 If "Set name=test" is entered in lowercase letters at the DOS command
 line, the ENVIRON$("NAME") function returns "test" only if "name" is
 in all uppercase letters in the ENVIRON$ function. If "name" is not in
 uppercase letters or if it is in mixed case, a null string will be
 returned. In other words, the argument to the ENVIRON$ function must
 be in all uppercase letters or a null string will be returned.

 This behavior occurs in Microsoft QuickBASIC versions 4.00, 4.00b, and
 4.50, Microsoft BASIC Compiler versions 6.00 and 6.00b, and Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS.

 Program
 -------

    A$= ENVIRON$("NAME")          'Don't use ENVIRON$("name")
    PRINT A$

 Output
 ------

    test


 888. "Out of String Space" Using DB/lib

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900406-40
 Last Modified: 25-MAY-1990    ArticleIdent: Q62211

 A customer reported that when using DB/lib with Microsoft QuickBASIC
 Compiler version 4.50 for MS-DOS, he received an "Out of string space"
 error when running his program. The solution to the problem was to
 decrease the number stored in the "DBPOOL" environment variable.
 According to the customer, this environment variable allocates memory
 for DB/lib, apparently from string space. He said that the default
 value for this variable was 64 (meaning 64K). When he set DBPOOL to
 16, his program functioned normally.

 Although this problem has not been duplicated by Microsoft, AJS
 Publishing, the developer of DB/lib, has confirmed the above
 information about the DBPOOL environment variable and the possibility
 of a memory conflict with QuickBASIC.


 889. How to Get the Current Drive with Microsoft BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900517-73 B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q62213

 BASIC programs can call an interrupt to get the currently selected
 drive. The interrupt in question is 21 Hex, function 19 Hex. Before
 calling the interrupt, AH (the upper byte of the AX register) must be
 set to 19 Hex. The interrupt returns the number of the current drive
 in AL (the lower byte of the AX register). The drive numbers
 correspond to the letters of the alphabet (for example, 0 = A, 1 = B,
 etc.).

 This information applies to Microsoft QuickBASIC Compiler versions
 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 For more information on interrupt 21 Hex, function 19 Hex, see Page 367
 of "Advanced MS-DOS Programming, Second Edition," by Ray Duncan
 (Microsoft Press, 1988).

 Note that BASIC PDS version 7.00/7.10 supports the function "CURDIR$",
 which can also be used to get the currently selected drive. However,
 using this method requires some string parsing. Although the code is
 smaller, it may be slower.

 The following sample program reports the current drive:

    'The include file "qb.bi" contains the DECLARE statement for
    'Interrupt and the TYPE definition for RegType.  If you are
    'using QBX.EXE, the include file to use is called "qbx.bi".

    '$INCLUDE: 'qb.bi'
    DIM Regs AS RegType

    'Set AH to 19 Hex:
    Regs.ax = &H1900
    'Call the interrupt
    CALL interrupt(&H21, Regs, Regs)

    'Regs.ax must be ANDed with &HFF so that AH will be cleared.
    'It must be cleared so the CHR$ function will be passed an
    'ASCII code in the range of the letters A-Z (65-90).
    PRINT "The current drive is "; CHR$((Regs.ax AND &HFF) + 65)

    END


 890. QB.EXE/QBX.EXE Incorrectly Allows GO As a Variable

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified:  2-JAN-1991    ArticleIdent: Q62266

 The QB.EXE and QBX.EXE environments incorrectly allow the keyword GO
 to be used as a variable. The BC.EXE compiler correctly flags this
 usage as a syntax error.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 in Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; in Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS (buglist6.00,
 buglist6.00b); and in the QBX.EXE environment in Microsoft BASIC
 Professional Development System (PDS) version 7.00 for MS-DOS
 (buglist7.00). This problem is corrected in Microsoft BASIC PDS 7.10
 (fixlist7.10).

 This error is not trapped in the QB.EXE/QBX.EXE environments because
 GO is not a keyword on its own. GO must always be used with the
 keywords TO or SUB to complete the combined phrases GOTO and GOSUB.
 Because QB.EXE and QBX.EXE both format the code as it is entered, "GO
 TO" is changed to be "GOTO". Thus, GO on its own is not checked during
 QBX.EXE's final pass in creating the internal pseudocode (pcode).

 The following code example fails to give an error in the QB.EXE and
 QBX.EXE environments, but correctly causes a "Syntax error" when
 compiled with BC.EXE:

    GO = 1


 891. Problem Using SETMEM and SHELL in QuickBASIC 4.50

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 14-JUN-1990    ArticleIdent: Q62267

 Using the SETMEM function with a parameter less than 0 (zero) in
 Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 deallocates memory
 from BASIC's far heap. Normally, the memory can be regained with
 another call to SETMEM with a positive parameter. However, if a SHELL
 statement is executed between the two CALLs to SETMEM, the program
 will not be able to reclaim the memory. This happens both when
 executing from the QB.EXE environment or as an executable (.EXE) file
 that uses the BRUNxx.EXE run-time module. The only workaround is to
 compile the program as a stand-alone EXE using BC.EXE with the /O
 option.

 Microsoft has confirmed this to be a problem in QuickBASIC 4.00,
 4.00b, and 4.50, and in Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS (buglist6.00, buglist6.00b). This problem was
 corrected in Microsoft Professional Development System (PDS) version
 7.00 for MS-DOS (fixlist7.00).

 The following code sample reproduces this problem:

    before& = FRE(-1)                ' Get original Value.
    temp& = SETMEM(-30000)           ' Deallocate memory.
    SHELL "CLS"
    temp& = SETMEM(30000)            ' Try to Reallocate memory.
    after& = FRE(-1)                 ' Get New value, which should be
                                     ' the same value as the original.
    CLS
    PRINT "Before Call: "; before&   ' If the difference between these
    PRINT "After  Call: "; after&    ' two values is 30000 then the
                                     ' problem is reproduced.
    differ& = before& - after&
    PRINT " Difference  ";differ&    ' This should be 0.


 892. Two Fixed-Length Strings 32K Long in COMMON Hang QuickBASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 18-OCT-1990    ArticleIdent: Q62269

 The following two-line program hangs QB.EXE and QBX.EXE:

    COMMON A AS STRING * 32760
    COMMON B AS STRING * 32760

 When run, the line and column counters at the bottom-right corner of
 the screen will be set to 1, the message "Binding" will be displayed
 at the bottom-left corner, and the machine will be hung, requiring a
 soft reboot. If running in the DOS compatibility box of OS/2, only the
 DOS box will be hung.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; in the QB.EXE
 environment of Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS (buglist6.00, buglist6.00b); and in the QBX.EXE environment of
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are researching
 this problem and will post new information here as it becomes
 available.

 The problem does not occur in programs compiled with BC.EXE.


 893. Invalid Entries in Symbol Table Using F1 in QB.EXE, QBX.EXE

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900517-174 B_BasicCom
 Last Modified:  2-JAN-1991    ArticleIdent: Q62455

 Within the QB.EXE or QBX.EXE programming environment, if you create a
 variable of any type and then position the cursor on the variable and
 press F1, the Help window will appear, showing the type of the
 variable and how it is used in the program. If you then change the
 type of the variable and request help on the variable again, it will
 now be shown as being defined as both types, even though the variable
 appears in your program only once.

 This information applies to QB.EXE for QuickBASIC version 4.50 for
 MS-DOS, and QBX.EXE for Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Although the variable appears in the Help window as being defined as
 two variable types, memory is only allocated for the variable of the
 type it was last declared as. The symbol table used for displaying
 help on variables is updated only when QB.EXE or QBX.EXE is returned
 to the root state, which is when a new program is loaded or the
 current program is saved. To eliminate the duplicate entries, save the
 current program by pressing ALT+F, then "S" for Save or "A" for Save
 As. (The program does not need to be reloaded.)

 The following steps duplicate the problem:

 1. Load QB.EXE or QBX.EXE and type the following on a separate line:

      x$ = ""

 2. Place the cursor on the "x$" and press F1 to get help on the
    variable.

 3. With Help visible, change the line to read:

       x = 0

 4. Place the cursor on the "x" and press F1 to get help on the
    variable.

 You will now see the following in the Help window:

    x is a symbol that is used in your program as follows:

     | D:\TEST.BAS -----------------------
     | variable of type: STRING
     | variable of type: SINGLE precision


 894. How to Find All Available Logical Drives in BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900521-38 B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q62458

 A BASIC program can call interrupts to find out which logical drives
 are available. The interrupts used are 21Hex, function 0EHex (Select
 disk) and 21Hex, function 19Hex (Get current disk). The method
 involves circulating through each possible logical drive (A-Z) and
 calling the interrupt to select that drive. If this is successful,
 subsequently calling the interrupt to get the current drive should
 return that same drive. If it isn't the same, the drive wasn't
 successfully selected and therefore isn't available.

 This information applies to Microsoft QuickBASIC Compiler versions
 4.00, 4.00b, and 4.50 for MS-DOS, Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS, and Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Function 0EH of interrupt 21H (Select disk) requires input from the
 following registers:

    AH (upper byte of AX) = 0EH
    DL (lower byte of DX) = drive code (0=A, 1=B, etc.)

 When called, it makes the drive passed in DL current, if possible. If
 that drive is not available, the interrupt does not return an error.
 That is why function 19H of interrupt 21H (Get current disk) must be
 called to see if function 0EH was successful. Function 19H requires
 the following registers for input:

    AH (upper byte of AX) = 19H

 It returns the following:

    AL (lower byte of AX) = current drive code (0=A, 1=B, etc.)

 For more information on interrupt 21H, functions 0EH and 19H, see
 Pages 355 and 367 (respectively) of "Advanced MS-DOS Programming,
 Second Edition," by Ray Duncan (Microsoft Press, 1988).

 The following program displays all the available logical drives:

 'Remember to invoke QB.EXE (or QBX.EXE) with the /L switch) because
 'support for CALL Interrupt is in QB.QLB (or QBX.QLB).

 '$INCLUDE: 'qb.bi'                    'Use 'qbx.bi' for QBX.EXE.
 DIM Regs AS RegType                   'Holds register values.

 PRINT "The following logical drives are available:";

 FOR Drive% = 0 TO 25                  'Circulate through drives A-Z.

    Regs.ax = &HE00                    'Function 0EH (AH = 0EH).
    Regs.dx = Drive%
    CALL Interrupt(&H21, Regs, Regs)   'Select a drive, if it's there.

    Regs.ax = &H1900                   'Function 19H (AH = 19H).
    CALL Interrupt(&H21, Regs, Regs)   'Get currently selected drive.

    IF (Regs.ax AND &HFF) = Drive% THEN  '(Regs.ax AND &HFF) = AL.
       PRINT " "; CHR$(Drive% + 65);   'If current drive = last drive
    END IF                             'selected, drive is available.

 NEXT Drive%


 895. Must Start Program to Use Set Next Statement from Debug Menu

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900528-1
 Last Modified: 11-JUN-1990    ArticleIdent: Q62812

 When debugging a BASIC program in the QB.EXE or QBX.EXE environment,
 the Set Next Statement command from the Debug menu cannot be used
 unless the program is first started.

 This information applies to QB.EXE in Microsoft QuickBASIC versions
 4.00, 4.00b, and 4.50, to QB.EXE in Microsoft BASIC Compiler versions
 6.00 and 6.00b, and to QBX.EXE in Microsoft BASIC Professional
 Development System (PDS) version 7.00.

 To use the Set Next Statement option, the program must be started in
 one of the following ways:

 1. Restart the program by choosing Restart from the Run menu
    by pressing ALT, R, R.

 2. Use the F8 key to step to the first line of the program.

 3. Start the program with SHIFT+F5 (or choose Start from the Run
    menu). Then stop the program with a breakpoint or by pressing
    CTRL+BREAK.

 After this, you should be able to use the Set Next Statement option.
 To use this debugging option, move the cursor with the arrow keys or
 mouse to the line of code where you want execution to begin. Then
 choose Set Next Statement from the Debug menu. That line will be
 highlighted, showing that it will be the next line to execute when you
 continue running the program.


 896. Passed Parameters Incorrectly PRINTed from SUB in Library

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900515-50 buglist4.50
 Last Modified: 20-JUN-1990    ArticleIdent: Q62816

 This article demonstrates a case where PRINTing integer and
 floating-point numbers from a SUBprogram that is either in a library
 or in a separate module gives unpredictable results. The problem
 occurs if the variables are passed to the SUB through the argument
 list and if several of the variables are separated by commas when
 PRINTed in one PRINT statement.

 Microsoft has confirmed this to be a problem in QuickBASIC version
 4.50 and in Microsoft BASIC Compiler versions 6.00 and 6.00b
 (buglist6.00, buglist6.00b). This problem was corrected in Microsoft
 BASIC Professional Development System (PDS) version 7.00
 (fixlist7.00).

 There are several ways to work around this problem. This problem does
 not occur if you use the /X switch on the compile line. The problem
 also does not occur if the SUB is part of the module from where it is
 CALLed or if the variables are passed through COMMON SHARED
 statements. The problem also does not occur if the variables are
 PRINTed on separate lines, or are separated by semicolons instead of
 commas.

 The following code shows the problem:

 From within QB.EXE 4.50, make a module or library from the following
 code:

     DECLARE SUB printsub (a%, b%, c%, d%)
     SUB printsub (a%, b%, c%, d%)
     PRINT "1: ", a%, b%, c%, d%
     PRINT "2: ", a%, b%, c%, d%
     PRINT "3: ", a%, b%, c%, d%
     END SUB

 If you made a Quick library from the above SUBprogram, load the
 library into QuickBASIC version 4.50 as follows:

    QB /L libname

 Then, from within QB.EXE 4.50, run the following main program:

 ' Program: TEST.BAS
     DECLARE SUB printsub (a%, b%, c%, d%)
     CLS
     CALL printsub(9, 16, 4, 70)   'the values do not matter

 Output
 ------

    1:             9             16            4             70
    2:             9             21317         4             70
    3:             9             21317         4             70

 To work around this problem, compile with the /X option, as follows:

    BC /X TEST.BAS ;


 897. WAIT() Causes Execution to Continue If Any Bit Is Set

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900421-2 B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q62891

 The WAIT() statement stops monitoring the input port and resumes
 execution as soon as any bit changes at the input port.

 The WAIT() statement cannot be used to suspend program execution until
 only a certain bit pattern is read from a designated input port.
 However, this can be done using the INP() function as shown in the
 program below, which loops until the byte read from port 1 is 13.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 Code Example
 ------------

    DO
     x% = INP(1)
    LOOP UNTIL x% = 13


 898. SELECT CASE Example Correction for QuickBASIC 4.5 Manual

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900613-130 docerr
 Last Modified: 20-JUN-1990    ArticleIdent: Q63004

 On Page 121 of the "Microsoft QuickBASIC 4.5: Learning to Use" manual,
 there is an error in the sample code for the SELECT CASE statement.

 This information applies to Microsoft QuickBASIC version 4.50 for
 MS-DOS.

 The following code fragment from Page 121 is incorrect:

    IF LEN(Choice$) = 1 THEN
        ' Handle ASCII keys
            SELECT CASE ASC(Choice$)
               CASE ESC
                   PRINT "Escape key"
                   END
               CASE IS 32, 127
                   PRINT "Control code"
                     .
                     .
                     .

 The statement "CASE IS 32, 127" should be changed to the following:

    CASE IS < 32, 127

 The "<" (less than) symbol is missing from the example.

 A correct version of the example is in the QB Advisor online Help
 system for QuickBASIC version 4.50. You can find this code in "Example
 2" from the example hypertext link when getting help on SELECT CASE.


 899. DEFINT A:DEFLNG B Before SUB Gives "Cannot Precede SUB" in QB

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified:  8-NOV-1990    ArticleIdent: Q63008

 Placing two DEFtype statements (DEFINT, DEFLNG, DEFSNG, DEFDBL,
 DEFSTR, or DEFCUR) on the same line separated by a colon incorrectly
 gives the error "Statement cannot precede SUB/FUNCTION definition" in
 QB.EXE and "Invalid statement preceding SUB/FUNCTION definition" in
 QBX.EXE. The BC.EXE compiler correctly compiles this line without
 error.

 To work around this problem, place each DEFtype on a separate line
 before the SUB/FUNCTION line.

 Microsoft has confirmed this to be a problem with the QB.EXE
 environment of Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50; in
 the QB.EXE environment of Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS (buglist6.00, buglist6.00b); and in the QBX.EXE
 environment of Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 To reproduce this problem, add the following line before any SUB or
 FUNCTION in the QB.EXE or QBX.EXE environment:

    DEFINT A:DEFLNG B

 The resulting SUB will appear as follows:

    DEFINT A:DEFLNG B
    SUB test
    ...
    END SUB

 To work around this problem, enter each DEFtype as a separate line, as
 follows:

    DEFINT A
    DEFLNG B
    SUB test
    ...
    END SUB

 Note that if you load a program resembling this into the QB.EXE or
 QBX.EXE editor, the editor will automatically put each DEFtype
 statements on its own line and remove the colon.


 900. QB Sample Function to Convert from Floating-Point to String

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900608-167 B_BasicCom
 Last Modified:  8-AUG-1990    ArticleIdent: Q63095

 This article provides a code example of a FUNCTION procedure that
 always returns the string equivalent of a real number in the format
 "WholeNumber.Fraction". This works around the usual behavior of the
 STR$ function, which, depending on how a real number is represented in
 binary, returns either a string in the form of "WholeNumber.Fraction"
 or a string in scientific notation.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 STR$ merely converts a SINGLE or DOUBLE into a string based on a real
 number's internal representation. Because some real numbers cannot be
 represented exactly in binary, the STR$ function returns some numbers
 in scientific notation and others in normal notation. The RealString$
 FUNCTION below never returns scientific notation, but always returns
 normal notation.

 Code Example
 ------------

 The code example below provides a FUNCTION procedure that consistently
 converts a real number into a string of the format "WholeNumber.Fraction".
 Please note that this function is provided as a general example of how
 to approach solving this programming problem. It represents only one
 solution; others may be possible.

 1. Description: The RealString$ function converts a DOUBLE-precision
    number into a string, rounding the result to the specified
    precision.

 2. The parameters are as follows:

    a. RealNumber - Any DOUBLE type value.

       Note: You can also pass INTEGER, LONG, and SINGLE types in
       conjunction with the BASIC keyword CDBL. Of course, STR$ with
       the INTEGER and LONG types will yield the same result. For
       example:

          a$ = RealString$(CDBL(b!),10)
               where b! is a variable of type SINGLE

    b. MaxPrecision - Indicates the maximum number of decimal places
       you are willing to tolerate to the right of the decimal point.
       For this function to work properly, MaxPrecision MUST be greater
       than or equal to the total number of fractional decimal places
       of the value being passed in RealNumber. For example, if you are
       calling this function with .005 in RealNumber, you MUST pass a
       number no less than 3 in MaxPrecision. A number greater than 3
       still returns "0.005" in RealString$. For example, passing 5
       through MaxPrecision returns ".005" NOT "0.00500". Zeros are NOT
       padded in the string to give a result the length of
       MaxPrecision.

       WARNING: If MaxPrecision is substantially greater than the
       fractional decimal places in the value passed through parameter
       RealNumber, extraneous results may be returned in RealString$.
       For example:

          a$ = RealString$(.05,30) returns
          "0.0500000007450580596923828125"

 3. Returns: RealString$ returns a string containing the string
    equivalent of RealNumber. For real numbers greater than -1 and less
    than 1, RealString$ always appends a zero in the 1's digit
    position. For example, a$ = RealString$(.005,3) returns "0.005" in
    a$.

    Note: The maximum number of possible digits to the right of the
    decimal point is determined by the parameter MaxPrecision. (See
    above.)

 '********************  RealString FUNCTION **************************
 FUNCTION RealString$ (RealNumber AS DOUBLE, MaxPrecision AS INTEGER)

   IF MaxPrecision < 0 OR MaxPrecision > 50 THEN
            RealString$ = ""
   ELSE

      ' Break the RealNumber into its whole and decimal parts
      whole& = FIX(RealNumber#)
      decimal# = ABS(RealNumber# - whole&)

      ' Add in a rounding factor. This compensates for numbers
      ' such as .05 that can't be stored exactly in binary. For
      ' example, .05 is represented as .04999. This is the means
      ' to round it up to .05 as it should be.
      decimal# = decimal# + 5 * 10 ^ -(MaxPrecision% + 1)

      IF decimal# >= 1 THEN
         whole& = whole& + 1
      END IF

      ' Convert the fractional part to a string
      DecString$ = ""

      FOR i% = 1 TO MaxPrecision + 1
              DecDigit% = FIX(decimal# * 10)
              DecString$ = DecString$ + RIGHT$(STR$(DecDigit%), 1)
              decimal# = decimal# * 10 - FIX(decimal# * 10)
      NEXT i%

      ' Ensure that the fractional part is equal
      ' in length to the maximum precision allowed
      IF LEN(DecString$) > MaxPrecision THEN
         DecString$ = LEFT$(DecString$, MaxPrecision%)

         ' Remove all trailing zeros from the end of the
         ' fractional part
        i% = LEN(DecString$)

        WHILE i% > 0
           IF MID$(DecString$, i%, 1) = "0" THEN
              DecString$ = LEFT$(DecString$, i% - 1)
           ELSE
              i% = 0
           END IF

           i% = i% - 1
        WEND

      END IF

      ' Include the decimal point before the fraction
      IF DecString$ <> "" THEN
              DecString$ = "." + DecString$
      END IF

      ' Compose a string of the whole and fractional parts of
      ' the real number
      RealString$ = STR$(whole&) + DecString$
   END IF      ' (END of IF from very top of function)

 END FUNCTION

 Sample Program Using This Function
 ----------------------------------

 DECLARE FUNCTION RealString$ (RealNumber AS DOUBLE, MaxPrecision AS_
 INTEGER)

 CLS
 PRINT RealString$(3.1415927, 7)
 PRINT RealString$(437.137827#, 5)
 PRINT RealString$(.000173, 10)
 PRINT RealString$(99.997,2)
 END

 Sample Output
 -------------

    3.14157927
    437.13783
    0.000173
    100


 901. Pocket Soft's .RTLink Gives Overlay Support to Compiled BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900618-68 B_BasicCom
 Last Modified: 27-JUN-1990    ArticleIdent: Q63269

 .RTLink is a third-party linker made by Pocket Soft, Inc., that allows
 overlay support for QuickBASIC versions 4.00, 4.00b, and 4.50, and
 enhanced overlay support for Microsoft BASIC Professional Development
 System (PDS) version 7.00. .RTLink allows the following overlay
 enhancements that are currently not available with QuickBASIC or
 BASIC PDS 7.00:

 1. Overlay support in QuickBASIC 4.00, 4.00b, and 4.50 or BASIC
    compiler 6.00 and 6.00b.

 2. Up to two more additional run-time modules (such as the
    BRUNnxxx.EXE or BRT70xxx.EXE run-time modules).

 3. Multiple overlay areas. Overlays in BASIC PDS 7.00 are limited to
    just one overlayable area of memory.

 4. Overlays calling overlays that use the same overlay area (nested
    overlay calls).

 DISCLAIMER: .RTLink is manufactured by Pocket Soft, Inc., a vendor
 independent of Microsoft. Microsoft makes no warranty, implied or
 otherwise, regarding the performance or reliability of .RTLink. You
 are responsible for double-checking any information on which you base
 a financial decision. Contact your dealer or the product manufacturer
 to verify information.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS.

 The first version of .RTLink that works with BASIC PDS 7.00 is .RTLink
 version 3.11. Earlier versions of .RTLink can create overlays with
 QuickBASIC 4.00, 4.00b, and 4.50, and BASIC Compiler 6.00 and 6.00b,
 but not with BASIC PDS 7.00. Please note that Microsoft has not tested
 .RTLink with these products and therefore cannot guarantee
 compatibility.

 For more information about .RTLink, contact:

    Pocket Soft, Inc.
    P.O. Box 821049
    Houston, TX  77282
    (713) 460-5600
    Orders: (800) 336-1166


 902. QB & QBX Insert Default REM $STATIC Before a SUB or FUNCTION

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900612-76 B_BasicCom
 Last Modified: 10-JAN-1991    ArticleIdent: Q63270

 The QB.EXE and QBX.EXE editors automatically insert an invisible REM
 $STATIC metacommand before the first SUB or FUNCTION procedure if you
 have a REM $DYNAMIC in effect in a module-level (main program level)
 window. This REM $STATIC is visible only when the file is saved as
 Text and then viewed in other text editors or TYPEd in MS-DOS. This
 automatic REM $STATIC actually does not affect arrays dimensioned
 inside the SUB or FUNCTION procedures, as explained further below.

 This information applies to the QB.EXE environment that comes with
 Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50 for MS-DOS, and to
 the QBX.EXE environment that comes with Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Note that the STATIC clause on a SUB or FUNCTION statement retains the
 value of local variables between invocations of that procedure. No
 STATIC clause on the SUB or FUNCTION statement means local variables
 are not retained between invocations. Do not confuse the STATIC clause
 of a SUB or FUNCTION statement with the array types of "static" (or
 $STATIC) or "dynamic" (or $DYNAMIC). These are distinct concepts.

 A static (or $STATIC) array is dimensioned at compile time. A dynamic
 (or $DYNAMIC) array is dimensioned at run time.

 The STATIC clause of SUB or FUNCTION statements affects locally
 dimensioned arrays as follows:

 1. SUB or FUNCTION statements with no STATIC clause appended (such as
    "SUB x") force all locally dimensioned arrays to be dynamic, and
    the REM $STATIC metacommand (if any) is ignored.

 2. SUB or FUNCTION statements with a STATIC clause (such as "SUB x
    STATIC") allow locally dimensioned arrays to be dimensioned
    dynamically or statically. For example, a REM $DYNAMIC metacommand
    makes locally dimensioned arrays dynamic in a STATIC SUB. Without
    using a metacommand, the locally dimensioned arrays will be static
    (unless dimensioned with a variable in the subscript).

 Example 1
 ---------

 If you type the following code example into QB or QBX, save the file
 as text, and use the TYPE command to display the file in DOS, you will
 see that QB or QBX inserted a REM $STATIC just before the "SUB sub1"
 line. This is by design, and doesn't affect any arrays.

    REM $DYNAMIC
    CALL sub1
    END
    SUB sub1
      PRINT "hello"
    END SUB

 Example 2
 ---------

 When QB or QBX automatically places the REM $STATIC before a SUB or
 FUNCTION, the REM $STATIC actually does not affect that SUB or
 FUNCTION.

 In the case of a non-STATIC SUB, all locally dimensioned arrays are
 always $DYNAMIC. For example:

    CALL sub1
    END

    REM $STATIC
    SUB sub1
      REM $STATIC ' QB and QBX ignore this.
      DIM array1(1000)
    END SUB

 In the code above, array1() is a $DYNAMIC array. This is because all
 arrays in non-STATIC SUBs and FUNCTIONs are required to be $DYNAMIC.
 The REM $STATIC metacommand does not affect arrays in non-STATIC SUBs.
 QB.EXE, QBX.EXE, and BC.EXE ignore both of the REM $STATIC
 metacommands in the above example.

 The only way to make any array static in a SUB or FUNCTION is to place
 the STATIC clause on the SUB or FUNCTION statement, as in the following
 example, where "array1" is static and "array2" is dynamic:

    CALL sub1
    END

    SUB sub1 STATIC
      DIM array1(1000)   ' Array defaults to a static array.
      z=20
      DIM array2(z)   ' A variable in the subscript makes array dynamic.
    END SUB

 From these examples, you can see that the REM $STATIC that QB or QBX
 automatically inserts before the first SUB or FUNCTION can be ignored.
 It won't affect the arrays dimensioned in the SUB or FUNCTION. You do
 not need to compensate for it or program around it.


 903. Single-Line DEF FN Can Cause Program to Rerun ON ERROR

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50 SR# S900606-
 Last Modified:  8-NOV-1990    ArticleIdent: Q63272

 A program will incorrectly return from an error-handling routine if an
 error occurs in a single-line DEF FN function. If the error occurs
 during the execution of a single-line DEF FN function, when the error
 handler executes a RESUME or RESUME NEXT, the program will resume on
 the line after the DEF FN definition instead of on the line or line
 after where the DEF FN function was invoked. This usually results in
 an infinite loop that eventually causes an "Out of stack space" error
 after the FN function invocations have been nested too many times.

 Microsoft has confirmed this to be a problem in QuickBASIC versions
 4.00, 4.00b, and 4.50; in Microsoft BASIC Compiler versions 6.00 and
 6.00b (buglist6.00, buglist6.00b); and in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS
 (buglist7.00, buglist7.10). This problem occurs in both the
 QB.EXE/QBX.EXE editor environment and the BC.EXE compiler. We are
 researching this problem and will post new information here as it
 becomes available.

 The following code example demonstrates this problem:

    10 ON ERROR GOTO handler
    20 REM For the following program:
    30 CLS
    40 DEF fnx (x%) = 1 / x%
    45
    50 PRINT "line after the DEF FN": PRINT
    60 PRINT fnx(0)
    70 END
    80 handler:
    90   RESUME NEXT

 In the example above, an error will occur on the PRINT fnx(0). In the
 error handler, the RESUME NEXT should cause the program to RESUME on
 line 70 after the PRINT fnx(0), but instead the program will resume on
 the line after the DEF FN definition (line 45). This will cause the
 PRINT fnx(0) on line 60 to be executed again, causing another error,
 which effectively is an infinite loop. The program will eventually run
 out of stack space and quit with a run-time error.

 To work around this problem, simply expand the single-line DEF FN to a
 multiple-line DEF FN ... END DEF. To correct the example above, you
 would make the following changes:

    10 ON ERROR GOTO handler
    20 REM For the following program:
    30 CLS
    40 DEF fnx (x%)
         fnx = 1 / x%
       END DEF
    45
    50 PRINT "line after the DEF FN": PRINT
    60 PRINT fnx(0)
    70 END
    80 handler:
    90   RESUME NEXT

 This program will execute correctly. The FN function will return a 0
 and the program will resume on the line after the PRINT fnx(0)
 statement.


 904. Editing Before First Line in Procedure Can Cause QB Problems

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom SR# S900115-
 Last Modified: 21-SEP-1990    ArticleIdent: Q63273

 Editing before the first line in a SUB/FUNCTION procedure can cause
 problems in the QB.EXE and QBX.EXE environments. Normally, you would
 get the following correct message:

    Blank lines not allowed before SUB/FUNCTION line. Is remark OK?

 However, in some cases, making other changes before the SUB/FUNCTION
 line can cause the QB and QBX environments to make unwanted changes.
 For example, if a remark is accepted for the line before the first
 line and then the comment line is deleted, the "Blank lines not
 allowed" message incorrectly appears and REMarks out the SUB/FUNCTION
 line.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 that comes with Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS and Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS (buglist6.00, buglist6.00b); and in the QBX.EXE environment
 that comes with Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are
 researching this problem and will post new information here as it
 becomes available.

 Besides comments, the only statements that are normally placed before
 SUB/FUNCTION lines are DEFtype statements (DEFINT, etc.). To place a
 DEFtype statement before the SUB/FUNCTION line, we recommend that you
 type it elsewhere in the program and use the cut and paste editing
 functions to move the DEFtype statement.

 To correct most editing problems such as this in the QBX.EXE editor,
 choose the Undo command from the Edit menu in BASIC PDS 7.00 or 7.10,
 which can undo as many as the last 20 modifications.

 The following information (from the QBX Help screen for the "Blank
 lines not allowed" dialog box) describes the behavior of the QBX
 editor with respect to blank lines before SUB/FUNCTION statements:

    Ordinarily the SUB or FUNCTION statement that begins a
    procedure is the first line in the View window. When you
    try to use the smart editor to put a blank line above
    the SUB or FUNCTION statement, the editor always transforms
    that blank line into a comment line.

 To edit more easily before the first line in a SUB or FUNCTION, you
 can save the file in text format and use a different editor or word
 processor to edit the code.


 905. "Statement Label Not Allowed Between SELECT CASE" Help Hangs

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900608-162 buglist4.50
 Last Modified: 29-JUN-1990    ArticleIdent: Q63436

 In Microsoft QuickBASIC, line labels are not allowed between a SELECT
 CASE statement and the following CASE statement. The QB.EXE
 environment will detect the error and will display a dialog box
 informing you of the error. Choosing Help from the dialog box, and
 then either pressing the ESC key or choosing OK to get back to your
 program will cause your machine to hang.

 Microsoft has confirmed this to be a problem in the QB.EXE environment
 of QuickBASIC version 4.50. We are researching this problem and will
 post new information here as it becomes available.

 This problem does NOT occur in the QuickBASIC Extended environment
 (QBX.EXE) of Microsoft BASIC Professional Development System (PDS)
 version 7.00.

 The following code example demonstrates the problem. When run inside
 the QuickBASIC environment, the syntax error is detected. If the Help
 option is selected for the error message, anything else done to exit
 Help and get back to the program results in the machine hanging.

 Code Example
 ------------

 X = 1
    SELECT CASE X         'You will get an error message telling you
 30   CASE 1              'that it is illegal to have a line label here
           PRINT "You will hang if you choose help on the error!"
    END SELECT


 906. Error L2029 "Unresolved External" Due to Wrong LIB.EXE Syntax

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900702-127 B_BasicCom S_UTILity H_Fortran S_C
 Last Modified: 17-JAN-1991    ArticleIdent: Q63659

 If a comma instead of a plus (+) sign is used on the LIB utility
 command line to indicate an additional object filename, the following
 will occur:

 1. The .LIB file will be created without error but will not contain
    the additional .OBJ file.

 2. The additional .OBJ will be interpreted as the .LST (listing) file
    and thus be overwritten.

 3. An "L2029: unresolved external" error will occur at link time.

 This information applies to the LIB.EXE utility when used with any
 supported Microsoft language, such as Microsoft QuickBASIC versions
 4.00, 4.00b, and 4.50, Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2, and Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.


 907. INKEY$ Fails with Various CTRL, ALT Key Combinations QB 4.00

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.00 buglist4.00b buglist4.50 B_BasicCom SR# S900706-
 Last Modified: 13-JUL-1990    ArticleIdent: Q63781

 The INKEY$ statement fails to return any value with certain CTRL and
 ALT key combinations that should return extended (2-byte) codes. The
 table below lists the keys that fail to return values:

    CTRL+                         ALT+
    -----                         ----

    TAB                           ` (back apostrophe)
    INS (INSert)                  BACKSPACE
    DEL (DELete)                  TAB
    Keypad 5                      [ and ]
    Keypad /                      ; and "
    Keypad *                      , and . and /
    Keypad -                      ENTER
    Keypad +                      Keypad / * - and +

 Microsoft has confirmed this problem with Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50, and Microsoft BASIC Compiler versions
 6.00 and 6.00b for MS-DOS and OS/2 (buglist6.00, buglist6.00b). The
 problem does not occur with earlier versions of Microsoft BASICs. This
 problem was corrected in Microsoft BASIC Professional Development
 System (PDS) version 7.00 (fixlist7.00).

 Function keys, editing keys, and most CTRL and ALT key combinations
 should be returned from INKEY$ as a two-character code where the first
 character is a null character (CHR$(0)) and the second character
 identifies the key pressed.

 Code Example
 ------------

 The following code example demonstrates how to examine key codes for
 any type of key:

    WHILE i$ <> CHR$(27)   'Exit with ESC (ESCape) key
       i$ = INKEY$
       SELECT CASE LEN(i$)  'Type of key depends on length
          CASE 1:
              PRINT "Single character:", ASC(i$), i$
          CASE 2:
              PRINT "Double character:", ASC(RIGHT$(i$,1))
          CASE ELSE
              REM no key pressed
       END SELECT
    WEND
    END


 908. Entering QB 4.50 with Multi-Module Program Requires Full Menus

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900703-108
 Last Modified: 13-JUL-1990    ArticleIdent: Q63798

 Loading a multiple-module program into the QuickBASIC environment
 (QB.EXE) requires having the Full Menus option on (located on the
 Options menu). When you enter QB.EXE without Full Menus on, a dialog
 box with the following message displays:

    Multiple-module programs require Full Menus.
    Switch to Full Menus and continue loading?

 Choosing either OK or Cancel switches the screen back to the MS-DOS
 output screen and then displays, "Press any key to continue," at the
 bottom of the screen. Pressing a key returns you to the editor screen.
 If you chose Cancel, no program files will be loaded, and the Full
 Menus option remains off. If you chose OK, the multiple modules
 (specified in the .MAK file associated with your program) are now
 successfully loaded, and the Full Menus option will now be on.

 This behavior occurs in Microsoft QuickBASIC version 4.50 for MS-DOS.

 Microsoft's intent for providing the (optional) shortened menus in
 4.50 is to simplify the initial environment for people who are first
 learning QuickBASIC.

 This information does NOT apply to QuickBASIC versions earlier than
 4.50, since earlier versions don't have an option to turn off Full
 Menus and display shortened menus. The QBX.EXE environment in
 Microsoft BASIC Professional Development System (PDS) 7.00 also does
 not have an option to display shortened menus.


 909. Example of Assembly Function Returning Long Integer to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | H_MASM S_QUICKASM B_BasicCom SR# S900718-16
 Last Modified: 10-AUG-1990    ArticleIdent: Q64105

 The two programs below demonstrate how an assembly language function
 can return a long integer to a Microsoft BASIC program.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, query in the Knowledge Base or the Software/Data
 Library for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is IFUNC.BAS, which displays a long
 integer returned from an assembly language function:

    DECLARE FUNCTION QPrint&

    FOR i% = 1 to 5
       PRINT QPrint&
    NEXT

 The following program is AINT.ASM, which will return a long integer
 parameter when called:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in
 ; MASM 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         longnum dd 12345

 .CODE
         PUBLIC QPrint
 QPrint  PROC
         mov ax, WORD PTR longnum        ; return value in ax and
         mov dx, WORD PTR longnum + 2    ;   dx registers
         ret
 QPrint  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC IFUNC.BAS;
    MASM AINT.ASM;
    LINK IFUNC AINT;

 IFUNC.EXE produces the following output:

    12345
    12345
    12345
    12345
    12345


 910. Sample Assembly Function Returning Single to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | H_MASM S_QUICKASM B_BasicCom SR# S900718-21
 Last Modified: 10-AUG-1990    ArticleIdent: Q64106

 The two programs below demonstrate how an assembly language function
 can return a single-precision variable to a Microsoft BASIC program.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, search in the Software/Data Library or the Knowledge
 Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is SFUNC.BAS, which displays a
 single-precision number returned from an assembly language function:

    DECLARE FUNCTION QPrint!
    FOR i% = 1 to 2
       PRINT QPrint!
    NEXT

 The following program is ASING.ASM, which will return a
 single-precision number when called:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         singlenum dd 98.6

 .CODE
         PUBLIC QPrint
 QPrint  PROC FAR
         push bp
         mov bp, sp
         push si
         push di
         push es

         push ds         ; set es = ds
         pop es

         mov si, offset dgroup:singlenum
         mov di, [bp+6]  ; load value into address at bp+6

         mov cx, 4
         rep movsb

         mov ax, [bp+6]  ; load offset of temp value in ax and
         mov dx, ss      ; ss into dx

         pop es
         pop di
         pop si
         pop bp
         ret 2
 QPrint  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC IFUNC.BAS;
    MASM ASING.ASM;
    LINK IFUNC ASING;

 IFUNC.EXE produces the following output:

    98.6
    98.6


 911. Sample Assembly Function Returning Double to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | H_MASM S_QUICKASM B_BasicCom SR# S900718-40
 Last Modified: 13-AUG-1990    ArticleIdent: Q64107

 The two programs shown below demonstrate how an assembly language
 function can return a double-precision number to a Microsoft BASIC
 program.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, query in the Software/Data Library for the following
 word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is DFUNC.BAS, which displays a
 double-precision number returned from an assembly language function:

    DECLARE FUNCTION QPrint#
    FOR i% = 1 to 2
       PRINT QPrint#
    NEXT

 The following program is ADBL.ASM, which will return a
 double-precision number when called:

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         doublenum dq 6765.89

 .CODE
         PUBLIC QPrint
 QPrint  PROC
         mov bp, sp
         push es
         push si
         push di

         push ds          ; set es = ds
         pop es

         mov si, offset dgroup:doublenum
         mov di, [bp+6]   ; load value into address at bp+6
         mov cx, 4
         rep movsw        ; 4 words at 2 bytes = 8 bytes

         mov ax, [bp+6]   ; load offset of temp value in ax and
         mov dx, ss       ;   ss into dx

         pop di
         pop si
         pop es
         pop bp

         ret 2
 QPrint  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC DFUNC.BAS;
    MASM ADBL.ASM;
    LINK DFUNC ADBL;

 DFUNC.EXE produces the following output:

    6765.89
    6765.89


 912. Assembly Function Returning Variable-Length String to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QUICKASM SR# S900718-47
 Last Modified: 13-AUG-1990    ArticleIdent: Q64428

 The two programs below demonstrate how an assembly language function
 can return a variable-length string to a Microsoft BASIC program.

 Note: This routine will not work inside the QuickBASIC Extended
 environment (QBX.EXE) or when compiled using the Far Strings option
 (BC /Fs) in Microsoft BASIC Professional Development System (PDS)
 version 7.00 or 7.10. For information on interlanguage programming
 with far strings in Microsoft BASIC PDS, see Chapter 13, "Mixed
 Language Programming with Far Strings," in the "Microsoft BASIC 7.0:
 Programmer's Guide" for versions 7.00 and 7.10.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, query in the Software/Data Library or this Knowledge
 Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is SFUNC.BAS, which displays a
 variable-length string returned from an assembly language function
 (QPrint).

    DECLARE FUNCTION QPrint$(slen%)
    CLS
    FOR i% = 1 to 3
       TString$ = QPrint$(i%)  ' i% is the length of the string
       PRINT TSTring$, LEN(TString$)
    NEXT

 The following assembly language program is ASTR.ASM, which contains
 the function QPrint. The QPrint function returns a string, and the
 passed integer parameter (argument) returns the length of the string.

 ; The following handy .MODEL MEDIUM,BASIC directive is found in MASM
 ; 5.10 but not in earlier versions:
 .MODEL MEDIUM, BASIC
 .DATA
         str      db 10 dup (?)    ; my own string
         mystring dw ?             ; my own descriptor (length)
                  dw ?             ;  (offset)

 .CODE
         PUBLIC QPrint
 QPrint  PROC
         push bp
         mov bp, sp
         push ds
         push es

         mov bx, [bp+6]      ; get the ptr to the string descriptor.
         mov cx, [bx]

         push ds
         pop es                    ; set es = ds

         mov di, offset dgroup:str ; load the offset into di
         mov al, 'a'               ; load character to fill
         rep stosb                 ; store "a" into the string
         mov cx, [bx]              ; put the length in cx again
         mov bx, offset dgroup:mystring ; put offset of string
                                        ;  descriptor in bx
         mov [bx], cx                   ; length in first two bytes
         mov [bx+2], offset dgroup:str  ; offset into second two bytes
         mov ax, bx                     ; load address of descriptor
                                        ;   into ax
         pop es
         pop ds
         pop bp

         ret 2
 QPrint  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC SFUNC.BAS;
    MASM ASTR.ASM;
    LINK SFUNC ASTR;

 SFUNC.EXE produces the following output:

    a
    aa
    aaa


 913. Example of Assembly Function Returning Integer to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom H_MASM S_QUICKASM SR# S900718-12
 Last Modified:  5-SEP-1990    ArticleIdent: Q64429

 The two programs below demonstrate how an assembly language function
 can return an integer to a Microsoft BASIC program.

 This information about interlanguage calling applies to QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and MASM, query in the Software/Data Library or this Knowledge
 Base for the following word:

    BAS2MASM

 Code Example
 ------------

 The following BASIC program is IFUNC.BAS, which displays an integer
 returned from an assembly language function:

    DECLARE FUNCTION QPrint%
    FOR i% = 1 to 5
       PRINT QPrint%
    NEXT

 The following assembly language program is AINT.ASM, which contains
 the QPrint function. The Qprint function returns an integer.

 .MODEL MEDIUM, BASIC
 .DATA
         shortnum dw 12345

 .CODE
         PUBLIC QPrint
 QPrint  PROC
         mov ax, shortnum    ; return value in ax register
         ret
 QPrint  ENDP
         END

 To demonstrate these programs from an .EXE program, compile and link
 as follows:

    BC IFUNC.BAS;
    MASM AINT.ASM;
    LINK IFUNC AINT;

 IFUNC.EXE produces the following output:

    12345
    12345
    12345
    12345
    12345


 914. Abrupt Branch to ON Event GOSUB Handler from Separate Handler

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900712-87 B_BasicCom
 Last Modified:  3-AUG-1990    ArticleIdent: Q64430

 When program control is within an ON <event> GOSUB handler, it is
 still possible to trap other events (where <event> can be COM, KEY,
 PEN, PLAY, STRIG, TIMER, etc.). This is normal behavior for ON <event>
 GOSUB trapping, but may be undesirable for those who want to disable
 all event trapping within an ON <event> handler. This article gives a
 code example demonstrating normal flow of control when a second
 trappable key is pressed within a given ON KEY GOSUB handler. The
 comments in this program show a method of temporarily disabling KEY
 and other event trapping within an ON KEY GOSUB handler.

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS, to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC
 PDS (Professional Development System) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 Within an ON <event> GOSUB handler, event trapping is suspended within
 the handler for only the trapped event. Any other active event traps
 (set with other ON <event> GOSUB statements) triggered within an event
 handler will cause control to immediately branch to the other ON
 <event> handler during execution of the initial handler. Upon
 terminating the second handler, control resumes where it left off in
 the original handler. This abrupt transfer of control may be
 problematic for those who want all actions surrounding a particular
 event, a key press for example, to be processed in full before
 subsequent key presses or events are handled.

 The code example below demonstrates a case of control branching from
 one ON KEY handler to another when a second key is pressed within the
 first handler. The example contains the code (remarked out) necessary
 to temporarily disable all ON KEY and other event trapping within the
 initial ON KEY handler. If you unremark (uncomment) the code shown,
 the program will complete each handler without interruption.

 Code Example
 ------------

 'DECLARE SUB EventsStop ()  ' These are the DECLARE statements for the
 'DECLARE SUB EventsOn ()    ' SUBs that disable and enable key and
                             ' event trapping. (DECLARE statements are
                             ' not needed or supported for QuickBASIC
                             ' 3.00 or earlier versions.)
 CLS

 ON KEY(1) GOSUB F1KeyHandler   ' Trapping for F1 function key.
 ON KEY(2) GOSUB F2KeyHandler   ' Trapping for F2 function key.

 KEY(1) ON
 KEY(2) ON

 PRINT "Please, press the F1 key"
 SLEEP
 PRINT "Exiting program"
 END

 ' To temporarily disable all key and event trapping within an
 ' event handler, the CALL to SUB EventsStop must be the first
 ' statement and the CALL to SUB EventsOn must be the last statement
 ' of the handler before the RETURN.

 F1KeyHandler:
         'CALL EventsStop       ' Include this statement to temporarily
                                ' disable all or selected ON KEY and
                                ' event statements

         PRINT "In F1 key handler"
         PRINT "Press F2 to jump to F2 key handler"
         SLEEP
         PRINT "Exiting F1 key handler"

         'CALL EventsOn         ' Include this statement so that any
                                ' keys pressed or events occurring
                                ' during the execution of this handler
                                ' will be processed at this point.
         RETURN

 F2KeyHandler:
         'CALL EventsStop       ' Include this statement to temporarily
                                ' disable all or selected key and event
                                ' trapping within this handler.
         PRINT "In F2 key handler"
         PRINT "Exiting F2 key handler"

         'CALL EventsOn         ' Include this statement so that
                                ' any trappable keys or events triggered
                                ' during the execution of this handler
                                ' will be processed at this point.
         RETURN

 SUB EventsOn               'All keys and events to enable go in here
         KEY(1) ON
         KEY(2) ON

         'TIMER ON          'Examples of events that may be enabled
         'COM(1) ON
 END SUB

 SUB EventsStop             'All keys and events to temporarily disable
         KEY(1) STOP        'go in here
         KEY(2) STOP

         'TIMER STOP        'Examples of events that may be temporarily
         'COM(1) STOP       'disabled
 END SUB

 Additional References
 ---------------------

 For more description of normal program flow within an ON <event> GOSUB
 handler, please see the following:

 1. Page 315 of "Microsoft BASIC 7.0: Programmer's Guide" for BASIC PDS
    versions 7.00 and 7.10

 2. Page 234 of "Microsoft QuickBASIC 4.5: Programming in BASIC" manual
    for QuickBASIC version 4.50

 3. Page 289 of "Microsoft QuickBASIC 4.0: Programming in BASIC:
    Selected Topics" manual for QuickBASIC versions 4.00 and 4.00b

 4. Page 357 of "Microsoft QuickBASIC Compiler" manual for versions
    2.00, 2.01, and 3.00


 915. How to Define a String Array in FIELDs in a FOR...NEXT Loop

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_MQuickB B_BasicCom B_GWBasicI B_BasicInt
 Last Modified:  6-AUG-1990    ArticleIdent: Q64498

 Below is an example of defining a string array in multiple FIELD
 statements invoked in a FOR ... NEXT loop.

 This information applies to all Microsoft BASIC products that support
 FIELD statements, including the following:

 1. Microsoft QuickBASIC version 1.00 for Apple Macintosh

 2. Microsoft BASIC Compiler version 1.00 for Apple Macintosh

 3. Microsoft BASIC Interpreter versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for Apple Macintosh

 4. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for MS-DOS

 5. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS

 6. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS
    OS/2

 7. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2

 8. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23 for
    MS-DOS

 Code Example
 ------------

 (Note: To run this program in GW-BASIC, you must add a line number to
 each line.)

 OPEN "test.dat" AS #1 LEN = 300
 DIM F$(30)
 i = 1
 FOR j = 1 TO 10
 FIELD #1, (j - 1) * 30 AS temp$, 10 AS F$(i), 10 AS F$(i + 1), 10 AS F$(i + 2
 i = i + 3
 NEXT
 LSET F$(30) = "1234567890"
 LSET F$(15) = "ABCDEFGHIJ"
 PUT #1, 1
 CLOSE

 OPEN "test.dat" AS #1 LEN = 300
 i = 1
 FOR j = 1 TO 10
 FIELD #1, (j - 1) * 30 AS temp$, 10 AS F$(i), 10 AS F$(i + 1), 10 AS F$(i + 2
 i = i + 3
 NEXT
 GET #1, 1
 PRINT F$(30), F$(15)

 References:

 For more information about alternatives to multiple FIELD statements
 in the latest Microsoft BASIC products, query for a separate article
 in this Knowledge Base using the following words:

    Long and FIELD and 255

 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS and MS OS/2 introduce the ability to have arrays
 in user-defined TYPEs, which allows you to write an array to disk all
 at once. For more information, query for a separate article in this
 Knowledge Base using the following words:

    RANDOM and BINARY and PUT and Array and TYPE


 916. "Overflow" from "&H nn" or "&O nn" with Illegal Embedded Space

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 10-AUG-1990    ArticleIdent: Q64592

 The ampersand character, when used to signify Hexadecimal (&H) or
 Octal (&O) values, can give an "Overflow" error if a space is embedded
 in the number.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50,
 to Microsoft BASIC Compiler versions 6.00 and 6.00b, and to Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 The following code examples cause an "Overflow" error (in the QB.EXE
 or QBX.EXE environment or in the BC.EXE compiler):

    AnyVarName = &H 80

    AnyVarName = & 80

    AnyVarName = &O 80

    PRINT &H 80

 The QBX.EXE environment immediately displays this error message
 because of the syntax checker, while the QB.EXE environment only
 catches the error upon execution.

 QuickBASIC compiler versions 3.00 and earlier ignore this syntax error
 and interpret the faulty information as a zero (0).


 917. ON KEY Key Trap with INKEY$ Loop Requires Additional Key Press

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900731-96 B_BasicCom
 Last Modified: 13-AUG-1990    ArticleIdent: Q64785

 A commonly used key-trapping strategy relies on using an INKEY$ loop
 to wait for a key press that is then handled by an ON KEY GOSUB
 handler. Using this strategy requires two key presses: one that
 triggers the ON KEY trap and another to exit the INKEY$ loop upon
 returning from the key handler. When making use of a key handler that
 performs a process transparent to the user, the key trap may appear to
 require two keystrokes for processing to continue. This behavior may
 be problematic for those who want processing to resume after one
 keystroke. This article contains a code example demonstrating this
 behavior and three other code examples illustrating alternate
 key-trapping strategies that require only one key press for processing
 to continue.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 When an INKEY$ loop is used in conjunction with the ON KEY statement
 to wait for a key press, control is passed to the ON KEY handler when
 a trappable key press occurs. Because the ON KEY GOSUB statement
 clears the keyboard buffer, the INKEY$ loop will still be waiting for
 a key press when control is returned from the ON KEY GOSUB handler.
 Therefore, a second key press is required to exit the INKEY$ loop.

 This behavior can be overcome either by using the SLEEP statement in
 place of the INKEY$ loop, by setting a flag within the ON KEY handler
 that will cause the INKEY$ loop to abort after a key trap, or by
 RETURNing from the key handler to a line number or label outside of
 the INKEY$ loop.

 The following code example demonstrates the requirement for a second
 key press:

    CLS
    ON KEY(1) GOSUB handler:
    KEY(1) ON
    PRINT "Press the F1 key"
    WHILE INKEY$ = ""
    WEND
    END
    handler:
            PRINT "In key handler"
            RETURN

 The following strategies can be used to allow processing to continue
 after one key press:

 Sample 1: Using The SLEEP Statement
 -----------------------------------

    CLS
    ON KEY(1) GOSUB handler:
    KEY(1) ON
    PRINT "Press the F1 key"
    SLEEP                    'Note: The SLEEP statement was not supported
    END                      '      until QuickBASIC version 4.00b. This
                             '      example will fail in earlier versions.
    handler:
            PRINT "In key handler"
            RETURN

 Sample 2: Using Flag to Exit Out of INKEY$ Loop
 -----------------------------------------------

    CONST TRUE = -1
    CONST FALSE = NOT TRUE

    CLS
    TrappedFlag% = FALSE
    ON KEY(1) GOSUB handler:
    KEY(1) ON
    PRINT "Press the F1 key"
    WHILE INKEY$ = "" AND NOT TrappedFlag%
    WEND
    END

    handler:
            TrappedFlag% = TRUE
            PRINT "In key handler"
            RETURN

 Sample 3: RETURN to a Fixed Line Label or Line Number
 -----------------------------------------------------

    CLS
    ON KEY(1) GOSUB handler:
    KEY(1) ON
    PRINT "Press the F1 key"
    WHILE INKEY$ = ""
    WEND

    OutOfLoop:
    END

    handler:
            PRINT "In key handler"
            RETURN OutOfLoop:

 WARNING: Do not use the RETURN <line> statement if the ON KEY() GOSUB
 statement at the main-level code traps a key pressed within a SUB or
 FUNCTION procedure, since RETURN <line> would then leave unrecoverable
 return addresses on the stack, which eventually leads to an "Out of
 Stack Space" error after many key-trapping GOSUB iterations. RETURN
 <line> should only be used in the handler for keys trapped at the main
 program level.

 Sample 3 above works without producing the "Out of Stack Space" error
 because no keys are pressed or trapped in SUB or FUNCTION procedures.


 918. How to Run QuickBASIC 4.50 on Two Floppy System (No Hard Disk)

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-SEP-1990    ArticleIdent: Q64787

 This article describes an optimal method to set up and use Microsoft
 QuickBASIC version 4.50 on a dual (two) floppy system that does not
 have a hard drive. You can use either 3.5-inch disks or 5.25-inch
 disks.

 For a listing of the contents of each 4.50 release disk, query in this
 Knowledge Base on the following word:

    QB45QCK

 Make (SETUP) Copies of Release Disks
 ------------------------------------

 To set up QuickBASIC 4.50 to operate on a two-floppy system lacking a
 hard disk drive, you can either use SETUP.EXE or copy all of each
 original floppy to a working floppy disk. Then, put the ORIGINAL disks
 in a safe place. The 5.25-inch (354K) disk version comes on five
 disks.

 Do NOT use the ORIGINAL disks except to make working copies. By never
 using the ORIGINAL disks and just running from copies, you can be more
 sure of having a secure backup. This applies to all software products.

 Because there is insufficient space on one normal-density (354K)
 floppy to have COMMAND.COM, QB.EXE, and QB45QCK.HLP, you should create
 a separate, bootable "source" disk that includes COMMAND.COM. The
 source files of programs that you write can be stored on this source
 disk. Please refer to the FORMAT command in your MS-DOS manual to
 learn how to make a bootable floppy disk.

 How to Set Up 3.5-Inch (720K) Disk Version of 4.50
 --------------------------------------------------

 If you have a 3.5-inch disk system, QuickBASIC comes on three 3.5-inch
 (720K) disks. There is no 3.5-inch Utilities 2 disk because it has
 been combined with the 3.5-inch Utilities 1 disk. If the SETUP program
 prompts you for the Utilities 2 disk, keep the Utilities 1 disk in the
 drive and continue with SETUP.

 For the 3.5-inch (720K) disk version of 4.50 (three disks), set up as
 described below:

 1. Format a bootable disk, then copy the following to it: your MS-DOS
    COMMAND.COM file, all the files you need from the 4.50 Program Disk,
    and the source files you want to compile.

 2. Start up with this Program/source disk in Drive B and the help files
    disk in Drive A. (The QB45ENER.HLP and QB45ADVR.HLP help files will
    be on the same disk, requiring one less swap when you use the Help
    system compared to 354K disks.)

 3. Make Drive B the current drive and type QB.

 4. In QB.EXE, choose Set Paths from the Options menu and set all paths
    with the following:

       A:\;B:\

    Notes
    -----

    When you are prompted for a file not currently in a disk drive, you
    should use Drive A for all disk swaps.

    Press SHIFT+F1 to access the help system.

 How to Run QB.EXE on 354K Floppies
 ----------------------------------

 Once you have created a bootable source disk and copies of the release
 disks as explained above, you can run QuickBASIC on 354K floppies
 as follows:

 1. Insert your copy of the Program disk in Drive A.

 2. Insert your "source" disk in Drive B.

 3. Type the following:

       B:   (to make Drive B the current drive)

 4. Type the following:

       A:\QB    (to run QB.EXE while Drive B is the current drive)

 5. In QB.EXE, choose Set Paths from the Options menu and set all
    paths with the following:

       A:\;B:\

    (This path information is stored in the A:\QB.INI file. If you
    change items in the Options menu, QB.INI is automatically created
    in the directory where you are running QB.EXE.)

 Press SHIFT+F1 to access the help system. When the Program disk is in
 Drive A, no disk swapping is necessary to access the QB45QCK.HLP help
 file. You will be prompted to swap the disk if other .HLP files are
 needed while using the help system.

 When prompted for any disk, swap in Drive A (not in Drive B).

 When you open a source file in QB.EXE (using ALT+F+O), the default
 directory will be the current directory (Drive B), which contains .BAS
 source files.

 How to Use Make EXE File Option on 354K Floppies
 ------------------------------------------------

 If you choose the Make EXE File option (from the Run menu) within
 QB.EXE, the first prompt will be for BC.EXE. The Utilities 1 disk
 should be inserted in Drive A, and your response to the prompt will be
 "A:". This ensures that BC can find the .BAS file in Drive B.

 The .OBJ file will be put in the working directory on Drive B and will
 thus be kept with the source code. (If the working directory was Drive
 A when you invoked QB.EXE, the .OBJ file would be put on the Utilities
 1 disk, which doesn't have enough room to hold the .OBJ file.)

 The next prompt will be for the location of the BCOM45.LIB or
 BRUN45.LIB library (which isn't found automatically yet since Drive B
 is the current drive). In either case, your response should be "A:".
 If you are prompted for BRUN45.LIB, no disk swapping is necessary. If
 you are prompted for BCOM45.LIB, a disk swap is needed.

 The .EXE file will be written to the source disk (in Drive B).

 After the Make EXE File operation is completed, you will be prompted
 for QB.EXE; the response once again is "A:" (which requires another
 disk swap to load QB.EXE).

 As you can see, you will always be using Drive A for disk swapping,
 which should be easy to remember. When in doubt of where to swap,
 always swap in Drive A.

 How to Avoid Excessive Disk Swapping
 ------------------------------------

 Putting all programs necessary for an operation (such as Make EXE
 File) on one disk helps save disk swapping. However, if you plan to
 compile with the BC /O (Stand-alone .EXE) option, note that the size
 of BC.EXE plus BCOM45.LIB is 318,400 bytes, which does not leave
 enough space on a 354K disk to add LINK.EXE, which has 69,133 bytes.
 This means you need to do extra disk swapping when choosing the
 Stand-Alone .EXE (BC /O) option on 354K disks (compared to choosing
 the EXE Requiring BRUN45.EXE option).

 To avoid disk swapping, QuickBASIC can be run on high-density disks
 (such as high-density 3.5-inch floppies, high-density 5.25-inch
 floppies, or a hard disk).

 How to Run an .EXE program
 --------------------------

 To run an .EXE program, quit QB.EXE or choose Shell from the File menu.
 Either one will return you to Drive B where your newly created .EXE
 program is located. If the .EXE is a stand-alone program (compiled BC
 /O, which uses the BCOM45.LIB library), it can be run as is. If the
 EXE requires the run-time module (BRUN45.EXE), the BRUN45.EXE file
 must be located on the source disk (Drive B).

 (QuickBASIC 4.50 may not allow you to use BRUN45.EXE in one drive
 while the other drive is the current drive. If you get the "Input
 Run-time Module Path" prompt, try typing "A:\" instead of
 "A:\BRUN45.EXE". If this doesn't find the BRUN45.EXE module even
 though it is on Drive A, you must put BRUN45.EXE on the source disk in
 the current drive.)

 With both your compiled .EXE program and BRUN45.EXE on the source disk
 (on the current drive), you will not be prompted to find BRUN45.EXE at
 run time. Note that BRUN45.EXE takes up 77,440 bytes of disk space. To
 make more room, remove unneeded sample programs and unneeded .OBJ
 files after making .EXE programs.

 How to Make the SHELL Command Work on Your System
 -------------------------------------------------

 If you get "Illegal Function Call" when you attempt to execute SHELL
 (with the SHELL statement in a program or the DOS Shell option from
 the QB.EXE File menu), you probably do not have the COMMAND.COM file
 in the current disk directory or specified in your COMSPEC MS-DOS
 environment variable. SHELL must know where to find COMMAND.COM.

 Because there is insufficient space on one normal-density (354K)
 floppy to have COMMAND.COM, QB.EXE, and QB45QCK.HLP, Microsoft
 suggests creating a separate, bootable disk that includes COMMAND.COM
 and your source files. When you SHELL to DOS (using the disk strategy
 described in this article), the default drive will be Drive B, which
 contains the bootable source-file disk.

 When doing a SHELL, a program first looks for COMMAND.COM in the
 directory specified by the system COMSPEC environment variable, then
 looks next in the current directory.

 The MS-DOS SET command can be used to assign the COMSPEC environment
 variable in your AUTOEXEC.BAT file or on the MS-DOS command line, as
 follows:

    SET COMSPEC=A:\COMMAND.COM

 To tell MS-DOS where to find COMMAND.COM, you can also specify the
 following command in your MS-DOS version 3.20 CONFIG.SYS file, and
 reboot your system

    SHELL=A:\COMMAND.COM /E:1000 /P

 where /E:<size> sets the size (in bytes) for MS-DOS environment space,
 and /P tells the command processor that it is the first program in the
 system so that it can process the MS-DOS EXIT command. This SHELL=
 statement may not work correctly under MS-DOS version 3.30, but it
 works properly under MS-DOS version 3.20.

 Note: COMMAND.COM is the program that processes all command-line
 arguments that you type in MS-DOS.


 919. C's _getvideoconfig Returns Incorrect Mode If Set from BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C S_QuickC SR# S900808-148
 Last Modified:  4-SEP-1990    ArticleIdent: Q64875

 The C graphics function _getvideoconfig will not correctly return the
 current video mode set by a BASIC program. To work around this
 problem, the BIOS interrupt 10 (hex) function 0F (hex) can be used in
 place of the _getvideoconfig function. This is shown in the sample
 programs below.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50;
 to Microsoft BASIC Compiler versions 6.00 and 6.00b; and to Microsoft
 BASIC Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.

 The following BASIC program, TEST.BAS, sets the video to screen mode 9
 (EGA) and then calls a C function to return the current graphics mode:

    DECLARE FUNCTION CProc% CDECL ()
    SCREEN 9
    CLS
    PRINT "Video mode: "; CProc%
    while inkey$="" : wend
    END

 The following C program, CVID.C, uses the C graphics function
 _getvideoconfig, which returns an incorrect value when the video mode
 has been set by BASIC.

 #include <graph.h>

 int CProc(void) {
    struct videoconfig vc;
    _getvideoconfig(&vc);
    return(vc.mode);
 }

 Compile and link as follows:

    BC TEST.BAS ;
    CL /c /AL CVID.C ;
    LINK /NOE TEST CVID ;

 Normally, the returned video mode will be 3, which is incorrect. The
 following C routine replaces CVID.C. When this is compiled and linked
 to TEST.BAS, the correct video mode, 16, is returned.

 #include <dos.h>

 int CProc(void) {
    union REGS inregs, outregs;
    inregs.h.ah = 0xF;
    int86(0x10, &inregs, &outregs);
    return(outregs.h.al);
 }


 920. "File Not Found ..." If BASIC RUNs a C 6.00 Overlaid Program

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom S_C SR# S900807-15
 Last Modified:  5-SEP-1990    ArticleIdent: Q64877

 When a Microsoft C Professional Development System (PDS) version 6.00
 overlaid program is executed by using the RUN statement from an .EXE
 program compiled in Microsoft QuickBASIC version 4.00, 4.00b, or 4.50,
 or in Microsoft BASIC Compiler version 6.00 or 6.00b, the error
 message "File not found in module ..." will display.

 This is due to BASIC not handling the new C 6.00 methods of overlay
 management. This incompatibility has been corrected in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, and to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS.

 The following programs demonstrate the problem. The first program is
 A.BAS:

    print "in basic"
    run "b.exe"

 Compile and LINK in QuickBASIC 4.00, 4.00b, and 4.50 or Microsoft
 BASIC Compiler version 6.00 or 6.00b:

    BC /O A ;
    LINK A.OBJ ;         [ This LINK creates A.EXE. ]

 The following two programs are the C code that the BASIC program
 calls. The first is B.C:

    void f(void);
    void main(void)
    {
        printf("here is c 6.00\n");
        f();
    }

 The following is C.C:

    void f(void)
    {
        printf("in overlay\n");
    }

 Compile and LINK using Microsoft C PDS 6.00, as follows:

    CL /c /AL b.c ;
    CL /c /AL c.c ;
    LINK b.obj (c.obj) ;

 When A.EXE is run, the following message displays:

    File not found in module A        at address 246B:0042


 921. "Statement Unrecognizable" Using "_" in DATA Statement

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900807-9 B_BasicCom
 Last Modified:  5-SEP-1990    ArticleIdent: Q64896

 The line-continuation character in BASIC (the underscore, "_") cannot
 be used to continue a DATA statement. Using an underscore on a DATA
 statement gives a "Statement unrecognizable" error message at compile
 time. This is a design limitation of the line-continuation feature of
 Microsoft BASIC compilers.

 The following lines, when compiled, demonstrate this behavior:

    DATA 10, 20, 30,_
         40, 50, 60

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS; and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2.


 922. Joystick STICK, STRIG Use BIOS Int 15 Hex, or Direct Hardware

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900822-65 B_BasicCom
 Last Modified: 17-JAN-1991    ArticleIdent: Q65195

 The way in which BASIC handles joystick commands, such as the STICK
 function, STRIG function, and STRIG statement, depends on which kind
 of Intel microprocessor chip the computer has.

 If the computer has either an Intel 80286 or 80386 microprocessor, the
 joystick commands are handled by going through BIOS interrupt 15 hex.
 If the computer has an 8086/8088 or 80186/80188 microprocessor, the
 joystick commands talk directly to the hardware.

 This information applies to Microsoft QuickBASIC versions 3.00, 4.00,
 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 This difference in joystick handling is due to the fact that the ROM
 BIOS routines for handling the joystick are not reliable on the first
 8088- and 8086-based machines. QB.EXE and programs compiled with
 BC.EXE automatically check what type of processor the machine has and
 use that information to decide whether to go through the BIOS or to go
 directly to the port for the joystick.

 This implies that if problems are encountered programming the joystick
 in QuickBASIC on an 80286 or 80386 machine, it is probably due to the
 ROM BIOS functions not working correctly or consistently on that
 machine. On 80286 and 80386 machines, QuickBASIC will make generic
 interrupt 15 hex calls. QuickBASIC should work correctly if the BIOS
 is handling the joystick correctly on 80286 and 80386 machines.

 For more information on how to use the CALL INTERRUPT statement to
 invoke BIOS interrupt 15 Hex to help diagnose game port (or joystick)
 problems, query on the following words:

    STRIG and STICK and BIOS


 923. No CHAIN with ALL, MERGE, DELETE, or Line # in Compiled BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI GWBASIC.EXE BASICA.EXE
 Last Modified: 21-SEP-1990    ArticleIdent: Q65503

 The <filespec> parameter of the CHAIN statement is a string expression
 that identifies the program to which control is passed. In compiled
 BASIC, the filespec may include a path specification, but does not
 allow any other options. This differs from the GW-BASIC and BASICA
 interpreters. QuickBASIC does not support the ALL, MERGE, DELETE, or
 line-number options of the CHAIN statement available in BASICA and
 GW-BASIC. The ALL option, however, can be simulated by using
 QuickBASIC's COMMON statement to share variables between CHAINed
 programs.

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2; to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2; to Microsoft GW-BASIC Interpreter versions 3.20,
 3.22, and 3.23 for MS-DOS; and to all versions of the BASICA
 Interpreter sold by IBM, Compaq, or other original equipment
 manufacturers (OEMs).

 More Information

 GW-BASIC and BASICA interpreter programs assume the extension xxxx.BAS
 on a CHAINed-to file. BASIC compiler 6.00 and 6.00b, BASIC PDS 7.00
 and 7.10, and QuickBASIC 4.00, 4.00b, and 4.50 compiled programs
 assume an extension of xxxx.BAS within the QB.EXE or QBX.EXE
 environment, or an extension of xxxx.EXE if compiled and run outside
 the environment. (In the QB.EXE environment of QuickBASIC 2.00, 2.01,
 or 3.00, you can CHAIN only to xxxx.EXE files, so you must either omit
 the filename extension or specify xxxx.EXE.) To simplify using the
 CHAIN filespec argument, just omit the name extension on the filespec,
 which works the same in all versions of compiled or interpreted BASIC.

 Compiled BASIC does not support the ALL, MERGE, DELETE, or line-number
 options of the CHAIN statement available in BASICA or GW-BASIC. In
 GW-BASIC and BASICA programs, CHAIN with ALL specifies that all
 variables in the current program are passed to the CHAINed-to program.
 This effectively makes every variable COMMON to each program. CHAIN
 with MERGE leaves any OPENed files open, preserves the current OPTION
 BASE setting, and merges new line numbers from the CHAINed program by
 numerical position. Using CHAIN with MERGE also means that any DEFINT,
 DEFSNG, DEFDBL, DEFSTR, or DEF FN statement need not be restated in
 the CHAINed program. The CHAIN with DELETE allows the programmer to
 delete a range of line numbers from the CHAINing program to make room
 for the new lines in a CHAIN MERGEd program. Without the line-number
 option, execution always starts at the beginning of the program.

 The interpreter's CHAIN ALL option can be simulated by using compiled
 BASIC's COMMON blocks.

 Files can be left open across a chain if you compile the program to
 require the run-time module (compile without /O).

 For more information on the syntactical differences between QuickBASIC
 and GW-BASIC/BASICA programs, see Page 312 in the "Microsoft
 QuickBASIC 4.5: Programming In BASIC" manual for QuickBASIC version
 4.50.


 924. BASIC "Statements/Labels Illegal Between SELECT CASE and CASE"

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified: 21-SEP-1990    ArticleIdent: Q65504

 Line numbers are allowed in most BASIC source statements. One area
 line numbers are not allowed in is an area of BASIC's SELECT CASE
 statement. If a line number precedes the first CASE ExpressionList
 part of the statement, the error "Statements/labels illegal between
 SELECT CASE and CASE" will be returned.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 The first versions of BASIC (interpreter) required line numbers for
 every line. For upward compatibility, this feature is still available
 in the newer BASICs. Some statements that are new to the language,
 however, restrict the use of the line number feature. One such
 statement is the SELECT CASE statement. Line numbers are allowed
 anywhere in the statement except between the SELECT CASE
 TextExpression and the first CASE ExpressionList.

 This limitation can be inconvenient to a programmer who wants to use
 line numbers in each line so that the ERL function can report the line
 on which an error occurred. However, with syntax checking turned on in
 QB.EXE or QBX.EXE, it is very unlikely an error will exist.

 The code example below demonstrates this discussion.

 Code Example
 ------------

 CLS
 INPUT "Enter acceptable number (1-10): ", num
 '   Line numbers are OK to use on the SELECT statement:
 10     SELECT CASE num
 ' The following statement generates the error "Statements/labels
 ' illegal between SELECT CASE and CASE":
 15      CASE IS = 10
 ' Removing the "15" eliminates the error.
 '   It is OK to put line numbers inside of the rest of the CASE:
 20         PRINT "Maximum number"
         CASE 6 TO 9
            PRINT "Higher, but not the maximum"
         CASE 2 TO 5
            PRINT "Moderate picker, aren't you"
         CASE 1
            PRINT "A low number indeed"
         CASE ELSE
            PRINT "RESPONSE OUT OF RANGE"
      END SELECT


 925. BC.EXE May Hang Using Single Quotation Marks in String CONST

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist4.00 buglist4.00b buglist4.50
 Last Modified: 21-SEP-1990    ArticleIdent: Q65569

 If you use an editor other than QB.EXE to write a program and BC.EXE
 hangs at compile time, one possible cause is the use of single
 quotation marks to delimit a string literal when declaring a string
 CONST. Using single quotation marks to delimit a string constant
 rather than double quotation marks is incorrect syntax and is flagged
 by QB.EXE, but may cause the BC.EXE compiler to hang. In QuickBASIC
 version 3.00, QB.EXE will also hang as a result of using single
 quotation marks.

 This problem occurs in Microsoft QuickBASIC versions 3.00, 4.00,
 4.00b, and 4.50, and in Microsoft BASIC Compiler versions 6.00 and
 6.00b (buglist6.00, buglist6.00b) for MS-DOS and OS/2. This problem
 was corrected in Microsoft BASIC Professional Development System (PDS)
 version 7.00 (fixlist7.00) for MS-DOS and OS/2.

 When the following one-line program is written with an editor other
 than QB.EXE and compiled using BC.EXE, the BC.EXE compiler will hang.
 (In QuickBASIC 3.00, QB.EXE will hang):

    CONST A$ = 'Hello World'

 The compiler may generate the error "R6000: internal stack overflow"
 before it hangs, or it may go into an infinite loop, generating
 "R6000: Internal stack overflow" errors.

 To work around this problem, use the correct syntax, as follows:

    CONST A$ = "Hello World"

 Note: The CONST statement was first introduced in QuickBASIC 3.00.


 926. Mismatched DEFtypes in Main and SUBs Can Zero SHARED Variables

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900823-150 B_BASICCOM
 Last Modified: 20-SEP-1990    ArticleIdent: Q65584

 If DEFtype statements (DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR, or
 DEFCUR) make passed variables differ in type between a calling routine
 and the SUB or FUNCTION procedure that the calling routine invokes,
 then a "Parameter Type Mismatch" error displays in QB.EXE or QBX.EXE.
 However, if the DEFtype usage makes SHARED or COMMON SHARED variables
 differ in type between procedures, then those variables will be
 unexpectedly 0 (zero) or null at run time.

 Programmers must be very careful to use DEFtype statements
 consistently between procedures that use SHARED or COMMON SHARED
 statements because the compiler or environment cannot catch this case
 of type mismatch.

 This information applies to Microsoft QuickBASIC versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b and 4.50 for MS-DOS; to Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2; and to
 Microsoft Professional Development System (PDS) versions 7.00 and 7.10
 for MS-DOS and MS OS/2. (Note: The CURRENCY data type, declared with
 DEFCUR or the "@" suffix, is only available in BASIC PDS versions 7.00
 and 7.10. Also, LONG integers, declared with DEFLNG or the suffix "&",
 are not supported in QuickBASIC 1.x, 2.x, or 3.00.)

 For more information, query in this Knowledge Base on the following
 words:

    DEFTYPE AND SHARED AND SUB

 The types of variables that are passed (INTEGER, LONG integer, SINGLE
 precision, DOUBLE precision, STRING, or CURRENCY) must match between
 the CALL statement (or FUNCTION procedure invocation) and the formal
 parameter list in the SUB (or FUNCTION) statement.

 Undeclared local variables are allowed in SUBprograms and FUNCTIONs,
 and they are considered to be different from variables declared in the
 main level of code with the same name. Undeclared nonshared, nonpassed
 variables are initialized to a value of zero (for numerics) or null
 (for strings).

 For any SUB or FUNCTION procedure that administers the DEFtype
 statement exactly as in the main level of code, the expected values of
 SHARED variables will pass correctly to that procedure.

 However, if DEFtype affects the SHARED or COMMON SHARED variables in
 the SUB or FUNCTION code differently than in the main code, the values
 of SHARED or COMMON SHARED variables in the offending SUB or FUNCTION
 will be initialized to zero or null. The BC.EXE compiler or
 QB.EXE/QBX.EXE environment cannot trap this kind of type mismatch for
 COMMON SHARED variables, because variables of different types are
 allowed to use the same name. The linker cannot trap this type
 mismatch because BASIC's variables are not public symbols, and thus
 are not known to the linker by name.

 Since neither the environment, the compiler, nor the linker can trap
 the type mismatches for SHARED or COMMON SHARED variables, you must
 exercise care to use DEFtype statements consistently; otherwise,
 variables may be unexpectedly zero or null.

 Code Example
 ------------

 The code example below illustrates improper use of DEFtype statements,
 which inconsistently affects the type of the variable TRUE1 in COMMON
 SHARED. TRUE1 is SINGLE precision and correctly passed in COMMON
 SHARED in the main level, FUN2, and SUB2, but is a local INTEGER
 variable and not passed through COMMON SHARED in FUN1 and SUB1.

 If you type the program below into QB.EXE or QBX.EXE line by line in
 source code order, you will need to change the automatic DEFtype in
 each procedure's window to the DEFINT or DEFSNG statements shown. This
 is because in QB.EXE or QBX.EXE, a procedure automatically inherits
 the DEFtype statement of the window in which the SUB or FUNCTION
 statement was first typed.

 This code can be loaded as is into QB.EXE/QBX.EXE to show the type
 mismatch problem, but note that the QB.EXE/QBX.EXE environment will
 redisplay the DEFtype statements according to the following rules:

    By default, the QB.EXE/QBX.EXE environment makes the DEFSNG
    statements invisible, since SINGLE precision is the default data
    type. Also, if a letter range is not covered by a DEFtype statement
    visible in a procedure's window in QB.EXE/QBX.EXE, then you can
    assume DEFSNG applies to variables with first letters in that
    range. Also, the current DEFtype assignments are determined in
    source code order. The DEFtype for a given range of first letters
    is carried to all subsequent code until changed by any subsequent
    DEFtype statement, and the QB.EXE/QBX.EXE environment displays this
    effect by automatically displaying the correct DEFtype statements
    in each procedure window (remember DEFSNG is invisible).

 Editors other than QB.EXE/QBX.EXE do not change the display of
 DEFtype; thus, you can only figure out the DEFtype for a given range
 of first letters by looking at all DEFtype statements in source code
 order and remember where they are changed by any subsequent DEFtype
 statement(s). (See comments in code below for an example.)

 (Note that the QB.EXE editor in QuickBASIC versions 2.x and 3.00 does
 not change the visibility of any DEFtype statements -- what you see is
 what you get, in source code order. QuickBASIC 1.x does not come with
 an editor. Also, you need to remove the DECLARE statements and
 FUNCTION ... END FUNCTION blocks in the program below to demonstrate
 the type mismatch problem in QuickBASIC 1.x, 2.x, or 3.00.)

 DECLARE FUNCTION fun1% ()
 DECLARE FUNCTION fun2% ()
 DECLARE SUB sub1 ()
 DECLARE SUB sub2 ()

 DEFINT D-O
 ' Note that variables beginning with D through O are now integer. The
 ' variable TRUE1 is not covered by this, thus TRUE1 is a SINGLE
 ' precision variable in COMMON SHARED.
 COMMON SHARED TRUE1
 COMMON SHARED false
 CLS
 false = 0
 TRUE1 = NOT false   ' TRUE1 is assigned a value of -1 (or nonzero)
                     ' since the NOT operator applied to 0 equals -1.
 PRINT "TRUE1 = "; TRUE1
 PRINT "Function #1 returns:  TRUE1 = "; fun1%
 PRINT "Function #2 returns:  TRUE1 = "; fun2%
 CALL sub1
 CALL sub2
 SLEEP 2

 DEFINT A-C, P-Z
 ' If this source is loaded into QB.EXE/QBX.EXE, this displays
 ' DEFINT A-Z, since DEFINT D-O is still in affect from further above;
 ' and putting DEFINT A-C, D-O, and P-Z together makes DEFINT A-Z.
 ' Thus the variable TRUE1 is now a local integer variable and
 ' is not in COMMON SHARED.
 FUNCTION fun1%
  d = TRUE1
  fun1% = d
 END FUNCTION

 DEFSNG A-C, P-Z
 ' If loaded into QB.EXE/QBX.EXE, this displays DEFINT D-O, since
 ' the DEFSNG is automatically made invisible, and D-O are still
 ' defined as integer from further above. TRUE1 is a SINGLE
 ' precision variable in COMMON SHARED.
 FUNCTION fun2%
  d = TRUE1
  fun2% = d
 END FUNCTION

 DEFINT A-C, P-Z
 ' If this source is loaded into QB.EXE/QBX.EXE, this displays
 ' DEFINT A-Z, since DEFINT D-O is still in affect from further above;
 ' and putting DEFINT A-C, D-O, and P-Z together makes DEFINT A-Z.
 ' Thus the variable TRUE1 is now a local integer variable and
 ' is not in COMMON SHARED.
 SUB sub1
   PRINT "In sub #1, TRUE1 = "; TRUE1
 END SUB

 DEFSNG A-C, P-Z
 ' If loaded into QB.EXE/QBX.EXE, this displays DEFINT D-O, since
 ' the DEFSNG is automatically made invisible, and D-O are still
 ' defined as integer from further above. TRUE1 is a SINGLE
 ' precision variable in COMMON SHARED.
 SUB sub2
   PRINT "In sub #2, TRUE1 = "; TRUE1
 END SUB

 Sample Output
 -------------

 TRUE1 is a SINGLE precision variable equal to -1 and correctly passed
 in COMMON SHARED in the main level, FUN2, and SUB2, but is a local
 INTEGER variable equal to zero (0) and not passed through COMMON
 SHARED in FUN1 and SUB1:

    TRUE1 = -1
    Function #1 returns:  TRUE1 =  0
    Function #2 returns:  TRUE1 = -1
    In sub #1, TRUE1 =  0
    In sub #2, TRUE1 = -1


 927. SELECT CASE Documentation Error in "Learn BASIC Now", MS Press

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900828-7 docerr
 Last Modified: 20-SEP-1990    ArticleIdent: Q65599

 In the book "Learn BASIC Now" (Microsoft Press, 1989), an incorrect
 example of the SELECT CASE statement is shown on Pages 116 and 117.

 Page 116 Example
 ----------------

 The (incorrect) example at the bottom of Page 116 is as follows:

    SELECT CASE userNum%
         CASE IS 1 TO 5
              PRINT "The number you entered was between 1 and 5."
         CASE IS 6 TO 10
              PRINT "The number you entered was between 6 and 10."
    END SELECT

 The SELECT CASE example on Page 116 should be corrected to read as
 follows:

    SELECT CASE userNum%
         CASE 1 TO 5
              PRINT "The number you entered was between 1 and 5."
         CASE 6 TO 10
              PRINT "The number you entered was between 6 and 10."
    END SELECT

 Page 117 Example
 ----------------

 The (incorrect) code example on Page 117 is as follows:

    SELECT CASE word$
         CASE IS "a" TO "m"
              PRINT "The word you entered was in the range a to m."
         CASE IS "m" to "z"
              PRINT "The word you entered was in the range m to z."
    END SELECT

 The code example on Page 117 should be corrected to read as follows:

    SELECT CASE word$
         CASE "a" TO "m"
              PRINT "The word you entered was in the range a to m."
         CASE "m" to "z"
              PRINT "The word you entered was in the range m to z."
    END SELECT

 The examples on Pages 116 and 117 incorrectly use the IS keyword in
 the CASE statement. The IS keyword should only be used when specifying
 a relational operator, such as <=, >=, =, or <> in a conditional
 expression. For example

    CASE IS <= 5

 correctly uses the IS keyword.

 SELECT CASE is correctly described in the Online Help system of the
 Microsoft QuickBASIC Interpreter (QBI.EXE version 1.00) on the disk
 that comes with the "Learn BASIC Now" book.

 QBI.EXE version 1.00 has the same language features as QuickBASIC
 version 4.50, but note that QBI.EXE is just an interpreter and cannot
 create .EXE programs.


 928. How to BSAVE and BLOAD Multiple Screen Pages in SCREEN 0

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900817-137 B_BasicCom docerr
 Last Modified: 21-SEP-1990    ArticleIdent: Q65749

 The graphics GET and PUT statements cannot be used to store or draw
 text screens in SCREEN mode 0 (zero). Therefore, it is necessary to go
 directly to video memory, using the BSAVE and BLOAD statements, in
 order to store and draw text mode (SCREEN 0) screens. This article
 gives an explanation and an example of BSAVEing and BLOADing all eight
 of the text mode SCREEN pages available on 256K EGA and VGA graphics
 adapters. The code can be easily adapted for the number of video pages
 supported by any adapter.

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS; and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS.

 In text mode, the video pages, sometimes called video buffers, are
 stored starting at address B800:0000 hex, where the portion before the
 colon is the segment and the portion after is the offset. Each video
 page buffer starts on a 4K boundary (or every &H1000 bytes = 1000 hex
 = 4096 decimal). Therefore, saving video pages is a straightforward
 process of changing to segment &HB800, starting at an offset of n*4096
 (&H1000) bytes for each nth page, and BSAVEing 4K of memory to a file.
 Note that you count pages from 0. Therefore, page 0 is at offset 0 *
 4096, or offset 0, from segment B800 hex, so you start saving at
 address B800:0000. To change the segment pointer used by the BSAVE
 statement in BASIC, use the DEF SEG statement. Because the BSAVE
 statement has an "offset" parameter, it is simple to save multiple
 pages by changing the offset parameter in the BSAVE statement with the
 formula PageN%*4096, where PageN% is the current page (counting from
 zero) being saved.

 For more information about graphics programming and video page
 buffers, see Chapter 3 of "Programmer's Guide to PC and PS/2 Video
 Systems" by Richard Wilton (Microsoft Press, 1987).

 Documentation Error
 -------------------

 Wilton's book (mentioned above) contains a documentation error on Page
 75 when discussing video pages. It incorrectly states the following:

    ...each page starts on a 1 KB (1024-byte) boundary

 This should be corrected to say:

    ...each page starts on a 4 KB (4096-byte) boundary.

 Note that Wilton's book uses "KB" as an abbreviation for kilobyte
 (1024 bytes), whereas this Knowledge Base uses "K".

 The next sentence in Wilton's book correctly states the following:

    The four 80-by-25 pages thus start at B800:0000, B800:1000,
    B800:2000, and B800:3000.

 Code Example
 ------------

 The SLEEP statement in the following program should be replaced with
 the statement INPUT X$ in order to run in QuickBASIC 2.00, 2.01, 3.00,
 or 4.00. (The SLEEP statement was first introduced in QuickBASIC 4.00b
 and BASIC compiler 6.00.)

 FOR i% = 0 TO 7 ' If your EGA only supports 4 pages, use 3, not 7.
   SCREEN 0, 0, i%, i% ' Initialize each screen page.
   CLS
 NEXT

 FOR i% = 0 TO 7 ' If your EGA only supports 4 pages, use 3, not 7.
    SCREEN 0, , i%, i% ' Cycle through the pages and write chars.
    FOR j% = 1 TO 2000
      PRINT CHR$(i% + 127); ' Print some colorful characters.
      COLOR j% MOD 16
    NEXT j%
    filename$ = "page" + CHR$(i% + &H31) + ".pic"
    DEF SEG = &HB800 ' Change segment to video memory.
    BSAVE filename$, i% * &H1000, &H1000 ' Save the i%-th page.
    DEF SEG ' Important: Move back to the default data segment!
    LOCATE 10, 10: COLOR 23: PRINT "Hit any key for next page"
    SLEEP
 NEXT

 WHILE INKEY$ <> "": WEND

 FOR i% = 0 TO 7 ' If your EGA only supports 4 pages, use 3, not 7.
    SCREEN 0, 0, i%, i%
    CLS
    COLOR 7
    PRINT "hit any key to restore page "; i%;
    SLEEP: WHILE INKEY$ <> "": WEND
    filename$ = "page" + CHR$(i% + &H31) + ".pic"
    DEF SEG = &HB800
    BLOAD filename$, i% * &H1000
    DEF SEG
    SLEEP
 NEXT i%

 SCREEN 0, 0, 0, 0 ' Clean up before ending
 KILL "page?.pic"  ' and kill the picture files.
 END


 929. TAB() Function Is Affected by Nonprinting Control Characters

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900916-2 B_BasicCom B_GWBasicI B_BasicInt
 Last Modified:  8-NOV-1990    ArticleIdent: Q65886

 Sending control characters to a device in conjunction with the TAB()
 function may result in output not appearing as desired. This is
 because the TAB() function does not distinguish what is and what is
 not a control character. This behavior is due to the fact that control
 characters and escape sequences are device and hardware specific but
 the TAB() function treats them like any other character.

 This information applies to the following products:

 1. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, 4.50 for MS-DOS

 2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS

 3. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2

 4. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, 3.23 for MS-DOS

 The TAB() function is a device I/O function that moves the print
 position when used in the PRINT, PRINT #, and LPRINT statements. The
 position it moves to is based on how many characters have been sent to
 the file or device.

 When you send ASCII text data to a file or device, TAB() functions as
 desired. But when you send control characters or escape sequences
 (that may be device or hardware specific), the TAB() function counts
 these characters along with the other characters, which results in the
 desired print position being off by the number of "nonprinting"
 control characters sent. This device-independent behavior of TAB() is
 by design.

 To work around this behavior, the program must keep track of the
 current print position and/or the number of control characters sent.
 When keeping track of the current print position, the program can then
 use the SPACE$() or SPC() function to move to the desired position.
 When keeping track of the number of control characters sent, the
 desired column of the TAB() function can be added to the number of
 control characters sent to get the desired print position. The
 following code examples demonstrate both methods.

 Example 1
 ---------

 This example uses the variable CTRLCHARS to keep track of the control
 characters sent for a given line of text, and puts it in the TAB()
 function when evaluating how far to move over:

    10 LPRINT CHR$(27) + CHR$(52)    'SET EPSON PRINTER IN ITALIC MODE
    20 CTRLCHARS = 2
    30 LPRINT TAB(10 + CRTLCHARS) "HELLO"    'PRINT HELLO ON LINE 10

 Example 2
 ---------

 This example uses the SPACE$() function to move the print position to
 the desired column:

    10 LPRINT CHR$(27) + CHR$(52)    'SET EPSON PRINTER IN ITALIC MODE
    20 LPRINT SPACE$(10); "HELLO"    'SPACE OVER 10 PLACES AND PRINT HELLO


 930. How to Get Absolute Address of String Variable in BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900725-36 B_BasicCom
 Last Modified: 19-OCT-1990    ArticleIdent: Q65924

 This article describes how to get the absolute memory address of the
 contents of a variable-length string variable in compiled BASIC. The
 sample code below also shows how to PEEK at the string in memory.

 To get the physical (or absolute) address, you must multiply the
 segment value (which is in paragraphs) by 16 bytes per paragraph, and
 then add the offset value (which is in bytes). However, there are some
 integer tricks necessary to work around the fact that the VARPTR,
 VARSEG, SADD, and SSEG functions return a signed short integer instead
 of an unsigned address, as described further below.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS and MS OS/2; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 The above BASICs use a medium memory model. This means that a compiled
 .EXE program (as well as a program being executed within the QB.EXE or
 QBX.EXE environment) consists of multiple code segments and one data
 segment (DGROUP). In the above BASICs, certain data items, such as
 dynamic non-variable-length-string arrays, reside outside the near
 data segment (DGROUP). In BASIC PDS 7.00 and 7.10, the contents of far
 variable-length strings also reside outside DGROUP. Code and data
 objects can thus be found in various places in memory, and the general
 layout of these items is more complex than in earlier BASICs.

 To determine the absolute address of any data item, you first must
 obtain the segment and offset of that data item.

 The VARSEG function returns the segment of any variable or near string
 descriptor. However, in BASIC PDS 7.00 and 7.10, you must use the SSEG
 function (instead of VARSEG) to find the segment for the contents of
 far strings because VARSEG is useless for far strings. VARSEG just
 finds the segment of the descriptor for near strings in BASIC PDS 7.00
 and 7.10. SSEG can be used to find the segment of the contents of both
 near and far strings in BASIC PDS 7.00 and 7.10.

 The offset can be found with the SADD function (for the contents of
 variable-length strings) or the VARPTR function for all other data
 types (including fixed-length strings).

 The segment value is measured in paragraphs, whereas the offset is
 measured in bytes. You must multiply the segment value by 16 bytes per
 paragraph to convert to bytes. (Segments are numbered on paragraph
 boundaries, which are every 16 bytes.)

 To get the physical (or absolute) address, you must multiply the
 segment value by 16 decimals (10 Hex) and then add the offset value.

 Special Integer Handling Is Required for Addresses Above 32767
 --------------------------------------------------------------

 The VARPTR, VARSEG, SADD, and SSEG functions return values anywhere
 between 0 (zero) and FFFF hex (or between 0 and 65535 in unsigned
 decimal notation).

 However, if VARPTR, VARSEG, SADD, or SSEG return an address value
 between 8000 hex and FFFF hex (or between 32768 and 65535 in unsigned
 decimal notation), which you may assign to a short or long integer,
 then BASIC reports the integer as negative (from -32768 to -1,
 respectively). This occurs because the VARPTR, VARSEG, SADD, and SSEG
 functions return a signed short integer. BASIC does not have an
 unsigned data type. This means that if the integer variable returned
 (from VARPTR, VARSEG, SADD, or SSEG) is negative, you must convert it
 to its equivalent unsigned value and assign to a long integer. (A long
 integer can store positive numbers between 32768 and 65535, unlike a
 short integer.) The Unsigned& FUNCTION below is provided for this
 purpose.

 For more information about converting a BASIC signed integer to
 unsigned and assigning to a long integer, search for a separate
 article using following words:

    how AND convert AND BASIC AND unsigned AND integer

 Code Example of Calculating Absolute Address of String Contents
 ---------------------------------------------------------------

 This program determines the absolute address of the contents of a
 variable-length string in memory. The program also uses the PEEK
 function and prints the string byte by byte. To make the program work
 in BASIC PDS 7.00 or 7.10 when using BC /Fs (far strings) or running
 in QBX.EXE, you must use SSEG instead of VARSEG, as shown (or else the
 wrong address will be used and PEEK will return random characters).

 DECLARE FUNCTION Unsigned& (param%)
 CLS
 strng$ = "Quigzy Sticks are gurus"  ' initialize variable
 offset% = SADD(strng$)    ' Get VARPTR value, assign to short integer
 ' Use only one of the following segment% assignments, depending upon
 ' which BASIC version you have:
 segment% = VARSEG(strng$)  ' Get VARSEG value, assign to short integer
                            ' in QuickBASIC 4.x, BASIC compiler 6.00x.
                            ' In BASIC PDS 7.00/7.10, VARSEG only gives
                            ' segment for near string descriptors;
                            ' VARSEG is useless for far strings.
 'segment% = SSEG(strng$)  ' Get SSEG value, assign to short integer
                           ' in BASIC PDS 7.00/7.10 if using BC /Fs
                           ' (far strings) or running in QBX.EXE.
                           ' SSEG works with far or near strings.
 ' Convert short integer offset% to unsigned long integer loffset& :
 loffset& = Unsigned&(offset%)
 ' Convert short integer segment% to unsigned long integer lsegment& :
 lsegment& = Unsigned&(segment%)
 lsegment& = lsegment& * 16  ' Convert segment paragraphs to bytes.
 address& = lsegment& + loffset&   ' Calculate absolute address.
 DEF SEG = segment%
 FOR i = 0 TO (LEN(strng$) - 1)
   a = PEEK(loffset& + i)          'Print out the string byte by byte.
   PRINT CHR$(a);
 NEXT
 PRINT : PRINT
 PRINT "The above string is located at the following RAM location:"
 PRINT "Absolute machine address in decimal : "; address&
 PRINT "Absolute machine address in hex     :  "; HEX$(address&)

 FUNCTION Unsigned& (param%)
 ' This function returns the unsigned long integer form of the
 ' short integer param%, which was passed as input.
    IF param% < 0 THEN
       Unsigned& = &HFFFF& AND param%
    ELSE
       Unsigned& = param%
    END IF
 END FUNCTION

 Manual Example of Calculating Absolute Address in Hex Notation
 --------------------------------------------------------------

 Multiplying by 16 corresponds to shifting the segment value 4 bits to
 the left in binary notation (2 ^ 4 = 16), or in hex notation, shifting
 the segment value to the left by one hex digit. The easiest way
 manually to multiply by 16 is to work with segment values in Hex and
 append a zero to the right side of the Hex value.

 For example, assume the segment value is &h1234 and the offset value
 is &h4321. To add the segment and offset together and calculate the
 absolute address, you must first multiply the segment by &h10, as
 follows:

    &h1234 times &h10 equals &h12340

 &h12340 is thus the absolute byte location of the segment. Now, add
 the offset to the absolute byte location of the segment, as follows:

    &h12340 plus &h4321 equals &h13661


 931. Using INTERRUPT 15 hex for Time Increments Less Than 1 Second

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900907-9 B_BasicCom
 Last Modified: 18-OCT-1990    ArticleIdent: Q65927

 The resolution of the ON TIMER (n) GOSUB statement is limited to
 increments of 1 second.

 The following are three separate methods to work around this
 limitation (to obtain a smaller time interval):

 1. Use BIOS INTERRUPT 15 hex, with function 86 hex (or, in decimal,
    INTERRUPT 21 with function 134) for resolution at intervals of 976
    microseconds (976 millionths, or .000976 of a second).

 2. Use BIOS INTERRUPT 1A hex (26 decimal) with function 0 for a
    resolution at about 18.20648 ticks per second (or .05492549
    seconds).

 3. Use the ON PLAY statement for resolution at 30 times per second
    (or .0333333).

 This article describes method 1 above. To find two additional
 articles, which explain methods 2 and 3, search in this Knowledge Base
 for the following exact words:

    BASIC and timer and increments and smaller and second

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS.

 By using the INTERRUPT service routine 15 hex with function 86 hex (in
 decimal: INT 21 with function 134) you can delay the execution of the
 program for a interval of 976 microseconds. This interrupt and
 function work properly only on IBM AT and PS/2 class machines, and
 will fail on PC or XT class machines, which do not support this
 function. Method 2 or 3 above can be used if this INTERRUPT fails on
 your machine.

 Note that the INTERRUPT routine is only designed for MS-DOS, and is
 NOT supported under OS/2 protected mode.

 For more information regarding interrupts under MS-DOS, please refer
 to "Advanced MS-DOS Programming, Second Edition", by Ray Duncan,
 published by Microsoft PRESS (1988).

 Sample Code
 -----------

 '| *******************************************************************
 '|   The DELAY% function below uses an interrupt call to suspend the
 '|   execution of the program for a given number of microseconds, in
 '|   integrals of 976 microseconds.
 '|   This program uses BIOS interrupt 15 hex with function 86 hex
 '|   (or, in decimal, interrupt 21 with function 134).
 '|
 '|   NOTE : This interrupt only works on AT and PS/2 machines, and
 '|          will fail on PC or XT class machines. The function will
 '|          return a value of 1 when it fails to delay the program,
 '|          and a value of 0 when it completes the call.
 '|
 '| *******************************************************************

 DECLARE FUNCTION DELAY% (Integral AS LONG)

 '|  Use the following $INCLUDE metacommand in Microsoft QuickBASIC
 '|  4.00/4.00b/4.50 or BASIC Compiler 6.00/6.00B:
 REM $INCLUDE: 'QB.BI'
 '|  You must change 'QB.BI' to 'QBX.BI' above if you are using
 '|  BASIC PDS 7.00 or 7.10.

 FUNCTION DELAY% (Integral&)
         '| Set up the register parameters used by INTERRUPT routine:
         DIM ToDOS AS RegType, FromDOS AS RegType

         '| Interrupt service 15 hex with function 86 hex will suspend
         '| the calling process for a specified interval in microseconds.
         DOSINT% = &H15
         ToDOS.Ax = &H8600

         '| Calculate the Microseconds to pause (Integrals of 976):
         MicroSeconds& = Integral& * 976

         '| The Delay value is a long integer and must be broken into
         '| the component high/low integer parts:
         ToDOS.Dx = VAL("&H" + HEX$(MicroSeconds& MOD &H10000))
         ToDOS.Cx = VAL("&H" + HEX$(MicroSeconds& \ &H10000))

         CALL INTERRUPT (DOSINT%, ToDOS, FromDOS)
         '| This interrupt service only works on a AT or PS/2 machine
         '| and will fail on PC/XT machines, and possible other machines.
         IF FromDOS.Flags AND 1 THEN
            ReturnDelay% = 1    '| Failed interrupt call
         ELSE
            ReturnDelay% = 0    '| Call Worked and should have delayed
         END IF
         '| Return the flag to the caller:
         DELAY% = ReturnDelay%
 END FUNCTION


 932. Explanation of Why BASIC Programs Can Open Devices As Files

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900817-47 B_BasicCom
 Last Modified: 19-OCT-1990    ArticleIdent: Q65935

 This article explains how Microsoft BASIC compilers, QuickBASIC, and
 GW-BASIC can open character device drivers as if they were files, as
 in the following line of code:

    OPEN "\DEV\CON" FOR OUTPUT AS #1

 BASIC can interact with character device drivers in this way because
 this feature is built into MS-DOS.

 This information applies to Microsoft QuickBASIC versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft
 BASIC Compiler versions 6.00 and 6.00b for MS-DOS; to Microsoft BASIC
 Professional Development System (PDS) 7.00 and 7.10 for MS-DOS; and to
 all versions of GW-BASIC (3.23, 3.22, 3.20 and earlier) for MS-DOS.

 DOS supports two types of device drivers: character device drivers and
 block device drivers. Character device drivers drive those devices
 that input and output data one character at a time. A typical
 character device is the keyboard or the line printer.

 DOS provides the ability to open the character device driver for I/O;
 you can access the driver by name as if it were a file. The name can
 be up to eight characters in length. This "name" is internal to the
 device driver and is unrelated to the actual piece of hardware you are
 interacting with. DOS keeps a list internally of the names of
 character device drivers installed at boot time plus some default
 devices that are always present.

 DOS provides several character device drivers by default. Any program
 can open CON (the console), AUX (the communications port), PRN (the
 line printer), and LPT1 or LPT2. For example, when you install
 ANSI.SYS, this device driver replaces the default DOS CON device
 driver; therefore, anything printed to the CON device will actually be
 filtered by ANSI.SYS.

 For an example of sending escape codes to ANSI.SYS in BASIC through
 the CON device, search for a separate article in this Knowledge Base
 using the following words:

    ANSI and ESCAPE and CON and QUICKBASIC

 Some character device drivers can interact with your program by
 sending and receiving control data strings. BASIC provides the IOCTL$
 function and the IOCTL statement to input and output data control
 strings to character device drivers.

 Note: Very few device drivers support IOCTL data control strings.
 BASIC's IOCTL and IOCTL$ work correctly only with device drivers that
 have this ability built in.

 For more information on device drivers, consult a book on programming
 DOS such as "Advanced MS-DOS Programming, Second Edition" by Ray
 Duncan, published by Microsoft Press (1988).


 933. Versions of Utilities (LINK, LIB, Etc.) Shipped with BASIC

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | S_LINK S_EDITOR S_CodeView S_MAKE S_NMAKE B_BasicCom S_PWB
 Last Modified: 17-OCT-1990    ArticleIdent: Q66164

 Below is a list of the specific versions of Microsoft utility programs
 shipped with Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00,
 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; with Microsoft BASIC
 Compiler versions 5.35, 5.36 for MS-DOS and 6.00, 6.00b for MS-DOS and
 MS OS/2; and with Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2.

 This list of utilities includes LINK.EXE (Microsoft Linker), CV.EXE
 (Microsoft CodeView for MS-DOS), CVP.EXE (Microsoft CodeView for MS
 OS/2 protected mode), M.EXE (Microsoft Editor for MS-DOS), MEP.EXE
 (Microsoft Editor for MS OS/2 protected mode), LIB.EXE (Microsoft
 Library Manager), MAKE.EXE (Microsoft Program Maintenance Utility),
 and NMAKE.EXE (newer Microsoft Program Maintenance Utility). LINK.EXE,
 LIB.EXE, MAKE.EXE, and NMAKE.EXE are bound applications (that is, they
 run under either MS-DOS or MS OS/2).

 Note: "Segmented Linker" in the table below means segmented-executable
 linker. A "-" in the table below indicates that the utility is not
 shipped with the product.

                     +-----------------------+
                     | QuickBASIC for MS-DOS |
                     +-----------------------+

 Product  Object  Segmented  Overlay  CV/  M/MEP    LIB  MAKE  NMAKE
 Version  Linker  Linker     Linker   CVP  Editor
 -------  ------  ---------  -------  ---  ------   ---  ----  -----

 1.00      3.02       -         -      -     -        -    -      -
 1.01      3.02       -         -      -     -        -    -      -
 1.02      3.02       -         -      -     -        -    -      -
 2.00       -         -        3.06    -     -        -    -      -
 2.01       -         -        3.06    -     -        -    -      -
 3.00       -         -        3.06    -     -        -    -      -
 4.00       -         -        3.61    -     -        -    -      -
 4.00b      -         -        3.65    -     -        -    -      -
 4.50       -         -        3.69    -     -        -    -      -

 Note that QuickBASIC versions 1.x, 2.x, 3.00, and 4.x cannot take
 advantage of the code overlay capabilities of the overlay linker.

            +---------------------------------------+
            | BASIC Compiler for MS-DOS and MS OS/2 |
            +---------------------------------------+

 Product  Object  Segmented  Overlay  CV/  M/MEP    LIB  MAKE  NMAKE
 Version  Linker  Linker     Linker   CVP  Editor
 -------  ------  ---------  -------  ---  ------   ---  ----  -----

 5.35      1.10       -         -      -     -       -     -     -
 5.36      1.10       -         -      -     -       -     -     -

 For MS-DOS and MS OS/2:

 6.00       -     5.01.20       -     2.20  1.00    3.11  4.07   -
 6.00b      -     5.01.20       -     2.20  1.00    3.11  4.07   -

 +--------------------------------------------------------------------+
 | BASIC Professional Development System (PDS) for MS-DOS and MS OS/2 |
 +--------------------------------------------------------------------+

 7.00       -     5.05          -     2.35  1.20    3.16   -    1.10
 7.10       -     5.10          -     3.10    -     3.17   -    1.11

 Note that Microsoft BASIC Professional Development System (PDS)
 version 7.00 for MS-DOS and MS OS/2 is the first version to support
 the code overlay feature of the linker (LINK.EXE).

 BASIC PDS 7.10 introduces the Programmer's WorkBench (PWB.EXE) version
 1.10 for mixed-language and OS/2 programming.


 934. LSET Can Assign One TYPE Variable to a Different TYPE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901017-34 B_BasicCom
 Last Modified: 12-NOV-1990    ArticleIdent: Q66424

 The LSET statement can assign a variable dimensioned as one
 user-defined TYPE to a variable dimensioned as a different
 user-defined TYPE. This can be useful in assigning string TYPEs that
 differ in length.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 4.50 for MS-DOS, to Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS and MS OS/2, and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 Direct (or LET) assignment of differing TYPEs correctly gives a "Type
 Mismatch" error, because direct assignment requires identical TYPEs.

 LSET allows you to assign any user-defined TYPE variable to any other
 user-defined TYPE variable. However, you must be cautious not to
 mismatch numeric elements (INTEGER, LONG, SINGLE, or DOUBLE) (or
 CURRENCY in BASIC PDS only) when using LSET assignment of record TYPE
 variables, or else you will assign spurious values.

 Note: If the user-defined TYPEs are of different lengths, LSET copies
 only the number of bytes in the shorter of the two variables. For
 example, if you LSET a 10-byte variable into a 2-byte variable, LSET
 will copy only 2 bytes of the larger variable into the smaller
 variable. If you LSET the 2-byte variable into the larger one, it will
 copy only the first 2 bytes of the larger variable.

 In the following code example, LSET assigns a variable of one TYPE to
 a variable of another TYPE.

 Code Example
 ------------

    TYPE Type1
       FirstName AS STRING * 10
       LastName AS STRING * 12
    END TYPE
    TYPE Type2
       FullName AS STRING * 22
    END TYPE
    DIM Var1 AS Type1
    DIM Var2 AS Type2

    Var1.FirstName = "John"
    Var1.LastName = "Smith"
    LSET Var2 = Var1   ' Assigns record variables of differing TYPEs
    PRINT Var2.FullName
    END

 The output is as follows:

    John      Smith


 935. "Learn BASIC Now" Reply Letter: Appnote BB0353

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | policy BB0353 appnote
 Last Modified: 21-NOV-1990    ArticleIdent: Q66489

 Below is the form letter that Microsoft sends in response to
 unsolicited letters from customers who are asking questions about
 "Learn BASIC Now." This form letter is sent out from Microsoft Product
 Support Services (PSS) as application note number BB0353.

 "Learn BASIC Now" is written by Michael Halvorson and David Rygmyr and
 is published by Microsoft Press (1989).

 Note: Page 1 of 2 is shown below for this reply letter. Page 2 of 2,
 the "Product Assistance Checklist," is shown in a separate article
 found by querying for the following words:

    product and assistance and checklist

 BB0353: "Learn BASIC Now" Reply Letter
 --------------------------------------

 Dear "Learn BASIC Now" Customer:

 Thank you for your letter concerning Microsoft Press's "Learn BASIC
 Now."

 "Learn BASIC Now," a Microsoft Press release, is a self-study tutorial
 sold through Microsoft Press. To make "Learn BASIC Now" more
 competitive in the marketplace, the product does not have support
 costs built into the retail price. Therefore, Microsoft is providing a
 900-number support service. Other sources of support include your
 Microsoft Press documentation or using your online help F1 key (if
 possible).

 Microsoft is providing support for "Learn BASIC Now" through a new
 service called "OnCall(TM) for BASIC." To access "OnCall for BASIC," call
 (900) 896-9999. The cost is $2 per minute, and the service is
 available Monday through Friday from 8 AM to 5 PM Pacific Standard
 Time. To obtain the best possible service, we recommend you have your
 Microsoft Press "Learn BASIC Now" reference manual and disks handy
 when you call.

 We welcome your letters containing product suggestions and feedback on
 documentation. Although we are unable to respond to your technical
 questions by letter, we do forward your letters to the "Learn BASIC
 Now" development team. There are many supplemental sources of
 information relating to the BASIC languages, including reference
 guides and books published by Microsoft Press, or you can call our
 "OnCall for BASIC" service at (900) 896-9999.

 Support is also available electronically through Microsoft OnLine and
 CompuServe. One of the features of these services is to provide access
 to the Microsoft Knowledge Base. The Microsoft Knowledge Base contains
 the latest technical information about Microsoft language products.
 For more information about Microsoft OnLine, which is designed for
 software developers, call (800) 443-4672. For more information about
 CompuServe, which is the largest general online information service
 for personal computer users, call (800) 848-8199.

 Thank you for supporting Microsoft Press's "Learn BASIC Now."

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BB0353


 936. QuickBASIC Reply Letters: Appnotes BM0350, BM0351, BM0352

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | policy B_MQuickB BM0350 BM0351 BM0352 appnote
 Last Modified: 13-NOV-1990    ArticleIdent: Q66491

 Below are the three form letters that Microsoft sends in response to
 unsolicited letters from customers who have QuickBASIC for MS-DOS or
 for Macintosh:

    Appnote Number       Description
    --------------       -----------

    BM0350               QuickBASIC Suggestion Reply Letter
    BM0351               QuickBASIC Question Reply Letter
    BM0352               QuickBASIC Problem/Docerr Reply Letter

 These form letters are sent out from Microsoft Product Support
 Services (PSS) as application notes.

 This information applies to Microsoft QuickBASIC versions 1.00, 1.01,
 1.02, 2.00, 2.01, 3.00, 4.00, 4.00b, 4.50 for MS-DOS, and to Microsoft
 QuickBASIC version 1.00 for Apple Macintosh.

 Note: Page 1 of 2 is shown below for each reply letter. Page 2 of 2,
 the "Product Assistance Checklist," is the same for each reply letter,
 and is shown in a separate article found by querying for the following
 words:

    product and assistance and checklist

 BM0350: QuickBASIC Suggestion Reply Letter
 ------------------------------------------

 Dear MS-DOS and Macintosh QuickBASIC Customer:

 Thank you for your letter and suggestion concerning QuickBASIC.
 Although we are unable to respond to your technical questions by
 letter, we do forward your letters to our QuickBASIC development team.
 This procedure provides developers with customer feedback, which will
 in turn make Microsoft's products even better. Now that we can no
 longer respond to letters (unless solicited by Microsoft), we are
 providing the following new service:

 Microsoft now offers a new two-tiered support program for QuickBASIC.
 All QuickBASIC customers will be given two specific phone numbers to
 call. First, our regular toll line is designed to answer questions
 about set up and installation procedures, problem reports, and
 documentation errors concerning our current version of QuickBASIC,
 version 4.50 for MS-DOS and version 1.00 for the Apple Macintosh. You
 can call (206) 646-5101, Monday through Friday (except holidays), 8 AM
 to 5 PM Pacific Standard Time.

 Second, customers who have questions should refer to our 900-number
 support line, which is designed to offer support on programming, code
 debugging, and problem solving issues for all versions of QuickBASIC
 earlier than 4.50, and other issues not supported on our QuickBASIC
 toll line. We are offering this 900-number service to provide a higher
 quality of service, extended hours, and a shorter waiting time. To
 access "OnCall(TM) for BASIC," call (900) 896-9999. The cost is $2 per
 minute, and the service is available Monday through Friday from 6 AM
 to 6 PM Pacific Standard Time. To obtain the best possible service, we
 recommend you be at your computer and have your QuickBASIC reference
 manuals and disks handy when you call. Also, please refer to the
 enclosed product assistance checklist.

 There are many supplemental sources of information relating to the
 BASIC languages, including reference guides and books published by
 Microsoft Press, or you can contact our "OnCall for BASIC" service at
 (900) 896-9999. Support is also available electronically through
 Microsoft OnLine and CompuServe. One of the features of these services
 is to provide access to the Microsoft Knowledge Base. The Microsoft
 Knowledge Base contains the latest technical information about
 Microsoft language products. For more information about Microsoft
 OnLine, which is designed for software developers, call (800)
 443-4672. For more information about CompuServe, which is the largest
 general online information service for personal computer users, call
 (800) 848-8199.

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BM0350

 BM0351: QuickBASIC Question Reply Letter
 ----------------------------------------

 Dear MS-DOS and Macintosh QuickBASIC Customer:

 Thank you for your letter concerning QuickBASIC. Although we are
 unable to respond to your technical questions by letter, we do forward
 your letters to our QuickBASIC development team. This procedure
 provides developers with customer feedback, which will in turn make
 Microsoft's products even better. Now that we can no longer respond to
 letters (unless solicited by Microsoft), we are providing the
 following new service:

 Microsoft now offers a new two-tiered support program for QuickBASIC.
 All QuickBASIC customers will be given two specific phone numbers to
 call. First, our regular toll line is designed to answer questions
 about set up and installation procedures, problem reports, and
 documentation errors concerning our current version of QuickBASIC,
 version 4.50 for MS-DOS and version 1.00 for the Apple Macintosh. You
 can call (206) 646-5101, Monday through Friday (except holidays), 8 AM
 to 5 PM Pacific Standard Time.

 Second, customers who have questions should refer to our 900-number
 support line, which is designed to offer support on programming, code
 debugging, and problem solving issues for all versions of QuickBASIC
 earlier than 4.50, and other issues not supported on our QuickBASIC
 toll line. We are offering this 900-number service to provide a higher
 quality of service, extended hours, and a shorter waiting time. To
 access "OnCall(TM) for BASIC," call (900) 896-9999. The cost is $2 per
 minute, and the service is available Monday through Friday from 6 AM
 to 6 PM Pacific Standard Time. To obtain the best possible service, we
 recommend you be at your computer and have your QuickBASIC reference
 manuals and disks handy when you call. Also, please refer to the
 enclosed product assistance checklist.

 There are many supplemental sources of information relating to the
 BASIC languages, including reference guides and books published by
 Microsoft Press, or you can contact our "OnCall for BASIC" service at
 (900) 896-9999. Support is also available electronically through
 Microsoft OnLine and CompuServe. One of the features of these services
 is to provide access to the Microsoft Knowledge Base. The Microsoft
 Knowledge Base contains the latest technical information about
 Microsoft language products. For more information about Microsoft
 OnLine, which is designed for software developers, call (800)
 443-4672. For more information about CompuServe, which is the largest
 general online information service for personal computer users, call
 (800) 848-8199.

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BM0351

 BM0352: QuickBASIC Problem/Docerr Reply Letter
 ----------------------------------------------

 Dear MS-DOS and Macintosh QuickBASIC Customer:

 Thank you for your letter concerning your QuickBASIC problem and/or
 documentation error. Although we are unable to respond to your
 technical questions by letter, we do forward your letters to our
 QuickBASIC development team. This procedure provides developers with
 customer feedback, which will in turn make Microsoft's products even
 better. Now that we can no longer respond to letters (unless solicited
 by Microsoft), we are providing the following new service:

 Microsoft now offers a new two-tiered support program for QuickBASIC.
 All QuickBASIC customers will be given two specific phone numbers to
 call. First, our regular toll line is designed to answer questions
 about set up and installation procedures, problem reports, and
 documentation errors concerning our current version of QuickBASIC,
 version 4.50 for MS-DOS and version 1.00 for the Apple Macintosh. You
 can call (206) 646-5101, Monday through Friday (except holidays), 8 AM
 to 5 PM Pacific Standard Time.

 Second, customers who have questions should refer to our 900-number
 support line, which is designed to offer support on programming, code
 debugging, and problem solving issues for all versions of QuickBASIC
 earlier than 4.50, and other issues not supported on our QuickBASIC
 toll line. We are offering this 900-number service to provide a higher
 quality of service, extended hours, and a shorter waiting time. To
 access "OnCall(TM) for BASIC," call (900) 896-9999. The cost is $2 per
 minute, and the service is available Monday through Friday from 6 AM
 to 6 PM Pacific Standard Time. To obtain the best possible service, we
 recommend you be at your computer and have your QuickBASIC reference
 manuals and disks handy when you call. Also, please refer to the
 enclosed product assistance checklist.

 There are many supplemental sources of information relating to the
 BASIC languages, including reference guides and books published by
 Microsoft Press, or you can contact our "OnCall for BASIC" service at
 (900) 896-9999. Support is also available electronically through
 Microsoft OnLine and CompuServe. One of the features of these services
 is to provide access to the Microsoft Knowledge Base. The Microsoft
 Knowledge Base contains the latest technical information about
 Microsoft language products. For more information about Microsoft
 OnLine, which is designed for software developers, call (800)
 443-4672. For more information about CompuServe, which is the largest
 general online information service for personal computer users, call
 (800) 848-8199.

 Sincerely,

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services
 BM0352


 937. GAMESHOP.EXE "Error 05", Using SET COMSPEC=COMMAND.COM /E:n

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901101-34
 Last Modified:  5-DEC-1990    ArticleIdent: Q66743

 GAMESHOP.EXE blanks the screen or gives "Error 5" if you mistakenly
 use the COMMAND.COM /E:n option in the COMSPEC environment variable in
 MS-DOS (such as in your AUTOEXEC.BAT file). The following is an
 example:

    SET COMSPEC=C:\DOS\COMMAND.COM /E:256

 This is not considered a problem with Microsoft Game Shop because you
 should normally use only COMMAND.COM /E:n on your SHELL= command in
 your MS-DOS CONFIG.SYS file.

 This information applies to Microsoft Game Shop (released October 15,
 1990) for MS-DOS. (Microsoft Game Shop contains the QuickBASIC QBI.EXE
 interpreter version 1.00, which supports the BASIC language defined by
 Microsoft QuickBASIC version 4.50. The QuickBASIC Interpreter QBI.EXE
 1.00 environment is a subset of the QuickBASIC QB.EXE 4.50
 environment, which is a separate product.)

 The problem comes up after you select a game from the GAMESHOP.EXE
 menu. After selecting a game to play, the screen blanks out and the
 machine is apparently frozen. You can type CTRL+BREAK to break out of
 the program and return to the DOS command line, but you still cannot
 see anything on the screen. By typing CLS or another screen command,
 your screen will return.

 On some machines, you will see the following error statement:

    "ERROR 05 IN MODULE GAMESHOP"
    (Error 5 means "Illegal function call".)

 Remove the /E:n option from the COMSPEC environment variable within
 your AUTOEXEC.BAT file, and instead, set your environment size in your
 CONFIG.SYS file. For example, use the following in your CONFIG.SYS
 file:

    SHELL=C:\DOS\COMMAND.COM /E:256

 The COMSPEC environment variable is used to set the drive, directory
 path, and filename for COMMAND.COM, which is MS-DOS's command
 interpreter. COMMAND.COM switches are not allowed in the COMSPEC
 environment variable and may cause problems. The COMMAND.COM switches
 should be set in the SHELL command in your CONFIG.SYS file as stated
 above.

 This is a limitation only when you are going through the menu in
 GAMESHOP.EXE. You can still run QBI.EXE and run any game you want with
 no problem. Because GAMESHOP.EXE uses a SHELL to run the games, the
 invalid COMSPEC variable causes problems.


 938. How to POKE Keystrokes Such as F3 (Last Command) into Keyboard

 Product Version(s): 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  8-NOV-1990    ArticleIdent: Q66744

 Instead of using CALL INTERRUPT to push keystrokes into the keyboard
 buffer, the code example below POKEs a key directly into the keyboard
 buffer area in memory under MS-DOS.

 This information applies to QuickBASIC versions 3.00, 4.00, 4.00b, and
 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS; and to Microsoft BASIC Professional Development System
 (PDS) versions 7.00 and 7.10 for MS-DOS.

 In many applications, it is often useful to echo the command line to
 the screen during repetitive execution of a program. This makes the
 program easier to use by allowing you to avoid typing in the command
 line at the completion of each instance of the program. The code
 example below shows a quick way to push the F3 keystroke into the
 keyboard buffer, which echoes the previously entered command line to
 the screen.

 Code Example
 ------------

 DEF SEG = 0      ' Set default segment to 0
 POKE 1054,0      ' Push 0 for extended key into keyboard buffer
 POKE 1055, 61    ' Push F3 key scan code into keyboard buffer
 POKE 1050, 30    ' Set beginning (head) buffer position
 POKE 0152, 32    ' Set ending (tail) buffer position
 DEF SEG          ' Return current segment pointer to default segment

 References
 ----------

 For more articles about reading from and writing to the keyboard
 buffer, search in this Knowledge Base for the following words:

    interrupt and keyboard and buffer

 The addresses for the keyboard buffer area, head, and tail (used in
 the above code example) are documented in "The New Peter Norton
 Programmer's Guide to the IBM PC & PS/2" by Peter Norton and Richard
 Wilton, published by Microsoft Press (1988).

 Keyboard scan codes are documented in Appendix D of "Microsoft
 QuickBASIC 4.5: Programming in BASIC"; in Appendix A of "Microsoft
 QuickBASIC 4.0: Language Reference" for 4.00 and 4.00b; in Appendix A
 of "Microsoft BASIC Compiler 6.0: Language Reference" for 6.00 and
 6.00b; and in Appendix A of "Microsoft BASIC 7.0: Language Reference"
 manual for BASIC PDS versions 7.00 and 7.10.


 939. "Product Assistance Checklist" for BASIC/Pascal Reply Letters

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | appnote B_BasicCom B_GWBasicI B_BasicInt S_Pascal S_QuickPas
 Last Modified: 14-NOV-1990    ArticleIdent: Q66770

 The "Product Assistance Checklist" shown below accompanies the
 following application notes as page 2 of 2:

    Appnote
    Number  Title
    ------  -----

    BM0350  QuickBASIC Suggestion Reply Letter (MS-DOS and Macintosh)
    BM0351  QuickBASIC Question Reply Letter (MS-DOS and Macintosh)
    BM0352  QuickBASIC Problem/Docerr Reply Letter (MS-DOS and Macintosh)

    BB0353  "Learn BASIC Now" Reply Letter

    BB0354  BASIC PDS Question Reply Letter
    BB0355  BASIC PDS Suggestion Reply Letter
    BB0356  BASIC PDS Problem/Docerr Reply Letter

    BB0357  GW-BASIC/Other Interpreters Reply Letter

    BP0359  Pascal Suggestion Reply Letter
    BP0360  Pascal Question Reply Letter
    BP0361  Pascal Problem/Docerr Reply Letter

 For the contents of page 1 of 2 for each application note, search in
 this Knowledge Base for the number of the individual application note.

 Product Assistance Checklist
 ----------------------------

 This checklist is designed to assist you when you need help with a
 Microsoft product. Before you call Microsoft, please gather all
 information that applies to your problem. So that we can assist you as
 quickly as possible, note any on-screen messages that appear when the
 problem occurs. Have your manuals and product disks close at hand and
 have all the information requested on this form available when you
 call.

 Diagnosing the Problem
 ----------------------

 Many common problems are related to how the system's environment is
 set up.

 Under MS-DOS, to ensure that your system is using the utilities and
 programs that came with your Microsoft product, check your system's
 path and directory structure. Pay particular attention to device
 drivers loaded in your CONFIG.SYS file and any programs that you load
 from your AUTOEXEC.BAT file, such as TSR (terminate and stay resident)
 utilities. You can rename these system configuration files and restart
 your system to determine if the contents of these files are related to
 your problem.

 Under Apple Macintosh systems, you may need to remove INIT files or
 other memory-resident programs from the System Folder; then restart the
 Macintosh to determine if a conflict is occurring.

 Please be prepared to answer the following questions regarding your
 problem, your hardware, and your software.

 General Information
 -------------------

 1. What product and version number are you using?

 2. Can you reproduce the problem?

 3. Does the problem occur with another copy of the original disk of
    your Microsoft software?

 4. Does the problem occur on another computer system, if available?

 5. If you are running any other software at the same time, such as a
    windowing environment or memory-resident utility, does the problem
    still occur when you don't use the other software?

 Software
 --------

 1. Operating system name and version. (You can determine the version
    by typing the VER command at the MS DOS or OS/2 prompt. On Apple
    Macintosh systems, select "About the Finder" from the Apple menu.)

 2. Network software? Does the problem still occur without the network
    loaded?

 3. Microsoft Windows, or other windowing environment, and version?

 4. Other software loaded (keyboard enhancers, print spoolers, etc.)?

 Hardware
 --------

 1. Computer manufacturer and model.

 2. Memory configuration.

 3. Video graphics adapter and display manufacturer and model.

 4. Other boards and peripherals (mouse, printer, network interface,
    etc.).

 The Microsoft Knowledge Base containing answers to common questions
 and descriptions of known problems is available on the CompuServe
 information service. For information about CompuServe, call (800)
 848-8990.

 Microsoft Product Support Services also provides Microsoft OnLine and
 OnLine Plus, which are comprehensive electronic support options
 oriented specifically for the software developer and corporate
 customer. For more information on these services, please contact
 Microsoft OnLine Telemarketing at (800) 443-4672.


 940. BASIC Files Limited to 32 MB Without DOS 4.00/4.01 Patch

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901107-113 B_BASICCOM
 Last Modified:  5-DEC-1990    ArticleIdent: Q67147

 QuickBASIC or other programs that use file I/O (Input/Output) may give
 incorrect results when accessing files larger than 32 megabytes (MB)
 under MS-DOS versions 4.00 and 4.01. (MS-DOS 4.00 and later introduce
 the capability for file sizes larger than 32 MB.) This is a problem
 with MS-DOS 4.00 and 4.01, and can be corrected with a program called
 PATCH32M available in the Software/Data Library and as an application
 note from Microsoft.

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50; to Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 Under DOS 4.00 and 4.01, when you append to files larger than 32
 megabytes in length, BASIC's LOF function returns incorrect values for
 the file length. Specifically, if you write to a random-access file,
 and the size moves past the 33,554,432 byte (32 MB) boundary, the file
 size given by MS-DOS's DIR command and BASIC's LOF function may remain
 at the last even record boundary below 33,554,432 bytes. However, the
 file will be written properly, and a CHKDSK /F followed by a DIR will
 return the correct size.

 This is a problem in MS-DOS versions 4.00 and 4.01, and can be
 corrected by running the patch program PATCH32M.EXE available in the
 Software/Data Library. For information on how to obtain PATCH32M.EXE,
 search in the Software/Data Library for the word PATCH32M.

 Additional information may be found by querying in the Microsoft
 Knowledge Base on the following words:

    DOS and 4.01 and 32 and MB


 941. DRAW Statement to Erase or Redraw Image May Not Work Correctly

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM B_GWBASICI buglist4.00 buglist4.00b buglist4.50
 Last Modified:  5-DEC-1990    ArticleIdent: Q67205

 Under some circumstances the DRAW statement will incorrectly redraw
 the same figure.

 A common method of erasing an image is to draw an image with the
 drawing color and then redraw it with the background color. However,
 as this article describes, it is possible that DRAWing the exact same
 picture over the previously drawn picture may not completely erase the
 image, resulting in "droppings" being left on the screen.

 Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
 Compiler versions 2.00, 2.01, 3.00, 4.00, 4.00b, and 4.50 for MS-DOS;
 in Microsoft BASIC Compiler versions 6.00 and 6.00b (buglist6.00,
 buglist6.00b) for MS-DOS and MS OS/2; in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 (buglist7.00,
 buglist7.10) for MS-DOS and MS OS/2; and in Microsoft GW-BASIC
 Interpreter versions 3.20, 3.22, and 3.23 (buglist3.20, buglist3.22,
 buglist3.23). We are researching this problem and will post new
 information here as it becomes available.

 When the DRAW command "TA" is executed, the angles calculated should
 be consistent. However, a second iteration of the same command with a
 different color produces a slightly different image.

 The problem seems to occur only in certain examples, regardless of the
 screen mode or product version used. Microsoft has duplicated this
 problem only when using the "TA" angle rotation command in conjunction
 with a "B" (move but don't plot) command.

 The code example below demonstrates this problem. The program below
 continually draws a line and then immediately redraws that line with
 the background color to erase the line. On each iteration of the loop,
 the angle of the line is rotated. For a few of the lines, the DRAW
 command will not completely erase some of the lines drawn.

 Code Example
 ------------

 SCREEN 9: CLS
 L$ = "U65 BU5 D70"
 DO
         FOR i = 0 to 360 STEP 3
                 DRAW "C14TA=" + VARPTR$(i) + L$
                 DRAW "C0TA=" + VARPTR$(i) + L$
         NEXT i
 LOOP UNTIL INKEY$ <> ""
 END

 In this specific example, the "BU" command must be in the DRAW string
 or the problem will not occur.

 Additional reference words: buglist3.00 buglist2.01 buglist2.00


 942. Keywords Limited to 9 Characters When Adding to QB 4.50 Help

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist4.50
 Last Modified:  5-DEC-1990    ArticleIdent: Q67312

 This article describes a specific problem encountered when adding to
 the online help file (QB45QCK.HLP) for QuickBASIC version 4.50 using
 HELPMAKE.EXE. The problem occurs only if you add a keyword that is
 larger than 9 characters.

 When the cursor is on a keyword larger than 9 characters and you press
 the F1 key (context-sensitive help), the QuickBASIC environment
 mistakenly displays QuickBASIC's "Symbol Help" screen for that
 keyword, instead of the context-sensitive help that you added to the
 help file. (The "Symbol Help" screen describes one of the symbols in
 your program, such as a variable, SUB, or FUNCTION description.) This
 behavior only occurs when you add keywords larger than 9 characters
 and attempt to make them "context sensitive." However, you can still
 access the help for the keyword you have added by choosing
 QuickBASIC's Help menu, selecting Index, and then selecting the
 correct topic in the index help screen.

 This limitation applies only to Microsoft QuickBASIC version 4.50.
 This limitation does not apply to the QuickBASIC extended environment
 (QBX.EXE), which comes with the BASIC Professional Development System
 (PDS) 7.00 and 7.10 for MS-DOS.

 You can easily work around this problem. To select a customized
 keyword from the QuickBASIC 4.50 environment, you should only add the
 first 9 characters of the intended keyword to QuickBASIC's online help
 file. For example, if you want to add AddMenuItem (an 11-character
 keyword) to the help file, truncate AddMenuItem to AddMenuIt (9
 characters). This lets you use the F1 key for context-sensitive help
 in the environment. The side effect of this strategy is that pressing
 F1 for a variable, such as AddMenuItemIndex% (or any other variable
 where the first 9 characters are "AddMenuIt"), always gives the
 context-sensitive help (Topic Help) that you added for AddMenuItem,
 instead of QuickBASIC's Symbol Help.

 For more information on how to modify QuickBASIC's online help file,
 please refer to the HELPMAKE.DOC file distributed on disk with the
 "HELPMAKE Utility Version 1.00 for QB 4.50" application note available
 from Microsoft Product Support Services. The HELPMAKE utility is also
 documented in Chapter 8, "HELPMAKE," in the "Microsoft QuickC Version
 2.0: Toolkit" manual.


 943. How to Use CALL INTERRUPT to Diagnose COM "Device I/O" Error

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM
 Last Modified:  5-DEC-1990    ArticleIdent: Q67315

 This article contains a code example showing how to obtain and decode
 the information contained within the communications line-status and
 modem-control registers. The contents of the registers is found by
 calling BIOS interrupt 14 hex, with function 3. This information is
 helpful in pinpointing the cause of communications port (COM1 or
 COM2), errors such as "Device I/O" errors.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS and to Microsoft BASIC PDS (Professional
 Development System) versions 7.00 and 7.10 for MS-DOS.

 Calling interrupt 14 hex with function 3 hex is helpful in finding
 whether a "Device I/O" error stems from problems such as break,
 framing, or overrun problems during communications. If you are trying
 to pinpoint the underlying cause of a communications error, you should
 call the interrupt from within an ON ERROR GOTO handler in your BASIC
 program. The code sample below demonstrates how the communications
 port status can be checked when a "Device I/O" error is generated.

 For more information on how to overcome communications-related errors,
 query on the following words:

    Device I/O and solve and common and communications and port and
    problems

 Information on interrupt 14 hex with function 3 hex can be found in
 the following books:

    "The New Peter Norton Programmer's Guide to the IBM PC & PS/2; the
    Ultimate Reference Guide to the Entire Family of IBM Personal
    Computers" by Peter Norton and Richard Wilton, published by
    Microsoft Press (1985). See page 230.

    "The Programmer's PC Sourcebook" by Thom Hogan, published by
    Microsoft Press (1988). See page 220.

 To run the following sample program in the environment, the quick
 library QB.QLB (or QBX.QLB, if using BASIC PDS) must be loaded as
 follows:

    QB /L QB.QLB      [The DOS command line if using QuickBASIC]
    QBX /L QBX.QLB    [The DOS command line if using BASIC PDS]

 To make an .EXE file from DOS, the compiled program must be linked
 with the library QB.LIB (or QBX.LIB, if using BASIC PDS).

 Code Example
 ------------

 DECLARE SUB GetPortStatus (MessageCount%)
 '$INCLUDE: 'qb.bi'   'Include this line if using QuickBASIC
 '$INCLUDE: 'qbx.bi'   'Include this line if using BASIC PDS
 DIM SHARED InRegs AS RegType, OutRegs AS RegType
 DIM SHARED StatusMessage(15) AS STRING * 35
 CLS
 ON ERROR GOTO ErrorHandler:
 ERROR 57      'This statement forces a "Device I/O" error

 ' The following code (REMARKed out) is a sample routine that reads
 ' communications port input. Remove the ERROR 57 line above and the
 ' REMARKs in this section of code to run the sample when data is being
 ' sent from another device to COM1. It is unlikely that the following
 ' code segment will generate a "Device I/O" error. The code is merely
 ' included as an indication of where the communications routine is
 ' located relative to the rest of the code. It is recommended that you
 ' replace the following code segment with your own communications
 ' routine, especially if your code leads to "Device I/O" or other
 ' communications related errors.

 'OPEN "COM1:300,N,8,1,BIN,CD0,CS0,DS0,OP0,RS,TB2048,RB2048" FOR _
  RANDOM AS #1

 'WHILE LOC(1)=0
 'WEND

 'WHILE NOT EOF(1)
 '   a$ = INPUT$(LOC(1),1)
 'WEND

 Done:
 'CLOSE #1
 END

 ErrorHandler:
    IF ERR = 57 THEN
       CALLGetPortStatus(LastMessage%)
       FOR i% = 0 TO LastMessage% - 1
          PRINT StatusMessage(i%)
       NEXT i%
    END IF
    RESUME Done:

 REM $STATIC
 SUB GetPortStatus (MessageCount%)
    MessageCount% = 0
    InRegs.AX = &H300   ' Load the service number 3 hex in the
                        ' high byte of AX
             ' Call BIOS interrupt 14 hex
    CALL Interrupt(&H14, InRegs, OutRegs)

    ' Decode the upper 8 bits of AX containing line-status
    ' register information:

    IF OutRegs.AX AND 2 ^ 8 THEN
       StatusMessage(MessageCount%) = "Data ready"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 9 THEN
       StatusMessage(MessageCount%) = "Overrun error"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 10 THEN
       StatusMessage(MessageCount%) = "Parity error"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 11 THEN
       StatusMessage(MessageCount%) = "Framing error"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 12 THEN
       StatusMessage(MessageCount%) = "Break-detect error"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 13 THEN
       StatusMessage(MessageCount%) = _
          "Transfer holding register empty"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 14 THEN
       StatusMessage(MessageCount%) = "Transfer shift register empty"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 15 THEN
       StatusMessage(MessageCount%) = "Time-out error"
       MessageCount% = MessageCount% + 1
    END IF

    ' Decode the lower 8 bits of the AX register containing
    ' modem-status information:

    IF OutRegs.AX AND 2 ^ 0 THEN
       StatusMessage(MessageCount%) = "Delta clear-to-send"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 1 THEN
       StatusMessage(MessageCount%) = "Delta data-set-ready"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 2 THEN
       StatusMessage(MessageCount%) = "Trailing-edge ring detector"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 3 THEN
       StatusMessage(MessageCount%) = _
          "Delta receive line signal detect"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 4 THEN
       StatusMessage(MessageCount%) = "Clear-to-send"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 5 THEN
       StatusMessage(MessageCount%) = "Data-set-ready"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 6 THEN
       StatusMessage(MessageCount%) = "Ring indicator"
       MessageCount% = MessageCount% + 1
    END IF
    IF OutRegs.AX AND 2 ^ 7 THEN
       StatusMessage(MessageCount%) = "Received line signal detect"
       MessageCount% = MessageCount% + 1
    END IF
 END SUB


 944. CLEAR Can Cause "Subscript out of Range" with $DYNAMIC Array

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom
 Last Modified:  5-DEC-1990    ArticleIdent: Q67373

 Increasing the stack space with the CLEAR statement also reinitializes
 all variables. This includes erasing the memory for any $DYNAMIC
 arrays and initializing the elements of a $STATIC array to zero or
 null strings. For this reason, CLEAR should normally be used only as
 the very first executable statement in a program. Using it anywhere
 else can cause problems. For example, once you have used CLEAR, if you
 attempt to access an element of a $DYNAMIC array, the error "Subscript
 out of range" will be generated. This is expected behavior because the
 CLEAR statement deallocates all memory for the dynamic array. After a
 CLEAR, all $DYNAMIC arrays must be re-created with the REDIM
 statement.

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2; to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2; and to all versions of GW-BASIC (such as 3.20,
 3.22, 3.23) for MS-DOS.

 The following code block produces the error "Subscript out of range"
 on the "x(11) = 34" assign statement:

 COMMON x()
 DIM x(30)
 CLEAR , , 4000
 x(11) = 34

 Suggested Solution #1
 ---------------------

 Create a dynamic variable and redimension the variable.

 ' $DYNAMIC
 COMMON x()
 DIM x(30)
 CLEAR , , 4000
 REDIM x(30)
 x(11) = 34

 Suggested Solution #2
 ---------------------

 In QuickBASIC version 4.00 or later, or BASIC compiler version 6.00 or
 later, use the LINK /ST[ACK]:n option, where n is the amount of bytes
 to allocate to the stack space out of DGROUP (maximum allowable stack
 is somewhere less than 64K).

 Reference
 ---------

 For related articles, query on the following words:

    LINK and STACK and default and size and 3.00 and 4.00 and QuickBASIC


 945. How to Use CALL INTERRUPT to Detect If SHARE.EXE Is Loaded

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM
 Last Modified:  5-DEC-1990    ArticleIdent: Q67379

 SHARE.EXE provides file sharing and locking to MS-DOS versions 3.00
 and later. To determine whether SHARE.EXE is currently loaded, you can
 make a call to the MS-DOS interrupt, &H2F (2F hex). You should load
 the ax register with &H1000 before the CALL INTERRUPT statement. After
 the call, the ax register will return with the value &H00FF (ff hex)
 if SHARE.EXE is loaded.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and
 6.00b for MS-DOS; and to Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS.

 The following program demonstrates how to call interrupt &H2F to
 detect if SHARE.EXE is loaded. It makes the interrupt call and then
 PRINTs what the three separate types of returns can mean. To use this
 program in the QB.EXE or QBX.EXE environment, use the /L environment
 switch to load the default Quick library, QB.QLB (or QBX.QLB for BASIC
 PDS 7.00 or 7.10). To make an executable program from this code, you
 must link with the library, QB.LIB (or QBX.LIB for BASIC PDS 7.00 or
 7.10).

 Program Example
 ---------------

 ' Use 'QBX.BI' with BASIC PDS 7.10 or 7.00 instead of 'QB.BI':
 REM $INCLUDE: 'QB.BI'

 DIM inregs as regtype
 DIM outregs as regtype
 inregs.ax = &H1000
 CALL interrupt(&H2F,inregs,outregs)

 ' CHECK results.
 IF outregs.ax = &HFF THEN
    PRINT "SHARE.EXE installed"
 ELSEIF outregs.ax = &H1 THEN
    PRINT "SHARE.EXE not installed, NOT O.K. to install"
 ELSE  ' outregs.ax = &H0
    PRINT "SHARE.EXE not installed, O.K. to install"
 ENDIF
 END


 946. Unexpected Results Using DOS TYPE to Display RANDOM File

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901119-101 B_BASICCOM B_GWBasicI
 Last Modified:  9-JAN-1991    ArticleIdent: Q68026

 When you display the contents of a BASIC RANDOM or BINARY access file
 with DOS's TYPE command, you may see unexpected or extra characters
 (as in example 1 below) and/or the file may appear truncated (as in
 example 2). This is because the TYPE command is designed to only
 display ASCII text files. Using the TYPE command on a non-ASCII file
 will produce output that resembles a corrupted or invalid file, but is
 actually valid binary numeric information readable from certain
 programs.

 This behavior of the DOS TYPE command occurs for binary numeric data
 stored files created in most Microsoft BASICs:

 1. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, 4.50 for MS-DOS (BINARY access was introduced in
    QuickBASIC 4.00 and later).

 2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS OS/2 and
    MS-DOS.

 3. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2.

 4. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, 3.23 for
    MS-DOS (RANDOM access supported, but not BINARY access).

 If extra text, which you did not write, appears in a file opened with
 RANDOM access, then you may be mistakenly writing a record size
 smaller than the RANDOM record buffer size you specified in your OPEN
 statement. (See example 1 below.)

 When you OPEN a file with RANDOM or BINARY access, PUT writes a
 numeric (INTEGER, LONG, CURRENCY, SINGLE, or DOUBLE) variable with a
 bit-by-bit representation. For instance, if you PUT the INTEGER 35 to
 a RANDOM file, the DOS TYPE command will not display 35, but will
 instead display an ASCII representation of the 2 bytes that make up
 the integer variable:

                                          Byte 1        Byte 2
                                          ------        ------

    Binary integer representation of 35:  00000000      00100011
    Decimal value of byte:                0             35
    ASCII Character representation:       NULL (blank)  #

 Because an INTEGER variable is stored in 2 bytes in two's complement
 signed binary integer format, DOS's TYPE command will display the
 INTEGER 35 as an ASCII blank followed by the ASCII # character.

 Thus, byte values from 0 to 255 will be displayed by DOS's TYPE
 command as control characters (ASCII 0 through 31), normal text (ASCII
 32 through 127), and line draw, symbolic, and foreign alphabetic
 characters (extended ASCII 128 through 255).

 Also, if DOS's TYPE command encounters any binary byte value equal to
 26, the output will be truncated at that point because TYPE treats 26
 (or CTRL+Z) as an end-of-file marker for ASCII text files.

 Code Examples
 =============

 The sample programs below apply to Microsoft QuickBASIC versions 4.00,
 4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00
 and 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2. (Earlier BASIC versions do not support the TYPE...END TYPE
 statement, or the new third argument for the PUT statement syntax,
 which is used in the examples below.)

 Example 1:
 ---------

 Below is an example of how extra characters will appear in your RANDOM
 access file if you mistakenly write a record size smaller than the
 record buffer size you specified in your OPEN statement.

 When you OPEN a RANDOM access file, the PUT statement writes only as
 many characters as are in the variable being PUT. If the record length
 you specified in your OPEN statement exceeds the number of characters
 that you PUT, then PUT does not fill out the remainder of the record
 or clear the remaining information that was previously on the disk.
 This location may contain unpredictable data from an old file that was
 deleted. (To avoid this problem, make sure to PUT records of a size
 equal to the OPEN statement's record buffer length, and don't leave
 records or portions of records unwritten.)

      TYPE FileOutput
           TextString AS STRING * 50
      END TYPE
      DIM FileVar(3) AS FileOutput
      FileVar(0).TextString = "Hello World"
      FileVar(1).TextString = "Hello Again"
      F$ = "TESTFILE.DAT"
      OPEN F$ FOR RANDOM AS #1 LEN = 70
      PUT 1, 1, FileVar(0)
      PUT 1, 2, FileVar(1)
      GET 1, 1, FileVar(2)
      GET 1, 2, FileVar(3)
      CLOSE #1
      PRINT FileVar(2).TextString        'Prints correct information
      PRINT FileVar(3).TextString        'Prints correct information
      SHELL "TYPE TESTFILE.DAT"          'May show extra characters
      'Extra characters will appear in positions 51-70.

 Also, the following example demonstrates how you can apparently
 receive extra characters in a variable.

      TYPE FileIO1
           TextString AS STRING * 50
      END TYPE
      TYPE FileIO2
           TextString AS STRING * 70
      END TYPE
      DIM FileVar1 AS FileIO1
      DIM FileVar2 AS FileIO2
      FileVar1.TextString = "Hello From 1"
      OPEN "TESTFILE.DAT" FOR RANDOM AS #1 LEN = 70
      PUT 1, 1, FileVar1
      PUT 1, 2, FileVar1
      GET 1, 1, FileVar2
      PRINT FileVar2           ' May contain extra characters
      CLOSE #1

 Example 2:
 ---------

 DOS's TYPE command will print the contents of a file to the screen
 until it reads an end-of-file (EOF) marker, a byte value equal to 26.
 (But in the File Allocation Table on disk, MS-DOS itself keeps track
 of the exact length of the file, instead of using CTRL+Z to mark the
 end of file.)

 It is possible for a byte value equal to 26 to correctly occur in your
 random access file without your realization. An example of this
 follows. (This example requires QuickBASIC 4.00b or later, where a
 2-byte string length is written to disk in front of variable-length
 strings written as the third argument of the PUT statement.)

    FileName$ = "TESTFILE.DAT"
    OPEN FileName$ FOR RANDOM AS #1 LEN = 80
    FOR I = 1 TO 5
       READ L$
       'L$ = LEFT$(L$+SPACE$(80), 78)   'Gets rid of extra characters
       PUT 1,,L$
    NEXT I
    CLOSE #1
    SHELL "TYPE TESTFILE.DAT"
    DATA "This line is fine"
    DATA "This line is also fine"
    DATA "This line is 26 characters"
    DATA "This line won't be printed by TYPE"
    DATA "neither will this line"

 The results will be:

    ##This line is fine***********************************
    ##This line is also fine******************************

 Note: ## refers to the 2-byte string length; * refers to a possible
 extra character.

 The third through fifth lines are not printed because QuickBASIC
 includes a 2-byte integer, which stores the length of the string,
 before each variable length string. Because the third line is 26
 characters long, QuickBASIC stores a CHR$(26) before the third line.
 The DOS command TYPE then interprets the CHR$(26) as an EOF marker.

 Note that even though DOS's TYPE command did not display all of your
 file, you can still GET all the information in the file.


 947. Checking Game Port with CALL INTERRUPT If STICK & STRIG Fail

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901115-120 B_BasicCom
 Last Modified: 17-JAN-1991    ArticleIdent: Q68121

 If you are experiencing problems with BASIC's game port (or joystick)
 routines, such as STICK or STRIG, this article provides information
 that may help you to diagnose whether the symptom is the result of a
 ROM BIOS problem. This information applies only if your computer has
 an Intel 80286 or 80386 microprocessor chip.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS; and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS.

 The way in which BASIC handles joystick commands (which include the
 STICK function, STRIG function, and STRIG statement) depends on which
 kind of Intel microprocessor chip the computer uses. If the computer
 has an 8086/8088 or 80186/80188 microprocessor, the joystick commands
 talk directly to the hardware without going through the BIOS. If the
 computer has either an Intel 80286 or 80386 microprocessor, the
 joystick commands are handled by going through BIOS interrupt 15 hex.
 Because of errors in some BIOS joystick functions on some computers,
 STICK or STRIG may not work at all, or may not work properly.

 If your computer has an Intel 80286 or 80386 microprocessor chip, you
 can use the code example below to determine if the problem you are
 having is ROM BIOS related. The program accesses the game port by
 directly calling INTERRUPT &H15 with function &H84, which is the BIOS
 joystick routine. If the problem still occurs when calling the BIOS
 joystick routine directly, then the problem is with the computer's
 BIOS joystick function and not with BASIC's STICK or STRIG.

 To access the BIOS joystick routines, you call interrupt &H15 (21
 decimal). The AH register should contain &H84 (132 decimal) to
 indicate the game port support function.

 Register values prior to issuing interrupt &H15 should be:

    AX = &H8400    ' This puts &H84 in the AH register.
    DX = 0 or 1

 If DX = 0, this indicates to "read switch settings." If DX = 1, this
 indicates "read resistive inputs."

 Depending on the value of DX when you make the call, different
 parameters will be returned by the interrupt. If DX = 1, then upon
 returning from Interrupt &H15, the registers will contain:

    AX = Port1 x coordinate
    BX = Port1 y coordinate
    CX = Port2 x coordinate
    DX = Port2 y coordinate

 If DX = 1, then bits 4 - 7 are used to represent switches. The AX
 register will contain the switch settings in bits 4 through 7. BX, CX,
 and DX will be unchanged.

 The following code example shows how to use the CALL INTERRUPT routine
 to directly call the BIOS joystick routines. To compile the program,
 use the following compile and link lines:

    BC joystick.bas ;
    LINK joystick ,,, QB.LIB ;   [For BASIC PDS 7.x use QBX.LIB ;]

 To run this program in the QB.EXE or QBX.EXE environment, invoke QB or
 QBX with the /L option (to load the QB.QLB or QBX.QLB Quick library).

 JOYSTICK.BAS
 ------------

 'This code prints to the screen the values of AX, BX, CX, DX registers
 'when interrupt &H15, function &H84 is called with given values in the
 'DX register. This will allow you to observe the values
 'corresponding to a specific action taken on a given device attached
 'to either of the two game ports supported by an IBM or compatible.

 '$INCLUDE 'QB.BI'     ' For BASIC PDS 7.x, use QBX.BI
 DIM inregs AS RegType
 DIM outregs AS RegType
 inregs.ax = &H8400          'puts &H84 in AH register
 DO
  inregs.dx = 1          '1 - read resistive inputs
  CALL INTERRUPT(&H15, inregs, outregs)
  CLS
  LOCATE 16, 10: PRINT "RESISTIVE INPUTS: (STICK)"
  LOCATE 19, 20: PRINT "AX","BX","CX","DX"
  LOCATE 20, 20: PRINT  outregs.ax, outregs.bx, outregs.cx, outregs.dx

  inregs.dx = 0          '0 - read switch settings
  CALL INTERRUPT(&H15, inregs, outregs)
  LOCATE 6, 10: PRINT "SWITCH SETTINGS: (TRIGGER)"
  LOCATE 9, 20: PRINT " AX"
  LOCATE 10,20: PRINT outregs.ax       'only bits 4 - 7 are important
 LOOP WHILE INKEY$ = ""           'loop till any key is pressed
 END

 References:

 Note: The INTERRUPT routine is considered an external subroutine by
 the compiler. The routine is located in the files QB.LIB and QB.QLB
 for QuickBASIC 4.x and in QBX.LIB and QBX.QLB in BASIC PDS 7.x.
 Programs that execute a CALL INTERRUPT statement when compiled in the
 QB.EXE editor require the presence of the QB.QLB or QBX.QLB Quick
 library. This means that QB.EXE and QBX.EXE must be invoked with the
 /L option, which automatically loads the correct Quick library.

 Compiled programs that execute CALL INTERRUPT must be linked with the
 file QB.LIB or QBX.LIB. More information on the use of CALL INTERRUPT
 can be found under the CALL statement in the language reference manual
 for each BASIC product. For more information on how to use CALL
 INTERRUPT, query on the following words:

    CALL and INTERRUPT and application and note and QuickBASIC

 For a description of the dependency of STICK and STRIG on computers
 with certain Intel chips, query on the following:

    STICK and STRIG and BIOS

 It may be possible to avoid the BIOS routines altogether by directly
 accessing the game port using get and put functions. (BASIC's INP and
 OUT statements cannot do this because of the speed required to read
 the port.) It may be possible for you to write an assembly subroutine,
 which could be called from BASIC to talk directly to the game port.

 Information on programming the game port can be found in the following
 texts:

 1. Page 433 of "The Programmer's PC Sourcebook" by Thom Hogan,
    published by Microsoft Press, 1988

 2. "IBM Technical Reference Options and Adapters" Volume 2, "Game
    Control Adapter", published by IBM


 948. BASIC Can Write Files for MS Excel Spreadsheet

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901029-75 B_MQuickB B_BasicCom B_BasicInt W_eXceL M_eXc
 Last Modified: 15-JAN-1991    ArticleIdent: Q68122

 Microsoft QuickBASIC can manipulate ASCII text files used by Microsoft
 Excel in either comma separated values (CSV) or tab separated values
 (TEXT) file formats.

 QuickBASIC can generate these file formats with the standard BASIC
 statements OPEN, CLOSE, PRINT, and WRITE.

 This information applies to Microsoft QuickBASIC versions 1.00, 2.00,
 3.00, 4.00, 4.00b, and 4.50 for MS-DOS; Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS and MS OS/2; Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS and MS OS/2; Microsoft BASIC Interpreter versions 2.00, 2.01,
 and 3.00 for Apple Macintosh; Microsoft QuickBASIC versions 1.00 and
 1.00b for Apple Macintosh; Microsoft BASIC Compiler version 1.00 for
 Apple Macintosh; and GW-BASIC Interpreter versions 3.20, 3.22, and
 3.23 for MS-DOS.

 Microsoft Excel supports two TEXT file formats: tab (TEXT) files, and
 comma (CVS) delimited files. Both of these files contain the textual
 information in each cell, no formulas, and a delimiter between each
 column and a carriage return plus linefeed (CR/LF) at the end of each
 row on MS-DOS computers (but just CR ending each row on Macintosh
 computers).

 Tab delimited files have a tab character separating each column. To
 generate a tab character in BASIC, use the CHR$() function with a
 parameter of 9. For example,

    Tab$ = CHR$(9)

 Comma delimited files have a comma character separating each column.
 There are several ways to generate a comma in the output file. One way
 is to use BASIC's CHR$() function with a parameter of 44. For example,

    Comma$ = CHR$(44)

 If a cell contains a comma, the value from the cell will be enclosed
 in double quotation marks. In BASIC, you can use the WRITE command to
 place an item in double quotation marks.

 BASIC Code Example
 ------------------

         REM ** Create a COMMA Delimited File **
         Comma$ = CHR$(44)
         OPEN "EXCEL.CVS" FOR OUTPUT AS #1
         PRINT #1, "Employee Information"
         PRINT #1, " "
         PRINT #1, "First"; Comma$; "Last Name"; Comma$; "Age"
         PRINT #1, " "
         PRINT #1, "Loren"; Comma$; "Moe"; Comma$; 35
         PRINT #1, "Arthur"; Comma$; "Nelson"; Comma$; 21
         PRINT #1, "George"; Comma$; "Merriman";Comma$; 30
         PRINT #1, " "
         CLOSE #1

         REM ** Creates a TAB Delimited File **
         Tab$ = CHR$(9)
         OPEN "EXCEL.TXT" FOR OUTPUT AS #2
         PRINT #2, "Employee Information"
         PRINT #2, " "
         PRINT #2, "First"; Tab$; "Last Name"; Tab$; "Age"
         PRINT #2 " "
         PRINT #2, "Loren"; Tab$; "Moe"; Tab$; 35
         PRINT #2, "Arthur"; Tab$; "Nelson"; Tab$; 21
         PRINT #2, "George"; Tab$; "Merriman"; Tab$; 30
         PRINT #2, " "
         CLOSE #2


 949. Gama Fax TSR Program Conflicts with BASIC Keyboard Input

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901207-36 B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q68157

 This article gives information about using QuickBASIC version 4.50
 with the software Gama Fax CB version 4.3.1 (latest version as of
 1/1/91). Gama Fax CB is manufactured by the company Gama Link. This
 software operates a fax dispatcher.

 Gama Fax CB is a TSR (terminate and stay resident) program that can
 interfere with BASIC's keyboard input in key trapping techniques, such
 as ON KEY GOSUB and INKEY$. The TSR program slows down BASIC's
 keyboard input so that a delay occurs before the input is eventually
 read. An explanation and workaround is provided below.

 This information applies to Microsoft QuickBASIC versions 2.00, 2.01,
 3.00, 4.00, 4.00b, 4.50 for MS-DOS; to Microsoft BASIC Compiler
 versions 6.00 and 6.00b for MS-DOS; and to Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10 for
 MS-DOS.

 This conflict is due to the operation of the Gama Fax software. Gama
 Fax CB runs as a background task that constantly monitors
 communications port input while other programs (like QuickBASIC
 programs) run in the foreground. This means that the TSR program
 competes for processing time with QuickBASIC.

 It is possible to control how much background processing time the Gama
 Fax software will take. By adjusting this time, you may be able to
 correct the problem with BASIC keyboard input. There is a
 configuration file called GFAX.$DC that comes with the Gama Fax
 software. Inside GFAX.$DC is a line with the statement "GFXSHUTDOWN",
 followed by some numbers. After that line, add the following line:

    QUANTUMS number1 number2

 This command splits the foreground and background time slices. The
 number1 is the number of time ticks assigned to the foreground process
 (your BASIC program). The number2 is the number of time ticks assigned
 to the background process (the Gama Fax software).

 Below are some number combinations that have been successful for other
 Gama Fax users:

    QUANTUMS 4 50
    QUANTUMS 2 50     <-- most successful
    QUANTUMS 2 100

 Other combinations may work with other machines or other versions of
 QuickBASIC. If the above configuration does not solve the problem and
 you need more assistance in configuring the Gama Fax software, contact
 Gama Link at (408) 744-1430.


 950. How to Truncate a File Using DOS Interrupts from BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901228-74  B_BASICCOM
 Last Modified: 15-JAN-1991    ArticleIdent: Q68159

 The following BASIC code shows how to truncate a file using DOS
 functions. A more clumsy approach in BASIC would be to read a
 specified amount of records one at a time, writing these records to
 another file, deleting the first file, and then renaming the new file
 to the old file. The approach using DOS functions (below) is quicker
 and more efficient.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50
 for MS-DOS; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS; and to Microsoft BASIC Professional System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 You can invoke MS-DOS service functions using the CALL INTERRUPT
 statement in BASIC.

 You can set the size of any file to any arbitrary value by executing
 MS-DOS interrupt 21 hex with service 40 hex using CX = 00 hex. The
 usual technique is to call service 42 hex to set the file pointer
 location and then immediately call service 40 hex with CX = 00 hex to
 update the new file size.

 The program below is written so that the Truncate% FUNCTION is generic
 as possible and works with any file. ProcessFile() sets up the
 file-specific information, which in turn calls the Truncate% FUNCTION.
 Truncate% generates the specific interrupt calls to truncate the file
 at the specified record. The two SUB programs PrintFile() and
 CreateFile() are only needed as an example.

 Program Example
 ---------------

 ' You must run QB or QBX with the /L option to load the QB.QLB or
 ' QBX.QLB Quick library which contains the INTERRUPT routine used in
 ' this program. You must LINK with QB.LIB or QBX.LIB when making an
 ' .EXE program which uses the CALL INTERRUPT statement.
 CONST NumRec = 10
 TYPE TheType
      i AS INTEGER
 END TYPE
 DIM SHARED TheDim AS TheType
 ' In the following line, use 'QBX.BI' for BASIC PDS, or use 'QB.BI'
 ' for QuickBASIC 4.x:
 '$INCLUDE: 'QBX.BI'
 CALL CreateFile
 CALL PrintFile
 CALL ProcessFile(7)
 CALL PrintFile

 '################### File specific SUB #############################
 SUB ProcessFile (LastRec%)
 'Get the information about "TEST.DAT" and also the information
 'about the location of the LASTREC% where the file will be truncated.
      OPEN "test.dat" FOR RANDOM AS #1 LEN = LEN(TheDim)
      FilePointer% = LastRec% * LEN(TheDim)
      IF FilePointer% <> Truncate%(FILEATTR(1, 2), FilePointer%) THEN
           PRINT "error..."
      END IF
      CLOSE
 END SUB

 '################## Generic INT file truncator ####################
 FUNCTION Truncate% (handle%, FilePointer%)
 ' Generic function that will truncate any file at specified offset.
 '
 ' Receives:
 '       1) a DOS file handle;
 '       2) a file pointer offset in bytes, pointing where to truncate
 ' Returns:
 '       1) If successful, position of file pointer; or
 '       2) If error, flags register
 '
  DIM Regs AS RegType
      Regs.ax = &H4200                     'int 21 hex, service 42 hex
      Regs.bx = handle%                    'DOS Handle
      Regs.dx = FilePointer%               'offset in bytes from start
      CALL Interrupt(&H21, Regs, Regs)
      IF Regs.ax <> FilePointer% THEN      'AX returns pointer position
           Truncate% = Regs.flags            If error, return flag
      END IF
      Regs.ax = &H4000                     'INT 21 hex, service 40 hex
      Regs.bx = handle%                    'DOS handle
      Regs.cx = &H0
      CALL Interrupt(&H21, Regs, Regs)
      IF Regs.ax <> 0 THEN                 'Must be zero bytes written
           Truncate% = Regs.flags            'If error, return flag
      END IF
      Truncate% = FilePointer%             'return offset location
 END FUNCTION

 '############ Create Sample File using RANDOM Access ################
 SUB CreateFile
      KILL "test.dat"
      OPEN "test.dat" FOR RANDOM AS #1 LEN = LEN(TheDim)
      FOR j = 1 TO NumRec
           TheDim.i = j
           PUT #1, j, TheDim
      NEXT j
      CLOSE #1
 END SUB

 '########### Print contents of TEST.DAT ##################
 SUB PrintFile
      OPEN "test.dat" FOR RANDOM AS #1 LEN = LEN(TheDim)
      Max = LOF(1) / LEN(TheDim)
      FOR j = 1 TO Max
           GET #1, j, TheDim
           PRINT TheDim.i
      NEXT j
      CLOSE
 END SUB

 References:

 The INTERRUPT routine is located in the files QB.LIB and QB.QLB for
 QuickBASIC 4.x and in QBX.LIB and QBX.QLB in BASIC PDS 7.00/7.10.
 Programs that execute a CALL INTERRUPT statement when compiled in the
 QB.EXE/QBX.EXE editor require the presence of the QB.QLB/QBX.QLB Quick
 library. This means that QB.EXE or QBX.EXE must be invoked with the /L
 option, which automatically loads the correct Quick library. Compiled
 programs that execute CALL INTERRUPT must be linked with the LINK
 library QB.LIB or QBX.LIB. More information on the use of CALL
 INTERRUPT can be found under the CALL statement in the language
 reference manual or online help. For more information on how to use
 CALL INTERRUPT, query on the following words:

    CALL and INTERRUPT and application and note and QuickBASIC


 951. CLOSE Doesn't Release Far Heap Used by First OPEN "COM" Buffer

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901012-19 B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q68164

 When you use the OPEN "COMn:" statement, the far heap memory allocated
 for the communications receive and transmit buffers is not deallocated
 when the file is closed. However, this communications memory area
 allocated in the far heap is reused if the COM port is reopened. [Far
 heap memory usage is indicated by the FRE(-1) function.]

 Note that the file's memory overhead portion consumed in DGROUP (the
 default data segment) is completely released by the CLOSE statement.
 [DGROUP memory is reported by the FRE("") function in QuickBASIC 4.x
 and in BASIC Compiler 6.00/6.00b, but reported by the STACK function
 in BASIC PDS 7.00/7.10.]

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50; to Microsoft BASIC Compiler versions 6.00 and 6.00b for
 MS-DOS; and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS.

 By default, the communications transmit and receive buffers are set at
 512 bytes. The transmit and receive buffer sizes can be changed by
 parameters in the OPEN "COMn:" string. For example,

    TB2048 = Increases the transmit buffer size to 2048 bytes.
    RB2048 = Increases the receive buffer size to 2048 bytes.

 The following code example duplicates this far heap consumption
 behavior:

 PRINT "Far Heap before open:"; FRE(-1)
 OPEN "COM1:9600,N,8,1,RB4096" FOR RANDOM AS #1
 PRINT "Far Heap after open:"; FRE(-1)
 CLOSE #1
 PRINT "Far Heap after close:"; FRE(-1)

 The output from this program shows that after the OPEN statement, the
 far heap is correctly reduced by 4096 plus some additional memory
 needed to maintain a file. But after the CLOSE, only a few bytes
 (equal to the file overhead release in DGROUP memory) get reallocated
 to the far heap.


 952. BASIC Program to Reboot or "Cold" Reboot the Machine

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901024-65 restart boot S_C S_QuickC B_BasicCom
 Last Modified: 15-JAN-1991    ArticleIdent: Q68224

 This article gives two ways to reboot your machine from within a BASIC
 program.

 WARNING: Please be sure to CLOSE all open files before rebooting the
 computer, so as not to lose buffered data.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and
 4.50; to Microsoft BASIC Compiler 6.00 and 6.00b for MS-DOS; and to
 Microsoft BASIC Professional Development System (PDS) 7.00 and 7.10
 for MS-DOS.

 Method 1
 --------

 The first method of rebooting the machine requires only BASIC code.
 This program sends a command directly to the keyboard I/O port using
 BASIC's OUT statement. This causes the keyboard controller chip to
 reboot the machine just as if you had typed CTRL+ALT+DEL on the
 keyboard. Note that this command is supported only on the AT and
 higher class of machines. This example will not work on the IBM PC- or
 XT-class machines or clones.

 ' REBOOT.BAS
 DEFINT A-Z
 DEF SEG = &H40      ' If the memory location &H0072:0073 in the BIOS
 POKE &H72, &H34     ' data area contains &H1234, then this will cause
 POKE &H73, &H12     ' a warm reboot (no self test or memory
                     ' count). Anything else causes does a cold reboot
                     ' (self test and memory count).
 DEF SEG             ' Return to BASIC's default segment.
 Command% = &HFE     ' Reset Processor command.
 Port% = &H64        ' Keyboard I/O Port
 OUT Port%, Command% ' Reboot

 Method 2
 --------

 Another way to reboot your machine is to jump directly to the ROM BIOS
 initialization code (which normally executes automatically when the
 machine's power is first turned on). This method of rebooting the
 machine should work on all members of the IBM PC and PS/2 family of
 computers, as well as the clones of these machines.

 In order to do this, however, your chosen language must have support
 for "pointers to functions" as in C or assembly. Because BASIC does
 not support a function pointer data type, you must write a C or
 assembly procedure to jump to the ROM BIOS boot code. You can call
 this C or assembly procedure from your BASIC program.

 Two separate articles in the Microsoft Knowledge Base describe how to
 reboot the MS-DOS computer. One article uses C alone to reboot, and
 one article uses C with inline assembly code to reboot. Search for
 these two articles using the following words:

    reboot and machine and QuickC

 For more information about calling C from BASIC, search on the word
 BAS2C. For more information about calling assembly language from
 BASIC, search on the word BAS2MASM.


 953. Passing BASIC Numeric Arrays from BASIC to C and Back to BASIC

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910114-113 B_BasicCom
 Last Modified: 29-JAN-1991    ArticleIdent: Q68663

 The following example demonstrates how to pass numeric arrays from
 compiled BASIC to Microsoft C then back to BASIC using BASIC's "by
 reference" calling convention.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and 4.50
 for MS-DOS, to Microsoft BASIC Compiler 6.00 and 6.00b for MS-DOS and
 MS OS/2, and to Microsoft Professional Development System 7.00 and
 7.10 for MS-DOS and MS OS/2.

 For more information about passing other types of parameters between
 BASIC and C, and a list of which BASIC and C versions are compatible
 with each other, query in the Software/Data Library for the following
 word:

     BAS2C

 The example below differs from the other BAS2C array-passing examples
 in that the example below lets you pass array data from BASIC to C
 then back to BASIC. The other BAS2C examples pass array data from
 BASIC to C but not back to BASIC.

 Code Example
 ============

 Compile and link the sample programs below as follows:

    BC /O ByRefB.BAS ;
    CL /c /W3 /AM ByRefC.C
    LINK /NOE ByRefB ByRefC ;

 ByRefB.BAS
 ----------

 ' Declare the BASIC and C routines to use the same calling
 ' convention. In this case we want the BASIC "BY REFERENCE"
 ' calling convention.

 DECLARE SUB BTest (Array1%(), Array2!(), Array3#(), Array4&())
 DECLARE SUB CTest (Array1%(), Array2!(), Array3#(), Array4&())
 ' $STATIC
 DIM A%(10), B!(10) ' Define some STATIC data in "DGROUP"
 ' $DYNAMIC
 DIM C#(10), D&(10) ' And, some DYNAMIC data
 CLS
 FOR i% = 0 TO 10   ' Initialize the arrays
     A%(i%) = i%
     B!(i%) = .5 * i%
     C#(i%) = 1.5 * i%
     D&(i%) = i% * i%
 NEXT i%
 CTest A%(), B!(), C#(), D&()
 PRINT A%(10), B!(10), C#(10), D&(10)
 END
 SUB BTest (Array1%(), Array2!(), Array3#(), Array4&())
     PRINT
     FOR i% = 0 TO 10
         PRINT Array1%(i%), Array2!(i%), Array3#(i%), Array4&(i%)
     NEXT i%
 END SUB

 ByRefC.C
 --------

 #include <stdio.h>

 /**
  ** Use "typedef" to reduce complexity/readability of code.
  **
  ** BASIC's BY REFERENCE is a near handle to a far pointer for the
  ** actual data of numeric arrays.
  **/
 typedef int    far * near * HInt ;
 typedef long   far * near * HLng ;
 typedef float  far * near * HSng ;
 typedef double far * near * HDbl ;

 /**
  ** Define the BASIC routine as a "standard BASIC" call so the
  ** parameters will be the same.
  **/
 extern void pascal BTest ( HInt, HSng, HDbl, HLng ) ;

 /**
  ** Define our C routine as a "standard BASIC" routine so we look
  ** like BASIC. This simplifies the parameter passing since we
  ** all look the same on the stack.
  **/
 void pascal CTest (HInt IntArray, HSng SngArray,
                    HDbl DblArray, HLng LngArray)
     {
         int j, i;
         printf ("\nOriginal Array Values\n") ;
         BTest ( IntArray, SngArray, DblArray, LngArray ) ;
         for (i = 0, j = 10; i < 6; i++, j--)
             {
                 (*IntArray)[i] = (*IntArray)[j] ;
                 (*LngArray)[i] = (*LngArray)[j] ;
                 (*SngArray)[i] = (*SngArray)[j] ;
                 (*DblArray)[i] = (*DblArray)[j] ;
             }
      printf ("\nModified Array Values\n") ;
         BTest ( IntArray, SngArray, DblArray, LngArray ) ;
         printf ("\nModified Last Array Elements\n") ;
         (*IntArray) [10] = (int)    3 ;
         (*SngArray) [10] = (float)  4.45 ;
         (*DblArray) [10] = (double) 30.303 ;
         (*LngArray) [10] = (long)   445 ;
     }

 Program Output
 ==============

  Original Array Values

   0             0             0             0
   1             .5            1.5           1
   2             1             3             4
   3             1.5           4.5           9
   4             2             6             16
   5             2.5           7.5           25
   6             3             9             36
   7             3.5           10.5          49
   8             4             12            64
   9             4.5           13.5          81
   10            5             15            100

  Modified Array Values

   10            5             15            100
   9             4.5           13.5          81
   8             4             12            64
   7             3.5           10.5          49
   6             3             9             36
   5             2.5           7.5           25
   6             3             9             36
   7             3.5           10.5          49
   8             4             12            64
   9             4.5           13.5          81
   10            5             15            100

  Modified Last Array Elements

   3             4.45          30.303        445


 954. Repackaged QuickBASIC 4.50 Correction; Requires Two Drives

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910117-22 docerr
 Last Modified: 14-FEB-1991    ArticleIdent: Q69044

 In the repackaged release of Microsoft QuickBASIC version 4.50, the
 "System Requirements" section on the back cover of the manual
 incorrectly states that a system with "One 3 1/2" disk drive" is
 supported.

 The repackaged release of QuickBASIC 4.50 actually requires two disk
 drives (for 3.5-inch disks or double-sided 5.25-inch disks).

 In the repackaged release of Microsoft QuickBASIC 4.50, the "System
 Requirements" are presently listed as follows:

    System Requirements
    * 384 available user memory
    * MS-DOS or PC-DOS operating system version 2.1 or higher
    * One 3 1/2" disk drive or two double-sided 5 1/4" disk drives

 The first two system requirements are correct, but the third
 pertaining to floppy drive requirements should be changed to read as
 follows:

    * Two disk drives (for double-sided disks)

 Although some customers have claimed to be able to run QuickBASIC from
 one 3.5-inch floppy drive, they still had to use a system with two
 floppy drives to run the QuickBASIC SETUP.EXE utility.

 The QuickBASIC SETUP utility was not designed to be run using only one
 floppy drive. SETUP will not allow you to do this, even if you
 redirect drives through DOS.

 Microsoft has confirmed this to be a documentation error in the
 repackaged release of Microsoft QuickBASIC version 4.50 for MS-DOS.

 Reference:

 The repackaged release of QuickBASIC 4.50 has packed (compressed)
 files on four 5.25-inch disks or two 3.5-inch disks, plus an
 UNPACK.EXE program, and the two manuals are combined into one spine
 and shipped without a box. The previous release had normal (nonpacked)
 files on five 5.25-inch disks and three 3.5-inch disks, and shipped
 with two manuals. The previous release was packaged inside a box.


 955. PRINT TAB Blanks Out Passed-Over Characters in BASIC

 Product Version(s): 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910117-30 B_BasicCom B_GWBasicI
 Last Modified:  6-FEB-1991    ArticleIdent: Q69045

 BASIC's TAB() function will blank out any characters that are being
 passed over on the screen. This feature is by design.

 This information applies to Microsoft GW-BASIC versions 3.20, 3.22,
 and 3.23; to Microsoft QuickBASIC versions 2.00, 2.01, 3.00, 4.00,
 4.00b, and 4.50; to Microsoft BASIC Compiler 6.00 and 6.00b; and to
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10 for MS-DOS.

 Consider the following code:

       CLS
       PRINT "1234567890"
       PRINT "abcdefghij"
       LOCATE 2,1
       PRINT TAB(4); "DEF"

 This program prints the following on the screen:

       1234567890
          DEFghij

 The letters "abc", which TAB passed over, have been overwritten with
 blanks.

 An exception to this behavior is if you trace (F8) in the QB.EXE
 editor of QuickBASIC 4.00, 4.00b, or 4.50, or QBX.EXE of BASIC PDS
 7.00 or 7.10, where TAB does not erase passed-over text:

       1234567890
       abcDEFghij


 956. Predefined Keys Trap All SHIFT Combinations; PEEK SHIFT Status

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910117-124 B_BASICCOM
 Last Modified:  6-FEB-1991    ArticleIdent: Q69046

 The predefined key traps KEY(0) through KEY(14), KEY(30), and KEY(31)
 are active no matter what combinations of the SHIFT, CTRL, ALT, CAPS
 LOCK, and NUM LOCK keys are active. If you want to distinguish and
 trap both the SHIFTed and unSHIFTed status for a given key, you must
 either set up two user-defined key traps, or check the contents of the
 SHIFT register while the predefined key is being trapped.

 This information applies to Microsoft QuickBASIC versions 4.00, 4.00b,
 and 4.50 for MS-DOS, to Microsoft BASIC Compiler 6.00 and 6.00b for
 MS-DOS, and to Microsoft BASIC Professional Development System (PDS)
 versions 7.00 and 7.10 for MS-DOS.

 The following program demonstrates that even though a user-defined key
 trap, ON KEY(15), is activated for the SHIFT+DOWN ARROW key
 combination, the trap is never executed because the predefined DOWN
 ARROW key trap, ON KEY(14), takes precedence:

 Code Example 1
 --------------

 KEY 15, CHR$(3) + "P"
 ON KEY(15) GOSUB ShiftArrow
 KEY(15) ON
 ON KEY(14) GOSUB DownArrow
 KEY(14) ON
 CLS
 DO
    a$ = INKEY$
 LOOP UNTIL a$ = "q"

 KEY(15) OFF
 KEY(14) OFF
 END
 ShiftArrow:
    PRINT "Shift-Down arrow..."
    RETURN
 DownArrow:
    PRINT "Down arrow..."
    RETURN

 The next program demonstrates how to use the PEEK function to
 determine if the SHIFT key is currently being pressed when the key
 trap occurs:

 Code Example 2
 --------------

 ON KEY(14) GOSUB ArrowKey
 KEY(14) ON
 CLS
 DO
     a$ = INKEY$
 LOOP UNTIL a$ = "q"
 KEY(14) OFF
 END
 ArrowKey:
     DEF SEG = 0
     IF (PEEK(1047) AND 3) = 0 THEN
          PRINT "Down arrow..."
     ELSE
          PRINT "Shift-Down arrow..."
     END IF
     DEF SEG
     RETURN

 The disadvantage of the method in example 2 is that if anything should
 happen to delay the time between the key press and the time that the
 trap routine is called (for example, if an INPUT statement is being
 executed when the key is pressed), then the user may release the SHIFT
 key before it can be detected.

 The last option is to invoke a user-defined key trap for both the
 SHIFTed and unSHIFTed keys; and not to use the predefined key trap.

 Reference:

 For more information on this topic, query on the following words:

    key and trap and CAPS and NUM and LOCK and user and defined


 957. Amdek Keyboard Problems Selecting Text in QB.EXE/QBX.EXE

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM SR# S910114-73
 Last Modified:  6-FEB-1991    ArticleIdent: Q69048

 There have been some reported keyboard problems with Amdek computers.
 One customer, who was originally unable to select text in the QB.EXE
 environment, reported that the key combinations described below worked
 on his Amdek System 88 (XT compatible).

 Microsoft has not tested any version of QuickBASIC on the Amdek System
 88 and makes no compatibility claim with Amdek and QuickBASIC. These
 keyboard problems have been reported only for this brand and model of
 computer.

 This information applies to QuickBASIC versions 4.00, 4.00b, and 4.50
 and to Microsoft BASIC Professional Development System (PDS) versions
 7.00 and 7.10 for MS-DOS.

 If you cannot select text when running in the QB.EXE or QBX.EXE
 environment on the Amdek System 88, try the following key
 combinations:

    Normal Key Stroke       Amdek Key Stroke    Operation
    -----------------       ----------------    ---------

    SHIFT+DOWN ARROW        SHIFT+CTRL+X        Select one line down
    SHIFT+UP ARROW          SHIFT+CTRL+E        Select one line up
    SHIFT+LEFT ARROW        SHIFT+CTRL+S        Select one char. left
    SHIFT+RIGHT ARROW       SHIFT+CTRL+D        Select one char. right
    SHIFT+CTRL+LEFT ARROW   SHIFT+CTRL+A        Select one word left
    SHIFT+CTRL+RIGHT ARROW  SHIFT+CTRL+F        Select one word right
    SHIFT+PGUP              SHIFT+CTRL+R        Select one screen up
    SHIFT+PGDN              SHIFT+CTRL+C        Select one screen down


 958. Instant Watch Truncates Display of String After Null Byte

 Product Version(s): 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM SR# S910107-22 buglist4.50
 Last Modified:  6-FEB-1991    ArticleIdent: Q69108

 If you set an instant watch on a string variable that contains a null
 byte, CHR$(0), then instant watch will only display the contents of
 the string up to the null character. The problem occurs for both
 variable length and fixed-length string variables.

 Microsoft has confirmed this to be a problem in QB.EXE in Microsoft
 QuickBASIC version 4.50 for MS-DOS and in QBX.EXE in Microsoft BASIC
 Professional Development System (PDS) versions 7.00 and 7.10
 (buglist7.00 and buglist7.10) for MS-DOS.

 To do an instant watch on a variable in either the QB.EXE or QBX.EXE
 environment, you must suspend execution of the program, move the
 cursor under the variable you want to watch, and press SHIFT+F9. The
 variable name and contents will appear. Instant watch is valuable for
 viewing the contents of your variables during execution of the
 program.

 Doing an instant watch on a variable (SHIFT+F9) will cause a window to
 pop up with the name of the variable and its value. Setting a watch on
 a variable is different than doing an instant watch. Setting a watch
 will cause a line to appear at the top of your editing screen with the
 name of the variable and its value. This line will remain at the top
 of your editing screen until you delete it.

 Code Example
 ------------

 As the example below demonstrates, if you do an instant watch on a
 string variable that contains the null character, CHR$(0), then
 instant watch will only display the contents of the string up to the
 null character. If you set a watch on the same variable, the whole
 value of the string will be displayed.

    C$ = "Hello" + CHR$(0) + "World"
    PRINT "PRESS ANY KEY TO CONTINUE"
    DO
    LOOP UNTIL INKEY$ <> ""

 The following steps demonstrate the problem:

 1. Run the above code in either the QB.EXE or QBX.EXE environment.

 2. While the program waits for you to press a key, press CTRL+BREAK to
    suspend execution of the program.

 3. Move the cursor under C$ and press SHIFT+F9. Just "Hello" will
    display. "World" will fail to display.

 4. Select the Add Watch button from the instant watch window. The
    following correct value will now display:

       "Hello World"

 Note: CHR$(0) is displayed as a blank in the watch line at the top of
 the editing screen.


 959. QB 4.x Program Example to Create or Remove Directory

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910123-221
 Last Modified:  6-FEB-1991    ArticleIdent: Q69110

 In Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10, the statement to make a directory is MKDIR(Directory$), and
 the statement to remove a directory is RMDIR(Directory$). Because
 QuickBASIC versions 4.00, 4.00b, and 4.50 do not have these
 statements, two alternative ways of creating and removing directories
 are listed below.

 The following information applies to Microsoft QuickBASIC versions
 4.00, 4.00b, and 4.50 for MS-DOS.

 The first method to either create or remove directories is simple, but
 requires more memory and is slower. This first method requires using
 the SHELL statement.

 Directory$ = "Dir1"   ' Put the new directory name to create here.
 Sh$ = "MKDIR "+ Directory$
 SHELL Sh$             ' Creates a directory named Dir1.

 You could substitute "RMDIR " for "MKDIR " above to remove the
 directory.

 Method two below uses a CALL INTERRUPT statement to make and remove
 directories. This method uses less memory and is faster because it
 does not do a SHELL. It also returns a code to tell you whether or not
 the operation was successful.

 ' MRDIR.BAS
 ' Example program to Make or Remove DIRectories.
 '
 ' To run this program in QB.EXE, type the following at the DOS prompt:
 '      QB MRDIR /L
 ' Type in the program, and run it (SHIFT+F5).
 DECLARE FUNCTION MakeDir% (Directory$)
 DECLARE FUNCTION RemoveDir% (Directory$)
 ' $INCLUDE: 'QB.BI'
 CLS
 PRINT "1. Make a Directory"
 PRINT "2. Remove a Directory"
 DO
       C$ = INKEY$
 LOOP UNTIL C$ = "1" OR C$ = "2"
 IF C$ = "1" THEN
       INPUT "Enter the name of the new directory ", Directory$
       x = MakeDir(Directory$)
 ELSE
       INPUT "Enter the name of the directory to be removed ",
 Directory$
       x = RemoveDir(Directory$)
 END IF
 IF x = 0 THEN PRINT "Successful" ELSE PRINT "Unsuccessful"

 ' The following function creates a new subdirectory in the current
 ' directory. This function returns 0 if the directory was created
 ' successfully, or returns 1 if the directory could not be created.
 FUNCTION MakeDir% (Directory$)
       DIM inreg AS RegType, outreg AS RegType
       IF RIGHT$(Directory$, 1) <> CHR$(0) THEN
          Directory$ = Directory$ + CHR$(0)
       END IF
       inreg.ax = &H3900     'Function 39 hex of interrupt 21 hex.
       inreg.dx = SADD(Directory$)   'Offset of string variable.
       CALL INTERRUPT(&H21, inreg, outreg)
       MakeDir% = (outreg.flags AND 1)   'Return success flag.
 END FUNCTION

 ' The following function deletes an existing subdirectory from the
 ' current directory. This function returns 0 if the directory was
 ' deleted successfully, or returns 1 if the directory could not be
 ' deleted.
 FUNCTION RemoveDir% (Directory$)
       DIM inreg AS RegType, outreg AS RegType
       IF RIGHT$(Directory$, 1) <> CHR$(0) THEN
          Directory$ = Directory$ + CHR$(0)
       END IF
       inreg.ax = &H3A00       'Function 3A hex of interrupt 21 hex.
       inreg.dx = SADD(Directory$)  'Offset of string variable.
       CALL INTERRUPT(&H21, inreg, outreg)
       RemoveDir% = (outreg.flags AND 1)  'Return success flag.
 END FUNCTION


 960. Underscore+CR+LF Added Before DATA Statement If > 250 Columns

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50
 Last Modified: 14-FEB-1991    ArticleIdent: Q69156

 If an indented DATA statement in a program exceeds the 250th column
 and the program is then saved as ASCII text in the QB.EXE or QBX.EXE
 environment, then an underscore (_) plus a carriage return (CR, ASCII
 value 13) plus a linefeed (LF, ASCII value 10) will be added
 immediately in front of the DATA statement. The actual data contents
 in the DATA statement will not not changed.

 The addition of "_<CR><LF>" in front of the DATA statement occurs only
 if the last character in the DATA statement exceeds the 250th column,
 and the DATA statement is immediately preceded on the same line by
 spaces, a line number, line label, or other code.

 Microsoft has confirmed this problem in QB.EXE in Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50 for MS-DOS; in QB.EXE in Microsoft
 BASIC Compiler versions 6.00 and 6.00b (buglist6.00 and buglist6.00b)
 for MS-DOS; and in QBX.EXE in Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10 for MS-DOS (buglist7.00 and
 buglist7.10). Microsoft is researching this problem and will post new
 information here as it becomes available.

 If the DATA statement is in the first column on the line or if the
 file is saved using Fast Load and Save format, then the problem does
 not occur (whether or not the line exceeds the 250th column).

 The added "_<CR><LF>" characters have no affect on the performance of
 the QuickBASIC program, and in QB.EXE or QBX.EXE, the "_<CR><LF>"
 characters just appear as an extra space. Each save in ASCII text
 format will add what appears to be an additional space in front of the
 DATA statement. Note that you can only see the "_<CR><LF>" characters
 if you type the file in DOS or load the file into a standard text
 editor.

 However, the problem does have an adverse affect if you load a
 line-numbered program into the GW-BASIC or BASICA Interpreter. In
 GW-BASIC or BASICA, the file is loaded only up to the "_<CR><LF>". The
 rest of the file is ignored and the message "Direct Statement In File"
 appears. For example, make the following line-numbered DATA statement
 exceed 250 characters, save it as an ASCII text file in QB.EXE or
 QBX.EXE, then try to load the file into GW-BASIC or BASICA:

    100 DATA 123,1234567890,1234567890, ... ,1234567890


 961. Bad Values When QLB Function Used as SUB Parameter

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910118-99
 Last Modified: 14-FEB-1991    ArticleIdent: Q69157

 If a FUNCTION returning a floating-point value is located in a Quick
 library and is directly used as the second, third, or later parameter
 of a SUB or FUNCTION in a program, then incorrect values may be passed
 to the SUB or FUNCTION being called. This problem occurs only in the
 QuickBASIC environment.

 Microsoft has confirmed this problem with Microsoft QuickBASIC
 versions 4.00, 4.00b, and 4.50. This problem does not exist with the
 Microsoft BASIC Professional Development System (PDS) versions 7.00
 and 7.10.

 When compiled and linked (with the FUNCTION in a .LIB library) into an
 .EXE file, the same program will run correctly.

 A simple workaround for this problem is to assign a temporary variable
 to the return value of the Quick library function, then pass that
 temporary variable when you invoke the SUB or FUNCTION.

 The results may vary depending upon the number and type of parameters
 passed to the FUNCTION within the Quick library. If the Quick library
 function accepts parameters, bad values may be passed to the calling
 SUB or FUNCTION.  However, if no parameters are accepted by the Quick
 library function, a machine hang may occur when that function is used
 as a parameter to another SUB or FUNCTION.

 Using the debug options when creating the Quick library, or using the
 ON ERROR GOTO ... RESUME lines in either the main program or in the
 Quick library, does not eliminate the problem. The code below
 demonstrates the problem.

 The following function goes in the Quick library:

 DECLARE FUNCTION func1! (x!)
 FUNCTION func1! (x!)
     func1! = x! * 2
 END FUNCTION

 The following program invokes the Quick library's function directly in
 the parameter list of the SUB foo, and demonstrates the problem:

 DECLARE FUNCTION func1! (x!)
 DECLARE SUB foo (a!, b!)
 CALL foo (100, func1! (45))
 END
 SUB foo (a!, b!)
 PRINT a!; b!  'This should print 100 90, but incorrectly prints 90 90
 END SUB

 A simple modification using a temporary variable (y!) in the calling
 program works around the problem, as shown below:

 DECLARE FUNCTION func1! (x!)
 DECLARE SUB foo (a!, b!)
 y! = func1! (45)
 CALL foo (100, y!)
 END
 SUB foo (a!, b!)
     PRINT a!; b!
 END SUB


 962. VAL Function Returns "Type Mismatch" for Some Invalid Numbers

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM SR# S910121-320
 Last Modified: 14-FEB-1991    ArticleIdent: Q69162

 The VAL function may return the error message "Type mismatch" in
 specific cases if the string value is not a valid number. In most
 other cases, VAL normally returns 0 (zero) for invalid numbers.

 This information applies to Microsoft QuickBASIC 4.00, 4.00b, and
 4.50, to Microsoft BASIC Compiler 6.00 and 6.00b, and to Microsoft
 BASIC Professional Development System (PDS) 7.00 and 7.10.

 Microsoft is researching this problem and will post new information
 here as it becomes available.

 The VAL function returns the numeric value of a string expression that
 represents a number. VAL interprets the sequence of characters until a
 character is found that cannot be recognized as part of a number. If
 the string is not a valid number (such as a string of alphabetic
 characters), the VAL function returns zero. However, in certain cases,
 a string of alphabetic characters will return the "Type mismatch"
 error.

 The problem often occurs with a string expression that starts out with
 a valid numeric expression, such as "&" (for example, &H for
 hexadecimal notation), "-" (for example, a negative number), or "+"
 (for example, a positive number), but follows that with an invalid
 character. When parsing such a string, the VAL function will encounter
 an invalid numeric format and give "Type mismatch" when it should
 return zero.

 Examples
 --------

 PRINT VAL("12.32")            '12.32 prints correctly
 PRINT VAL("s%k&r3ds")         '0 prints correctly
 PRINT VAL("&+%we3")        'Gives "Type mismatch", but should be 0

 The string expressions listed below generate the "Type mismatch" error
 when passed to the VAL function. This is not a complete list.

 Each line in the table below shows combinations of characters, which
 are grouped by the following rules:

    [] = Encloses symbol required to pass to VAL
    |  = Logical or (separates choices in a list of characters)
    char = CHR$(32) through CHR$(126)
    real = A valid number which contains a decimal point
    NULL = A byte value equal to 0 (zero)
    integer = A valid number with no decimal point

 List of known string of symbols:

 [ & | D | E | NULL ] +% [ NULL | char ]
 [ & | D | E | NULL ] +& [ NULL | char ]
 [ & | D | E | NULL ] +@ [ NULL | char ]
 [ & | D | E | NULL ] -% [ NULL | char ]
 [ & | D | E | NULL ] -& [ NULL | char ]
 [ & | D | E | NULL ] -@ [ NULL | char ]

 [ + | - | . | integer | NULL ] .% [ NULL | char ]
 [ + | - | . | integer | NULL ] .& [ NULL | char ]

 [ + | - | . | real | NULL ] D% [ NULL | char ]
 [ + | - | . | real | NULL ] D& [ NULL | char ]
 [ + | - | . | real | NULL ] D@ [ NULL | char ]
 [ + | - | . | real | NULL ] E% [ NULL | char ]
 [ + | - | . | real | NULL ] E& [ NULL | char ]
 [ + | - | . | real | NULL ] E@ [ NULL | char ]

 [ . ][ real ][ % | & ]
 [ E | D ][ integer ][ % | & | @ ]

 For other examples where the VAL function gives a "Type mismatch"
 error, query on the following words:

    BASIC and VAL and type and mismatch


 963. BASIC Uses Radians, Not Degrees, for Trigonometric Functions

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BASICCOM B_GWBasicI B_BasicInt B_MQuickB
 Last Modified: 14-FEB-1991    ArticleIdent: Q69164

 You must pass angle measurements in radians (not degrees) to BASIC's
 trigonometric functions (SIN, COS, and TAN).

 All versions of Microsoft BASIC require radians for the built-in
 trigonometric functions (SIN, COS, TAN). Therefore, the value returned
 from BASIC's SINe, COSine, and TANgent will be different than your
 calculator's value, unless your calculator is using radians.

 To convert degrees to radians, multiply the degrees by pi/180, where
 pi equals 3.14159265359.

 This information applies to the following BASIC versions:

 1. Microsoft QuickBASIC versions 1.00, 1.00a, and 1.00b for Apple
    Macintosh.

 2. Microsoft BASIC Compiler version 1.00 for Apple Macintosh.

 3. Microsoft BASIC Interpreter versions 1.00, 1.01, 2.00, 2.10, and
    3.00 for Apple Macintosh.

 4. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
    4.00, 4.00b, and 4.50 for MS-DOS.

 5. Microsoft BASIC Compiler versions 5.35 and 5.36 for MS-DOS.

 6. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and
    MS OS/2.

 7. Microsoft BASIC Professional Development System (PDS) versions 7.00
    and 7.10 for MS-DOS and MS OS/2.

 8. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, and 3.23 for
    MS-DOS.

 Code Example
 ------------

 'Radians = degrees * PI / 180
 PI = 3.141593
 X = 45
 ' The following prints .8509035, which is the SIN of 45 radians,
 ' which may not be what you wanted:
 PRINT SIN(X)

 ' Now, convert X to radians before passing to the SIN function:
 PRINT SIN(X * PI / 180)  'This gives .7071068 as the SIN of 45 degrees


 964. How to Work Around Floating-Point Accuracy/Comparison Problems

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI
 Last Modified: 14-FEB-1991    ArticleIdent: Q69333

 To reliably test whether two floating-point variables or expressions
 are equal (using IEEE format or MBF), you must subtract the two
 variables being compared and test whether their difference is less
 than a value chosen at the limits of significance for single or double
 precision. NO OTHER TEST FOR EQUALITY WILL BE RELIABLE. The following
 formulas reliably test whether X and Y are equal:

 1. For single precision, you must test whether the difference of X and Y
    is less than the value 7 significant digits smaller than X or Y.
    Divide X or Y by 10^7 to find the comparison value. For example:

       IF ABS(X! - Y!) <= (X! / 10^7) THEN PRINT "Equal within 7 digits"

 2. For double precision, you must test whether the difference of X and Y
    is less than the value 15 significant digits smaller than X or Y.
    Divide X or Y by 10^15 to find the comparison value. For example:

       IF ABS(X# - Y#) <= (X# / 10^15) THEN PRINT "Equal within 15 digits"

 The IEEE floating-point format is found in Microsoft QuickBASIC
 versions 3.00 (QB87.EXE coprocessor version only), 4.00, 4.00b, and
 4.50 for MS-DOS; in Microsoft BASIC Compiler versions 6.00 and 6.00b
 for MS-DOS and MS OS/2; and in Microsoft BASIC Professional
 Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
 OS/2.

 MBF (Microsoft Binary Format) is found in Microsoft QuickBASIC
 versions 3.00 (QB.EXE non-coprocessor version only), 2.01, 2.00, 1.01,
 and 1.00 for MS-DOS; and in Microsoft GW-BASIC Interpreter versions
 3.20, 3.22, and 3.23 for MS-DOS.

    NOTE: Significant digits in a calculated number can be lost due to
    the following: multiple calculations, especially addition of
    numbers far apart in value, or subtraction of numbers similar in
    value. When a number results from multiple calculations, you may
    need to change your test for equality to use fewer significant
    digits to reflect the mathematical loss of significant digits. If
    your test of significance uses too many significant digits, you may
    fail to discover that numbers compared for equality are actually
    equal within the possible limit of accuracy.

 In the above BASIC versions that use IEEE floating-point format,
 intermediate calculations are performed in an internal 64-bit
 temporary register, which has more bits of accuracy than are stored in
 single- or double-precision variables. This often results in an IF
 statement saying that the intermediate calculation is not equal to the
 expression being compared, as in the following example:

    X = 25
    Y = 60.1
    IF 1502.5 = (X * Y) THEN PRINT "equal"

 Running the above code will NOT print "equal". In contrast, the
 following method using a placeholder variable will print "equal", but
 is still NOT a reliable technique as a test for equality:

    Z = 25 * 60.1
    IF 1502.5 = Z THEN PRINT "equal"

 Note that explicit numeric type casts (! for single precision, # for
 double precision) will affect the precision in which calculations are
 stored and printed. Whichever type casting you perform, you may still
 see unexpected rounding results:

    PRINT 69.82! + 1    'single precision, prints 70.82
    PRINT 69.82# + 1    'double precision, prints 70.81999999999999

 For an exact decimal (base 10) numeric representation, such as for
 calculations of dollars and cents, you should use the CURRENCY (@)
 data type found in BASIC PDS 7.00/7.10. The CURRENCY data type exactly
 stores up to 19 digits, with 4 digits after the decimal place.

 Reference:

 Both the IEEE and MBF standards attempt to balance accuracy and
 precision with numeric range and speed. Accuracy measures how many
 significant bits of precision are not lost in calculations. Precision
 refers to the number of bits in the mantissa, which determines how
 many decimal digits can be represented.

 Both IEEE format and MBF store numbers of the form 1.x to the power of
 y (where x and y are base 2 numbers; x is the mantissa, and y is the
 exponent).

 MBF single precision has 24 bits of mantissa, and double precision has
 56 bits of mantissa. All MBF calculations are performed within just 24
 or 56 bits.

 IEEE single precision has 24 bits of mantissa, and double precision
 has 53 bits of mantissa. However, all single and double precision IEEE
 calculations in QuickBASIC 3.00/4.x, BASIC Compiler 6.00/6.00b, and
 BASIC PDS 7.00/7.10 are performed in a 64-bit temporary register for
 great accuracy. As a result, IEEE calculations are more accurate than
 MBF calculations, despite MBF's ability to represent more bits in
 double precision.

 Most numbers in decimal (base 10) notation do NOT have an exact
 representation in the binary (base 2) floating-point storage format
 used in single- and double-precision data types. Both IEEE format and
 MBF cannot exactly represent (and must round off) all numbers that are
 not of the form 1.x to the power of y (where x and y are base 2
 numbers). The numbers that can be exactly represented are spread out
 over a very wide range. A high density of representable numbers is
 near 1.0 and -1.0, but fewer and fewer representable numbers occur as
 the numbers go towards 0 or infinity.

 The above limitations often cause BASIC to return floating-point
 results different than you might expect, as explained in many separate
 articles found with the following query:

    floating and point and format and QuickBASIC


 965. Microsoft BASIC Phone Support Policies; 900 Unblocking

 Product Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | B_BasicCom B_GWBasicI B_BasicInt
 Last Modified: 21-FEB-1991    ArticleIdent: Q69468

 The following open letter describes Microsoft's telephone support
 policies for Microsoft BASIC and QuickBASIC, as of February 20, 1991:

 Dear Microsoft BASIC or QuickBASIC Customer:

 On October 23, 1990, Microsoft announced Microsoft OnCall(TM) for
 Microsoft BASIC. OnCall for BASIC offers high-level support, extended
 service hours, and minimal hold time for all Microsoft BASIC products
 through a 900 phone number or a flat rate added to a toll number.
 Microsoft offers OnCall for BASIC in response to customer demand for
 faster, more sophisticated support.

 "The entry-level support line meets the requirements of most customers
 who need assistance with installing Microsoft QuickBASIC software and
 getting up to speed. Those who require priority support on more
 advanced issues now have an additional option with Microsoft OnCall
 for BASIC," said Charles Stevens, general manager of Microsoft's Data
 Access Business Unit. Common questions from Microsoft OnCall for BASIC
 customers include inquiries about Microsoft QuickBASIC memory
 management, inter-language calling, and error and event trapping.

 Microsoft OnCall for BASIC is offered through a 900 phone number at a
 cost of $2.00 per minute. Hold time will be minimal and customers will
 not be charged until they reach a technician. Extended service hours
 are from 6 AM to 6 PM Pacific Standard Time (PST), Monday through
 Friday (excluding holidays). The Microsoft OnCall for BASIC phone
 number is (900) 896-9999.

 In many businesses, universities, and government agencies, the phone
 systems are blocked from using our 900 phone number. Therefore, you
 may also access OnCall for BASIC through the following unblocking toll
 number: (206) 646-5102, which is open 6 AM to 6 PM PST, Monday through
 Friday (excluding holidays), with a flat-rate fee of $20.00 per call
 for programming assistance. Only Master Card, VISA, and American
 Express credit cards are accepted.

 The entry-level phone line for Microsoft QuickBASIC supports Microsoft
 QuickBASIC version 4.50 for DOS systems, and Microsoft QuickBASIC
 version 1.00 for Macintosh(R) systems. Technicians will help new
 Microsoft QuickBASIC users get up and running as quickly as possible.
 The entry-level Microsoft QuickBASIC support number is (206) 646-5101.
 Service hours are 8:00 AM to 5:00 PM PST, Monday through Friday
 (excluding holidays).

 Users of Microsoft BASIC Professional Development System and earlier
 versions of the Microsoft BASIC compiler will continue to have
 unlimited support on the Microsoft Product Support Services toll line,
 which is (206) 637-7096 for Languages and Hardware. Support for all
 Microsoft BASIC products will continue on CompuServe as well.

 Blain Barton
 BASIC Languages Team Manager
 Product Support Services


 966. MSHERC.COM Mistakenly Loads on CGA Computer; README Addition

 Product Version(s): 4.00 4.00b 4.50
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S910212-174 docerr B_BasicCom
 Last Modified: 21-FEB-1991    ArticleIdent: Q69537

 MSHERC.COM is a Hercules graphics driver supplied with Microsoft
 QuickBASIC version 4.50 and Microsoft BASIC Professional Development
 System (PDS) versions 7.00 and 7.10. QBHERC.COM is the equivalent
 driver supplied with Microsoft QuickBASIC versions 4.00 and 4.00b. You
 must run MSHERC.COM or QBHERC.COM before you can use Hercules graphics
 (SCREEN 3) in your BASIC programs.

 MSHERC.COM or QBHERC.COM should not load on a system that is using a
 graphics adapter other than Hercules. If invoked on a system using an
 EGA or VGA graphics card, MSHERC.COM or QBHERC.COM reports the
 following error and does not load:

    Hercules Video Card not present.
    Hercules Video Support Routines not installed.

 However, on some systems using CGA graphics cards, MSHERC will load
 into memory and display the following:

    Hercules Video Support Routines installed.

 This behavior consumes memory unnecessarily, and the message can be
 misleading because Hercules graphics (SCREEN 3) does not work on CGA
 systems. MSHERC.COM or QBHERC.COM should not be run on computers that
 have a CGA card.

 README.DOC Addition for MSHERC.COM
 ----------------------------------

 All documentation for the driver file MSHERC.COM was mistakenly left
 out of the manuals, online Help, and README.DOC file of QuickBASIC
 version 4.50 and BASIC PDS versions 7.00 and 7.10. MSHERC.COM is
 briefly mentioned in the packing list (PACKING.LST) of these products,
 but instructions are missing.

 The following instructions for QBHERC.COM are taken from the
 README.DOC file for QuickBASIC versions 4.00/4.00b and BASIC compiler
 versions 6.00/6.00b; this information applies to both QBHERC.COM and
 MSHERC.COM:

    The SCREEN statement now includes mode 3 for Hercules display
    adapters. The following is a brief summary of screen mode 3. See
    your Hercules documentation for details.

    QuickBASIC supports Hercules Graphics Card, Graphics Card Plus,
    InColor Card, and 100% compatibles.

    You must use a monochrome monitor.

    Hercules text mode is SCREEN 0; Hercules Graphics mode is SCREEN 3.

    You must load the Hercules driver (QBHERC.COM) before running your
    program. If the driver is not loaded, SCREEN 3 statement gives an
    "Illegal function call" error message. Type QBHERC to load the
    driver.

    Text dimensions are 80x25 (9x14 character box); bottom 2 scan lines
    of 25th row are not visible.

    Resolution is 720x348 pixels, monochrome.

    Number of screen pages supported is 2.

    The PALETTE statement is not supported.

    In order to use the Mouse, you must follow special instructions for
    Hercules cards in the Microsoft Mouse Programmer's Reference Guide.
    (This must be ordered separately; it is not supplied with either
    the QuickBASIC or the Mouse package.)






 Microsoft Mouse
 =============================================================================


 1. Availability of MENU.COM

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-NOV-1988    ArticleIdent: Q28420

 I have obtained a file with the .MNU extension for a third party
 application that requires a file from Microsoft called MENU.COM.

 If you have a mouse with driver Version 6.14, the MENU.COM file will
 be on your Mouse Setup Disk.

 If you have a version between Version 6.00 and Version 6.14, call
 Microsoft Product Support (206) 454-2030 about obtaining MENU.COM.

 If you have a version prior to Version 6.00, you will have the file on
 your System Disk.


 2. Network and Mouse Conflicts

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-DEC-1988    ArticleIdent: Q28421

 The bus mouse is interrupt selectable using the J4 jumper block
 located on the INPORT interface card. Make sure the netcard is not
 using the same interrupt; if your network card is using the same
 interrupt, it will crash when the mouse driver installs.

 The bus mouse uses its own I/O address (23c-23f). On the current
 interface cards this can be changed to the lower four bytes by
 selecting secondary INPORT (address 238-23b) over PRIMARY on the J3
 jumper setting. (note: moving the card to another slot may in
 addition solve the problem).

 If the above does not solve the problem or if you have the serial
 mouse, change the driver loading order or disable the driver (mouse
 off) when using the network.

 Contact the manufacturers of your netcard to see if they know of the
 above problem.


 3. IRQ Settings and Mouse Installation

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q12230

 The jumper on the bus mouse should be checked before the card is
 installed in any computer, especially if the card is moved from one
 machine to another. The board's jumper controls which interrupt
 request (IRQ) line is used. IRQ lines are used to facilitate
 information transfer from such I/O devices as disk controllers and
 serial ports. The jumper avoids IRQ conflicts with other devices
 already installed in the computer. Under each pair of pins on the card
 is a number between 2 and 5 (inclusive). The jumper selects the IRQ
 line. Microsoft ships the boards with the jumper set to IRQ 2, for
 installation in a typical IBM PC or PC XT. Because IBM changed the IRQ
 architecture in the PC AT by using using IRQ 2 for the second IRQ
 controller, the bus mouse jumper is usually set to IRQ 5 on an AT.

 While these jumper settings are correct for most installations, you
 should verify which (if any) IRQ lines are being used by every device
 already installed in the machine. There can be only one active device
 per IRQ line. Refer to the technical manuals for each manufacturer's
 product or contact the manufacturer directly for this information. The
 following is an IRQ allocation table as defined in the IBM PC and AT
 technical reference manuals (other manufacturers' software, hardware
 and add-on boards must follow this convention in order to be IBM
 compatible):

                                         PC-AT
 IRQ Line        PC, PC-XT       CTLR 1          CTLR 2

     0             Timer         Timer     | IRQ8  Clock
     1            Keyboard      Keyboard   | IRQ9  Redirected IRQ2
     2            Reserved       CTLR 2 <--| IRQ10 Reserved
     3              COM2          COM2     | IRQ11 Reserved
     4              COM1          COM1     | IRQ12 Reserved
     5           Hard disk        LPT2     | IRQ13 Coprocessor
     6          Floppy disk   Floppy disk  | IRQ14 Hard disk
     7             LPT1-3         LPT1     | IRQ15 Reserved

 Because the mouse can be jumpered in the IRQ range of 2 through 5 and
 there can be only one active device per IRQ line, the bus mouse can be
 installed only if at least one of these lines is free.

 For example, a bus mouse is to be installed in an IBM PC-AT with an
 IBM PC-AT Serial/Parallel Adapter configured as COM1 and LPT1,
 respectively; a Color Graphics Adapter; and a multi-function card with
 128K of memory and a serial port configured as COM2. On this computer,
 there is only one IRQ line still available on IRQ controller 1: IRQ 5.
 IRQ 2 is used by the AT's second IRQ controller and IRQ lines 4 and 3
 are used by COM1 and COM2. The CGA does not use an IRQ line and the
 parallel port uses IRQ 7, which falls outside of the mouse's range.
 The bus mouse should be jumpered for IRQ 5, thereby using the last IRQ
 line in the normal IRQ range of 0 through 7 of the first IRQ controller.
 The user of this computer should be aware of this for future
 expansion.

 The Enhanced Graphics Adapter (EGA) is now becoming a popular display
 card for PCs and XTs. The EGA includes a hardware feature that allows
 software to enable interrupts on IRQ2 to indicate the start of
 vertical retrace. Therefore, if an EGA and bus mouse are installed in
 a PC or XT, IRQ2 is no longer available for the mouse. In a full XT
 with a hard disk, two serial ports, an EGA, and a bus mouse, there
 will be an IRQ line overlap between two devices. Therefore, one device
 will have to be sacrificed to free up an IRQ line for the bus mouse.
 This is not a design deficiency of the bus mouse; it is a fundamental
 design restriction in the PCs and XTs.

 As discussed above, there are only eight IRQ lines in the PC and XT,
 of which four are used up by the motherboard and other standard
 equipment. The other four lines go quickly. Almost all expansion cards
 require that a free IRQ line be available, such as the following:

 1. Network cards
 2. Bisync communication cards
 3. Tape back-up units
 4. Some clock/calendar hardware
 5. Serial communication cards
 6. EGAs
 7. Emulation boards
 8. Hard disk controllers

 There are more desirable devices to install in a machine than IRQ
 lines to handle them. To help relieve the crowding of IRQ lines, the
 IBM AT includes a second IRQ controller with seven more lines.
 Currently, hardware is evolving to take advantage of the new AT
 architecture.

 Once the hardware is installed, the software must be loaded. When the
 mouse driver loads, using either MOUSE.SYS from CONFIG.SYS or
 MOUSE.COM from a batch file or the keyboard, the file will be loaded
 into memory and the driver will then install itself. This installation
 requires a few seconds. Various operations are undertaken, including
 mouse hardware initialization. This is the primary reason for the
 delay before the mouse installation message appears.

 If the error message "MOUSE: Microsoft mouse not found!" appears,
 there can be a number of hardware-related causes, such as a broken
 mouse; however, the problem more likely is an IRQ contention problem
 either between the mouse and another device or between the serial
 ports.

 Typical bus mouse related problems are between the mouse and the hard
 disk controller, i.e., bus mouse jumpered on IRQ 5 in an XT or IRQ 2
 in an AT. The common symptom for this problem is the inability to
 perform a warm boot (CTRL+ALT+DEL). If the bus mouse is jumpered on
 the same line as a serial port, network card, or emulator card,
 irregular and unreproducible system crashes can occur. In Windows,
 with a bus mouse doubled up on the IRQ line used by a modem, the mouse
 will "go away" when communications software is run.

 The standard isolation procedure is to verify IRQ-line usage and if no
 problems are uncovered, the next step is to remove as much hardware as
 possible. In this way, the conflict should be uncovered between
 particular devices and a resolution of the problem will follow.


 4. Bus Mouse and Cipher Tape Drive Card

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q46793

 Problem:

 When using the Microsoft Bus Mouse in an AST Premium 386/25, I got the
 following error message after I installed a Cipher Tape drive card:

    Bad or missing interrupt jumper

 Response:

 This problem occurred because the interrupt and primary/secondary
 jumper settings were wrong. To correct this problem, change J4 to
 interrupt 2, and J3 to secondary inport.


 5. Types Of Mice Available: Serial, Bus, and InPort

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-JUL-1988    ArticleIdent: Q28738

    Version 1.00 of the new white-button mouse is available in three
 varieties; there are no noticeable differences in function or speed.
 The type of mouse you want depends on the available resources of your
 system.
    The PS/2 Serial mouse will work in any IBM PS/2 mouse port or in
 any standard IBM 9- or 25-pin serial port. The PS/2 Serial mouse is
 recommended if you own an IBM PS/2 machine or have an available COM1:
 or COM2: serial port on your system.
    The Bus mouse has its own interface card, which includes the
 Microsoft InPort interface. It can be used with any IBM PC, XT, AT, or
 PS/2 model 25/30 with an available 8- or 16-bit slot. The Bus mouse is
 interrupt selectable (2 through 5), and frequently saves your serial
 ports for other uses.
    The InPort mouse is the same as the Bus mouse except that it does
 not come with a Microsoft InPort interface-equipped interface card.
 You must have the Microsoft InPort interface within your system (e.g.
 the MACH 20 has built-in InPort technology).


 6. Programming the Mouse Driver Versus Writing One

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-NOV-1988    ArticleIdent: Q28739

 If you plan to write an application with built-in mouse support,
 obtain the "Microsoft Mouse Programmer's Reference Guide." The manual
 includes a mouse library (for the Microsoft Compilers) and
 documentation on programming the mouse driver.

 Microsoft recommends that you program the mouse driver, rather than
 write your own mouse driver. This will maintain compatibility over any
 changes in future mouse hardware.

 If you need to write your own mouse driver, you can obtain the InPort
 Application Note (which is used with the Bus mouse) by calling
 Microsoft Product Support Services at (206) 454-2030.

 The Serial mouse protocol may be obtained by writing a formal request
 to our Mouse Product Manager (or contacting our Mouse ISV department),
 giving supported reasons for bypassing our mouse driver.


 7. Obtaining Hosiden Connectors Used with the Bus Mouse

 Product Version(s): 6.0 6.02 6.10 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28740

    The Hosiden connectors and sockets, which are used with the Bus
 Mouse with InPort hardware, can be obtained from HB Associates at
 1-800-423-3014.


 8. How to Deallocate or Disable the Mouse Driver

 Product Version(s): 6.0 6.02 6.10 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28741

    If the MOUSE.COM driver is installed, the Mouse Off command will
 deallocate the driver from memory if there were no other
 memory-resident programs loaded after it.
    If the MOUSE.SYS driver was installed, the Mouse Off command will
 only disable the driver and not deallocate.
    Although the mouse driver is deallocated or disabled, the mouse
 hardware will continue to send interrupts.



 9. Keyboard Styles for IBM and IBM Compatibles

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | non-numeric
 Last Modified: 31-AUG-1989    ArticleIdent: Q46918

 Use of the Microsoft Mouse menus is sometimes affected by the style of
 computer keyboard being used. The following are some major versions
 the IBM and IBM-compatible keyboard:

 1. The "standard" keyboard came with the original IBM PC. This
    keyboard includes a numeric keypad on the right-hand side and 10
    function keys across the top of the keyboard.

 2. The "extended" keyboard adds the F11 and F12 function keys to the
    standard keyboard.

 3. The "expanded" keyboard widens the standard keyboard and reproduces
    the nonnumeric keys and the cursor keys in the additional space.


 10. Leading Edge Model D Error "Unexpected SW Interrupt 33"

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-JUN-1988    ArticleIdent: Q29466

    The error message "Unexpected SW Interrupt 33" can occur on some
 Leading Edge Model D computers when installing a mouse driver.
    You usually can continue after this error message has appeared by
 typing C to continue. For a patch, call Leading Edge technical support
 at (617) 821-4300.


 11. Serial Mouse: "Driver Not Installed--Mouse Not Found" Message

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-APR-1988    ArticleIdent: Q29201

    A "Driver not installed--Mouse not found" error message usually
 pertains to a possible hardware problem.
    When isolating the source of the problem, first boot from a
 "vanilla" DOS (i.e., no AUTOEXEC.BAT or CONFIG.SYS files), then
 install the mouse driver manually from the Mouse Setup Disk.
    If the error remains, check your hardware set up for possible
 hardware conflicts or incorrect serial port configuration before
 determining if you have a possible faulty mouse.
     Your serial ports must follow an IBM standard and be configured as
 follows:

 COM1 using IRQ4 and configured as DTE (data terminal equipment).
 COM2 using IRQ3 and configured as DTE (data terminal equipment).

    The serial mouse does not work on serial ports configured as COM3
 or COM4. If you have only one serial port and it is configured as
 COM2, the mouse driver usually installs but does not work. Configure
 the port as COM1.
    If you have checked your configuration and the mouse driver does
 not install, checking the mouse on two machines is a good isolation
 test.


 12. Mouse Driver Installs but Mouse Does Not Work

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-JUN-1988    ArticleIdent: Q29202

    If the mouse driver is installed, but the mouse does not work, the
 problem may be due to one of the following problems:

    1. A hardware conflict
    2. A software conflict
    3. A faulty mouse

    If you have a serial mouse, make sure that your serial ports are
 correctly configured.
    To rule out a software conflict, boot from a "vanilla" DOS (i.e.,
 no AUTOEXEC.BAT or CONFIG.SYS files) and manually install the mouse
 driver from the Mouse Setup disk by typing Mouse.
    Problems can occur if the mouse driver is installed on a device
 other than the mouse. This is true in cases where a noisy bus causes
 the driver to install for a bus mouse, or a device such as a modem
 causes the driver to think a serial mouse is being used.
    If you suspect the driver is not installing on the correct port,
 use the mouse switches to direct the driver to the specific port.
    For example, if your mouse is on COM2, load the mouse driver with
 the following command:

    MOUSE /C2  <- install driver on COM2

    If you have a bus mouse, check the jumper settings for a possible
 interrupt conflict, an I/O address conflict, or expansion slot problems.
   If the problems continue, isolate the problem on another machine
 before determining if you have a faulty mouse.


 13. Serial Mouse Pin-Outs

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-JUN-1988    ArticleIdent: Q29204

    The serial mouse includes a 9- and 25-pin adapter cable to work with
 a standard 9- or 25-pin IBM serial port. The following are the pin-outs
 of the mouse cables:

                   Connectors

    Function    9 pin      25 pin

    RXD         pin 2      pin 3

    TXD         pin 3      pin 2

    RTS         pin 7      pin 4

    GND         pin 5      pin 7

    DTR         pin 4      pin 20

    The serial mouse is a data communication equipment (DCE) device,
 and is a female device (i.e., it has holes in its connectors). Because
 it is a DCE device, the port's functions should be one to one when
 making a cable for a nonstandard serial port.
    For example, the mouse's RXD should connect to your serial port's
 RXD and the mouse's TXD should connect to the serial port's TXD. This
 is true for other functions as well.


 14. Bus Mouse May Not Work on IRQ 2 on a 386 with OS/2

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-SEP-1988    ArticleIdent: Q29279

 The OS/2 mouse driver MOUSEA04.SYS will not install if you use the IRQ
 2 setting for OS/2 and a Wyse 386. MOUSEA03.SYS will install, but
 will not work in OS/2. The mouse works properly in DOS.

 OS/2 seems to be more sensitive to the IRQ usage. This problem occurs
 with both the old and new bus mice. To work around the problem, use
 another interrupt other than 2 on the 386.

 Although IRQ2 is not recommended for ATs or 386s, the mouse seems to
 work without any problems in the DOS environment (using all other
 interrupts); however, this does not seem to be the case in OS/2.


 15. Serial Mouse May Fail with an Older AT&T 6300

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  1-AUG-1988    ArticleIdent: Q28681

    There have been some reports that the mouse driver may not install
 correctly with a serial mouse connected to an older AT&T 6300. Using
 the "/C1" or "/C2" switch often solves the problem. If the problem
 continues, check the ROM date and upgrade the ROM if you are using an
 older one. AT&T recommends Version 1.43 ROM or later. Contact AT&T at
 (800) 222-7278 for ROM upgrade costs.


 16. Mouse EGA Register Interface

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-NOV-1988    ArticleIdent: Q29467

 An application note concerning the Mouse EGA Register Interface can be
 obtained by contacting the Microsoft Product Support Services Hardware
 Group at (206) 454-2030.

 The Microsoft Mouse EGA Register Interface is a library of nine
 functions. It can be called from assembly language programs or high
 level languages, such as FORTRAN, Pascal, C, and compiled BASIC. Its
 functions allow you to do the following:

 1. Read and write to one or more of the EGA write-only registers.

 2. Define default values for the EGA write-only registers or reset the
    registers to these default values.

 3. Confirm that the EGA Register Interface is present and if so,
    return its version number.

 If your program tries to set the EGA registers directly, rather than
 through the interface, the mouse cursor will draw incorrectly.


 17. No IBM DW4 or TopView Support for Bus Mouse with InPort

 Product Version(s): 6.00 6.02 6.10 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28682

 Problem:
    IBM DisplayWrite 4 does not recognize the Bus mouse with Microsoft
 InPort Device Interface. DisplayWrite 4 supports the serial mouse and
 older Bus mouse (with a 8255 chip), but does not have an upgraded
 mouse driver for the InPort interface Bus mouse.
    This problem also occurs with IBM TopView.

 Response:
    Because DisplayWrite 4 has custom-made pointing device drivers, you
 should contact your IBM dealer or have the IBM dealer contact
 IBM dealer support.



 18. Mouse Compatibility with IBM PCjr

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-SEP-1988    ArticleIdent: Q29469

 The Microsoft Mouse has not been tested with the IBM PCjr. Microsoft's
 PCjr Booster, which was discontinued, was the only official hardware
 that included mouse support (i.e., bus mouse hardware).

 We have received customer reports stating that gray-button serial mice
 work properly on the PCjr if a special serial adapter is obtained to
 make the PCjr serial I/O compatible.

 We have not confirmed that Microsoft's new white-button mouse will
 work properly with the PCjr using the special adapter.

 Solid Rock was a company that provided PCjr accessories, but it has
 since gone out of business.


 19. Mouse MREADME.DOC: Single Drive PCs

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-JUN-1988    ArticleIdent: Q29702

    If you have a single-drive PC without a hard disk, you will not be
 able to use the Mouse Setup program (MSETUP) to set up the mouse
 software.
    MSETUP installs the mouse driver, MOUSE.COM.
    On a single-drive PC, you must install the mouse driver yourself in
 one of the following two ways:

    Manual Installation:      Copy MOUSE.COM onto the disk you use to
                              start your computer. You can then load
                              the mouse driver manually each time you
                              start your system, by typing "MOUSE" at
                              the DOS prompt.

    Automatic Installation:   With MOUSE.COM on the disk you use to
                              start your computer, you can modify your
                              AUTOEXEC.BAT file so that the mouse
                              driver is automatically loaded each time
                              you start your system. Add the line
                              "MOUSE" to the AUTOEXEC.BAT file to
                              automatically load MOUSE.COM when you
                              start your computer.

    For more information on this subject, see the "What the MSETUP
 Program Does" section of the "Microsoft Mouse User's Guide."


 20. Some ASCII Control Characters Incorrect in Programmer's Manual

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | mouse menu
 Last Modified: 31-AUG-1989    ArticleIdent: Q46923

 A documentation error on Page 2-24 of "Microsoft Mouse Programmer's
 Reference Guide" incorrectly states that ASCII value 28 corresponds to
 CTRL+\, not CTRL-. This error was corrected in "Microsoft Mouse
 Programmer's Reference" from Microsoft Press.

 Control characters CTRL+H, CTRL+I, CTRL+J, CTRL+M, and CTRL+[ are not
 listed in the table on Page 2-24 because their ASCII values are the
 same as ASCII codes for backspace, horizontal tab, linefeed, carriage
 return, and escape, respectively.


 21. Mouse MREADME.DOC: Invoking the Control Panel in Word

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q29703

 Microsoft Word recognizes the CTRL+LEFT mouse button and SHIFT+LEFT
 mouse-button key combinations as Word operations.

 To invoke the Control Panel while working in Word, do the following:

 1. Hold down the CTRL key.
 2. Press the ALT or SHIFT keys before pressing the left mouse button.


 22. Mouse Driver Command Line Switches

 Product Version(s): 6.00 6.02 6.10 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28684

    The following are command-line switches for mouse driver 6.00 and above:

    SWITCH       DESCRIPTION

    /B           Look for Bus or InPort mouse at primary address
    /I1          InPort mouse at primary address
    /I2          InPort mouse at secondary address
    /C1          Serial mouse on COM1
    /C2          Serial mouse on COM2
    /S <nnn>     Horizontal and vertical sensitivity <nnn> = 0 to 100
    /H <nnn>     Horizontal sensitivity
    /V <nnn>     Vertical sensitivity
    /R0          InPort interupt rate disabled
    /R1          InPort interupt rate 30Hz (default)
    /R2          InPort interupt rate 50Hz
    /R3          InPort interupt rate 100Hz
    /R4          InPort interupt rate 200Hz

    Example: mouse /s75    <- sets mouse sensitivity to 75 (50 default)



 23. Driver "Removed from Memory" Versus "Disabled"

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q47138

 MOUSE.COM Versions 6.00 and later are removed from memory unless
 connected to a PS/2 mouse port. The message "Existing Mouse Driver
 Disabled" appears if the mouse is connected to a PS/2 mouse port or if
 other terminate-and-stay-resident programs (TSRs) prevent the mouse
 from being removed from memory.

 Earlier versions of the mouse driver do not deallocate.

 Versions 6.11 and 6.12 are the only versions that are removed from
 memory if connected to the PS/2 mouse port.


 24. MREADME.DOC: Using the Default Expert Mouse Menu

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-JUN-1988    ArticleIdent: Q29705

    The default Expert Mouse menu allows you to use a mouse to emulate
 keys, such as the ESCAPE, ENTER, and cursor keys, with applications
 that normally do not support mice.

    To use this menu, load it into memory before you start your
 application.
    To load the default menu, type the following after the prompt of
 the drive or directory where the DEFAULT.COM file resides:

    default

    Once the default menu is loaded, you can perform the mouse actions
 described in the following tables to emulate certain keys in your
 application:

                  Press                     To Emulate

                  The left mouse button     The F3 key
                  The right mouse button    A carriage return (the ENTER key)
                  Both mouse buttons        The ESCAPE key

                  Move                      To emulate

                  The mouse to the left     The LEFT ARROW key
                  The mouse to the right    The RIGHT ARROW key
                  The mouse up              The UP ARROW key
                  The mouse down            The DOWN ARROW key

    To remove the default menu from memory, type the following after
 the prompt of the drive or directory where the DEFAULT.COM file
 resides:

                  default off



 25. Supplemental Mouse Menus Disk (Expert and Basic Menus)

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 14-JUL-1989    ArticleIdent: Q35131

 The following Microsoft Mouse menus are available by contacting the
 Microsoft Information Center by calling (800) 426-9400 and requesting
 the Mouse Supplemental Menus disk:

    Filename                 Application
    --------                 -----------

    MSMENU.COM               Most text-based software
    MSDB3.COM                dBASE III PLUS
    MS123.COM                Lotus 1-2-3, Versions 1A and later
    MSSYM.COM                Lotus Symphony, Versions 1.20 and 2.00
    MSMM2.COM                MultiMate Advantage II
    MSPF.COM                 PFS: Professional File, Version 2.00
    MSPLAN.COM               PFS: Professional Plan, Version 1.00
    MSPW1.COM                PFS: Professional Write, Version 1.00
    MSPW2.COM                PFS: Professional Write, Version 2.00
    MSSC4.COM                SuperCalc 4, Version 1.00
    MSWP4.COM                WordPerfect, Version 4.20
    MSWP5.COM                WordPerfect, Version 5.00
    MSWS.COM                 WordStar, Versions 3.30 and 4.00
    MSWS5.COM                WordStar, Version 5.00

 In addition, you will receive an Expert Mouse Menus disk with the
 following menus:

    Filename                  Application

    MS123-1.COM               Lotus 1-2-3 Version 1A
    MS123-2.COM               Lotus 1-2-3 Version 2
    MSDW.COM                  DisplayWrite 3 Version 1.10
    MSMM.COM                  MultiMate Version 3.31

 The expert menus have more functionality than the basic menus. The
 menus are sold for a small fee.


 26. Ventura Publisher 2.0 and Mouse Driver 6.24b

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-JUL-1990    ArticleIdent: Q63224

 When mouse driver version 6.24b for the Microsoft Mouse is installed,
 Ventura Publisher version 2.0 is limited to black and white regardless
 of the screen colors selected.

 To correct this behavior, replace mouse driver 6.24b with mouse driver
 7.04.



 27. Mouse Versions Prior to New Mouse 1.00 Used MOUSE.SYS

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-SEP-1988    ArticleIdent: Q35082

 Although there is no difference in functionality between the MOUSE.SYS
 and MOUSE.COM drivers, versions prior to the new white-button Version
 1.00 mice used MOUSE.SYS loaded from the CONFIG.SYS rather than the
 MOUSE.COM used via the AUTOEXEC.BAT file.

 The MOUSE.COM driver provides greater flexibility in that it is able
 to deallocate from memory and is executable from DOS.


 28. Mouse Menu May Have Up to 32 Menus

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-JUN-1988    ArticleIdent: Q29882

    There are 32 Menu statements allowed for each Mouse Menu. A
 combination of Popup and Menu statements can exceed 32.


 29. 123.MNU Worked on Floppy But Not on Hard Drive

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q31045

 The Lotus 1-2-3 menu that was included with the original mouse (Word
 2.00 bundle) will not work if Lotus 1-2-3 was loaded from the hard
 disk and you have the bus mouse set for interrupt 5 on your IBM PC.
 The menu runs properly from a floppy.

 Change the interrupt setting to 2 on the bus card to resolve this
 problem.


 30. Windows Versions 1.01 and 1.02 and the Bus Mouse

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR59473
 Last Modified:  4-NOV-1988    ArticleIdent: Q19915

 Windows Versions 1.01 and 1.02 will hang or will not recognize bus
 mouse Version 5.03 (InPort hardware) or later.

 Windows Versions 1.01 and 1.02 contain an initial release of
 MOUSE.DRV. Beginning with Version 5.03 of the bus mouse, new InPort
 hardware was incorporated in the bus mouse design. An update to the
 MOUSE.DRV software is required for Windows to correctly recognize the
 mouse.

 The updated MOUSE.DRV is included in Windows Version 1.03 and later.
 In addition, it is included in the mouse Version 5.03 System disk and
 the current mouse Version 1.00 Setup disk.

 If you have Version 6.x of the mouse, you can obtain the updated
 MOUSE.DRV by calling Microsoft Product Support hardware group at (206)
 454-2030 and requesting for the "Mouse Drivers Update Disk."

 The above problem may also affect ISVs and OEMs that have developed
 stand-alone Windows applications or have licensed and adapted Windows
 using the initial Windows development software.


 31. Mouse-Cursor State and EGA Memory

 Product Version(s): 6.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-JUN-1988    ArticleIdent: Q31149

    The Microsoft Mouse driver EGA interface maintains the mouse-cursor
 state in the unused 8K of video memory available at the top of the
 four 64K buffers that comprise the 256K of total video memory
 available on a loaded EGA adapter. Normally this is of little
 consequence in programming such systems; however, if you resize the
 video buffer by reprogramming the CRT Controller's Offset register,
 problems may occur.
    You will know there is a problem if garbage appears on the display
 after panning through an enlarged virtual screen.
    To work around this problem, do not use Mouse Function 1 to show
 the mouse cursor. Instead, use an alternative method of monitoring the
 mouse's screen location (e.g. XOR some graphical object to the
 screen).


 32. CPANEL May Crash if /S Switch Used Previously

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35229

 If a value such as /s33 is passed to the mouse driver before invoking
 CPANEL, CPANEL may crash if you keep decrementing while in the CPANEL
 screen. The CPANEL will not be invoked and a divide overflow may
 occur, but the mouse driver remains intact.


 33. Using Mouse Menus with WordPerfect Version 5.00

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-JUN-1988    ArticleIdent: Q31293

    When using a Mouse menu with WordPerfect Version 5.00, the menu
 opens; however, no text appears at the current cursor location when a
 selection is made. Upon exiting WordPerfect, the characters from the
 menu appear at the DOS command prompt.
    WordPerfect Version 5.00 has keyboard macros that disable the Mouse
 menu while in WordPerfect. To use a Mouse menu with WordPerfect
 Version 5.00, you must start WordPerfect with the /nk switch. This
 will disable the keyboard macros and allow the Mouse menu to function
 normally.


 34. Mouse Driver Conflict with Fixed-Disk Organizer

 Product Version(s): 6.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 25-JUL-1988    ArticleIdent: Q31330

    The mouse driver may not install due to a possible conflict between
 the Microsoft Mouse driver and the IBM fixed-disk organizer (FDO).
    This problem can be avoided by altering the load order of the two
 programs. If the mouse driver is loading first and being destroyed by
 the FDO, edit your AUTOEXEC.BAT file so the FDO loads first. If the
 FDO is loading first, load it after the mouse driver.
    Please note that this workaround is not guaranteed to avert all
 conflicts, but it has yielded positive results in many instances.


 35. "Microsoft Mouse Driver Not Found" Error Message

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-JUL-1988    ArticleIdent: Q32263

    The MOUSE.COM or MOUSE.SYS driver must be loaded before attempting
 to load a mouse menu. The "Microsoft Mouse driver not found" error
 message is generated when a mouse expert menu tries to load without
 the mouse driver already loaded.
    This error message should not be confused with the message "Driver
 not installed-- Microsoft Mouse not found", which is a mouse driver
 not loading message.


 36. CPANEL Defaults to Display Page 0

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35230

 CPANEL may not display in a graphics application that uses graphics
 pages greater than 0. CPANEL defaults to display on Page 0 of the
 graphics page.

 To work around this problem, use the /S switch to the mouse driver.


 37. /S1 or /S2 Yields Same Result as /S0

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35231

 If a sensitivity switch of value 1 or 2 is passed to the mouse driver,
 you may not recognize any mouse cursor change for mouse movement. A
 sensitivity value of 3 seems to be the minimum sensitivity that the
 mouse driver moves the cursor.


 38. Internal Processing Error and OS2MOUSE.V12 with Mouse

 Product Version(s): 1.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  6-JUL-1990    ArticleIdent: Q63226

 When OS2MOUSE.V12 is installed and the communications manager is
 selected, an internal processing error is detected and the system will
 hang.

 To correct this problem, reinstall the mouse driver using the drivers
 that were supplied with the OS/2 package and the system will not hang
 when the communications package is selected.

 We are researching this problem and will post new information here as
 it becomes available.


 39. Symphony Mouse Menu Works in Text Mode Only

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28425

    When using the Symphony mouse menu, please make sure Symphony is
 set up for "text and graphics separate".

    If you are running Symphony with an EGA, Symphony comes up in green
 for "text and graphics separate" configurations. Combined
 configuration will display in red when Symphony is running.


 40. Standard Mouse Menus Do Not Deallocate

 Product Version(s): 4.x 5.x 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-AUG-1988    ArticleIdent: Q23827

 You cannot deallocate a standard mouse menu (a menu that loads with
 MENU.COM) from memory. Entering "menu off" will disable the keyboard
 emulation; however, it will not deallocate from memory.


 41. Available Mouse Menus

 Product Version(s): 4.x 5.x 6.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-AUG-1988    ArticleIdent: Q23836

    Version 6.00 of the Microsoft Mouse contains "Expert Mouse Menus"
 for Lotus 1-2-3 Versions 1A and 2.00, MultiMate Version 3.31, and
 DisplayWrite 3 Version 1.10. The "Mouse Programmer's Reference Guide"
 contains "Standard Mouse Menus" for previous versions (date mid-1985)
 of Symphony, WordStar, Multiplan, and VisiCalc.


 42. Expert and Standard Mouse Menus

 Product Version(s): 4.x 5.x 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-AUG-1988    ArticleIdent: Q23837

 Question:
    What is the difference between an Expert and a Standard mouse menu?

 Response:
    Standard mouse menus are loaded with MENU.COM, while an Expert
 mouse menu is an executable .COM file.


 43. CPANEL Does Not Display in the OS/2 DOS 3.x Box

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35232

 CPANEL will not work in the OS/2 DOS 3.x box unless you load the DOS
 mouse driver rather than the OS/2 mouse driver.


 44. MSETUP Installs on Drive Specified

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35250

 If you have more than one hard-disk partition, MSETUP has the
 capability of installing the mouse software on a partition that may
 not be your C: drive. If you select to do this, you must manually edit your
 AUTOEXEC.BAT file to invoke the mouse driver and optionally CPANEL.
 For example, to install the mouse software on your D: drive, you must
 edit your AUTOEXEC.BAT on your boot drive C: to the following:

 D:\mouse1\mouse
 D:\mouse1\cpanel



 45. Standard Mouse Menus Are Not in .COM Format

 Product Version(s): 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-AUG-1988    ArticleIdent: Q23829

    You cannot write menus in .COM format with the "Mouse
 Programmer's Reference Guide." The reference guide allows you to
 create standard mouse menus, which are installed with the MENU.COM
 file.
    If you are a developer interested in creating menus in .COM format,
 an Expert Menus Toolkit is available that allows you to create expert
 mouse menus. For more information, call Microsoft Hardware Development
 at (206) 882-8080, and ask for information on Expert Menus Development
 software.


 46. Earlier Versions with Mouse Menu Software

 Product Version(s): 4.x 5.x 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-AUG-1988    ArticleIdent: Q24163

    The content of the "Microsoft Mouse Programmer's Reference Guide"
 is similar to earlier versions of the mouse containing the mouse
 programming.
    If you are writing standard mouse menus, the commands in the
 "Microsoft Mouse Programmer's Reference Guide" are the same as they
 were with versions prior to Version 6.00. The major changes include
 better documentation, examples, and updated mouse libraries. If you
 have a version prior to Version 5.03, we recommend that you obtain the
 "Microsoft Mouse Programmer's Reference Guide" if you are having any
 problems with MENU.COM or MAKEMENU.EXE.


 47. Applications That Do Not Use the Mouse

 Product Version(s): 4.x 5.x 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-AUG-1988    ArticleIdent: Q24164

 The "Microsoft Mouse Programmer's Reference Guide" allows you to write
 your own mouse menus for programs without mouse support. The reference
 guide includes the necessary software and documentation to provide
 keyboard emulation using mouse menus. Mouse menus will run in text
 mode with most programs that do not grab the keyboard interrupts.


 48. MENU.COM Needed to Load .MNU Files

 Product Version(s): 4.x 5.x 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-AUG-1988    ArticleIdent: Q24178

 With the release of Version 6.00 of the mouse, we decided to separate
 the programming aspects of the mouse and place them in the "Microsoft
 Mouse Programmer's Reference Guide." The guide contains the menu
 installer MENU.COM and the menu compiler MAKEMENU.EXE. If you have the
 software prior to Version 6.00, you will find MENU.COM and
 MAKEMENU.EXE on your system diskette.



 49. Mouse Menus May Hang in the OS/2 DOS 3.x Box

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35251

 Mouse menus may hang in the OS/2 DOS 3.x box if you are using the OS/2
 mouse drivers. To work around this problem, use the DOS mouse drivers
 that were included with your mouse and do not load the OS/2 mouse
 driver.


 50. Menu Problems with Leading Edge D2 in 43-Line Mode

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28428

    The characters on the screen get trashed if you load a mouse menu
 in 43-line text mode using a Leading Edge D2 with monochrome display.
 The characters are readable, but the top two or three lines of pixels
 composing the characters are repeated beneath the characters (similar
 to a vertical ghost effect).

    Resetting the EGA into the 43-line mode corrects the problem
 temporarily. Run EGA.EXE with the argument EGA, or set switch 5 on the
 display adapter to the open position to disable the auto-mode
 selection feature (this process produces the same effect as the EGA
 EGA command).


 51. Erratic Cursor Movement Using 123 Mouse Menu

 Product Version(s): 4.x 5.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-NOV-1988    ArticleIdent: Q24710

 If the cursor moves erratically when using the 123.MNU mouse menu
 provided with Version 5.00 of the mouse, make sure no other
 memory-resident programs are interfering. If the problems persist,
 contact Microsoft Product Support at (206) 454-2030 for the 123 Menu
 disk, which includes an updated 123.MNU file.

 If you own Mouse Version 6.00, use the MS123-2.COM found on your
 Expert Mouse Menus disk. This supersedes the 123.MNU file.


 52. Operation of InPort Chip Versions 1.00 and 1.10 Versus 1.20

 Product Version(s): 1.00 1.10 1.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-MAR-1990    ArticleIdent: Q49003

 Versions 1.00 and 1.10 of the Microsoft Mouse InPort Chip operates in
 the timer interrupt mode (mouse service routine interrupt occurs at a
 fixed rate).

 Version 1.20 of the InPort Chip operates in the data interrupt mode
 (mouse service routine interrupt occurs whenever mouse data is
 present).


 53. Bus Mouse with InPort Not Supported in IBM PC-DOS 4.00

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q35364

 IBM PC-DOS Version 4.00 has three special mouse drivers that only work
 with the DOS Shell: PS/2, serial, and bus mouse (non-InPort).

 For bus mice with InPort, we recommend that you load the mouse driver
 that was included with your mouse (MOUSE.COM) and delete the following
 command line in the DOSSHELL.BAT that loads the IBM DOS shell mouse
 driver:

 /MOS:PCMSPDRV.MOS


 54. Unable to Activate the Mouse in Chart

 Product Version(s): 6.00
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR64094
 Last Modified: 19-SEP-1988    ArticleIdent: Q25053

 You may be unable to activate the mouse in Chart; the mouse arrow may
 appear to be frozen.

 Chart defaults serial printer drivers to COM1:. Therefore, when using
 a serial mouse, it is necessary to start Chart and then change the
 Print Setup adapter in the Chart screen to something other than the
 COM port to which the mouse is connected. You must do the following to
 activate the mouse:

 1. Change the Print Setup adapter in the Chart screen from COM1: to
    LPT1:.

 2. Exit.

 3. Restart Chart.


 55. End User Made Mouse Menus Don't Run Under MS-DOS 4.00 or 4.01

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 20-JUN-1990    ArticleIdent: Q61105

 Mouse menus compiled with MAKEMENU.EXE and run with the MENU.COM that
 came with Mouse driver versions 6.24b and earlier will not work under
 MS-DOS version 4.00 or 4.01. The menu will install into memory, but
 will not be visible and will not interface correctly with the
 application.

 Currently, the only workaround is to load the ANSI.SYS driver with the
 /k option. This disables the extended keys on the keyboard, which
 allows your Mouse menus to work.

 Microsoft is researching this problem and will post new information
 as it comes available.


 56. Using PS/2 Serial Mice with Laptop Computers

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 14-JUL-1989    ArticleIdent: Q28492

    Microsoft PS/2 serial mice are not guaranteed to work correctly
 with laptops due to the low power specification on serial ports
 usually found on the laptops.

    PS/2 serial mice with the SSMA adapters (cigarette box shaped
 adapters) may not work properly with the Zenith laptop models 181 and
 183.
    The current mice with the UMA adapters (cigar-shaped adapters) with
 the Version 6.14 mouse driver have been tested informally and seem to
 work properly with the Zenith laptops.


 57. Restricted Mouse Cursor Movement in Pro Design II

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28493

    When using Pro Design II, the mouse cursor is restricted to a 1
 inch box in the top left-hand corner.

    This problem has been reported with the mouse driver Version 6.02 through
 mouse driver Version 6.11. Currently the problem cannot be isolated to a
 mouse driver problem since the cursor movement restriction seems to occur
 only with the Pro Design II application.
    Please contact American Small Business Computers, developers of Pro
 Design II, at (918) 825-4844. An update may resolve the problem.
    Microsoft is researching this problem and will post new information
 as it becomes available.


 58. NEC Multispeed Laptop Continues to Access Drive

 Product Version(s): 6.0 6.02 6.10 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28494

    When using the NEC Multispeed laptop with the mouse driver
 installed, the disk light stays on as if the disk is being accessed.

    NEC produced a patch INIT059.COM or ROM upgrade that resolves the
 problem.
    Please contact NEC's technical support at (800) 632-7368.


 59. Tests with the Compaq 386/20

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28495

    The new Bus and PS/2 serial mice work properly with the Compaq
 386/20 computer.

    The Version 1.0 mouse and revision G of the Bus interface board
 worked properly with the Compaq 386/20 with the Version 6.11 of the
 mouse driver.
    The white button and gray button serial mice tested successfully
 with the Compaq 386/20's serial port.


 60. FCC Class B Approval

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28496

    The new Version 1.0 mice have Class B FCC approvals.

    The InPort mouse and the InPort interface card of the new white
 button Version 1.0 mice have FCC Class B approvals (ID C3K7PN9937 for
 the mouse and C3K6P8 for the interface card respectively).


 61. Interrupt Setting for the IBM PS/2 Model 30

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28497

    When setting the J4 interrupt setting on the mouse InPort interface
 card, Microsoft recommends jumper 2 or 3.

    Please check that other peripheral boards are not using the same
 interrupt setting as the mouse. Do not use pair 5 for the setting.


 62. Installing Windows when Using the PS/2 Mouse Port

 Product Version(s): 6.10 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28498

    If you are using the IBM PS/2 mouse port for your mouse, please be
 sure to select IBM PS/2 when selecting a pointing device during the
 Windows Version 1.04 installation.

    Selecting the Microsoft mouse when using the IBM PS/2 mouse port
 will not give you mouse control in Windows Version 1.04.


 63. DOS 2.xx Does Not Recognize \Mouse1\Mouse

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 26-APR-1988    ArticleIdent: Q28499

 Problem:
    After running the mouse setup routine and rebooting my machine, the
 mouse driver will not install.

 Response:
    Because DOS Version 2.xx does not recognize the path statement in
 command lines, such as /mouse1/mouse in the AUTOEXEC.BAT file, the
 mouse driver never installs.
    To work around this, edit your AUTOEXEC.BAT file to change the
 directory to your MOUSE1 subdirectory. Then, directly call the MOUSE
 and CPANEL as follows:

   CD \MOUSE1
   MOUSE
   CPANEL
   CD\


 64. Use MOUSE.SYS with Flight Simulator

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28500

    If you have Flight Simulator and a mouse, you should use the
 MOUSE.SYS file in the CONFIG.SYS file rather than the MOUSE.COM in the
 AUTOEXEC.BAT file that is installed by the mouse setup.

    The Version 6.11 of the mouse driver that uses the MOUSE.COM file,
 may cause Flight Simulator to continuously ask if you have a mouse.
 Using the MOUSE.SYS file solved the problem.


 65. Windows 1.01 MOUSE.DRV File Included with Mouse 1.0

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28502

    The current Mouse Setup disk contained in the EasyCad and MS
 Paintbrush software includes the mouse driver for Windows Version 1.01
 owners.

    Because the Windows Version 1.01 mouse driver does not recognize
 mice with InPort hardware, Microsoft has included an updated MOUSE.DRV
 file to resolve the problem.
    Copy the MOUSE.DRV file to your Windows Install disk and reinstall
 the Windows software. If you have Windows Version 1.03 or a newer
 version, you will not have this problem.


 66. Compaq Portable 3 Compatibility

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-SEP-1988    ArticleIdent: Q28503

 The Compaq Portable 3 has built-in hardware that includes a serial
 port and an expansion chassis slot. The serial mouse should work
 properly in the standard serial port. The bus mouse will not fit in
 the only slot available for the expansion chassis, but should fit in
 the expansion chassis slot (this has not been tested).


 67. STB VGA Extra Using Mouse

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q28504

 STB requests that callers having problems with the mouse and VGA Extra
 (unspecified symptoms) contact STB at (214) 234-8750.


 68. Mouse Installation with OS/2

 Product Version(s): 1.0
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 21-APR-1988    ArticleIdent: Q28505

    OS/2 does not use the mouse driver contained with the Microsoft
 mouse.

    The DOS mouse driver MOUSE.COM or MOUSE.SYS does not load if you
 install OS/2 on a machine unless you have a dual boot option where
 standard DOS is loaded. OS/2 has a custom driver MOUSExxx.SYS which
 will run in the OS/2 protected mode or DOS compatibility box. In
 addition to the OS/2 mouse driver, you should load the POINTDD.SYS and
 EGA.SYS as well. Refer to your OS/2 documentation for further OS/2
 mouse driver details.


 69. Cipher Data Tape Drive Conflicts with Bus Mouse

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-SEP-1988    ArticleIdent: Q28515

    The Cipher Data Tape Drive can be set to use I/O address 220-23F;
 however, this setting causes the drive to forward and reverse every
 time the Bus mouse moves.
    The Tape Drive can reportedly use another I/O address to resolve
 the conflict. This is not a problem with the serial mouse.


 70. Choice of Three Software Bundles for New Mouse 1.00

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q28517

 The new white-button mice are available in three software bundles. You
 can purchase a PS/2 serial or bus mouse with one of the following
 products:

 1. EasyCAD

 2. Microsoft Paintbrush with Mouse Menus

 3. Windows with Paintbrush for Windows


 71. Bus Mouse Jumper Settings J2, J3, and J4

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  5-JUN-1988    ArticleIdent: Q28538

    The new white-button Bus Mouse Version 1.00 interface card
 (Revision G) is an InPort interface half-size card. When installing
 the interface card, the jumper settings J2, J3, and J4 must be
 correctly set for the mouse to function properly.

    The J2 jumper setting allows you to use your Bus mouse from slot 8
 if you have an IBM PC XT. Set the top two pins to the "XT SLOT 8"
 configuration. If you have an IBM PC, AT, or some other non-IBM PC XT,
 you can leave the jumper setting on the "Normal" position (the lower
 two settings).
    The J3 jumper setting allows you to set another I/O address space
 other than the default 23C-23F. The "Primary" settings are the top two
 settings, while the "Secondary," which has the I/O address 238-23C, is
 the bottom two settings.
    Microsoft recommends that you only change this setting if another
 InPort interface hardware item is used in your system or if another
 system peripheral card is using the same I/O addresses.
    The J4 jumper setting allows you to select an IRQ or machine
 interrupt. Microsoft recommends that you select an interrupt from two
 through five that is not used in your system. In most instances,
 although you should confirm that another card is not using the same
 interrupt, an IBM PC or XT has interrupt two available for you to use
 and an IBM PC AT usually has interrupt five available.
    Refer to Page 6 of your "Microsoft Mouse User's Guide" for more
 information.


 72. Mouse and Flight Simulator 3

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 25-JUL-1988    ArticleIdent: Q32028

    Mouse driver Versions 6.02, 6.11, 6.14, and 6.23 have been tested
 with Flight Simulator 3 and all work normally.


 73. Mouse, Windows, Desqview, and HP Drawing Gallery

 Product Version(s): 6.00 6.10 6.14
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 25-JUL-1988    ArticleIdent: Q32064

    If you run Hewlett-Packard Drawing Gallery from either Windows or
 Desqview and exit the program normally, the mouse still works
 correctly; however, there is no cursor.
    To correct this problem, modify the PIF file included with the
 program. Under the Directly Modifies section, select Memory in
 addition to Screen.


 74. Earlier Versions of Generic Cad May Not Work with InPort

 Product Version(s): 1.00 5.03 6.00 6.02 6.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-AUG-1988    ArticleIdent: Q32129

    Generic Cad recommends Interrupt 3 for the J4 setting of the bus
 mouse.
    Be aware that older versions (possibly releases 1 and 2) of Generic
 Cad may not work correctly with versions of the bus mice that include
 the InPort Interface. Because Generic Cad goes directly to the
 hardware (i.e., it uses its own mouse driver), you must obtain an
 update to release 1 or 2. To obtain an update, contact Generic Cad by
 calling (206) 487-2934.


 75. Mouse Must be Removed to Run PS/2 Diagnostics

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 13-FEB-1989    ArticleIdent: Q33570

    When running the PS/2 diagnostics program with a Microsoft Mouse on
 the mouse port, the mouse must be disconnected. If the mouse is not
 disconnected the machine will hang.


 76. Sensitivity May Reset if a /R Switch Passed to the Driver

 Product Version(s): 6.24
 Operating System:   MS-DOS
 Flags: ENDUSER |  buglist6.24
 Last Modified: 11-OCT-1988    ArticleIdent: Q35974

 If an /R switch is passed to the MOUSE.COM, the sensitivity may reset.
 Note: the /R switch is only used with the Bus Mouse with InPort
 hardware.

 Microsoft has confirmed this to be a problem in Version 6.24. We are
 researching this problem and will post new information as it becomes
 available.


 77. Extension Cables for Microsoft Mice

 Product Version(s): 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-JUL-1989    ArticleIdent: Q32128

 Microsoft retails a 1.5-meter InPort extension cable. Although the
 cable was designed for the gray-button mouse, we have found, under
 informal testing, that the extension cable works with the new
 white-button mice (serial and bus).

 If you decide to make a longer cable, special wire is not needed. The
 Microsoft extension cable uses shielded, 7-conductor, 30-gauge wire. A
 heavier gauge wire might be considered for strength.

 If an extension is added to the serial mouse, the cable needs to pass
 the following pins straight through as follows:

    pins 2,3,4,7,20 and shield for the 25-pin D version, or
    pins 2,3,4,5,7 and shield if using the 9-pin version.

 Microsoft is not aware of any special considerations for special
 installation, such as alignment to compensate for cable
 characteristics, special cable termination (R, RC, etc.), needed for
 line drivers, or noise-immunity considerations.

 If you do anything to change the mouse cabling, the machine is likely
 to violate FCC Electromagnetic Interference regulations. The computer
 may interfere with nearby television or radio reception. Operation in
 a residential environment is especially ill-advised, and such a
 configuration certainly cannot be offered for sale without extensive
 testing and FCC certification.

 Microsoft takes no responsibility for the performance of its products
 when modified or used in a manner other than that intended and advised
 in the manual. Microsoft assumes the customer will comply with all
 applicable laws and regulations, and offers the above advice only on
 that basis.


 78. AT&T 6300 Plus and Bus Mouse

 Product Version(s): 5.00 5.30 6.00 6.10 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-JUL-1988    ArticleIdent: Q32682

    When using the bus mouse with the AT&T 6300 Plus, the J4 jumper
 must be set to either 3 or 4.
    There have been problems reported while using interrupt 5 with this
 computer; this should be a free interrupt on an AT machine. This
 problem may occur with any program that uses the mouse; however, the
 problem has not occurred with Paintbrush, CPANEL.COM, and DEFAULT.COM.


 79. DEFAULT.COM Included with Mouse

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-JUL-1988    ArticleIdent: Q32714

    If you have the new white-button mouse Version 1.00, the
 DEFAULT.COM file, which provides cursor emulation, is located on the
 Mouse Setup Disk. Version 6.00 through 6.10 owners have the
 DEFAULT.COM file located on their Mouse Expert Menus Disk. Mouse
 owners with versions prior to Version 6.00 can write their own menus
 using the mouse menu programming tools (MAKEMENU.EXE and MENU.COM)
 included with their mouse software.


 80. Resolution, Mickeys, or Points Per Inch of the Mouse

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-AUG-1988    ArticleIdent: Q33066

    The resolution (or mickeys) of Versions 5.x and 6.x of the mouse
 (gray buttons), and the new Version 1.00 of the mouse (white buttons)
 is 200 ppi. For example, the mouse driver can recognize 1/200th of an
 inch movement of the mouse. The resolution of Versions 1.x, 2.x, 3.x,
 and 4.x of the mouse (green buttons) is 100 ppi.


 81. PS/2 Mouse on Mouse Port Initializes Slowly

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  2-AUG-1988    ArticleIdent: Q33106

    If you load a program when using a serial PS/2 mouse on the PS/2
 mouse port, it will take longer to load than a serial or bus connect
 because the mouse initialization is performed through the PS/2 BIOS.


 82. Mouse and IBM Page Printer Hang System

 Product Version(s): 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  4-AUG-1988    ArticleIdent: Q33117

    When using the Microsoft Mouse with an IBM Page Printer, the mouse
 driver must use MOUSE.SYS rather than MOUSE.COM. To use the mouse with
 an IBM Page Printer, do the following:

    1. Copy MOUSE.SYS from the Setup/Basic Menus disk to the MOUSE1
       subdirectory of your hard drive.
    2. Edit your AUTOEXEC.BAT file (found in the root directory) and
       remove the following line:

       /MOUSE1/MOUSE

    3. Edit your CONFIG.SYS file (also found in the root directory) and
       insert the following line prior to the line that loads the Page
       Printer driver:

       DEVICE=C:\MOUSE1\MOUSE.SYS

    4. Reboot the machine. The mouse now can be used in conjunction
       with the Page Printer.


 83. Tempest-Approved Mouse

 Product Version(s): 6.00   | 6.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q47676

 Tempest versions of the Microsoft Mouse are available from Quality
 Tempest Products (QTP) of Herndon, Va.

 A Tempest "approved" mouse is one that has been modified so that there
 are no RF emissions. This modification is needed so the mouse can be
 used in sensitive or classified areas

 For more information, contact Steve Rice of QTP at (703) 834-5200.


 84. Jumper Settings for Bus Mouse Used in an XT 286

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-AUG-1988    ArticleIdent: Q34009

    For the purpose of setting the jumpers on the bus mouse card, the
 IBM XT 286 is equivalent to an IBM AT. The hard disk in the IBM XT 286
 uses IRQ 2. The typical settings are as follows:

    Jumper    Setting
      J2      normal
      J3      primary
      J4      IRQ 5

    As always, be sure that IRQ 5 is not being used for other hardware
 devices, such as a Bernoulli box, network card, or tape backup.


 85. Mouse and AutoCAD

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1988    ArticleIdent: Q33476

 AutoCAD contains its own mouse driver; therefore, it does not need to
 have the Microsoft Mouse Driver installed to take advantage of the
 Microsoft Mouse. If the Microsoft Mouse Driver is installed, it may
 cause a TSR-type error when AutoCAD is run.

 AutoCAD problems can be directed to Autodesk by calling (415)
 332-2344.


 86. Cursor Freezes when Using Old Mouse Driver on AT-Type Machine

 Product Version(s): 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-AUG-1988    ArticleIdent: Q33553

    The mouse cursor may freeze or leave contrails in application
 programs running on 80286 or 80386-based machines if the mouse driver
 is Version 5.03 or earlier.
    The keyboard ordinarily will still work correctly. You should
 update to the current version of the driver.


 87. Mouse Menu for Quattro

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-MAY-1989    ArticleIdent: Q34086

 The Lotus 1-2-3 mouse menus on the Mouse Expert Menus disk do not
 enable the pop-up menus in Quattro. To use the mouse with Quattro,
 install DEFAULT.COM or MSMENU.COM.

 MSMENU.COM allows you to scroll through the spreadsheet and select
 menu items with the mouse. The menus do, however, need to be activated
 with the SLASH (/) key. The menus function the same whether or not
 Quattro is loaded with the Lotus 1-2-3 menu tree.

 Note: DEFAULT.COM is now called MSMENU.COM.


 88. Selecting Communications Ports, Interrupts in COMPAQ SLT/286

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | mouse
 Last Modified: 19-MAR-1990    ArticleIdent: Q48414

 On a COMPAQ SLT/286, the communications port and its associated
 interrupt can be set by using the Setup/Diagnostic program included
 with the computer. The following is the procedure:

 1. Place the Setup disk in your floppy drive.

 2. Run the Setup program.

 3. At the menu screen, press F4 to select "change configuration."

 4. From the next menu screen, select "Modem async-device."

 5. From the next screen, select "system async device."

 6. From the next screen, select "com1."

 7. From the next screen, select "interrupt 4."

 8. Back up through the screens until you return to the DOS prompt.


 89. Text Mode Problem with Mouse Version 3.00

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 fixlist4.00
 Last Modified: 11-OCT-1988    ArticleIdent: Q11085

 Question:

 Were there any known problems with Hercules graphics support with the
 mouse Version 3.00? When we use the routine reccommended by Hercules
 to get the mouse into graphics mode, we still get a text mouse when we
 use function 0 of the mouse library.

 Response:

 There is a problem in the mouse driver that is defaulting the text
 cursor to the hardware text cursor, instead of to the software text
 cursor. Microsoft has confirmed this to be a problem in Version 3.00.
 This problem was corrected in Version 4.00.

 There are two possible solutions for the problem: use only driver
 Version 4.00 or later, or insert a mouse function 10 call (Set Text
 Cursor) into the beginning of the application program, with the second
 parameter (M2%) set to 0 (select software text cursor).


 90. Losing Data When Mouse and Data Transfer Are Involved

 Product Version(s): 6.00 6.11 6.14 6.24 6.24b
 Operating System:   DOS
 Flags: ENDUSER |
 Last Modified: 22-MAR-1990    ArticleIdent: Q49285

 Several customers report lost data or a system lock up when
 transferring high speed data from a modem or mainframe through a
 serial port. The mouse was resident in memory when the problem
 occurred.

 With communications going through COM2:, the interrupt 3 is in use.
 This interrupt has a higher priority than either interrupt 4 (for a
 mouse in COM1:) or interrupt 5 (bus mouse with interrupt 5 set on the
 J4 jumper).

 You should ensure that the communications equipment is loaded onto
 COM2: so that it can take advantage of the higher priority interrupt.
 The phenomenon is inherent with interrupt handling and established
 priorities.


 91. Intermittent Installation on the Packard-Bell PS/2 Port

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-MAY-1990    ArticleIdent: Q61591

 When the 400 dpi Microsoft Mouse is attached to the PS/2 port of the
 Packard-Bell PackMate 2, the Excel 5, and the Legend 5 computers, the
 mouse sometimes does not install correctly.

 When the mouse is attached to the serial port there are no
 installation problems.

 If you are experiencing this problem, contact Packard-Bell at
 (818) 773-4400.


 92. Sluggish or Jerky Mouse Motion in PC DOS Version 4.00 Shell

 Product Version(s): 4.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 11-OCT-1988    ArticleIdent: Q35975

 When using the IBM PC DOS Version 4.00 shell mouse drivers with an IBM
 PS/2, the mouse motion may appear sluggish or jerky.

 To work around this problem, do not load the PC DOS Version 4.00 mouse
 drivers /MOS:PC??DRV.COM (where ?? is PC or MS) and load the Microsoft
 mouse driver MOUSE.COM before running the DOSSHELL.BAT file.


 93. Deallocating Memory When Using Compaq and IBM Mouse Ports

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q43344

 When using a PS/2 style mouse port, you cannot deallocate the memory
 the mouse driver is using. The Mouse Off switch disables only the
 mouse. However, the memory will be deallocated if a bus or serial
 mouse is used.

 The following machines have PS/2 style mouse ports:

 1. COMPAQ 286e, 386s, 386e, and 386 20e

 2. IBM (all PS/2's)


 94. Mouse Will Not Work with PC Tools Deluxe 5.5 and 6.0

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 14-MAY-1990    ArticleIdent: Q61264

 If PC Tools Deluxe versions 5.5 and 6.0 are loaded as memory resident,
 the mouse cursor may or may not be displayed on the screen. If the
 mouse cursor is displayed, it will not move.

 This problem has been corrected in a later version of PC Tools.

 For information about this update, contact Central Point Software at
 (503) 690-8080.


 95. "Mouse Off" Hangs System: Samsung AT Compatible with J4 on 2

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  1-NOV-1988    ArticleIdent: Q37252

 On the Samsung S-500 AT compatible, typing "Mouse Off" may hang the
 system if the Bus mouse J4 jumper is set on interrupt 2. Moving the
 jumper to interrupt 5 eliminates the problem.


 96. Excellerator Requires Ms-DOS Version 3.30 with AT&T 6312

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-JAN-1989    ArticleIdent: Q37254

 When using the Excellerator (a code generation program) with an AT&T
 6312, MS-DOS Version 3.30 must be used.

 When any version of DOS earlier than Version 3.30 is used with the
 AT&T 6312 machine and the Excellerator, one of the following symptoms
 may occur:

 1. More than one cursor may appear.

 2. The mouse pointer may skip pixels as it is moved across the screen.

 3. Hieroglyphics may appear.

 According to Leading Index, the problem can be corrected by upgrading
 to MS-DOS Version 3.30.


 97. Mouse Command-Line Switches for Mouse Driver Version 7.04

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | Video 7 Video-7
 Last Modified: 29-AUG-1990    ArticleIdent: Q61592

 The following are the current command-line options (switches) for
 Microsoft Mouse Driver version 7.04:

    Option  Description
    ------  -----------

    /B      Using bus mouse

    /Cn     Using serial mouse on port COMn
            (where:  0 <= n <= 1)

    /Dn     Enabling double-speed threshold
            (where:  0 <= n <= 100)

            0 => No threshold speed (always double speed)
            100 => Maximum threshold speed (rarely double speed)

    /Hn     Setting horizontal sensitivity
            (where:  0 <= n <= 100)

            0 => 0 horizontal mickeys per pixel scaling factor
               (i.e., no horizontal movement returned)
            100 => 100 horizontal mickeys per pixel scaling factor

    /In     Using Microsoft InPort Mouse on primary or secondary InPort
            (where:  n = 1  or  n = 2)

    /L(c)   Selecting language c
            Languages are defined as follows:

               c         Language             Ordinal Value
               -         --------             -------------

           (default)     English                    0
               F         French                     1
               NL        Netherlands (Dutch)        2
               D         German                     3
               S         Swedish                    4
               SF        Finnish                    5
               E         Spanish                    6
               P         Portuguese                 7
               I         Italian                    8
               K         Korean                     9
               J         Japanese                   10

    /Mn     Cursor mask override
            (where:  0 <= n <= 255, n = 0 => mask off)

            0 => Mask off
            Not 0 => Mask on

            (If software cursor is specified in function 10, then set
            cursor to default software cursor. It tells the mouse
            driver to determine which bit pattern to use to make
            the cursor visible.)

    /Nn     Using dampened cursor motion to fix LCD laptop display
            problems
            (where:  0 <= n <= 255)
            (This slows down the screen update rate.)

            0 =>    Skip 0 interrupts (this is, same as normal mouse)
            255 =>  Skip 255 mouse hardware interrupts before
                    processing data

    /Pn     Selecting ballistic curve number n
            (where:  1 <= n <= 4)

            (Note that this may change if the specification changes.)

    /R(n)   Setting interrupt rate
            (where:  1 <= n <= 4, default n = 1)

            1 => 30Hz
            2 => 50Hz
            3 => 100Hz
            4 => 200Hz

    /Sn     Setting both horizontal and vertical sensitivity
            (where:  0 <= n <= 100)

            0 => 0 mickeys per pixel scaling factor
                 (that is, no movement returned)
            100 => 100 mickeys per pixel scaling factor

    /Vn     Setting vertical sensitivity
            (where:  0 <= n <= 100)

            0 => 0 vertical mickeys per pixel scaling factor
                 (that is, no vertical movement returned)
            100 => 100 vertical mickeys per pixel scaling factor

    /Y      Disabling sprite and Video Seven code

            (To disable mouse driver hardware cursor support on
            certain Video Seven and C&T VGA controllers.)

    /Z      Using PS/2 mouse

            (This is added for PS/2 only. It directs the driver to look
            for the mouse at the mouse port.)


 98. Hot Spot Not Displaced Along Horizontal Axis with Driver 7.04

 Product Version(s): 7.04
 Operating System:   MS-DOS
 Flags: ENDUSER |  h_menupr menu programming INT33 MF9
 Last Modified: 27-JUL-1990    ArticleIdent: Q64177

 If mouse driver version 7.04 for the Microsoft Mouse is installed
 without the /Y switch, the hot spot will not be displaced along the
 horizontal axis.

 This problem will occur only in programs that use mouse function 9 to
 set the hot spot. Including a /Y switch when installing the mouse
 driver will eliminate this problem.


 99. Problem with Mouse and PS/2 Model 70A21

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 18-APR-1990    ArticleIdent: Q38654

 Older models of the PS/2 Model 70A21 will not boot with the mouse in
 the mouse port.

 The machine hangs and gives an 8603 error, indicating something is
 wrong with the mouse. The mouse functions properly in the serial
 ports, and an IBM mouse will work in the mouse port with the drivers
 provided by Microosft.

 There is a patch that will correct this problem. Contact Microsoft
 Product Support Services at (206) 454-2030 for this patch.


 100. "Interrupt Jumper Missing" Error Message

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-DEC-1988    ArticleIdent: Q38754

 The "Interrupt jumper missing" message can appear when installing the
 driver on a bus mouse. This can be caused by several things.

 It frequently appears because the interrupt selected on the
 J4 jumper is conflicting with existing hardware. If the
 IRQ vector is being used by anything else this message will
 appear.

 The message also can appear because the J2 jumper is set on slot 8 and
 not to normal as it should be.

 It also is possible that the interface card is defective. This can
 only be verified by installing the mouse and software onto another
 machine and testing the mouse.


 101. How to Define, Display Graphics Mouse Cursor in FORTRAN 5.00

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | H_fortran
 Last Modified: 10-JUL-1990    ArticleIdent: Q51225

 The following code shows how to define and display a graphics mouse
 cursor in Microsoft FORTRAN version 5.00:

 c This program displays mouse cursor in a shape of a cross.
 c The program terminates when the user presses the ENTER
 c key.

       include 'fgraph.fi'
       include 'fgraph.fd'
       integer*2 m1,m2,m3,m4
       integer*2 mcursor(32)
       integer*2 arrloc(2)
       integer*4 arradds
       equivalence (arrloc(1),arradds)

       do 50 i=1,16                   !define the screen mask
  50      mcursor(i) = #ffff
          mcursor(17) = #0000         !define the cursor mask
          mcursor(18) = #0180
          mcursor(19) = #0180
          mcursor(20) = #0180
          mcursor(21) = #7ffe
          mcursor(22) = #0180
          mcursor(23) = #0180
          mcursor(24) = #0180
          mcursor(25) = #0000
          mcursor(26) = #0000
          mcursor(27) = #0000
          mcursor(28) = #0000
          mcursor(29) = #0000
          mcursor(30) = #0000
          mcursor(31) = #0000
          mcursor(32) = #0000

       m1 = 0
       call mousel(m1,m2,m3,m4)         !reset mouse driver
       dummy = setvideomode($erescolor) !set video mode (EGA)
       m1 = 9
       m2 = 1
       m3 = 1
       arradds = locfar(mcursor) !get address of cursor array
       call mousel(m1,m2,m3,arrloc(1))  !set graphics cursor
       m1 = 1
       call mousel(m1,m2,m3,m4)         !show cursor
       read(*,*)                        !press enter to quit
       m1 = 2
       call  mousel(m1,m2,m3,m4)        !hide cursor
       dummy = setvideomode($defaultmode) !set video mode
       end


 102. Serial Mouse May Hang on ATT 6300

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-MAR-1989    ArticleIdent: Q40162

 When either MOUSE.COM or MOUSE.SYS is loaded using a serial mouse on
 some of the ATT 6300's, the machine will hang.

 You can correct this problem by specifying the COM port the mouse is
 attached to by using the /C1 or /C2 command-line switches. You can do
 this either in a manual start up or by including the information in
 the AUTOEXEC.BAT or CONFIG.SYS files.


 103. Mouse and Lotus 1-2-3 Mouse Menu Under Windows/286

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-MAR-1989    ArticleIdent: Q41087

 To run Lotus 1-2-3 and the Mouse Menu for Lotus under Windows, the
 123.PIF file included with Windows must be edited. The key point to
 note is that under the "Directly Modifies" option of the PIF file the
 check boxes for both Screen and Memory must be turned on. Add any
 parameters or set the initial directory if necessary. Save these
 changes so you will not have to repeat them again.

 After the 123.PIF file is correctly configured, load the Mouse and
 Menu in memory as you normally would before going into Lotus 1-2-3.
 Bring up Lotus 1-2-3 within Windows and the Menu should function
 correctly. If not, reboot the system from the original floppy DOS disk
 to make sure nothing else in memory is interfering, then load the
 mouse and menu into memory.


 104. ATI Wondercard Graphics Adapter

 Product Version(s): 1.00 2.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 13-FEB-1989    ArticleIdent: Q31338

 Certain BIOS versions of the ATI Wondercard Graphics Adapter and
 Microsoft Mouse Driver Versions 6.02, 6.10, 6.11, and 6.14 are
 incompatible. ATI has solved this problem by offering a BIOS upgrade.

 The BIOS version is displayed when booting your computer. If you do
 not know the BIOS version of the Wondercard, reboot the machine. The
 board and BIOS versions that do work together are as follows:

 Board Version                      BIOS Version

    1                             1.16 (or higher)
    2                             2.07 (or higher)
    3                             3.07 (or higher)
    4                             4.07 (or higher)

 It is also possible to disable the VGA emulatoin on the ATI card
 by running SMS (ATI's configuration program) with the following
 paramiters:

             sms egabios   (to disable VGA)
             sms vgabios   (to enable VGA)

 For more information about the BIOS upgrade, contact ATI at the
 following phone number and address:

 (416) 576-0711
 ATI 3761 Victoria Park Ave.
 Unit #2
 Scarborough, Ontario, Canada
 M1W352


 105. BOA Demo Program Does Not Work on AT&T 6300 Computer

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | att
 Last Modified: 20-MAR-1990    ArticleIdent: Q51227

 BOA, the Microsoft Mouse Demo Program, does not work on an AT&T 6300
 computer: it begins to draw a border and then hangs. Otherwise, the
 mouse appears to function correctly.


 106. PC Tools Version 5.00 Needs Mouse Driver Version 6.14 or Later

 Product Version(s): 1.x 2.x 3.x 4.00 4.01
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-MAY-1989    ArticleIdent: Q42317

 PC Tools Version 5.00 documentation recommends Version 6.14 or later
 of the mouse driver.


 107. Mouse and Renaissance Legacy II Switch Graphics Adapter

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 20-MAR-1990    ArticleIdent: Q51240

 Problem:

 A serial mouse is installed on a computer with a Renaissance video
 card and the mouse driver reports that it is installed. However, the
 mouse does not respond in programs.

 Response:

 The Renaissance card has an InPort-type mouse adapter, which the mouse
 driver finds before it checks for a serial mouse.

 To correct this problem, include the /C1 or /C2 option on the mouse
 command line to specify where the mouse driver should look for the
 mouse. For example, do the following for COM1:

    mouse /C1


 108. Error in SIMPLE Mouse Menu in Programmer's Reference

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 22-MAR-1990    ArticleIdent: Q51489

 There is an error in the code for SIMPLE Mouse Menu on Page 74 of the
 "Microsoft Mouse Programmer's Reference Guide." The erroneous code
 reads as follows:

    dn:  TYPE 0,801       ;Down-arrow key

 It should read as follows:

    dn:  TYPE 0,80        ;Down-arrow key


 109. cegal() Function in EGA.LIB May Not Work Properly

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 16-APR-1990    ArticleIdent: Q43335

 When using cegal() in the EGA.LIB with Function f1, cegal() doesn't
 perform correctly. An example is shown below.

 Perform the following function in C

    outp(CRTC_INDEX,INDEX);

 where CRTC_INDEX is the port address and INDEX is the register.

 The mouse will not see the change in the EGA register; therefore, the
 above C call may cause the mouse to not perform properly because the
 call bypasses the BIOS routines.

 The following are two ways to perform this call so that the mouse will
 see the change in the EGA register:

 1. Use the EGA.LIB (this does not work):

          e1=0xf1;
          e2=0xd;
          e4=0;
          cegal(&e1,&e2,&e3,&e4,&e5);

 2. Use the equivalent BIOS call (this works):

          inregs.x.ax=0xf1;
          inregs.x.bx=0xd;
          inregs.x.dx=0;
          int86(0x10,&inregs,&outregs);


 110. NOTEPAD.COM Doesn't Work with Extended Keyboard

 Product Version(s): 1.00 1.01 2.00 2.01 2.50 3.00 4.00 5.00 5.02 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-JUN-1989    ArticleIdent: Q43336

 NOTEPAD.COM does not work with keyboards that have the extended
 function keys F11 and F12.

 No resolution to this limitation is expected because NOTEPAD.COM is
 no longer included with the mouse.


 111. Mouse and Token Ring Conflict

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 22-MAR-1990    ArticleIdent: Q57606

 With the mouse driver installed first, Token Ring does not install
 properly.

 It has been reported that if the mouse driver was loaded after the
 three drivers that are needed for Token Ring, both will work properly.


 112. MS123.COM May Not Work in Lotus 1-2-3 with Look & Link Add-On

 Product Version(s): 1.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-JUN-1989    ArticleIdent: Q43600

 MS123.COM may not work properly in Lotus 1-2-3 if Look & Link (a Lotus
 1-2-3 add-on by Personics) is being used.

 The workaround is to load MOUSE.SYS in the CONFIG.SYS file instead of
 loading MOUSE.COM in the AUTOEXEC.BAT file.


 113. Microsoft Mouse and the NEC Powermate

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-JUN-1989    ArticleIdent: Q43720

 When using the NEC Powermate and the Microsoft Mouse with the Bus
 Interface, you must place the J3 jumper to the secondary setting. The
 Powermate can use the primary addressing for its screen I/O.


 114. MOUSE.COM Solves PS/2 Serial Problems with Ventura Publishing

 Product Version(s): 1.01
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 20-MAR-1990    ArticleIdent: Q43781

 Ventura Publisher uses its own mouse driver for the PS/2 - Serial
 mouse. For the bus mouse, Ventura requires the Microsoft Mouse driver
 (MOUSE.COM) to be loaded.

 If you are experiencing problems using a PS/2 - Serial mouse,
 reinstall Ventura and select the Bus Mouse option.  This will load
 the Microsoft Mouse Driver rather than the driver supplied by Ventura.
 The problems that your experienced with your PS/2-Serial mouse will
 no longer be present.  You DO NOT need to replace your PS/2-Serial
 mouse to choose the bus mouse option.  Selecting the Bus mouse option
 bypasses Ventura's own mouse drivers.



 115. Using the 400 PPI Mouse with GEM

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-MAR-1990    ArticleIdent: Q59313

 When using the 400 PPI Serial Mouse with GEM, the mouse cursor jumps
 all over the screen.

 When installing GEM, select the Microsoft Bus Mouse option, even
 though you are using a serial mouse. When the bus mouse is selected
 during the installation process, GEM will use the Microsoft Mouse
 Driver that is supplied with the mouse.


 116. MS123 Mouse Menu Not Correctly Positioning Cursor

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-JUN-1989    ArticleIdent: Q44057

 If you position the Lotus cursor in 1-2-3 with the mouse cursor on an
 "unprotected cell," the Lotus cursor does not stay positioned on the
 cell selected by the mouse. The cursor jumps to the left or right,
 depending on which part of the cell the mouse cursor is located.

 If you position the Lotus cursor with the mouse cursor on "protected"
 cells, the cursor appears to stay positioned.

 One workaround in positioning the Lotus cursor with the mouse is to
 place the mouse cursor on the appropriate arrow keys that appear on
 the right side of the screen, or resort to using the keyboard cursor
 keys.


 117. Finding the COM1: Serial Port on a PC/XT/AT Machine

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q44126

 When connecting the Microsoft Mouse serial interface cable to your
 computer, you must first determine the location of the serial port.

 On a PC- or XT-class computer, the serial port is normally the male,
 25-pin, D-shaped connection in the back of the machine.

 On an AT-class computer, the serial connection is normally the male,
 9-pin, D-shaped connection on the back of the computer.

 There are exceptions, but these descriptions are a good rule of thumb.

 Note: If the machine has only one serial port, it should be set up as
 COM1: using IRQ4. If the serial port is set up as COM2: and it is the
 only serial port in the machine, the Microsoft Mouse driver might
 install, but the mouse might not function properly.

 COM3: and COM4: is not supported by the mouse driver.


 118. InPort/Bus Mouse Comparison and Overview

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | SR# G890626-21385
 Last Modified: 31-AUG-1989    ArticleIdent: Q46369

 Question:

 Could you clarify the difference between the Microsoft Bus Mouse and
 the InPort Mouse?

 Response:

 The Microsoft InPort device interface is a low-cost graphic device
 interface consisting of a 40-pin custom LSI IC and a compact 9-pin
 circular connector, which supports a variety of graphic input devices,
 especially mice.

 The following is a comparison between old Bus Mouse and new InPort
 Mouse:

 1. The InPort Mouse uses a custom Microsoft designed 40-pin LSI
    interface chip manufactured by OKI Inc. of Japan.

    The Bus Mouse uses a generic Intel 8255A parallel interface chip.

 2. The InPort Mouse allows the CPU interrupt rate to be programmable
    from 0 (no interrupt) to 200 Hz.

     The Bus Mouse CPU interrupt rate is fixed at 30 Hz.

 3. The InPort Mouse interrupts the CPU only when the mouse position
    or button status has changed.

     The Bus Mouse interrupts the CPU constantly regardless of mouse
     (in)activity.

 4. The InPort Mouse requires only two I/O operations to read the mouse
    XY position.

    The Bus Mouse requires four I/O operations to read mouse XY
    position.

 5. The InPort Mouse uses the compact Hosiden 9-pin circular connector.

    The Bus Mouse uses the bulky DB-9 connector.

 When used stand-alone with an IBM XT/AT PC, both mice use an interface
 board that plugs into the standard IBM XT/AT bus. In addition, since
 the InPort custom IC is essentially an enhanced, single-chip version
 of the Microsoft Bus Mouse interface board, other manufacturers can
 easily add the InPort interface to their PC plug-in cards. The
 following are examples:

 1. The Microsoft MACH 10 enhancement board

 2. Renaissance GRX graphics add-in boards

 3. Selected Verticom graphics controllers/adapters come with an InPort
    interface.

 The InPort Mouse can also connect to an RS-232 serial port, or the
 IBM PS/2 mouse port through an external adapter box.


 119. Mouse Driver Conflicts with Novell Network Software

 Product Version(s): 7.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 22-MAR-1990    ArticleIdent: Q59314

 Using MOUSE.COM Version 7.00 may cause problems with Novell network
 software.

 Using MOUSE.SYS or loading MOUSE.COM before the network software will
 resolve the conflict.

 Microsoft is researching this problem and will post new information
 here as it becomes available.


 120. Mouse Performance between Serial and Bus Mouse

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00 1.01
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-AUG-1989    ArticleIdent: Q46461

 Summary

 Although there are no differences in functionality between the bus and
 serial mouse, you should be aware that there are differences in the
 way the mouse interrupts the CPU (i.e., the mouse driver must be
 installed).

 The serial mouse is event driven. This means when you neither move the
 mouse nor press a button (i.e., the mouse is not in use), there is no
 degradation to the CPU processing. When the mouse is being used, an
 approximately 5-percent degradation to the CPU performance can occur.

 The bus mouse is not event driven. When you neither move the mouse nor
 press a button, the mouse interrupts the CPU at either the default (30
 Hz) or at the user-defined rate (50, 100, or 200 Hz).


 121. Cadkey and Mouse Driver 7.00

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-APR-1990    ArticleIdent: Q59859

 If Mouse Driver Version 7.00 is installed when Cadkey is used, the
 mouse is limited to a 1-inch x 1-inch area in the upper left-hand
 corner of the screen.

 Microsoft has confirmed this to be a problem in Mouse Driver Version
 7.00. This problem was corrected in Mouse Driver Version 7.04.


 122. Intermittent Installation on NEC 386 Machines

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-APR-1990    ArticleIdent: Q59860

 Mouse Driver Version 7.00 causes intermittent installation of the
 mouse on the NEC 386 computers.

 Microsoft has confirmed this to be a problem with the Mouse Driver
 Version 7.00. This problem was corrected in Version 7.04.


 123. 400 DPI Serial Mouse and Northgate Computers

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  2-MAY-1990    ArticleIdent: Q59861

 When the 400 PPI PS/2/Serial Mouse is installed on the 9-pin serial
 port of some Northgate Computer, the mouse may not install.

 When the 400 PPI PS/2/Serial Mouse is installed on the 9-pin serial
 port as a serial mouse, it uses pins 2, 3, 4, 5, and 7 to communicate
 with the serial port.

 The other pins in the 9-pin connector are used when the PS/2 adapter
 is connected to the mouse. Pin 8 of the built-in serial port, when set
 to a logic zero, is 1 to 2 volts higher than the voltage that would be
 present on an IBM compatible serial port. When a logic 1 is present on
 pin 8 and the mouse is connected to a 9-pin serial port, the mouse
 cannot reset. This prevents the mouse from installing.

 To work around this problem, do either of the following:

 1. Contact Northgate Technical Services at (800) 445-5037. They have
    found the cause of the problem and will work with you to make the
    necessary corrections to the motherboard.

 2. Use a 9- to 25-pin serial adapter to eliminate the signal from pin
    8. To do this, you need to purchase the adapter from a local
    electronics store. This adapter has a 9-pin female connector on one
    end and a 25-pin male connector on the other end. Once you have the
    adapter perform the following steps:

    a. Attach the adapter you purchased to the built-in serial port of
       your computer.

    b. Attach the mouse to the 25- to 9-pin serial adapter that was
       supplied with your mouse.

    c. Attach this adapter to the 9- to 25-pin adapter that you have
       already attached to your computer.


 124. Mouse Function 9 and Mouse Driver 7.00

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-APR-1990    ArticleIdent: Q59877

 Mouse Function 9 does not function correctly when Mouse Driver Version
 7.00 is installed. Vertical movement of the hot spot is blocked. The
 symptoms of this are as follows:

 1. The wrong menu item is selected when the mouse buttons are clicked.

 2. The line is drawn above the cursor in a graphics application

 Microsoft has confirmed this to be a problem in Mouse Driver Version
 7.00. This problem was corrected in Version 7.04.

 Major Products: First Publisher
                 Ultravision


 125. MSETUP Deletes Reference to MOUSE.SYS in CONFIG.SYS

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-APR-1990    ArticleIdent: Q59929

 The MSETUP program that is supplied with the 400 PPI Mouse (Mouse
 Driver Version 7.00 or later) deletes any reference to MOUSE.SYS in
 the CONFIG.SYS file.

 If you are operating under OS/2, do NOT run MSETUP.

 MSETUP deletes the MOUSE.SYS reference in CONFIG.SYS to prevent the
 loading of a older version of the mouse driver when the machine is
 booted.

 Do not run MSETUP on an OS/2 system, and do not load the DOS mouse
 driver to make the mouse work in the DOS box.


 126. Which Mouse Menus Work with Which Version of Lotus

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-APR-1990    ArticleIdent: Q59932

 Testing of the various versions of Lotus 1-2-3 with each of the
 available MS123 mouse menus and with either the Version 6.24b or
 Version 7.00 mouse driver yield the following results:

    Lotus     |  MS123       MS123-1     MS123-2     MS123-3
    Version   |  6.24b/7.00  6.24b/7.00  6.24b/7.00  6.24b/7.00
    ----------|-----------------------------------------------
      1A      |   yes/yes     yes/yes     yes/yes     yes/yes
              |     */*                                  /**
              |
      2.01    |   yes/yes     yes/yes     yes/yes     yes/yes
              |     */                       /**       **/**
              |
      2.2     |   yes/yes     yes/yes     yes/yes     yes/yes
              |     */*                                 */*
              |
      3.0     |    no/no       no/no       no/no      yes/yes
              |               ***/***     ***/***      **/**

 Notes: *   No mouse action on Master screen.
        **  No side bar menu.
        *** Cursor moves with mouse but no menu action.

 Summary of Normal Mouse Action (Yes in Above Chart)
 ---------------------------------------------------

 Usually, the mouse works in one of two ways: either the selected block
 moves around with the mouse movements, or a separate mouse cursor is
 on the screen and the selected block moves to the mouse cursor
 position upon clicking the left mouse button.

 In most cases, clicking the left mouse button activates a side bar
 menu with options such as page up, page down, page left, page right,
 home, end, and arrow key functions, and sometimes more (depends on the
 version of the menu).

 Also, in most cases, clicking the right mouse menu does the same as
 pressing the "/" (slash) key to bring up the standard Lotus menu.
 Moving the mouse changes the highlighted command. The right mouse
 button acts as an ENTER key. Clicking both buttons will return the
 mouse to the spreadsheet.


 127. Multimate Menu Will Work with Multimate Advantage 4.0

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-APR-1990    ArticleIdent: Q59934

 Informal testing with the Multimate Advantage II mouse menu has shown
 that it also works with Multimate Advantage Version 4.0.


 128. Pin-Outs of the 9-Pin Hosiden Socket

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-MAY-1990    ArticleIdent: Q61593

 The following is the signal configuration of the 9-pin Hosiden socket
 on the bus adapter of the Microsoft Mouse:

    Pin          Signal
    ---        ------

    1          +5v
    2           XA
    3           XB
    4           YA
    5           YB
    6           SW1
    7           SW2
    8           SW3
    9           Signal ground
    E           Shield ground


 129. Bus Mouse Port on Leading Edge 386 SX

 Product Version(s): 2.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 27-JUL-1990    ArticleIdent: Q64178

 The Leading Edge 386 SX computer has what appears to be a PS/2-style
 mouse port near the keyboard connector. This is actually an inport
 mouse connector designed for a Microsoft-compatible bus mouse,
 according to Page 6-13 of the "Leading Edge 386 SX User's Guide." The
 connection is a standard hosedin connector for an inport mouse.

 There is one switch that may or may not be in the correct position to
 install the mouse. This is Switch 3 on the motherboard. This must be
 in the ON position or the mouse will not install.


 130. Practical Peripherals and Serial Mouse Configuration

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | mouse modem practical peripherals
 Last Modified: 15-NOV-1990    ArticleIdent: Q66536

 If the Microsoft serial mouse is connected to COM 1, then a Practical
 Peripherals 2400 baud rate modem cannot be configured as COM 2.  This
 modem/mouse combination may work for a while, but eventually it
 will fail to an I/O address conflict between the mouse and the modem.

 Practical Peripherals technical support ([818] 991-8200)
 confirms this to be a problem.  They recommend that the modem be
 configured as COM 3 or COM 4.  The mouse should then remain on COM 1
 to separate the I/O addresses as much as possible.


 131. Serial Mouse with Timeline

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 13-JAN-1991    ArticleIdent: Q67339

 To use the Microsoft Serial Mouse with Timeline, a Symantec
 Corporation project management application, load the mouse driver by
 invoking MOUSE.SYS in the CONFIG.SYS file. Symantec Corporation
 technical support confirms that the Microsoft Mouse will not work
 correctly with Timeline if you use the MOUSE.COM driver file.


 132. 386MAX.SYS with MOUSE.COM 7.0 Can Hang Sprite Video Cards

 Product Version(s): 7.00 7.03 7.04
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S901024-6 B_BasicCom
 Last Modified: 15-NOV-1990    ArticleIdent: Q66561

 When used with 386MAX.SYS version 4.05 (an expanded memory driver by
 Qualitas Software), Microsoft Mouse driver versions 7.00, 7.03, and
 7.04 can hang computers equipped with video cards that have sprite
 capabilities (the ability to have a graphic cursor in text mode).

 This problem only occurs with the above mentioned versions. Earlier
 versions of the Microsoft Mouse driver will not cause this problem.

 Using Mouse driver version 7.04 with the "/y" line option will fix
 this problem.
 e.g.
     in DOS:

       mouse /y

  or in the AUTOEXEC.BAT:

       C:\MOUSE1\MOUSE /Y



 133. Correct Mouse Drivers for Express Publisher

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | driver mouse express publisher
 Last Modified: 13-JAN-1991    ArticleIdent: Q67340

 The application Express Publisher requires the 7.04 mouse
 driver to run correctly. Other mouse driver versions will not work
 according to the manufacturers, Power Up Software Corporation
 of San Mateo, CA.



 134. Trail of Multiple Cursors in Desqview 386

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | cursors trail mouse port setup
 Last Modified: 13-JAN-1991    ArticleIdent: Q67341

 If the Microsoft Serial Mouse is connected to a mouse port in a PS/2
 style machine, you may see a trail of red cursors inside the windows
 of Desqview 386 when you use QEMM 5.0.

 This is not a problem with the mouse. This problem occurs if you have
 selected "serial" in the port selection for the mouse when you set up
 Desqview. If you select "add-on board" for the mouse port selection in
 the Desqview Setup program, the mouse cursor will display normally.
 Note: This problem will not occur if the mouse is connected to the
 serial port.


 135. Mouse Menu Key Sequences: Corrections and Additions

 Product Version(s): 1.x 2.x 3.x 4.x 5.x 6.x 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | key sequence mouse menu docerr
 Last Modified: 10-FEB-1991    ArticleIdent: Q67854

 Page 71 of the "Microsoft Mouse Programmer's Reference Guide" lists
 "Key Sequences That Can't Be Simulated" using the menu programming
 TYPE statement. These keys cannot be simulated in a mouse menu because
 the key or key sequence is suppressed in the ROM BIOS. The list that
 is presented in the guide is incomplete, and in certain instances it
 is in need of revision.

 Each suppressed key mentioned is the lowercase character on the key.
 It is understood, but not explicitly stated, that the uppercase
 character on these keys will also be suppressed. A number of keys and
 key combinations that are suppressed and cannot be emulated are not
 mentioned in the guide. Some of the additions and corrections that can
 be made to the published list are given below.

 KEY COMBINATIONS FOR 83-KEY KEYBOARD
 ------------------------------------

 For the IBM PC and compatibles with a standard 83-key keyboard,
 the following keys and key combinations are suppressed.

 NOTE: Where applicable the uppercase character is given in
 parentheses.

 In Combination With the ALT Key
 -------------------------------

 RIGHT TAB
 ` (~)
 \ (|)
 ALT
 HOME
 PG UP
 NUMPAD 5
 NUMPAD
 +
 END
 PG DN
 INS
 DEL

 In Combination with the CTRL Key
 --------------------------------

 CTRL
 ` (~)
 NUMPAD 5
 NUMPAD
 +

 KEY COMBINATIONS FOR 84-KEY KEYBOARD
 ------------------------------------

 For the IBM AT and compatibles with a 84-key keyboard, the following
 keys and key combinations are suppressed:

 In Combination with the ALT Key
 -------------------------------

 ` (~)
 \ (|)
 TAB (right and left)
 ALT

 With ALT and on the Numeric Keypad
 ----------------------------------

 7 (HOME)
 1 (END)
 5
 0 (INS)
 9 (PG UP)
 3 (PG DN)
 - (SYS RQ)
 +

 In combination with the CTRL Key
 --------------------------------

 ENTER
 CTRL

 With CTRL and on the Numeric Keypad
 -----------------------------------

 5
 - (SYS RQ)
 +

 For the IBM PS/2 and compatibles with a 101- and 102-key keyboard, the
 following keys and key combinations are suppressed:

 In combination with the ALT key and on the Numeric Keypad
 ---------------------------------------------------------

 7 (HOME)
 1 (END)
 5
 0 (INS)
 9 (PG UP)
 3 (PG DN)
 - (SYS RQ)
 +

 In combination with the CTRL Key
 --------------------------------

 ` (~)
 CTRL
 ALT
 SCROLL LOCK

 With CTRL and on the Numeric Keypad
 -----------------------------------
 +

 EXCEPTIONS AND CORRECTIONS
 --------------------------

 The exceptions and corrections to the list of suppressed key and key
 combinations given on pages 71-72 of the "Microsoft Mouse Programmer's
 Reference" (Copyright 1989) are noted below.

 The followings key combinations can be represented using
 extended-keyboard-scan codes with the IBM PS/2 and compatibles with a
 101- and 102-key keyboard:

    ALT+BACKSPACE
    ALT+ESC
    CTRL+INS
    CTRL+TAB

 The ALT key used in combination with any one of the following keys can
 also be represented using extended-keyboard-scan codes for the IBM
 PS/2 and compatibles with a 101- and 102-key keyboard:

    [    ]
    ;
    '
    -
    ,
    .
    /
    *

 The CTRL key used in combination with the RIGHT ARROW and LEFT ARROW
 key can be represented on the PC, AT, and PS/2 keyboards.

 For more information about this topic, see "The Programmer's PC
 Sourcebook," pages 400-406; the "IBM PC/AT Technical Reference," pages
 4-21 and 5-14 to 5-23; and the "IBM PS/2 Hardware Technical
 Reference," pages 41-49.


 136. The Microsoft Mouse with Lotus 1-2-3 Release 3.1

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-FEB-1991    ArticleIdent: Q67860

 You can use the Microsoft Mouse with Lotus 1-2-3 version 3.1. The
 mouse will work correctly with both the COM and SYS versions of the
 drivers. Correct mouse use in 1.2.3 release 3.1 depends on whether or
 not the memory resident formatting and printing utility WYSIWYG is
 properly installed and loaded into memory. Without installation and
 loading of WYSIWYG, no mouse cursor will appear on the normal Lotus
 1-2-3 screen. If you try use a previous Lotus 1-2-3 Microsoft Mouse
 menu or the generic MSMENU, Lotus will not work correctly (for
 example, you will get erratic highlights and no cursor).

 It appears that in some instances there is a problem with earlier
 versions of the mouse driver even when WYSIWYG is correctly installed
 and loaded. A possible solution is to update the mouse driver to
 MOUSE.COM version 7.04. Another possible solution is to load MOUSE.SYS
 version 7.04 with the CONFIG.SYS file.

 Correct use of the mouse in Lotus 1-2-3 version 3.1 depends on proper
 installation of WYSIWYG, correct hardware configuration, and the right
 operating environment.

 Installation
 ------------

 The following steps are necessary to ensure that the Microsoft Mouse
 will work with Lotus 1-2-3 version 3.1:

  1. Complete installation of the mouse hardware and software. Be sure
     the mouse driver is loaded into memory.

  2. Complete the first-time installation of Lotus 1-2-3 3.1. If you did
     not choose to have the WYSIWYG files transferred to the hard disk
     the first time, you must rerun the installation program from the
     hard disk and choose the option to transfer the WYSIWYG files to
     the hard disk.

  3. After completing the first installation of Lotus 3.1, put the
     Add-In Support Disk into drive A and type "install" (without the
     quotation marks) at the A:> prompt. The installation program will
     place the WYSIWYG files into the default directory C:\123R3\ADDINS.

  4. When this second "install" is complete, go to the C:\123R3
     subdirectory and type "123". This takes you into the normal Lotus
     screen.

  5. Press the ALT+F10 key combination. You will see the Addin menu in
     the Lotus menu bar area.

  6. From the Addin menu, choose Load.

  7. Specify WYSIWYG.PLC as the add-in to read into memory.

  8. Select No-Key.

  9. WYSIWYG is now in memory, and you have a mouse cursor.

 10. You can get the regular Lotus menus by selecting Quit or using the
     key combination CTRL+BREAK. You also may toggle between the Addin
     menu and the main Lotus menu by clicking the right mouse button.

 Hardware
 --------

 You must have a mouse and mouse driver as well as a graphics
 display monitor and a graphics display card. Lotus 1-2-3 3.1
 also requires at least a 286 microprocessor.

 Operating Environment
 ---------------------

 Lotus 1-2-3 3.1 requires MS-DOS version 3.00 or later. It will not run
 in the DOS compatibility box of OS/2; however, it will run after you
 choose the DOS dual-boot option from OS/2. Lotus 1-2-3 3.1 will run
 under the DOS option of Windows 3.00 or it can be installed as a
 Windows 3.00 application.

 Additional Tips
 ---------------

 Microsoft Mouse Driver versions 7.03 and 7.05 will return a white
 arrow graphics cursor in Lotus 1-2-3 3.11 while all other mouse driver
 versions will return a blue graphics cursor.

 To select an item from a menu you must point to the menu item desired
 and hold the left mouse button down. Then move the highlight to the
 sub-menu choice. When you release the mouse button, the item will be
 selected.

 In addition to normal mouse cursor movement, you may also move the
 mouse cursor by selecting the arrow icons on the right hand side of
 the 1-2-3 screen.


 137. Running MSETUP from Drive B

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | driver mouse install b: msetup
 Last Modified: 10-FEB-1991    ArticleIdent: Q67862

 When you run the Setup program from drive B, the message "please
 insert disk into drive A" may occur. You can temporarily force drive B
 to emulate drive A. Using the DOS ASSIGN command, type

    ASSIGN A=B

 at the C:\DOS> prompt. Then, run MSETUP from drive B. After rebooting
 the system, the drives will return to their normal configuration.



 138. 400 DPI Serial Mouse and Epson Equity LT 386/SX

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-FEB-1991    ArticleIdent: Q67863

 The 400 DPI serial mouse may not install on the 9-pin serial port of
 an Epson Equity LT 386/SX. Epson America has confirmed this and offers
 a patch for this problem. You can obtain this patch from your Epson
 dealer.

 Note: Not all Epson dealers may be aware of this problem, but they
 should be able to get the patch from their main Epson supplier.



 139. Quattro Pro 2.0 Graphics Mode Needs /Y Switch

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-FEB-1991    ArticleIdent: Q68106

 Borland's Quattro Pro 2.0 requires mouse switch /Y when you run the
 7.04 mouse driver in graphics mode. This information is contained in
 the readme file that accompanies Quattro Pro 2.0.

 The graphics mode in Quattro Pro 2.0 is known as the "Annotate" mode.
 Owners of the Microsoft Mouse and Quattro Pro 2.0 also report that the
 earlier version 6.24b mouse driver will work in any mode of Quattro
 Pro 2.0. Borland recommends that you should not use a Microsoft Mouse
 driver earlier than version 6.10.


 140. I/O Addresses for the Microsoft Mouse

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-FEB-1991    ArticleIdent: Q68110

 The following are the ranges in which an I/O (Input/Output) port
 assignment may occur for the Microsoft Mouse. The ranges are given in
 hexadecimal numbers, and the serial communications port assignments
 conform to the IBM standard I/O address range assignments for PCs and
 PS/2s.

 SERIAL MOUSE
 ------------

 Port Assignments    Address Ranges
 ----------------    --------------

 COM1                3F8H-3FFH

 COM2                2F8H-2FFH

 BUS MOUSE (BUS INTERFACE BOARD SETTINGS)
 ----------------------------------------

 Primary Inport Range
 --------------------

 23CH-23FH

 Secondary Inport Range
 ----------------------

 238H-23BH

 An I/O port acts as a doorway through which information travels.
 Information may originate from the CPU, travel over data and address
 buses, pass through the I/O port, and finally reach a peripheral
 device such as the mouse. Although the CPU recognizes various ports
 through 16-bit port numbers that range from 00H through FFFFH, the
 port address is not actually an address found in main memory. A port
 assignment is a memory location separate from a (main) memory address
 that is associated with that particular I/O port.

 No other peripheral device, such as a modem or printer, may share the
 same I/O address with the mouse or the mouse may not function
 correctly.


 141. Pascal Example in Programmer's Guide Won't Compile

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | Pascal Mouse Programming Borland Turbo
 Last Modified: 11-FEB-1991    ArticleIdent: Q68881

 The "Making Calls from Borland Turbo Pascal Programs" sample in
 Appendix E of the "Microsoft Mouse Programmer's Reference" does not
 compile with Turbo Pascal versions 5.0 and 6.0.

 The CpuReg data structure needs to be defined as "Registers"
 variables. The semicolons need to be removed from the END lines that
 immediately precede ELSE. Finally, finding the segment and offset of
 the pointer of the address of the user array or subroutine (functions
 9,12,20,22,23,and 24) needs to be done outside of this procedure.
 Passing the first element of the array or the start point of the
 subroutine into the procedure, then calling the "ofs" and "seg"
 functions in the procedure doesn't seem to work. This is due to how
 the variables get dereferenced when passed into a procedure.

 The following example compiles in both Turbo Pascal version
 6.0 and Quick Pascal version 1.00:

 Procedure Mouse (Var m1, m2, m3, m4, m5 : integer );

 Var
    CpuReg: Registers;

 begin {mouse}

    if m1 >= 0 then
       begin
      CpuReg.AX := m1;        { Load Parameters       }
      CpuReg.BX := m2;        { into appropriate      }
      CpuReg.CX := m3;        { registers             }

      if (m1 = 9) or (m1 = 12) or (m1 = 20)
         or (m1 = 22) or (m1 = 23) or (m1 = 24) then
         begin
           CpuReg.DX  :=  m4;    {m4 = offset,         }
           CpuReg.ES  :=  m5;    { and m5 = segment    }
         end                       { of the user array }
                          { or subroutine     }

       else
       if  m1 = 16  then
        begin
          CpuReg.CX  := m2;           {Left  x coordinate }
          CpuReg.DX  := m3;           {Upper y coordinate }
          CpuReg.SI  := m4;           {Right x coordinate }
          CpuReg.DI  := m5;           {Lower y coordinate }
        end
      else
          CpuReg.DX  := m4;

      Intr($33, CpuReg);              {Call mouse driver  }
                             { at Interrupt 33H  }

      m1 := CpuReg.AX;                {Return values back }
      m2 := CpuReg.BX;                { to parameters     }
      m3 := CpuReg.CX;
      m4 := CpuReg.DX;

      if (m1 = 20) then               {special returns    }
         m2 := CpuReg.ES              { from subroutines  }
    end;
 end; {mouse}


 142. CADKEY Requires Microsoft Mouse Driver Version 7.04

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | AutoCAD EasyCAD FastCAD VersaCAD
 Last Modified: 10-FEB-1991    ArticleIdent: Q68930

 The CAD software package CADKEY requires that the Microsoft Mouse
 driver be updated to version 7.04 to run properly. Earlier
 versions of the driver, such as version 7.00, will not allow you to
 operate the mouse correctly in this software. In one instance, the
 cursor is confined to a small area of the upper-left-hand corner of
 the screen.

 CADKEY is produced and marketed by CADKEY Inc. The technical support
 number is (203) 647-9235. The CADKEY Inc. product referenced here is
 manufactured by vendors independent of Microsoft; we make no warranty,
 implied or otherwise, regarding the product's performance or
 reliability.


 143. Using the Microsoft Mouse with Open Access III

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-FEB-1991    ArticleIdent: Q68931

 The Microsoft Mouse can be successfully used with the application Open
 Access III by performing the following steps:

 1. Copy the Open Access III files MMENU.DEF and MMENU.MNU to the
    MOUSE1 subdirectory.

 2. Copy the file MENU.COM to the MOUSE1 subdirectory.

 3. Load the Microsoft Mouse driver.

 4. Go to the MOUSE1 subdirectory and type:

       MENU MMENU

    You should get a "Menu Installed" message.

 5. Go to the Open Access III subdirectory and start the Open Access
    III program.

 If this sequence does not work, you may have problems with memory
 resident software. In which case, perform the above steps after doing a
 "clean boot" with a copy of the original DOS floppy disk.

 You may obtain the MENU.COM program by calling Microsoft Product
 Support (Hardware).

 Open Access III is an integrated function application that combines a
 database, a word processor, and a spreadsheet into one application.
 The product is developed and marketed by Software Products
 International. The technical support number is (800) 937-4774.

 The Software Products International product referenced here is
 manufactured by a vendor independent of Microsoft; we make no
 warranty, implied or otherwise, regarding the product's performance or
 reliability.


 144. False Cursor Trail in SimEarth with Mouse Driver 7.00

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-FEB-1991    ArticleIdent: Q68932

 Microsoft Mouse Driver version 7.00 displays a false cursor trail in
 the planet simulation program SimEarth. You may temporarily correct
 this problem by using a /B switch when loading SimEarth (that is
 SimEarth /B).

 For a permanent fix you can obtain an updated mouse driver from Microsoft
 Product Support or Microsoft Customer Service.

 More info:

 SimEarth is developed and marketed by Maxis. The technical support
 number is (415) 376-6434. The Maxis product referenced here is
 manufactured by a vendor independent of Microsoft; we make no
 warranty, implied or otherwise, regarding the product's performance or
 reliability.


 145. Microsoft Mouse Incompatible with Commodore PC 40-III

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 10-FEB-1991    ArticleIdent: Q68953

 The Commodore PC 40-III and PC 10-III may not work with the Microsoft
 Serial Mouse. The mouse port for these machines is not designed to
 function with the Microsoft Mouse.

 You may obtain further information and assistance by calling Commodore
 technical support at (703) 644-4170. The Commodore product referenced
 here is manufactured by a vendor independent of Microsoft; we make no
 warranty, implied or otherwise, regarding this product's performance
 or reliability.


 146. Using a Bus Mouse on a Tandy 1000

 Product Version(s): 1.x 6.x 7.x
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-FEB-1991    ArticleIdent: Q68955

 When using a bus mouse on a Tandy 1000 computer, you may not be able
 to run the mouse on IRQ2. A better choice may be IRQ5, even though the
 computer may have a hard drive.

 The early models of the Tandy 1000 used IRQ2 for a hard card, which
 may have been optionally installed. These models included the Tandy
 1000, Tandy 1000A, Tandy 1000SX, and Tandy 1000TX.

 Later models used IRQ5 for hard cards. These models included the
 Tandy 1000SL, Tandy 1000SL/2, Tandy 1000TL, and Tandy 1000TL/2.


 147. WordPerfect 5.1 and WordStar 6.0 Mouse Support

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | word processor
 Last Modified: 10-FEB-1991    ArticleIdent: Q68956

 WordPerfect version 5.1 incorporates Microsoft Mouse support; however,
 WordStar versions 5.5 and 6.0 do not. The following information
 identifies whether or not a menu is needed to use the Microsoft Mouse
 with WordStar or WordPerfect.

 Product                  Description
 -------                  -----------

 WordStar version 6.0     Not Microsoft Mouse aware: see below note
 WordStar version 5.5     Not Microsoft Mouse aware: uses MSWS5.COM
 WordPerfect version 5.1  Microsoft Mouse aware: no menu needed
 WordPerfect version 5.0  Not Microsoft Mouse aware: uses MSWP5.COM

 Note:
 WordStar 6.0 sometimes works with MSWS5.  But we do not gurantee this
 version to work with WS 6.0.

 It is important to learn how the built-in mouse menus in WordPerfect
 version 5.1 work. In color modes, the normal cursor is a rectangular
 red text cursor. A right-button click causes a menu line to appear at
 the top of the screen. Then, by clicking and holding the left mouse
 button, you may drag the highlight down the chosen drop-down menu to
 make the desired menu selection.

 The products referenced here are manufactured by vendors independent
 of Microsoft; we make no warranty, implied or otherwise, regarding
 these products' performance or reliability.


 148. Using MSMENU.COM with ACT! version 2.0

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 11-FEB-1991    ArticleIdent: Q68958

 You can use the Microsoft Mouse with ACT! version 2.0. In order to use
 the mouse correctly, you must first load the generic menu DEFAULT.COM
 or MSMENU.COM. Appendix H-1 of the ACT! "Reference Manual" specifies
 DEFAULT.COM, but the more current MSMENU.COM or MENU.COM work as well.

 Copy one of these files to the ACT! subdirectory. The directions for
 ACT! specify that you:

 1. Load the mouse.

 2. In the subdirectory in which ACT! is installed, type "MSMENU MSACT"
    (without the quotation marks).

 3. After the menu is loaded in this way, type "ACT!" (without the
    quotation marks). You will now have the use of the mouse in ACT!

 The file MSACT.MSE is a menu file that comes with ACT!. If the mouse
 and menu are loaded properly, then the mouse should give basic cursor
 movement with the buttons serving the following functions:

    Button                   Function
    ------                   --------

    Left Button Click        Same as ENTER
    Right Button Click       Same as F2 (edit mode)
    Both Buttons Click       Same as ESC

 Note: These button assignments may not work properly in DOS 4.00.

 If you do not have a copy of MSMENU.COM, you may obtain a copy by
 calling Microsoft Customer Service or Product Support and ordering
  "The Microsoft Mouse Supplemental Menus Disk."

 ACT! is a database software program that helps keep track of business
 contacts. ACT! is developed and marketed by Contact Software
 International. The technical support number is (214) 418-4885. The
 Contact Software International product referenced here is
 manufactured by a vendor independent of Microsoft; we make no
 warranty, implied or otherwise, regarding this product's performance
 or reliability.


 149. NEC Mouse Port, Lotus 3.1, and Microsoft Serial Mouse

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | NCR
 Last Modified: 10-FEB-1991    ArticleIdent: Q68959

 The mouse cursor may freeze when you use the Microsoft Mouse in the
 PS/2 mouse port of some of the NEC 286 and 386 machines while running
 the WYSIWYG mode of Lotus 1-2-3 version 3.1. Contact NEC technical
 support at (508) 264-4300 for more information.

 The products included here are manufactured by vendors independent of
 Microsoft; we make no warranty, implied or otherwise, regarding the
 products' performance or reliability.






 Microsoft Programmer's Work Bench [Development Environment]
 =============================================================================


 1. Using the Features of PWB to Build a Program with Overlays

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 18-APR-1990    ArticleIdent: Q60050

 A MAKE file built with PWB can be modified (within reason) with the
 user supplied information section. This section, coded as

    # << User_supplied_information >>

 can contain other instructions that PWB (actually NMAKE or NMK) is
 supposed to carry out during the MAKE cycle. All instructions that
 follow this "fence" are not changed by PWB.

 The following instructions detail two implementations of that "fence"
 to allow PWB to build a program that uses overlays.

 While the following steps appear tedious, they are simple in practice.

 Once the changes are made, the only time you need to edit the MAKE
 file directly is to change your overlay structure, or to add or delete
 modules. When adding or deleting modules, you must both edit the
 program list with Make.Edit Program List and modify the commands in
 the user section. If you are only modifying the overlay structure, you
 change just the user section.

 The overlay structure in the example is as follows:

    HELLO.OBJ  (root)
        |
        +----A.OBJ (first  overlay)
        |
        +----B.OBJ (second overlay)

 All of the .OBJs are built from .C files with the same base name.

 1. Use PWB to build the program list in the normal way. This step is
    the same for any new program list.

    a. Start PWB.

    b. Choose Make.Set Program List and specify a new name -- HELLO.MAK
       in this example.

    c. Add HELLO.C, A.C, and B.C to the list. (If you have additional
       .C or .OBJ files, you would add them as well.) When all the
       files are listed, select Set Dependencies.

    d. Choose Options.Build Options and click on the Set Initial
       Build Options button and select DOS EXE.

    e. From Options.Compile Options, select the proper memory model.

    f. From Options.Link Options.Set Debug Options, turn off
       Incremental Link.

    g. From the Options.Browse Options dialog box, turn Generate Browse
       Information on.

    h. Choose Make.Rebuild All to make sure that the program builds
       properly without overlays. If it doesn't, review your work in
       previous steps.

 2. Now that you have a working program list, add the non-PWB
    information to the end.

    a. Choose Make.Clear Program List so that you can edit the MAKE
       file. Attempting to edit the current program list results in the
       message "No-edit file may not be modified."

    b. Choose File.Open to open the MAKE file so you can modify it.

    c. Go to the end of the file and start a blank line.

       Starting in column 1, add the following line:

          # << User_supplied_information >>

       Be sure to enter the line exactly as shown -- spacing is
       significant. This line is a "fence". Everything below the fence
       is yours and is not modified by PWB. Conversely, you should not
       modify anything above the fence because that section belongs to PWB.

    d. Below the fence starting in column one, add the pseudo-target:

          OVERLAID : $(OBJS)

       Be sure it starts column 1. Do not put a blank line after this line.

    e. Copy the command section from the $(PROJ).EXE description block
       to immediately follow the pseudo-target. The command section begins
       on the line following the line that reads

          $(PROJ).exe : $(OBJS)

       and ends at the next blank line. Do not copy the $(PROJ).EXE
       line, and do not leave a blank after the target. After you have
       copied the commands, your file should appear as follows:

          ... PWB section here, unmodified ...

          # << User_supplied_information >>

          OVERLAID : $(OBJS)
          !IF $(DEBUG)                    # copy of commands...
                  $(LRF) @<<$(PROJ).lrf
          $(RT_OBJS: = +^
          ) $(OBJS: = +^
          )
          $@
          ...

    f. Use the following procedure to modify the commands to link an
       overlaid EXE instead of a normal EXE.

       Note: There are two subsections in this section: a debug section
       that starts at the first "!IF $(DEBUG)" and ends at "!ELSE", and
       a release section that starts after the "!ELSE" and ends at the
       first "!ENDIF".

       You need to make the following modifications to both
       subsections.

       i. Delete the line that reads as follows:

             ) $(OBJS: = +^

          After the right parenthesis on the line that moved up, put
          your list of .OBJ files with parentheses to indicate which
          ones go in which overlays. If you need to use more than one
          line for all of your objects, be sure to put a plus sign (+)
          at the end of each line except the last.

      ii. Replace "$@" on the next line with "$(PROJ).EXE".

          In our example,

                 $(LRF) @<<$(PROJ).lrf
             $(RT_OBJS: = +^
             ) $(OBJS: = +^     # delete this line
             )                  # append OBJ list here ...
             $@                 # replace this line with $(PROJ).EXE

          becomes:

                 $(LRF) @<<$(PROJ).lrf
             $(RT_OBJS: = +^
             ) hello.obj +
             (a.obj) +
             (b.obj)
             $(PROJ).exe

          Remember to make the changes in both branches of the !IF
          $(DEBUG).

    g. The last step is to modify the browser database build commands.
       These are the two lines at the very end of the file that begin
       with "$(NMAKEBSC...". PWB adds and deletes these lines in the
       PWB section as you turn browser information on and off.

       Since PWB won't delete and add these lines in the user section,
       enclose them in !IF $(BROWSE)...!ENDIF so they'll be executed
       only when you ask for browse information. You also need to
       delete the "$(NMFLAGS)" macro from the second line to prevent
       infinite NMAKE recursion.

       The following lines

          $(NMAKEBSC1) MAKEFLAGS=
          $(NMAKEBSC2) $(NMFLAGS) -f $(PROJFILE) $(PROJ).bsc

       become:

          !IF $(BROWSE)
              $(NMAKEBSC1) MAKEFLAGS=
              $(NMAKEBSC2) -f $(PROJFILE) $(PROJ).bsc
          !ENDIF

       If you need special NMAKE options for building the browser
       database, just add them where you removed $(NMFLAGS).

 3. Reactivate the MAKE file by selecting Make.Set Program List.

 4. With these changes, if you select Make.Rebuild All, you will still
    get a non-overlaid program because PWB normally builds the first
    target in the MAKE file. To build the overlaid program, modify the
    command line passed to NMAKE so that NMAKE builds your overlay
    target rather than the regular EXE. Select Options.NMAKE Options
    and specify "OVERLAID" as the target by putting it in the NMAKE
    options box, or use Make.Build Target.

 5. With "OVERLAID" in Options.NMAKE Options you can build your program
    by either selecting Make.Rebuild All or Make.Build *.EXE, as usual.
    If you want to build a non-overlaid program, delete "OVERLAID" from
    the NMAKE options box.

    Note that if you use debug options with overlays you will get a
    linker warning L4047. This warning, and the dialog box that says
    that CRT0DAT.ASM can't be found, are normal when building overlaid
    programs for debugging and can be ignored. You can debug the overlaid
    program normally, with full debugging information available.

    This MAKE file behaves almost identically to a regular PWB MAKE
    file. The only differences are that NMAKE options are NOT  passed
    to the browser build unless you add them to the browser build line,
    and that you must edit the user supplied section if you add or
    delete modules from the project.


 2.

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00 fixlist1.10 s_c
 Last Modified:  5-FEB-1991    ArticleIdent: Q60392

 TOOLS.PRE is a sample Programmer's WorkBench (PWB) initialization file
 that is installed (and modified) when C 6.00 is installed by running
 the Setup program. On pages 19 and 20 of "Microsoft C: Installing and
 Using the Professional Development System," it states that the
 contents of TOOLS.PRE can be merged with an existing TOOLS.INI file,
 if one exists, or it can be renamed to TOOLS.INI, if there isn't one.
 To work correctly, you must make sure that the contents of this file
 are preceded by a PWB tag (for example, [PWB]) because the supplied
 TOOLS.PRE lacks this tag.

 When merging the PWB 1.00 TOOLS.PRE file into an existing TOOLS.INI
 file, a [PWB] tag should be added just above the area where the file
 is merged. For example:

 [PWB]
   .
   .
   .
   (TOOLS.PRE contents)
   .
   .
   .

 [NEXT-TAG]

 If TOOLS.PRE is being renamed to TOOLS.INI, the tag should be added as
 the first line in the file. In either case, failure to add the tag
 will result in PWB ignoring the initialization information.

 Microsoft has confirmed this to be a problem in PWB version 1.00. This
 problem was corrected in PWB version 1.10.


 3. How to Abort Compilation When Using PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_c
 Last Modified: 17-JUL-1990    ArticleIdent: Q60500

 Question:

 How do I abort a compile that is in progress when using the
 Programmer's WorkBench (PWB) environment?

 Response:

 Under MS-DOS (or the OS/2 3.x compatibility box), use CTRL+C to abort.

 Under OS/2, use "Arg Meta Compile" to abort a compilation taking place
 in the background.

 The default keystrokes for Arg Meta Compile are ALT+A F9 CTRL+F3.

 You can also create a macro and assign it to a key to abort the
 compile process. Below is a sample macro that you could place in your
 TOOLS.INI file under the [pwb] tag.

    [pwb]
    Abort:=Arg Meta Compile
    Abort:Ctrl+F5

 Note: In either OS/2 or MS-DOS, the ESC key and CTRL+BREAK do not
 abort a compilation.


 4. PWB Makefiles Are Read-Only When Set as Active Program List

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 25-MAY-1990    ArticleIdent: Q60749

 When you choose the Make.Set Program List option within the
 Programmer's WorkBench (PWB) environment to set a program list for the
 current project, the makefile associated with the current program list
 is marked as read-only and is not editable.

 Code Example
 ------------

 // FOO.C

 #include <stdio.h>
 void main ( void )
 {
    printf ( "Foobar\n" ) ;
 }

 1. Using the above sample program, choose the Make.Set Program List
    menu options and call the program list FOO.MAK.

 2. Save the list.

 3. Choose the File.Open menu, and enter FOO.MAK as the file you want
    to open.

 4. Place your cursor anywhere in the file and press ENTER. You will be
    greeted with the following a pop-up message:

       No-edit file may not be modified.

 If you want to edit the makefile, choose the Make.Clear Program List
 options, and you can edit the makefile as you want.


 5. Why Zero-Length .SBR Files Are Left on the Disk by the PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 16-JAN-1991    ArticleIdent: Q61056

 When using the Source Browser functionality within the Programmer's
 WorkBench, you can expect to have zero-length .SBR files on your disk.
 This is by design of the PWBRMAKE utility.

 PWBRMAKE.EXE is a utility that converts the .SBR files created by the
 compiler for each program module into a single database file that can
 be read by the Programmer's WorkBench (PWB) Source Browser. The
 resulting Source Browser database file has the extension .BSC.

 When a Source Browser database (a .BSC file) is built from .SBR files,
 the .SBR files are truncated to zero length to save disk space since
 they can be quite large. .SBR files are truncated to zero length,
 rather than being deleted, because PWBRMAKE performs incremental
 updates to the database and, therefore, needs the time and date stamp
 from the files.

 When you rebuild part of your project, new .SBR files are built for
 those modules. Each .SBR file that has not been re-created during a
 build is included as a zero-length file. This tells PWBRMAKE that the
 file has no new contribution to make to the database, so no update of
 that part of the database is required.


 6. Do Not Start Programmer's WorkBench by Typing PWBED

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 11-JUL-1990    ArticleIdent: Q61307

 You cannot start the Programmer's WorkBench by typing PWBED. This is
 incorrect. Type PWB to start the Programmer's WorkBench environment.

 In the REAL MODE directory specified during setup, there will be two
 executables for the PWB, PWB.COM and PWBED.EXE. PWB.COM actually
 spawns PWBED.EXE. If you use PWBED to start the PWB, it will consume
 approximately 500K of memory. By executing a DOS SHELL from within the
 PWB and running CHKDSK, you will notice there is very little memory
 left.

 When you invoke the PWB the correct way (by typing PWB), then shell-
 out and do a CHKDSK, you will see that the PWB has only consumed
 approximately 8K of available memory.

 The PWB appears to work correctly if you invoke it with PWBED.
 However, since it is using so much memory, you will receive memory
 problems, such as "out of memory," "cannot compile," or "cannot
 build." These are caused because there is not enough memory to spawn
 either NMAKE, the compiler, or the linker.


 7. Steps Needed to Make Source Browser Usable

 Product Version(s): 1.00    | 1.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 11-JUL-1990    ArticleIdent: Q61309

 Before using the Browse menu options, you must first define and build
 the database the Source Browser will use. If this database is not
 already built, all options on the Browse menu will be grayed out and
 unusable.

 The following steps must be taken to define a database that is usable
 by the Source Browser menu options:

 1. Generate a program list using the Set Program List command in the
    Make menu. The PWB creates one internally if you do not specify one
    and the program only uses one source file. If a program is larger
    than one source file and a program list is not set, it is
    impossible to generate a Source Browser database.

 2. Choose Browse Options from the Options menu. You must select the
    Generate Browse Information field in the dialog box to create the
    Source Browser database.

 3. Build your program using the Make Menu option. You MUST have a
    successful build (compile AND link) of the program for a Source
    Browser database to be generated.

 The Browse Menu options should now be available for use.

 If, after taking the steps outlined above, the Browse Menu options
 are still unavailable for use, query on the following keywords:

    Browse and Options and Unavailable and Strange and Circumstances
 For printed documentation explaining the setup and use of the Source
 Browser, see Pages 50-52 of "Installing and Using the Professional
 Development System." You can also find information about the Source
 Browser in the online help under Programmer's WorkBench, Using the PWB
 Source Browser.


 8. SYS2070 Issued When Executing PWB.EXE for the First Time

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 13-JUN-1990    ArticleIdent: Q61572

 When running the Programmer's WorkBench (PWB) for the first time, the
 following OS/2 system error may be issued:

    Session Title:
    PWBED.EXE

    SYS2070: The system could not demand load the
    application's segment. MSHELP HELPSHRINK is in error.
    For additional detailed information also see message SYS0127

 This system error is caused by the PWB's use of a version of
 MSHELP.DLL that is not as current as the one that was shipped with C
 version 6.00. For the PWB to function correctly, the correct version
 of MSHELP.DLL must be in the LIBPATH.

 The README.DOC on the C version 6.00 Setup/Compiler 1 Disk warns of
 this potential problem, and suggests that QuickHelp (QH) be terminated
 as a background keyboard monitor before Setup is run.

 This problem is usually caused as a result of the Setup program not
 being able to copy its version of MSHELP.DLL over the old version of
 MSHELP.DLL. If another process (most likely a detached session of
 QH.EXE) was accessing this file during the execution of Setup, the
 Setup program will issue a message similar to the following:

    ERROR: Could not create file C:\OS2\DLL\mshelp.dll
    ERROR: File copy failed: A:\the PWB\mshelp.dll to C:\OS2\dll\mshelp.dll

 To solve this problem, take the following steps:

 1. Disable QH as a keyboard monitor:

    a. Press ALT+Q (to invoke QH).

    b. Press O (for the Options menu).

    c. Press T (to Terminate the monitor).

 2. Copy the up-to-date version of MSHELP.DLL from the distribution
    disk:

    a. Insert the Setup/Compiler 1 Disk into Drive A.

    b. Change the default Drive A.

    c. Run Setup with the /copy option by typing the following:

          setup /copy

    d. Press ENTER

    e. Press ENTER again (unless the setup files are in a drive other
       than A).

    f. At the prompt asking for the name of the file to copy, type
       MSHELP.DLL and press ENTER.

    g. At the prompt asking for the name of the directory to which to
       copy this file, type the directory in which the old MSHELP.DLL
       is located (most likely C:\OS2\DLL).

    h. Setup should then ask for the Programmer's WorkBench/Utilities
       for OS/2 Disk to be inserted into the setup drive.

    i. When Setup is finished copying the file, press ENTER at the
       next prompt.

 The PWB should now start up correctly.


 9. U1355 Bad Command or File Name

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr filename
 Last Modified: 27-SEP-1990    ArticleIdent: Q61607

 The following undocumented error may occur when attempting to run an
 executable file such as CL.EXE, LINK.EXE, NMAKE.EXE, etc., from inside
 the Programmer's WorkBench (PWB).

    U1355 Bad Command or File Name

 The error occurs because the directory containing the .EXE file is not
 specified in the search path or an incorrect LINK.EXE is being
 executed.

 This problem can be corrected by adding the missing directory name(s)
 to the path in the AUTOEXEC.BAT or STARTUP.CMD and rebooting, or
 executing NEW-VARS.BAT or NEW-VARS.CMD. If an incorrect linker is the
 problem, the search path can be rearranged to find the new version of
 the linker first, or the old linkers can be deleted or renamed.
 Finally, it may be necessary to delete the CURRENT.STS and PROG.STS
 files before the PWB will work correctly. This error is not documented
 in the PWB online help.


 10. Saving Compiler Results File in the PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 25-MAY-1990    ArticleIdent: Q61636

 The Programmer's WorkBench (PWB) deletes the compiler results file
 upon exiting the PWB. In DOS or OS/2, the file can be saved if the
 compiler results window is made current and the File.Save As menu
 option is selected.

 The compiler results file will appear similar to the following:

    +++ PWB  [E:\] Rebuild
            NMAKE  /z /a /f E:\pwb.mak
         cl /c /W4 /Fm /Ot /FoGLOBL.obj GLOBL.C
    Microsoft (R) C Optimizing Compiler Version 6.00
    Copyright (c) Microsoft Corp 1984-1990. All rights reserved.

    GLOBL.C
         echo @GLOBL.lrf > NUL
         link @GLOBL.lrf

    Microsoft (R) Segmented-Executable Linker  Version 5.10
    Copyright (C) Microsoft Corp 1984-1990.  All rights
    reserved.

    Object Modules [.OBJ]: GLOBL.obj,GLOBL.exe,NUL, /NOD:SLIBCE
    SLIBCEP , /NOI /BATCH /EXE /FAR /PACKC;


 11. Programmer's WorkBench Edit Switch Is Unimplemented

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 14-MAY-1990    ArticleIdent: Q61642

 The edit switch for the Programmer's WorkBench (PWB), documented on
 Page 79 of the version 6.00 "Microsoft C Reference" manual, is
 unimplemented in PWB version 1.00. The switch is designed to set the
 active file as read-only so that it cannot be edited.

 If you add an option in your TOOLS.INI file under the PWB tag to read
 either

    Edit:yes
    Edit:no

 PWB will return an error message saying "Edit is not an editor
 switch."

 As a workaround, invoke PWB with the /r option to open up the current
 file as read-only.


 12. Certain Key Sequences Cause R6003 or SYS1943 in PWB 1.00

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00 fixlist1.10
 Last Modified:  4-FEB-1991    ArticleIdent: Q61660

 In the Programmer's Workbench (PWB) version 1.00, it has been observed
 that certain unusual editing sequences can cause the following errors:

 In DOS:

    Run-time error R6003 - integer divide by 0

 In OS/2:

    SYS1943 protection violation, trap number 13

 The following sequences reproduce the errors:

    Procedure                             Keystrokes
    ---------                             ----------

 1. Bring up several files.               ALT+F O x3
    Select the Options menu.              ALT+O
    Select Linker options.                L
    Select Set Debug Options.             ALT+G
    Pull up help on the options.          F1
    Arg-refresh through several files.    ALT+A SHIFT+F7 x3
    Escape back to the Editor screen.     ESC x3

 2. Select the Options menu.              ALT+O
    Select Editor Settings.               S (or K)
    Go down thirteen lines.               DOWN ARROW key x13
    Backspace.                            BACKSPACE
    Undo.                                 ALT+BACKSPACE

 Note: Step 2 reproduces only the R6003 error in DOS, not the SYS1943
 error.


 13. PWB 1.00 Requires Decimal Value for Stack Size in LINK Options

 Product Version(s): 1.00    | 1.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | buglist1.00 fixlist1.10
 Last Modified:  5-FEB-1991    ArticleIdent: Q61871

 In the Programmer's WorkBench (PWB) version 1.00, there is a problem
 with changing a program's stack size in some situations. When
 specifying the stack size in the Link Options dialog box (from the
 Options menu), you must enter the value in the form of a decimal
 integer. Although the Help menu tells you this field accepts positive
 integers in octal and hexadecimal form, PWB 1.00 will not accept them.

 When an octal or hexadecimal value is entered in the stack-size field,
 any digits specified as A-F are discarded and replaced by 0 (zero). If
 digits precede a letter, the digits are retained and the letters are
 discarded.

 Microsoft has confirmed this to be a problem in PWB version 1.00. This
 problem was corrected in PWB version 1.10.


 14. SYS0002 Produced If MSHELP.DLL Not Installed

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | pwbhelp
 Last Modified: 23-JAN-1991    ArticleIdent: Q61955

 Under OS/2, if MSHELP.DLL is not installed correctly or is not on the
 LIBPATH, the following error may appear in a window when starting the
 Programmer's WorkBench (PWB):

                     Cannot Autoload Extension
                     e:\c600\binp\pwbhelp.pxt
 MSHELP:  SYS0002:  The system cannot find the file specified

                         < OK >   < Help >

 Make sure that the latest version of MSHELP.DLL (the one that was
 included with the Microsoft C Compiler version 6.00) is installed in a
 directory contained in your LIBPATH.

 If this file was not copied off the disks during setup, you can
 execute the following command with your Setup disk in Drive A:

    a:setup /copy

 Specify the file MSHELP.DLL at the prompt, then specify the
 destination directory.

 The default for SETUP.EXE is to put OS/2 DLLs in the C:\OS2\DLL
 directory. If you choose to install the DLLs in some other directory,
 you must edit the LIBPATH in your CONFIG.SYS file and restart the
 system.


 15. Enabling of Source Browser Menu Related to .BSC and .MAK Files

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 29-MAY-1990    ArticleIdent: Q61968

 The Source Browser feature of the Programmer's WorkBench (PWB) is
 enabled or disabled depending upon the existence of a database file
 (.BSC file) AND a program list (.MAK file). The existence of a .BSC
 database file alone does not guarantee that the Browse menu will be
 enabled for all modules in a project, even if the .BSC file was built
 from .SBR files for every module. The setting of a program list is
 also required.

 Thus, if a .BSC file is built outside of the PWB with PWBRMAKE, then
 upon entering the PWB, the Browser will be enabled for only one module
 at most (see below). The easiest method to enable the Browse menu for
 ALL modules is to select "Set program list" on the Make menu, then
 type in the base name of the .BSC file (with the .MAK or no extension)
 when it prompts you for the filename. If the .MAK file you enter does
 not exist, then the dialog box appears for adding files to the program
 list, whereas you can just select "Save List" without actually adding
 any files. At this point, the Browser menu will be enabled for all
 files you bring up into the PWB editor.

 The existence of a Source Browser database file means that the Browse
 menu will be enabled for a source file with a matching base name of
 the .BSC file.

 For example, assume a project consists of several modules, with the
 main source module called PROJECT.C. In addition, assume a Browser
 database file called PROJECT.BSC is built from the .SBR Browser
 information files produced by the compiler for every module in this
 project. If the file PROJECT.C is brought up in the PWB, the Browse
 menu will be enabled because the base name (PROJECT) is the same as
 the base name of the database file PROJECT.BSC.

 On the other hand, if any of the other source files in the project are
 opened in the PWB, the Browse menu will be disabled because the base
 names do not match the base name of the database file. Also, if
 PROJECT.C is made the current file (which enables the Browse menu) and
 an option is selected on the browse Menu, such as "Goto Reference"
 (which causes a jump to a different module), the Browse menu will
 become disabled. The only way to re-enable the Browse menu in this
 case is to make PROJECT.C the current file again.

 The way to enable the Browse menu for all modules is to set a program
 list to a file with the .MAK extension and the same base name as the
 .BSC file. Thus, in the example above, setting the program list to
 PROJECT.MAK will enable the Browse menu for all modules. In fact, this
 connection between the .BSC file and the .MAK file enables the Browse
 menu for the modules in the current project, and for ANY file opened
 under the PWB.

 The result is that if you bring up a file in the editor that is
 completely unrelated to the current project (and may not even have a
 related .BSC file), you can still use the Browse menu options.
 However, in this situation, the information available from the Browser
 still only pertains to the original project.

 In summary, the .MAK file and .BSC file relationship is based solely
 on the file existence, NOT the file contents. The program list does
 NOT need to contain the names of the modules in the current project
 (or even be an actual makefile) for the Browser to function.


 16. Modifying TOOLS.INI May Have No Effect on PWB Environment

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 17-JUL-1990    ArticleIdent: Q62170

 Changing settings in the TOOLS.INI file to modify the behavior of the
 Programmer's WorkBench (PWB) may not work under certain circumstances.
 For instance, if you decide to change the PWB to 50-line mode by
 setting "height:50" in the TOOLS.INI file, it will not work if the PWB
 was previously used in the 25- or 43-line mode.

 This is because some environment information is also recorded in the
 CURRENT.STS file, which is read in after the TOOLS.INI file --
 overriding the TOOLS.INI settings.

 The following are three workarounds for this problem:

 1. Use the /DS switch when invoking the PWB. This will ignore the
    CURRENT.STS file. However, this option also causes the current file
    history (of files being edited) to be ignored.

 2. Delete the CURRENT.STS file. This also causes the current list of
    programs being edited to be ignored.

 3. The better option is to select Editor Settings from the Options
    menu. When the list of editor switch settings appears, it can be
    changed and saved to the TOOLS.INI file by pressing SHIFT+F2. This
    will save the settings and cause the selection to take effect.


 17. Reversing Mouse Buttons in the PWB Cannot Be Done

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 25-JUL-1990    ArticleIdent: Q62330

 Currently under the Programmer's WorkBench (PWB) released with version
 6.00 of the Microsoft C Optimizing Compiler, it is not possible to
 reverse the functionality of the mouse buttons.

 It is possible to change the functionality of the mouse buttons under
 OS/2 and DOS, but this will be overridden by the PWB environment.


 18. Attempting to Expand a Help Dialog Box Hangs DOS

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 25-JUL-1990    ArticleIdent: Q62331

 When one of the pull-down menus in the Programmer's WorkBench (PWB)
 version 1.00 is selected (File, Edit, View, etc.) and then F1 is
 chosen for help on that menu, a small help screen appears. If CTRL+F10
 is chosen in an attempt to expand the window to full screen, the
 machine will hang under DOS. If the machine doesn't hang, it may
 require another invocation of CTRL+F10 to cause the problem.

 Under OS/2, the machine may not hang, but the PWB's functionality will
 be disrupted and attempts to free oneself may cause a GP fault. It may
 be possible to exit the PWB, but at the very least, the CURRENT.STS
 file will be corrupted so that future entrances to PWB will result in
 very odd window configurations.

 Microsoft has confirmed this to be a problem with the PWB version
 1.00. We are researching this problem and will post new information
 here as it becomes available.


 19. PWB Doesn't Update Mark Location If Mark Moves Up or Left

 Product Version(s): 1.00 | 1.00
 Operating System:   OS/2 | 1.00
 Flags: ENDUSER | buglist1.00
 Last Modified: 13-JUN-1990    ArticleIdent: Q62388

 If you set a mark in a file, and that location then moves upward or
 toward the left in the file, PWB does not reset the mark location;
 however, it does correctly update marks that move downward or to the
 right in the file.

 Consider the following file:

 /* Test.dat */
 test1

 test2

 test3

 Place the cursor on the "2" in test2. Choose the Search.Define Mark
 menu option. Name the mark "mark1" and press ENTER. Now, move the
 cursor to another location in the file. Choose the Search.Go To Mark
 option from the menus. Go to "mark1". Note that the cursor is back on
 the "2" in test2.

 Next, add another blank line between test1 and test2. Again, move your
 cursor and go to mark1. Note that the cursor is back on the "2" in
 test2.

 Now, delete both the lines between test1 and test2. Select the
 Search.Go To Mark option from the menus. Note that the cursor is on
 the same location as it was before you deleted these lines. The same
 behavior will happen if you delete any of the characters before the
 "2" in the test2 line.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench (PWB) version 1.00. We are researching this problem and will
 post new information here as it becomes available.


 20. PWB 1.00 "Set Dependencies" Fails with Spaces in #include Line

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00 fixlist1.10 s_c
 Last Modified:  5-FEB-1991    ArticleIdent: Q62578

 The Programmer's WorkBench (PWB) version 1.00 (shipped with C version
 6.00) includes a "Set Dependencies" option in the "Set Program List"
 window. This option automatically sets up build dependencies for all
 include files used in the current project. This option will fail with
 a message that the include file does not exist if there are embedded
 spaces between the left angle bracket (<) and the include-file name in
 an include directive line.

 The Set Dependencies option will work correctly if the space(s) are
 removed or if a new build option is added to the TOOLS.INI file.

 Although embedded spaces are legal in C programming syntax, the
 Programmer's WorkBench fails to parse the include line correctly if
 spaces exist before the filename. The following line of code shows the
 situation where the "Set Dependencies" error will occur:

    #include < stdio.h >

 The space before the "s" in stdio.h prevents PWB from finding the
 STDIO.H include file. (The trailing space after stdio.h does not
 affect the behavior of "Set Dependencies".)

 The full text of the error message window for the line above is as
 follows:

         stdio.h does not exist
    Cannot build its dependency tree.
    Abort dependency lists generation?
         <Yes>    <No>    <Help>

 Selecting <Help> displays a help screen that describes the problem as
 being either a mistyped filename or a nonexistent file, but the actual
 file DOES exist. Removing the embedded space will correct the problem.

 You can also add two new "build" lines to the TOOLS.INI file to make
 the PWB recognize include directives that contain spaces. These lines
 should be included under the section with the [PWB] tag, and should
 have the following syntax:

    build: include .c                                              \
        "^[ \t]*#[ \t]*include[ \t]*\"[ \t]*\\([^\"]+[ \t]*\\)\""  \
        case
    build: include .c                                              \
       "^[ \t]*#[ \t]*include[ \t]*<[ \t]*\\([^>]+\\)[ \t]*>"      \
        case system

 (Note: These build switch statements are broken down into multiple
 lines with the line continuation character (\) because of space
 limitations; you may enter each of them into the TOOLS.INI file on a
 single line, rather than multiple lines.)

 There is one drawback to this workaround; you will still get the error
 message shown above because the "old" build switch is applied before
 the new one. To have the new build switch take effect, you need to
 select "No" when prompted to abort the dependency list generation.
 Once you have selected "No" for each file with spaces in the include
 directive, the dependencies will then be generated correctly.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench version 1.00. This problem was corrected in the Programmer's
 WorkBench version 1.10.


 21. PWB 1.10 Dialog Boxes May Blink After Dialog Help Is Obtained

 Product Version(s): 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.10 flicker
 Last Modified: 19-FEB-1991    ArticleIdent: Q69347

 When working with the Programmer's WorkBench (PWB) version 1.10 under
 DOS, there are several instances where a dialog box may start flashing
 incorrectly. This situation occurs when you obtain help on a PWB
 informational pop-up dialog box and then return from the Help dialog
 screen. At this point you may find that the original dialog box is
 rapidly blinking.

 This problem may occur when trying to get help on a topic for which
 there is no help, trying to use an unassigned key, or when PWB informs
 you that you changed a file but didn't save it before you tried to
 exit. In each of these cases, PWB gives you a pop-up dialog box
 informing you of the situation. If you get help on this informational
 dialog box and then press ESC or click Cancel, the original dialog box
 will start blinking.

 This is not normal behavior, however, PWB is still fully functional
 and you may proceed by selecting an appropriate choice from the
 flashing dialog box.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench version 1.10. We are researching this problem and will post
 new information here as it becomes available.


 22. R6000 Stack Overflow After Deleting Current Makefile

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 25-JUL-1990    ArticleIdent: Q62668

 If you are viewing your makefile in a window in PWB 1.00, then delete
 the makefile from a shell; attempting to make the window containing
 the makefile active will cause a run-time error R6000, stack overflow.

 To duplicate this problem, bring up a sample program and set the
 program list to that file's makefile. Next, open up another window
 and open the makefile in that window. Now, either from the Run.Run
 <DOS-OS/2> Command menu or the File.<DOS-OS/2> Shell, delete that
 makefile.

 After returning back to the PWB, make the window containing the
 makefile the active program list either by pressing the F6 key to
 toggle windows or by clicking the left mouse button in that window.

 You will be faced with a popup message saying "File has been deleted
 from disk. Delete from memory?" Answering "yes" brings up the popup
 six to eight more times. Then, PWB will abort to the system prompt
 with an R6000 (stack overflow) error message and another message, "File
 has been deleted from disk."

 Microsoft has confirmed this to be a problem in PWB version 1.00. We
 are researching this problem and will post new information here as it
 becomes available.


 23. PWB 1.00 Extensions Only Return True Under DOS

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00
 Last Modified: 15-AUG-1990    ArticleIdent: Q63052

 Extensions written for use by the Programmer's WorkBench (PWB) version
 1.00 under the DOS operating system are recognized as returning true
 regardless of their actual return values.

 The use of return values as a way of providing conditional jumps
 inside PWB macros is a common practice that is affected by the above
 limitation for PWB extensions. The following sample extension and
 macro demonstrate the above problem. Once installed, both the foo()
 and foo2() functions will be seen as returning true to PWB.

 Sample Code
 -----------

 // foo.c

 #include <string.h>
 #include <stdlib.h>
 #include <ext.h>

 PWBFUNC foo( unsigned argData, ARG far *pArg, flagType fMeta );
 PWBFUNC foo2( unsigned argData, ARG far *pArg, flagType fMeta);

 // Switches.
 struct swiDesc swiTable[] =
 {
    { NULL, NULL, 0 }
 };

 // Commands.
 struct cmdDesc cmdTable[] =
 {
    { "foo", foo, 0, NOARG },
    { "foo2",foo2,0, NOARG },
    { NULL, NULL, 0, 0 }
 };

 void EXTERNAL WhenLoaded()
 {
     SetKey( "foo",         "alt+f" );
     SetKey( "foo2",       "ctrl+f" );
     return;
 }

 PWBFUNC foo( unsigned argData, ARG far *pArg, flagType fMeta )
 {
  return(FALSE);  /* FALSE is defined as 0 in ext.h */
 }

 PWBFUNC foo2( unsigned argData, ARG far *pArg, flagType fMeta)
 {
  return(TRUE);   /* TRUE is defined as 1 in ext.h  */
 }

 // End of foo.c

 ; macros in tools.ini to test foo and foo2

 load foo

 test:=foo ->loc1 arg "true" message => :>loc1 arg "false" message
 test2:=foo2 ->loc2 arg "true" message => :>loc2 arg "false" message

 test:alt+t
 test2:ctrl+2

 Microsoft has confirmed this to be a problem with PWB version 1.00. We
 are researching this problem and will post new information here as it
 becomes available.


 24. PWB Text Highlight with Mouse Acts Strange After Search

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-AUG-1990    ArticleIdent: Q63059

 The click-and-drag method of selecting text with the mouse in the
 Programmer's Workbench (PWB) sometimes works incorrectly when used
 after a search function.

 To reproduce this problem, do the following:

 1. Select a word in the text using the mouse (double-click on a single
    word).

 2. Execute the search function (select the Search menu, choose Find,
    then OK).

 3. Now try to highlight the text a few lines below the word you used
    to search on (using the click-and-drag method).

 The text will be highlighted starting at the original word that was
 searched for, rather than at the starting mouse position.

 To work around this problem, click the left button anywhere in the
 text window, then perform the text highlight.

 Microsoft has confirmed this to be a problem with the Programmer's
 Workbench version 1.00. We are researching this problem and will post
 new information here as it becomes available.


 25. PWB Does Not Return from DOS Shell with ";" in TMP

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 25-JUL-1990    ArticleIdent: Q62702

 If there is a semicolon ";" in your TMP environment variable, you may
 not be able to return to the Programmer's Workbench by typing "exit"
 after selecting "DOS Shell" from the File menu in PWB.

 Since the TMP environment variable is used to specify a single
 directory rather than a path, the semicolon character should not be
 used.

 To re-create this situation, type the following at the command line:

    set TMP=C:\TMP;

 Then select DOS Shell from within PWB. Typing "exit" on the DOS
 command line will not bring you back into PWB.

 To correct the problem, remove the semicolon from the end of the TMP
 environment variable.


 26. PWB BACKUP.BAK Does Not Create Backup of Source File Correctly

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER| buglist1.00
 Last Modified: 24-JUL-1990    ArticleIdent: Q63234

 Version 1.00 of the Programmer's Workbench does not create a backup of
 your source file correctly if the PROJECT.MAK has the same base name
 as the SOURCE.C file. When you build or rebuild the project, the file
 saved as your backup is a copy of the CURRENT.STS file.

 A workaround to this problem is to name your PROJECT.MAK with a
 different base name than your SOURCE.C file. This will still save a
 copy of your CURRENT.STS file with the base name of the PROJECT.MAK.
 However, it will correctly save a backup of the SOURCE.C as
 SOURCE.BAK.

 Microsoft has confirmed this to be a problem in version 1.00 of the
 Programmer's Workbench and will post new information here as it
 becomes available.



 27. PWB menukey Switch Resets to ALT When Shelling Out to DOS

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00
 Last Modified: 10-JUL-1990    ArticleIdent: Q63267

 If the "menukey" switch in the DOS version of the Programmer's
 Workbench (PWB) version 1.00 is set to anything other than ALT (which
 is the default), it will be redefined to the ALT key after shelling
 out to DOS. This means the menukey switch will lose its assignment
 anytime you choose Compile, Run Program, Debug Program, or DOS Shell.

 The menukey switch determines which keystroke activates the PWB main
 menu bar. The ALT key is normally used for this, but menukey can be
 redefined to any keystroke. For example, menukey is automatically
 defined to F9 if you select Brief Editor emulation when installing the
 Programmer's WorkBench.

 Whenever you invoke any function (such as Build) that goes out to DOS
 for execution and then returns, the menukey switch is reset to ALT, so
 that both ALT AND the user-defined keystroke invoke the menu.

 To work around this problem, you can use the Restart command to invoke
 a macro that redefines the menukey to the desired value each time you
 return from a DOS SHELL command, which will then keep ALT from
 activating the menu. For example, to make it so that F9 is always
 reset as the only menukey, put the following line in the PWB tagged
 section of the TOOLS.INI file:

    restart:= arg "menukey:F9" assign

 Since the Restart command, if it exists in TOOLS.INI, is invoked
 automatically when returning from a SHELL command, this guarantees
 that the key assignment will always remain consistent.

 Microsoft has confirmed that the automatic reactivation of ALT as the
 menukey is a problem with the Programmer's WorkBench version 1.00. We
 are researching this problem and will post new information here as it
 becomes available.


 28. PWB: Print Does Not Put CR/LF at EOL If Text Selected

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 25-JUL-1990    ArticleIdent: Q63318

 Using the Programmer's Workbench version 1.00, when a region of text
 is selected and the Print function is invoked, the resulting output
 contains linefeed characters (0x0A) at the end of each line, rather
 than a carriage return/linefeed (<CR><LF>) combination (0x0D and
 0x0A).

 Some printer drivers do not recognize this as a valid end-of-line
 (EOL) character and do not print correctly.

 To reproduce this problem, open a file that contains the <CR><LF>
 combination at the end of each line. Highlight a region of text in the
 file and from the File menu choose Print. Tab to the second field and
 type in the following:

    copy %s test.txt

 This will copy the region of selected to the file TEST.TXT. Using a
 standard hex file viewer, you can see that the end of a line is
 denoted by a single 0A. If you look at the original file using the hex
 viewer, it will contain 0A 0D at the end of each line.

 The Programmer's Workbench will recognize this type of file (with a
 single 0A at each end of line) and display it correctly if you try to
 open it within the Workbench, but many printer drivers do not
 understand this type of file.
 The workaround for this problem is to write a program that translates
 each 0x0A found in the output file to the bytes 0x0D and 0x0A, or use
 a printer driver that understands this type of file. In fact, most
 printers have an escape sequence or dip switch to make it recognize
 this type of file.

 Microsoft has confirmed this to be a problem with the Programmer's
 Workbench version 1.00. We are researching this problem and will
 post new information here as it becomes available.


 29. Unknown Function psrch with Brief Emulation in PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 25-JUL-1990    ArticleIdent: Q63319

 When using the Brief emulation feature of the Programmer's WorkBench
 version 1.00, reinitialization of the TOOLS.INI file will cause a
 number of unknown functions to appear when you try to use them. In
 short, most of the unknown functions that may be reported are related
 to search features such as the psearch switch. The error message
 associated with this search feature is commonly "Unknown function
 psrch."

 This error occurs only after you use the Initialize function.

 The Initialize function discards current macro definitions and rereads
 the appropriate section of TOOLS.INI. This is not exactly the same as
 restarting PWB; the Autostart macro is not executed after Initialize.
 The BRIEF emulation depends on the Autostart macro to define the
 search functions.

 To recover the definition of the missing macros, execute the toggle_re
 BRIEF emulation macro (CTRL+F6). To avoid having to remember to
 execute this macro, you can add this to the main section of TOOLS.INI:

    reinit:=Initialize Autostart
    reinit:Shift+F8

 Or you can define the macros as follows:

    psrch:=arg arg "String to Search for" prompt ->can
                                            psearch => :>can cancel
    msrch:=arg arg "String to Search for" prompt ->can
                                            msearch => :>can cancel
    qrepl:=arg arg qreplace
    srchname:="REoff"


 30. Problems Viewing README.DOC Inside PWB Online Help and QH

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER  |
 Last Modified: 15-AUG-1990    ArticleIdent: Q63661

 Problems can occur when attempting to access the README.DOC from
 within the DOS versions of Programmer's WorkBench (PWB) or QH via the
 online help.

 When attempting to view the README.DOC file using the online help
 inside the DOS version of PWB, the messages "Error displaying help"
 and then "Cannot process cross reference" may be displayed in
 successive dialog boxes.

 When attempting to view the README.DOC file from within QH, the
 message "The database README.DOC is not open, or the topic is not
 found" may be displayed.

 Again, these problems are found only in the DOS version of PWB and QH.
 Access of the README.DOC in this manner does not produce errors under
 the OS/2 versions of PWB or QH.

 The following are two possible workarounds for the problem in PWB:

 1. The README.DOC can be loaded into the help system by typing the
    following

       arg "$PATH:readme.doc!" arg pwbhelp

    with default keys:

       Alt+A $PATH:readme.doc! F1

    Note that this method may fail if there is another file named
    README.DOC in the path before the C 6.00 README.DOC. If this is the
    case, the other README.DOC will be loaded instead of the C 6.00
    README.DOC. This method can also fail if there is not enough memory
    to load the file into the help system.

 2. If the previous method fails, the C 6.00 README.DOC can be loaded
    into PWB as a normal text file via the File.Open menu option. The
    README.DOC can be found in the C 6.00 bound executable directory
    (for example, C:\C600\BINB).

 The following are three possible workarounds for the problem in QH:

 1. Inside QH, select View.Search, type "$PATH:readme.doc!" and press
    ENTER. Again, this will bring up the first README.DOC on the path.

 2. You can also select File.Open and load the the file by giving the
    full path and filename of the C 6.00 README.DOC. QH allows you to
    open any text file under 64K in size.

 3. To enable direct access of the README.DOC from within QH via the
    README.DOC button, it is necessary to point the QH environment
    variable to the directory where the README.DOC is located. For
    example:

       set qh=c:\c600\binb\readme.doc

    The QH environment variable is not documented in the C 6.00 printed
    or online documentation.

 Microsoft is researching this problem and will post new information
 here as it becomes available.


 31. CTRL+NUM/ May be Read as CTRL+/ in DOS with NUM LOCK On

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.10
 Last Modified: 15-NOV-1990    ArticleIdent: Q66740

 In versions 1.00 and 1.10 of Programmer's WorkBench (PWB), the
 CTRL+NUM/ (CTRL+/ on the numeric keypad) and ALT+NUM/ (ALT+/ on the
 numeric keypad) combinations may be interpreted as CTRL+/ and ALT+/
 (on the main keyboard). This problem happens only in DOS or the OS/2
 DOS 3.x box, and only on certain computers. This behavior will cause
 any macro or function assigned to CTRL+NUM/ or ALT+NUM/ to not execute
 when NUM LOCK is on.

 To reproduce this problem, assign a function or macro to CTRL+NUM/.
 Then execute the TELL function (CTRL+T by default) and press CTRL+NUM/.
 The TELL function prompts for a keystroke, then displays the name of
 the keystroke and the function assigned to it. With NUM LOCK on, TELL
 will return the following:

    unassigned:Ctrl+/.

 With NUM LOCK off, TELL will return the following:

    <function name>:Ctrl+num/.

 This behavior is identical for the ALT+NUM/ key name, but works
 properly for all other key names on the numeric keypad.

 If NUM LOCK is off, or if the protected-mode version of PWB is run,
 this behavior does not occur.

 This behavior has been observed on the following machines:

    Northgate 386-33
    PS/2 Model 70
    PS/2 Model 80-311

 Microsoft has confirmed this to be a problem in PWB version 1.00 and
 1.10. We are researching this problem and will post new information
 here as it becomes available.


 32. PWB Command-Line Option /DP Is Documented But Not Implemented

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 27-JUL-1990    ArticleIdent: Q63951

 The /DP switch for the Programmer's WorkBench (PWB), documented on
 Page 49 of the version 6.00 "Microsoft C Reference," is not
 implemented in version 1.00 of the PWB. This switch is designed to
 ignore the most recent program list upon starting the PWB.

 The /DP switch is mentioned only in the "Microsoft C Reference" and
 not in the online help.

 Upon invocation, the Programmer's WorkBench version 1.00 does not
 automatically set the program list to the last program list used.
 Therefore, the /DP command-line switch was not implemented because it
 would have no purpose.

 With the PWB version 1.00, there is no way to have the last program
 list set automatically at startup.


 33. With the "deflang" Switch PWB Prompts for Setting Program List

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  3-AUG-1990    ArticleIdent: Q64353

 As documented on Page 79 of the "Microsoft C Reference" shipped with C
 version 6.00 and in the online help, the "deflang" switch in the
 Programmer's WorkBench (PWB) sets the default filename extension for
 list boxes in PWB dialog boxes. Another (undocumented) feature of this
 switch is to enable you to be prompted to "Set Program List?" when
 loading a source file with a .MAK file associated with it in the
 current directory.

 By default, "deflang" is not set. You can set the deflang switch in
 the [PWB] tagged section of the TOOLS.INI file, for example:

    deflang:C

 This changes the default filename extension in the PWB's dialog boxes
 (such as Open in the File menu) from "*.*" to "*.c", so that only
 files with the .c extension show up by default. Other languages can be
 specified as well, as shown below:

    Switch Setting     Extension
    --------------     ---------

    no value            .*
    C                   .c
    Asm                 .asm
    BASIC               .bas
    FORTRAN             .for
    Pascal              .pas
    COBOL               .cbl
    LISP                .lsp

 Note that the online documentation specifies "Assembler" as the switch
 to use for .ASM files, but this is incorrect. "Asm" is the correct
 switch to use to make Assembler the default language.

 The deflang switch also enables you to be prompted as to whether or
 not the program list should be set automatically. If you load a file
 that has the extension specified by the "deflang" switch and you also
 have a .MAK file with the same base filename in the same directory,
 the PWB will prompt you about loading the program list.

 For example, assume that deflang is set to C and FOO.MAK and FOO.C are
 in the same directory. If you type PWB FOO.C at the command-prompt,
 the PWB will pause when loading and prompt with "Set Program List?
 FOO.MAK". At this point you can specify <yes> or <no>.

 When already in the PWB, if you select Open from the File menu, and
 select FOO.C as the file to open, the PWB will also prompt you at this
 point regarding whether or not you want FOO.MAK loaded as the program
 list, but only if NO program list is currently set.


 34. Can't Resize a Window with a Macro in PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 30-AUG-1990    ArticleIdent: Q64433

 A window cannot be resized using the "resize" function in a macro.
 After Programmer's WorkBench (PWB) performs the resize function, it
 waits for the you to respond with the UP ARROW or DOWN ARROW key.
 Functions that are placed in the macro after the resize function are
 ignored. If "record on" is selected and you try to record the resizing
 of a window, the macro will stop recording until the ENTER key on the
 numeric keypad is pressed.

 The following is an example:

    resizeit:= cancel arg arg nextmsg window resize up up up NumEnter

 The above example stops at the resize function and waits for you to
 resize the window. The remaining functions are ignored.

 To make a window a specified size, move the cursor to a location on
 the screen and then open the window with the "window" function.

 The following is an example of a macro that opens the "<compile>"
 window with a specified size:

 compile_size:= up up up up up up up up up up
 resize_it:=cancel meta down compile_size arg window window arg \
            "<compile>" setfile window
 resize_it:ALT+U

 Note: The size of the compile window can be adjusted by changing the
 number of ups on the compile_size line.


 35. PWB Hangs When Run with Some Communication Programs Under OS/2

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 30-AUG-1990    ArticleIdent: Q64435

 When running Programmer's WorkBench (PWB) under OS/2 while
 simultaneously running communication programs, PWB will appear to
 hang. To correct the problem, terminate any communication programs and
 PWB will resume as normal.


 36. "Cannot Open File current.$" May Mean Incorrect INIT Variable

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 17-DEC-1990    ArticleIdent: Q64566

 When using the Programmer's Workbench (PWB), the following message may
 appear as a pop-up dialog box when selecting Compile or DOS Shell (or
 OS/2 Shell for OS/2):

    +----- Cannot open file! -----+
    |   D:\TEST\SRC\X\current.$   |
    |  No such file or directory  |
    |-----------------------------|
    |      < OK >   < Help >      |
    +-----------------------------+

 One cause for this error is an incorrect setting of the INIT
 environment variable. To remedy the situation, exit PWB and make sure
 that the INIT environment variable is set to a valid directory name
 (for example, a directory that exists).

 To reproduce this message, set your INIT environment variable to an
 invalid directory, for instance (if a directory named X does not exist
 on your drive):

    SET INIT=X

 Then start PWB and try to compile a program. The message will appear
 in the middle of the screen.

 One possible reason why your INIT environment variable may be set
 incorrectly, even if your AUTOEXEC.BAT sets it correctly, is that you
 might have run out of environment space in the setting of the
 variable. You can refer to the "MS-DOS Encyclopedia," Article 2, for
 more information about increasing your environment space.


 37. How to Use the PWB with the Windows 3.00 SDK

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-AUG-1990    ArticleIdent: Q64788

 Detailed step-by-step instructions on how to set up the Programmer's
 WorkBench (PWB) for use with the Windows version 3.00 Software
 Development Kit (SDK) can be found in a file provided with the SDK
 called PWBINFO.WRI.

 The file explains how to set PWB switches so that Windows applications
 can be built from within PWB. The file also explains how to access the
 SDK's online help.

 This file can be viewed and printed with the WRITE program, which is
 packaged with the Windows 3.00 package.


 38. Tips for Using the Microsoft Advisor Online Help

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_quickc s_c s_qh
 Last Modified: 23-JAN-1991    ArticleIdent: Q64829

 The following are some tips for more effectively using the online
 documentation included with the Microsoft C Compiler version 6.00
 Programmer's Workbench (PWB) as well as the Microsoft Advisor
 command-line help system:

 1. Finding help on a topic for which the exact name is not known.

    If the exact spelling of a topic is not known, the help for that
    topic can't be accessed directly (for instance, by using the F1 key
    in PWB), but it can usually be found indirectly.

    By using the table of contents and selecting links that pertain to
    the subject in question, the topic can usually be found. To get to
    the table of contents from within QuickHelp, select the Categories
    menu, then "C 6.00".  From within PWB, choose the Help menu, then
    select Contents.

    If you know the general spelling of the topic, an alphabetical
    index is available by choosing Index from the main contents screen.

 2. "Paging" through the online documentation.

    The online documentation can be "paged through" like you would page
    through a manual.

    In PWB, CTRL+F1 takes you from one topic to the next sequential
    topic in the help file. In QuickHelp, Choose Next or Back from the
    View menu to move in either direction.

 3. Scanning a list of available topics (as in a printed index).

    There are alphabetical indices for every major component of the
    product. Just choose Index from the main contents screen and select
    the appropriate topic.

 4. Techniques for using the online help.

    For more information on how to use the help system, as well as on
    the general organization and structure of the help system, choose
    Using Help from the main contents screen.

    For additional help, see Chapter 4, "Using the On-Line Reference,"
    of the "Microsoft C Installing and Using the Professional
    Development System" manual that comes with C version 6.00.

 5. Printing out the online help files.

    By using the HELPMAKE utility, the help files can be decoded to
    readable text files, which can then be printed. For more
    information about the HELPMAKE utility, see Chapter 7 of the
    "Microsoft C Advanced Programming Techniques" manual that comes
    with C version 6.00.


 39. Predefined Identifiers in Microsoft C 6.00

 Product Version(s): 6.00   | 6.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_quickhelp s_c s_utils
 Last Modified: 24-OCT-1990    ArticleIdent: Q65472

 The following information is contained in the online help for the
 Microsoft C Compiler version 6.00.

 This information below can be accessed by using the following steps:

 1. Obtain help on the text "cl" using either the F1 key from the
    Programmer's WorkBench, or by using "qh cl" from the DOS or OS/2
    command lines.

 2. Select Preprocessor Options, then Predefined Identifiers.
 The compiler automatically defines identifiers useful in writing
 portable programs. You can use these identifiers to compile code
 sections conditionally. These identifiers are always defined unless
 otherwise stated.

    Identifier       Target Identified
    ----------       -----------------

    MSDOS            MS-DOS operating system
    M_I86            Member of the I86 processor family
    M_I86mM          Memory model type
                     <m> = T    Tiny
                           S    Small (default)
                           C    Compact model
                           M    Medium model
                           L    Large model
                           H    Huge model
    M_I8086          8088 or 8086 processor; default or with /G0
                        option
    M_I286           80286 processor; defined with /G1 or /G2 option
    _MSC_VER         Identifies the version of Microsoft C
    NO_EXT_KEYS      Disables Microsoft-specific language extensions
                        and extended keywords; defined only with /Za
                        option
    _CHAR_UNSIGNED   Changes default char type to unsigned; defined
                        only with /J option

 The _MSC_VER identifier has a value of 600 for the Microsoft C Compiler
 version 6.00. This identifier is not defined in Microsoft C versions
 5.10 and earlier.


 40. How to Add Other Language Compilers to PWB's Build Options

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_pascal b_basiccom s_c h_masm h_fortran b_cobol
 Last Modified: 24-OCT-1990    ArticleIdent: Q65568

 The Programmer's WorkBench (PWB) is an environment capable of
 utilizing different compilers for mixed-language programming. When
 installed during BASIC version 7.10 setup, PWB version 1.10 shows
 build options for the BASIC language only. However, it is possible to
 include other language compilers to utilize the full features of the
 PWB utility.

 The following information applies to the Programmer's WorkBench
 version 1.10 utility supplied with Microsoft BASIC Professional
 Development System (PDS) version 7.10 for MS-DOS and MS OS/2.

 Note that the 1.00 version of PWB is shipped with Microsoft C
 Professional Development System (PDS) version 6.00. The steps below
 should also apply to PWB version 1.00.

 The Programmer's WorkBench (PWB.EXE) is an advanced development
 environment capable of integrating several language compilers,
 NMAKE.EXE, LINK.EXE, and the CodeView debugger. It offers the ability
 to accomplish tasks, such as program development under protected mode
 and mixed-language programming. This ability is not available in the
 QuickBASIC extended development environment (QBX.EXE).

 Two special files, PWBC.PX$ (for protected mode OS/2) and PWBC.MX$
 (for DOS mode), reside on the BASIC PDS 7.10 disks and support the
 option of using the C compiler in PWB. Since SETUP.EXE (in BASIC PDS
 7.10) does not copy PWBC.PX$ and PWBC.MX$ during installation, these
 files must be unpacked and transferred to your machine, for example to
 the \BINP subdirectory located in the \BC7 directory. (Note: The
 UNPACK.EXE utility is found on disk 1 of the BASIC PDS package.) After
 unpacking, the files will have the names PWBC.PXT and PWBC.MXT.

 Next, the following command lines must be added to the TOOLS.INI file
 to make the C compiler available to PWB:

    [pwb - .BAS .BI]
       LOAD: LogicalDrive:\[Path]\PWBC.PXT

 For further information about installing PWBC.PXT and PWBC.MXT, see
 Page 54 of the "Microsoft BASIC 7.1: Getting Started" manual.

 If you want to program in languages other than BASIC or C [such as
 Microsoft Macro Assembler (MASM), Microsoft Pascal, Microsoft FORTRAN,
 or Microsoft COBOL 3.00/3.00a], the following steps will insert the
 initial build options to include other languages to PWB's build
 options menu. In the example below, options to include the MASM.EXE
 assembler are specified. If some other language's compiler is desired,
 substitute appropriate changes for that compiler, where noted in the
 specified areas:

  1. In PWB, go to the Options menu and select Build Options.

  2. Choose Save Current Build Options.

  3. Enter a meaningful message, such as "Options to Include MASM" in
     the window's edit field (if some other language is desired, change
     MASM to the appropriate name). Select the OK button from the "Save
     Current Build Options" and "Build Options" windows.

  4. Open the "TOOLS.INI" file in the PWB utility and go down to the
     bottom of the file. Somewhere near the bottom should be the tag
     "[PWB-Build Options: Options to Include MASM]" (or the language
     that was specified).

  5. In this section, add the following NMAKE instructions:

        build: inference .asm.obj masm_asm_obj
        build: command masm_asm_obj "masm $<;"

     Note: For languages other than MASM, distinguish a variable name
     in the inference rule to be used in the commands line (such as
     masm_asm_obj has been used above) and then specify the appropriate
     compiler in the commands line within the quotation marks. The
     special filename macro specified in the quotation marks, "$<",
     applies the command to any object that has an out-of-date
     executable file.

  6. Press SHIFT+F8 to reinitialize the file and then close it.

  7. Go to the File menu and select New (it is a good idea to close any
     files that are currently open before this step).

  8. Go to the Options menu and select Build Options.

  9. Choose Initial Build Options.

 10. Select the "Options to Include MASM" option (it should be near the
     bottom of the list).

 After completing these instructions, the PWB utility will now be ready
 to compile assembler along with BASIC source code, provided that paths
 to the necessary compilers are furnished.


 41. PWB Err Msg: Out of Local Memory. Unable to Recover.

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-OCT-1990    ArticleIdent: Q65913

 When setting a program list inside of the Programmer's WorkBench
 (PWB), the following message may occur:

    Out of Local Memory.  Unable to Recover.

 The error is printed on the screen and the PWB exits to DOS. This
 error may occur when the program list contains too many names. To
 resolve the problem, combine object modules into libraries whenever
 possible. Remove the .OBJ files from the program list and replace them
 with the new libraries. This will reduce the number of object modules
 that need to be defined in the program list.

 Another method that sometimes helps to alleviate the error is to open
 the File menu and close as many unneeded files as possible. This
 should be done before setting the program list.


 42. Situation Where PWB Online Help Text Disappears

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# S901010-118 B_BasicCom S_C B_cobol
 Last Modified: 24-OCT-1990    ArticleIdent: Q66229

 When requesting help in Microsoft Programmer's WorkBench (PWB)
 versions 1.00 and 1.10, the following sequence of events will cause
 the Help screen text to disappear, leaving only the hyperlinks.

 This information applies to Programmer's WorkBench version 1.00 (which
 comes with Microsoft C Professional Development System version 6.00
 for MS-DOS and MS OS/2), and to Programmer's WorkBench version 1.10
 (which comes with Microsoft COBOL Professional Development System
 version 4.00 and with Microsoft BASIC Professional Development System
 (PDS) version 7.10 for MS-DOS and MS OS/2).

 Microsoft has confirmed this to be a problem in PWB. We are
 researching this problem and will post new information here as it
 becomes available.
 Follow these steps to reproduce the problem:

 1. From the DOS or OS/2 prompt, enter PWB. From the File menu, select
    New. Type PLINES and request help by pressing F1 or single-clicking
    the right mouse button.

 2. In the Help dialog, double-click the left mouse button with the
    cursor on the hyperlink "Using PWB Functions."

 3. Double-click the left mouse button with the cursor on the hyperlink
    "PWB Functions by Category."

 4. Double-click the left mouse button with the cursor on the hyperlink
    "Moving Through Files."

 5. The vertical scroll bar will show that you are at the bottom of the
    dialog. Press PGUP and you will notice that the hyperlinks to Up,
    Index, Contents, and Back have disappeared. Double-click the left
    mouse button with the cursor on any of these empty hyperlinks; the
    text on the screen will disappear, with empty hyperlinks appearing
    on the screen.


 43. How to Insert Spaces Before a Block of Text in PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_EDITOR
 Last Modified: 24-OCT-1990    ArticleIdent: Q66231

 It is sometimes desirable to indent or move over a block of text in
 the Programmer's WorkBench (PWB) or the M Editor. The following steps
 can be used to insert spaces before a block of text to indent it:

 1. Get into boxarg mode. You can select this mode from the Edit menu
    under the Programmer's Workbench, or select the boxstream function
    under the Microsoft Editor.

 2. Highlight the area you want to contain the spaces. This may be
    anywhere in the file.

 3. Select the linsert function. By default, this is CTRL+N.

 The highlighted area should now be moved over and replaced by spaces.

 You don't have to be in boxarg mode for this to work; linsert always
 treats its argument as a boxarg regardless of the current mode.
 However, the highlight on the screen won't match the area that is
 going to be inserted unless you use boxarg mode.

 Also, ldelete can be used to unindent a block of text. However, you
 must be in boxarg or streamarg mode for it to work correctly. In
 linearg mode, it will delete entire lines.


 44. PWB's Use of Expanded Memory

 Product Version(s): 1.00 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-OCT-1990    ArticleIdent: Q66308

 The DOS version of the Programmer's WorkBench (PWB) will utilize
 expanded memory to swap its own segment overlays if it detects that
 expanded memory is available in the system. When PWB needs a new
 overlay, the existing overlay in memory is first copied into expanded
 memory. If there is not enough room in expanded memory to copy the
 overlay, the least recently used overlay is discarded to make room for
 it. This scheme allows most overlays to be read from expanded memory
 instead of from disk.

 Note that this is the only method by which PWB will take advantage of
 available expanded memory, and that PWB versions 1.00 and 1.10 have no
 internal provisions to make use of extended memory in any way.


 45. PWB May Exit to DOS If TMP Not Set Correctly

 Product Version(s): 1.00 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00 buglist1.10
 Last Modified: 24-OCT-1990    ArticleIdent: Q66309

 If the tmp environment variable is set only to a drive (with no path
 specified), the PWB may "crash" out to DOS when a compile is
 attempted. The screen will still show the PWB, but there will be a
 prompt displayed.

 This problem may be reproduced using the following procedure:

 1. Set up the environment to run the PWB.

 2. Set the tmp environment variable to the current drive, without
    specifying a path. For example:

       SET TMP=C:

 3. Execute the PWB and create or load a simple source file.

 4. Attempt to compile the source file. (Note: If the COMPILE option is
    not available on the make menu, make sure the file has a name with a
    .c extension.)

 Microsoft has confirmed this to be a problem with the Programmer's
 WorkBench versions 1.00 and 1.10. We are researching this problem and
 will post new information here as it becomes available.


 46. MASM Build Switches for PWB 1.10

 Product Version(s): 1.10    | 1.10
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified:  5-DEC-1990    ArticleIdent: Q66339

 When setting a program list containing .ASM files in Programmer's
 WorkBench (PWB) version 1.10, the following error message occurs:

    Program List: file 'filename' will be ignored
    File type unused by current build options

 The .ASM files are not recognized because PWB 1.10 does not contain
 build switches specific to any language. Build switches are now loaded
 from language extension files (.MXT for DOS and .PXT for OS/2). If you
 have an assembly language extension file, you will not see this error
 message. Language extensions are not necessary and are only a
 convenience for controlling the build process; only the build switches
 are really needed.

 The following build switches can be added to a tagged section in your
 TOOLS.INI file. To use these build options, first choose your language
 options from the Options Build Options menu, then initialize this
 section by typing {arg} tag_name {reinitialize} (type the following to
 invoke the sample build switch below:

    ALT+A asm_rules SHIFT+F8

 These switches can also be added to a custom set of build options
 saved by Save Current Build Options. They may then be initialized by
 choosing Build Options from the Options menu, and then selecting Set
 Initial Build Options to choose the new custom language options.

 Sample Build Switches
 ---------------------

 [pwb-asm_rules]
 ;
 ;   MASM build rules
 ;
 build:macro ASM "MASM"
 build:macro AFLAGS_G "/Mx /T"
 build:macro AFLAGS_D "/Zi"
 build:macro AFLAGS_R ""
 build:inference .asm.obj as_asm_obj
 build:release command as_asm_obj  \
             "$(ASM) $(AFLAGS_G) $(AFLAGS_R) $<, $@;"
 build:debug command as_asm_obj  \
             "$(ASM) $(AFLAGS_G) $(AFLAGS_D) $<, $@;"
 build:include .asm "^[ \t]*include[ \t]+\\([^ \t]+\\)"
 build:include .inc "^[ \t]*include[ \t]+\\([^ \t]+\\)"

 These assembly flags can then be modified from PWB by using the
 following macros. The macros must be assigned to keystrokes to be
 activated. This can be done using the <ASSIGN> pseudo file. They can
 then be used to redefine the flags to pass to MASM.

 ;
 ;   MASM option-setting macros
 ;
 setAFG:= arg "Global MASM Options?"  prompt -> cancel lasttext home \
         "build:macro AFLAGS_G \"" endline "\"" assign

 setAFD:= arg "Debug MASM Options?"   prompt -> cancel lasttext home \
         "build:macro AFLAGS_D \"" endline "\"" assign

 setAFR:= arg "Release MASM Options?" prompt -> cancel lasttext home \
         "build:macro AFLAGS_R \"" endline "\"" assign


 47. Unexpected Behavior with the /Gt Switch and the PWB

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_C
 Last Modified: 15-JAN-1991    ArticleIdent: Q66828

 Adding the /Gt compiler switch with an argument to the Additional
 Options section of the C Compiler Options on the Programmer's
 WorkBench (PWB) Options menu can cause the value of the argument to be
 changed or dropped.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench version 1.00. We are researching this problem and will post
 new information here as it becomes available.

 When you add the /Gt switch with an argument (for example, /Gt30) and
 click OK, then immediately go back into the Compiler Options dialog
 box; you will see that the /Gt30 switch you just set is now /Gt3.

 If you set a /Gt switch and specify a value, it will compile with that
 correct value because it was written to the file on disk that is used
 to build the program.

 If you go back in and look at the compiler options and see that the
 value is incorrect and Cancel the options dialog, you will still
 compile with your initial correct /Gt value.

 You will compile with the incorrect /Gt value only if you make another
 change in that dialog and select OK. This is because you changed the
 options, so PWB rewrites the options to the file on disk. In the case
 of /Gt, that option is written incorrectly and from that point on, you
 will compile with the incorrect /Gt value.

 Not all values of /Gt are incorrect. The most common incorrect values
 end in zero. The following are examples where the problem occurs:

    /Gt40 will turn into /Gt4
    /Gt0  will turn into /Gt
    /Gt20 will turn into /Gt

 Some other values that get changed are the following:

    /Gt113 will turn into /Gt3
    /Gt305 will turn into /Gt35
    /Gt14  will turn into /Gt4
    /Gt22  will turn into /Gt

 As a possible work around, do not set /Gt in the PWB, and set the
 environment variable CL to the desired threshold, as in the following
 example:

    set cl=/Gt40

 This value will be read by the compiler when it is called from the
 PWB.

 Also, you can set the /Gt switch on the Additional Options line in
 either Set Debug Options or Set Release Options, rather than the
 global Additional Options.


 48. REsearch() Function Prototype Not Found in EXT.H Header File

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.00 buglist1.10
 Last Modified:  4-DEC-1990    ArticleIdent: Q67274

 The Programmer's WorkBench (PWB) function REsearch(), although
 included in EXTSUP.LIB, is not prototyped in the EXT.H header file. To
 call REsearch(), use the following prototype:

 int REsearch( PFILE pFile, flagType fForward, flagType fAll,
               flagType fCase, flagType fWrap, char _far *pattern,
               fl *pflStart );

 For more information, see online help.

 Microsoft has confirmed this to be a problem in PWB versions 1.00 and
 1.10. We are researching this problem and will post new information
 here as it becomes available.


 49. PWB Help Crashes When Using "Moving Through a File"

 Product Version(s): 1.10   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.10
 Last Modified: 14-DEC-1990    ArticleIdent: Q67361

 When using the online help through the Programmer's WorkBench (PWB),
 the help system will crash if you do the following:

 1. After entering help, choose Contents.

 2. Select the Microsoft Advisor from the list of contents.

 3. Select the Programmer's WorkBench button followed by the "Moving
    Through a File" selection.

 At this point a header will appear on the screen and the elevator for
 the window will appear as though it is at the bottom of a page.

 The page can be scrolled up and the contents viewed, especially if
 highlighted, but the menu items at the top will be blacked out
 (although they are present). From this point, no further help can be
 accessed.

 If you exit help and then reenter, nothing will come up.
 Re-initializing does not reinstate the help system. Only shelling out,
 exiting, and reentering will allow you to access the help system.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench version 1.10. We are researching this problem and will post
 new information here as it becomes available.


 50. PWB Hangs with Novell NetWare

 Product Version(s): 1.00 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | s_quickc s_codeview s_c
 Last Modified: 14-DEC-1990    ArticleIdent: Q67483

 On certain installations of a Novell network, the network will cause
 the Programmer's WorkBench (PWB) to hang. This problem may also occur
 in CodeView or QuickC. The hang usually occurs when an attempt is made
 to use the mouse.

 If you have a peripheral (such as a mouse) that uses Interrupt Request
 Level (IRQ) 3, and your system is part of a network using Novell
 NetWare version 2.15 or earlier, your system may hang when you load
 QuickC, PWB, or CodeView. As a temporary solution, set your peripheral
 to use another interrupt. For more information, contact your Novell
 NetWare dealer.

 If taking these steps does not solve the problem, please contact
 Microsoft Product Support Services.


 51. PWB Menu Hyperlink in PWB.HLP is Inconsistent in Version 1.10

 Product Version(s): 1.10   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 23-JAN-1991    ArticleIdent: Q67614

 When selecting help on the Programmer's WorkBench (PWB) version 1.10
 from the Categories menu in QuickHelp version 1.70, the help screen
 for Microsoft Advisor Help System is presented instead. This behavior
 may be duplicated by following the procedure outlined below:

 1. Start QuickHelp without an argument to get help on any topic. This
    will bring up the main help screen.

 2. Select the Programmer's WorkBench choice under the Categories menu.

 Instead of bringing up the help screen for Programmer's WorkBench, you
 will see the screen for the Microsoft Advisor Help System.

 If the PWB.HLP help file is decoded using helpmake as follows

    helpmake /D /T /Opwb.doc pwb.hlp

 we can see that the reason for this is that the .context directive for
 Programmer's WorkBench appears in the wrong section in the decoded
 help file. The following line

    .context Programmer's Workbench

 appears above the section for "Microsoft Advisor Contents." To correct
 the problem, move the .context directive for Programmer's WorkBench to
 the proper section, which is the "Programmer's WorkBench Contents."

 The helpfile must then be recompressed, as follows:

    helpmake /E7 /T /Opwb.hlp pwb.doc

 The choice of /E7 is shown here for demonstration purposes only, and
 is strictly arbitrary in this case. If maximum compression is desired,
 the numerical argument to the /E switch may be left off, or /E15 may
 be specified. Maximum compression will restore the database as close
 to its original size and state as possible.


 52. "missing ':' in ->" Caused by Control Character

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 14-DEC-1990    ArticleIdent: Q67736

 When invoking the Programmer's WorkBench (PWB), if there is a control
 character at the end of the TOOLS.INI file, [usually a CTRL+Z (ASCII
 26) end-of-file marker] and you only have a [pwb] tagged section, an
 error message will appear stating "missing ':' in ->". Note that the
 "->" is the graphic right-arrow symbol.

 This is not a problem in the PWB. A control character is a legal macro
 name. The message indicates that a macro definition or key assignment
 is expected after the character. To keep this message from appearing,
 place the tag

    [end]

 before the control character at the end of your TOOLS.INI file. With
 this tag at the end of the file, you always suppress the message, even
 if you edit TOOLS.INI with an editor that inserts CTRL+Z's at the end
 of the file. This is because the -> symbol must be within the [pwb]
 tagged section for this error message to be displayed, and the [end]
 tag forces the -> into its own tagged section.

 Simply deleting the control character will work until you edit the
 file with an editor that replaces the CTRL+Z, then this message
 reappears. This may also when using the COPY command to concatenate
 files.


 53. Inconsistent Error Attempting to Load Nonexistent Extension

 Product Version(s): 1.00 1.10
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 28-DEC-1990    ArticleIdent: Q67777

 When attempting to load a Programmer's WorkBench extension through a
 macro definition in the TOOLS.INI file, if the extension file does not
 exist, or is not in the current path, the following error message is
 displayed in a dialog box:

    pwbhelp:  SYS0123:  A file name or volume label contains an
                        incorrect character

 This error message should indicate that the extension file could not
 be found; however, the message is generated by the OS/2 operating
 system's DLL loading code, and therefore, cannot be changed by PWB.

 The following error message is generated in the DOS version of PWB,
 which displays this message in a dialog box:

    No such file or directory

 To correct the problem, make sure that the directory in which the
 extension resides is in the current path.


 54. PWB May Record Incorrect Paths for Dependencies in Makefile

 Product Version(s): 1.00 1.10  | 1.00 1.10
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | buglist1.00 buglist1.10
 Last Modified:  6-FEB-1991    ArticleIdent: Q67780

 Creating a program list with dependencies in directories other than
 the project (makefile) directory may result in the Programmer's
 WorkBench (PWB) recording the wrong paths to these dependencies.

 The following steps illustrate the problem:

 1. Create subdirectories named TEST and TESTA under the same
    directory, with sample files FOO.C in TEST and GOO.C in TESTA.

 2. Invoke PWB from the TESTA directory.

 3. Create a program list.

 4. Add FOO.C and GOO.C with full path.

 5. Save the list.

 The resulting makefile will contain the line:

    OBJS = goo.c foo.c

 The correct line should read:

    OBJS = goo.c ..\TEST\foo.c

 Changing the location of the project makefile or changing the names of
 the subdirectories will generate the correct paths for dependencies in
 the makefile.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench versions 1.00 and 1.10. We are researching this problem and
 will post new information here as it becomes available.


 55. PWB Extensions in DOS Cannot Shell to DOS

 Product Version(s): 1.00 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q67792

 Extensions written for the Programmer's WorkBench (PWB) that require a
 call to the operating system do not work correctly under DOS. One
 example of this is the FILTER.C sample extension packaged with
 Microsoft C 6.00.

 When PWB.COM is executed under DOS, it spawns the main editor
 (PWBED.EXE). PWBED.EXE is cleared from memory when a DOS shell is
 executed from within the editor. Once the shell has completed,
 PWBED.EXE is reloaded from disk and initialized. The initialization is
 what causes the problem because it also initializes any extensions to
 the editor at the same time. This means that any information that the
 extension was keeping track of is lost.


 56. Not Enough Core Message Caused by Lack of Memory

 Product Version(s): 1.00 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q68070

 When loading the Programmer's WorkBench (PWB), a message box may
 appear on the screen containing the message "Cannot Autoload
 Extension, not enough core." The extension file that could not be
 loaded will be indicated. You need to free more memory so that the
 extensions can be loaded.


 57. Windows DLL Build Options Ignore .RC Files in PWB 1.10

 Product Version(s): 1.10   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.10 S_C P_WINSDK
 Last Modified: 11-JAN-1991    ArticleIdent: Q68155

 In the Programmer's WorkBench version 1.10, the default build options
 for creating a Windows DLL will ignore any .RC files included in the
 Program List, and therefore, will not build them into the project.

 Use the following steps to correct this problem:

  1. If there is a Program List currently set, clear it.

  2. Set the Main Language to C.

  3. Set the Initial Build Options to Windows DLL.

  4. Create a new Program List containing all the files you want in your
     project.

  5. Save the Program List. At this point, PWB will tell you that your
     .RC file will be ignored. Choose OK when that dialog box appears.

  6. Choose Editor Settings from the Options menu.

  7. Find the line that starts:

        build: target $(PROJ).dll

  8. Change the word "res_dll" on that line to "rc_dll".

  9. Move the cursor off that line to highlight the change. Press SHIFT+F2
     to save the new settings.

 10. Press F2 to exit the ASSIGN pseudofile.

 11. Choose Edit Program List from the Make menu.

 12. Choose Save List. The .RC file will now be saved in the Program
     List and used as expected.

 After these steps are taken, the settings will be saved in the .STS
 file for that project, and will remain correct as long as Set Initial
 Build Options is never selected when this Program List is set. In
 order to keep from repeating these steps for future projects, the
 build options should be saved under a descriptive name, such as
 "Corrected Windows DLL Settings." They can then be chosen for any
 future Windows DLLs.

 Microsoft has confirmed this to be a problem in the Programmer's
 WorkBench version 1.10. We are researching this problem and will post
 new information here as it becomes available.


 58. PWB Build Switch Reference Available as an Application Note

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | appnote softlib SW0330
 Last Modified: 29-JAN-1991    ArticleIdent: Q68367

 The "PWB Build Switch Reference" contains detailed descriptions and
 examples for customizing PWB build switches.

 The Programmer's WorkBench (PWB) can build various types of projects
 based on the information contained in "build switches." These build
 switches are interpreted by PWB in order to create a makefile for a
 project. The switches are normally set for you by PWB for common types
 of projects, but you may define your own build switches to handle an
 advanced project where you require more control over the build
 process. For example, customized build switches will allow you to
 utilize different languages, to incorporate other tools into a
 project, or to build new kinds of targets.

 Although build switch customization is documented in the PWB online
 help, the information is somewhat limited. Therefore, an application
 note was created to cover the customization process in detail. The
 title of this application note is "PWB Build Switch Reference" and it
 can be obtained by calling Microsoft Product Support Services at (206)
 637-7096.

 The "PWB Build Switch Reference" can also be found in the Software/
 Data Library (as file SW0330.ARC) by searching on the keyword SW0330,
 the Q number of this article, or S12875. SW0330 was archived using the
 PKware file-compression utility.

 Note that the application note found in the Software/Data Library is
 an ordinary text file, which lacks the typefaces and formatting of the
 printed version that is available by calling Microsoft Product Support
 Services. Because the printed application note is clearer and easier
 to follow, it is highly recommended that you call for the printed
 version, and that you use the downloaded version only as an interim
 copy.

 Also note that you normally DO NOT need to modify build switches just
 to customize the compile and link operations -- this can generally be
 done by selecting commands from the Options menu. By selecting options
 from the Compile or LINK Options dialog boxes, the correct build
 switches are automatically modified to contain the desired
 information.


 59. Brown Screen Color Changes to Yellow After Running PWB

 Product Version(s): 1.00 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER | s_c buglist1.00 buglist1.10 remapping
 Last Modified:  6-FEB-1991    ArticleIdent: Q69064

 After running PWB, the brown screen color changes to yellow until the
 system is rebooted or the video mode is reset.

 For example, if you run PWB and then run the Microsoft editor, the
 brown characters will appear yellow.

 To work around this problem, you can create a batch file called
 PWB.BAT. In this file, you can start PWB and then reset the video
 mode. For example:

     pwb.bat
             pwb %1 %2 %3 %4
             mode co80,25

 Microsoft has confirmed this to be a problem in PWB versions 1.00 and
 1.10. We are researching this problem and will post new information
 here as it becomes available.


 60. Reinitializing After Changing Editor Settings Is Very Slow

 Product Version(s): 1.10   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 11-FEB-1991    ArticleIdent: Q69142

 The current editor settings in the Programmer's WorkBench (PWB) may be
 changed by choosing Editor Settings from the Options menu, making a
 change to the <assign> pseudofile, and then saving that file. If
 SHIFT+F8 (initialize) is pressed while the <assign> pseudofile is
 still displayed, PWB may appear as though it is hung; it is actually
 reinitializing each statement of the editor settings (<assign>)
 pseudofile.

 The following steps will reproduce this behavior:

 1. Enter PWB and select the Options menu.

 2. Choose the Editor Settings menu.

 3. Make a change in the <assign> pseudofile and then save it.

 4. Press the "initialize" keystroke combination (SHIFT+F8) and a popup
    box will appear stating "reinitializing...". The reinitialization
    is actually taking place but it is very slow because PWB is
    rebuilding the <assign> pseudofile for each entry in your TOOLS.INI
    file.

 This behavior does not occur in PWB version 1.00. Version 1.10
 includes a change to the earlier version; you can see a new assignment
 (made via "arg textarg <assign>") immediately updated if you are
 viewing the <assign> pseudofile.

 This is expected behavior because the <assign> pseudofile is meant to
 show the settings that were in effect at the time the file was
 displayed. It is not recommended that it be dynamically updated except
 via the mechanism of actually editing the file. If you changed a
 setting via "arg textarg assign" (ALT+A textarg ALT+=), a better way
 to view your new setting(s) is by using "refresh" (SHIFT+F7), or by
 switching away and back again via "setfile" (F2).


 61. PWB Ignores Certain Compiler Switches in Additional Options

 Product Version(s): 1.00 1.10 | 1.00 1.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_c
 Last Modified: 25-FEB-1991    ArticleIdent: Q69145

 The compiler switches

    /Fo, /Fe, /F hexnum, /Fm, and /link link-info

 are ineffective when entered in the Additional Options field of the C
 Compiler Options dialog box from the Options menu of the Programmer's
 Workbench (PWB). This is the intended behavior. The functionality of
 all of these switches is provided through the Compiler, Link, and
 Build Options dialog boxes from the Options menu.

 The /Fo switch is overridden by PWB as it creates the .MAK file needed
 to build the project. To perform this function correctly:

 1. Set a program list from the Make menu.
 2. Choose Build Options from the Options menu.
 3. Choose the Build Directory button.
 4. Enter the destination path in that field, such as:

       C:\C600\PROJECT\

 5. Rebuild the project, and both the .EXE and .OBJ files will be placed
    in that directory.

 The other switches are used only to pass information to the linker
 when the CL command is used outside PWB without the /c option. Because
 PWB always compiles and links separately, these switches are lost. To
 utilize these switches from within PWB, select the appropriate options
 in the Link Options dialog box from the Options menu.


 62. How to Increase the Size of the PWB Build Status Box Under DOS

 Product Version(s): 1.00 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER | window dialog
 Last Modified: 22-FEB-1991    ArticleIdent: Q69475

 In the DOS version of the Microsoft Programmer's WorkBench (PWB)
 versions 1.00 and 1.10, the status box displayed in the center of the
 screen during a compile can be made larger by increasing the length of
 the command being executed.

 When Build or Rebuild All is selected from the Make menu in PWB, a
 build status box appears on the screen showing the command currently
 being executed. Unfortunately, this box is often too small and the
 current command being displayed gets truncated. One way to increase
 the size of this box is to increase the length of the NMAKE command
 line.

 To increase the length of the NMAKE command line, add the following
 text (without the quotation marks) to the NMAKE Options dialog box,
 which can be selected from the Options menu:

    "                                                /NOLOGO"

 Be sure to include the spaces when you type this line. Then, when you
 select Build or Rebuild All from the Make menu, the build status box
 will be almost as wide as the screen, allowing most of the subsequent
 commands to fit completely into the box.

 If you use the PWB "compile" command, or choose the Compile File
 option from the Make menu, the build status box behaves similarly --
 the longer the command to be executed command, the larger the box will
 be.






 Microsoft CodeView
 =============================================================================


 1. Sequential Mode Not Available in CodeView Version 3.00

 Product Version(s): 3.00 3.01 3.11  | 3.00 3.01 3.11
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q69065

 The CodeView sequential mode (/T option) is not available in CodeView
 version 3.00.

 In CodeView versions 2.30 and earlier, the /T option caused the
 debugger to operate in "sequential mode," which means that only a
 command-line interface was available. You could then type the command
 "=COM1" to redirect the input and output to the COM port, which
 allowed debugging via a remote terminal.

 The /T option and the "=COM1" command are not available in CodeView
 3.00, 3.10, and 3.11 because of the new windowing environment used in
 these versions.

 However, you can still redirect CodeView output to COM1 using the
 Redirected Output command.

 The Redirected Output command causes the CodeView debugger to write
 all subsequent command output to a device, such as another terminal, a
 printer, or a file. The term "output" includes not only the output
 from commands but also the command characters that are echoed as you
 type them.

 The second greater-than symbol (optional) appends the output to an
 existing file. If you redirect output to an existing file without this
 symbol, the existing file will be replaced. For example:

    >>COM1

 In the example above, output is redirected to the device designated as
 COM1 (probably a remote terminal). You might want to enter this
 command, for example, when you are debugging a graphics program and
 want CodeView commands to be displayed on a remote terminal while the
 program display appears on the originating terminal.

    >>OUTFILE.TXT

 In the example above, output is redirected to the file OUTFILE.TXT.
 This command is helpful in keeping a permanent record of a CodeView
 session.


 2. How Interrupts Are Handled in CodeView

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR55548
 Last Modified:  9-AUG-1989    ArticleIdent: Q11817

 Question:

 How does CodeView handle interrupt vectors? Does it mask any
 interrupts when it runs?

 Response:

 CodeView saves and restores about 60 interrupt vectors as a safety
 feature. However, it only redirects the following nine vectors for its
 own use:

    0       Divide By 0
    1       Single Step
    2       NMI
    3       Breakpoint
    9       Keyboard
    21H     DOS functions
    22H     DOS terminate
    23H     ^C
    24H     Critical Error

 The remaining estimated 51 vectors are never altered by CodeView
 unless something else (e.g. the program being debugged) alters them
 after CodeView has started up. In this case, CodeView restores them to
 their original value as it exits.

 When you enter G(o) and let your program run, CodeView relinquishes
 control and lets all interrupts (except the nine listed above) flow
 into your application for processing. However, when you hit a
 breakpoint, the 8259 Programmable Interrupt Controller is masked. This
 prevents interrupts from coming into your application while your
 program is suspended. If you enter G(o) again, CodeView reenables
 interrupts to your application.

 To avoid a bug in the 8086 family, CodeView masks the interrupt
 controller during T(race) commands and some P(rogram step) commands.
 CodeView Versions 2.00 and above solve this restriction by emulating
 the interrupts for your application.

 You normally do not single-step or trace real-time code, so this
 should not be a problem for developers writing interrupt-driven code.
 However, it is something you should be aware of if you are depending
 on interrupts to get to your application. For example, it will not
 work if you enter "T 1000" and expect your program to catch and
 process interrupts during the trace. You will need to set a breakpoint
 at the instruction with which you are concerned, then enter G(o).


 3. Debugging Routines That Are in Libraries

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER | TAR55321
 Last Modified: 21-AUG-1989    ArticleIdent: Q11877

 Question:

 When CodeView attempts to debug a function from a library module, it
 is unable to find the source even when that module was compiled with
 -Zi. It prompts me to "Enter Directory for Program (CR for None)?". I
 enter the directory in which PROGRAM.C resides, but CodeView cannot
 find it. Is there any solution other than not placing modules I wish
 to debug in libraries?

 Response:

 This is a consequence of the way the LIB utility works. When adding an
 object module to a library, LIB records only the source file's base
 name, not its extension. Therefore, "c:\c\source\module1.c" becomes
 "c:\c\source\module1" (no extension). When you are debugging an
 application that calls "module1", CodeView attempts to find
 "c:\c\source\module1". However, it does not accept the filename you
 give because the file is really named "module1.c".

 One way to work around this restriction is to rename your source file
 from "c:\c\source\module1.c" to "c:\c\source\module1" (no extension)
 after you have compiled it and put it into a library. This way, the
 actual name will match the name CodeView is searching for.

 Another solution is to use Library Manager Version 3.07 (which came
 with MASM 5.00) or later; this solves the problem by not stripping the
 file's extension as it is put into a library.


 4. CVP May Generate a Trap B with Large Programs Under OS/2 1.30

 Product Version(s): 2.20 2.30 3.00 3.10 3.11
 Operating System:   OS/2
 Flags: ENDUSER | gp fault protection violation
 Last Modified: 25-FEB-1991    ArticleIdent: Q69348

 Debugging a large application with CodeView under OS/2 version 1.30
 may result in a Trap B system error. Trap B is a "segment not present"
 exception, which results from changes that were made to this version
 of the operating system.

 In version 1.30 of OS/2, the code for DosPTrace() was made swappable,
 while in previous versions it was not. DosPTrace() is part of the OS/2
 API that allows a parent process to control the execution of a child
 process, and to access the child process's memory directly to insert
 breakpoints or change data.

 Because CodeView relies heavily on DosPTrace(), problems arise if this
 code is swapped from memory. The majority of problems occur when
 execution reaches a breakpoint while the DosPTrace() code is not
 present; control should then jump to code that is not currently in
 RAM.

 Because large programs (or heavily loaded systems) tend to result in
 more swapping, this problem appears much more readily when debugging
 large applications.

 The only sure workaround for this problem is to turn off swapping
 while debugging, but it also may help to increase or free up available
 memory. To disable swapping, modify the MEMMAN switch in CONFIG.SYS as
 follows:

    MEMMAN=NOSWAP

 To increase available memory, either install more memory in the
 computer itself or terminate all other unnecessary processes before
 debugging (to remove them from memory).

 This problem is the result of a design change with OS/2 1.30 and is
 not a problem with CodeView. This change is being reconsidered for
 future versions of OS/2. New information will be posted here as it
 becomes available.


 5. Using Two Monitors with CodeView

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER | TAR56465
 Last Modified: 11-SEP-1989    ArticleIdent: Q11966

 Question:

 How do I use CodeView with two monitors? Where is this option
 documented?

 Response:

 Invoke CodeView with the following command:

    CV /2 PROGRAM

 This command tells CodeView to put its display on your secondary
 monitor and lets your program's output go to the default display. This
 option is documented in the "CodeView Options" section of the
 "Microsoft CodeView and Utilities Software Development Tools for the
 MS-DOS Operating System" manual in all products except Microsoft C
 Version 4.00, where it is documented in the README file.

 You must have two monitors and two display adapters to use this
 feature. You must have a monochrome and a non-monochrome monitor;
 because a monochrome monitor's video memory is in a different
 location than a CGA, EGA, or VGA's. This is how CodeView implements
 the /2 option, by writing to both sets of video memory.

 When you use the /2 option, your program's display appears on the
 current default adapter and monitor, while the debugging display
 appears on the secondary adapter and monitor. You can switch which
 monitor is the current default adapter with the MS-DOS MODE command.
 "MODE MONO" causes standard output to go to the MDA, while "MODE CO80"
 causes standard output to go to your CGA, EGA, or VGA.

 For example, if you have both a CGA and an MDA, you might want to set
 the CGA up as the default adapter. You could then debug a graphics
 program with the graphics display appearing on the graphics monitor
 and the debugging display appearing on the monochrome adapter.


 6. /L Must Give Full Pathname to .DLL Unless in Current Directory

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 16-AUG-1989    ArticleIdent: Q47937

 When debugging dynamic link modules with CodeView Protect (CVP), you
 must use the /L switch. Before invoking CVP, make certain that the
 .DLL is in the LIBPATH specified in the CONFIG.SYS file. When invoking
 CVP with the /L switch, if the .DLL is not located in the current
 directory, you must specify the full drive and pathname to the DLL. An
 example is the following:

    CVP /L d:\os2\dll\stdll.dll stmain.exe

 In this example, the full drive and pathname are given for the DLL to
 be debugged. If the full pathname is not given, CodeView will come up.
 However, you will be unable to step into the DLL. CodeView will simply
 step over that call.


 7. CodeView Cannot Trace into Single-Line Functions

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 15-SEP-1989    ArticleIdent: Q47624

 CodeView Versions 2.20 and 2.30 do not trace into a function that is
 contained in a single line of code. For example, if the following
 program is compiled and loaded into CodeView, an attempt to trace into
 the function funct() results in the trace stepping over the function,
 rather than tracing into it.

 Sample Program
 --------------

 /* SIMPLE.C ... a very simplistic sample program                    */

 int funct(void);
 int x;

 void main(void)
 {
   x = funct()
  }

 /* single-line function. It does nothing more than return a value.  */

 int funct(void){return 1;}

 If the above function is modified so that it performs exactly the same
 task but is located on multiple lines, as follows, then CodeView
 handles it correctly:

 int funct(void)
  {
    return 1;
   }



 8. Trace Stops on Line Following a Loop Before Loop Is Done

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | S_C
 Last Modified: 15-SEP-1989    ArticleIdent: Q47625

 In trace mode, CodeView stops on the line following a loop that does
 not have open and close braces ({}), before the loop is done.

 When tracing through a loop without the braces ({}), the trace stops
 on the statement immediately following the loop each time through the
 loop, giving the impression that the statement is being executed
 inside the loop. Actual program execution is correct.

 The following program was compiled with C Version 5.10 with the
 command line

    cl /Zi /Od program.c

 and run using CodeView 2.20, as follows:

     cv program.exe

 The trace stops at the printf each time through the loop even though
 printf is not part of the loop, but does not print anything until the
 end of the program.

 Sample Program
 --------------

 #include <stdio.h>

 void main(void)
 {
     int i;
     int count;

     count = 0;

     for(i=0;i<3;i++)
         if(i)
             count++;

     printf("Count is %d\n",count);
 }


 9. The 37th Call Added to the Calls Menu Corrupts CodeView Screen

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist2.20 fixlist2.30
 Last Modified: 10-NOV-1989    ArticleIdent: Q50496

 The CodeView Calls menu shows the current depth of function calls as
 well as the line number the routine was called from and the parameters
 passed. The current routine is always at the top and the routine from
 which the current routine was called is directly below.

 The routines in the Calls menu are first labeled 0-9, and if you are
 nested more than ten levels deep, CodeView labels the next 26 calls
 A-Z, for a display that can accept 36 levels of subroutine calls. If
 you exceed this limit and then select the Calls menu, the CodeView
 display becomes corrupted.

 If the display is corrupted in this manner, the Redraw ("@") dialog
 command can be used to restore the display to it's original state.

 The Stack Trace dialog command (K) has the same function as the Calls
 menu and correctly handles nesting of more than 36 levels deep.

 Microsoft has confirmed this to be a problem with CodeView Version
 2.20. This problem was corrected in Version 2.30.


 10. Quickwatch Seems to Hang When Expanding Very Large Arrays

 Product Version(s): 3.00 3.10 3.11 | 3.00 3.10 3.11
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | s_quickc
 Last Modified:  6-FEB-1991    ArticleIdent: Q68010

 When expanding an element in a large array (usually greater than 1000
 elements, but system dependent), the quickwatch function appears to
 hang. This apparent problem is caused by the time it takes to re-align
 the data in the window, and is actually normal operation. If you place
 the same array element in the Watch Window, it will expand instantly.


 11. Structures Declared with Near, Far, Pascal, and Fortran

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | S_C S_QuickC buglist2.20 buglist2.30
 Last Modified: 16-AUG-1989    ArticleIdent: Q47694

 CodeView is unable to display elements of structures declared with the
 following keywords:

    near
    far
    pascal
    fortran

 Using ?? to display a structure yields the structure table with only
 one value inside. This value is the first element in the structure.
 Using w? or ? yields the following error message:

    Operand types incorrect for this operation

 Microsoft has confirmed this to be a problem with CodeView Versions
 2.20 and 2.30. We are researching this problem and will post new
 information as it becomes available.

 To work around this problem, recompile without these keywords, or
 obtain the address of the structure element and put a watch on the
 memory location.

 Consider the following large model program:

 struct { int x;
          int y;
          int z;} near a;    /* or far, pascal, fortran */

 void main(void)
 {
   a.x = 1;
 }

 To put a watch on a.x, you could issue the following commands:

 ? &a
 0x0345:0000       <- result is the address of the structure
 ww 0x0345:0x0     <- address of x
 ww 0x0345:0x2     <- address of y (two byte int from x)

 This puts a watch on the first and second elements (x and y) in the
 structure.


 12. Older Vega VGAs Hang CodeView When in VGA Mode

 Product Version(s): 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified: 14-AUG-1989    ArticleIdent: Q27212

 Question:

 Why does my old Vega VGA card cause CodeView to hang when I start it
 in VGA mode? It works properly when I start CodeView when the card is
 in CGA mode.

 Response:

 Some of the older Vega VGAs do not work correctly with CodeView. The
 Vega VGA card uses the same maskable interrupt for detecting graphics
 mode as CodeView.

 We recommend that you contact Vega by calling 1 (800) 248-1850 for
 advice if you experience this problem.


 13. Ambiguous Documentation of Enter ASCII (EA) Command

 Product Version(s): 2.10 2.20 | 2.10 2.20
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 16-AUG-1989    ArticleIdent: Q47764

 In the "Microsoft C 5.1 Optimizing Compiler" manual, the "CodeView and
 Utilities" section does not thoroughly document the EA command for
 CodeView. The following is a more complete explanation:

    EA address [list]

    The Enter ASCII (EA) command modifies array to the value of [list].
    Address refers to what you want to modify. [list] refers to a
    string literal such as "hello". EA will copy [list] to array. Thus,
    if you specify address by giving an array, such as an array of
    characters, the array will have [list] copied into it. However, if
    you were to give a pointer to a character, then the bytes that make
    up the pointer will be directly modified, not the block of memory
    the pointer is pointing at.

 Consider the following examples:

 char array[] = "Hello";
 char *ptr    = "Hello";

 >EA array "Hi"
 >EA ptr   "Hi"

 The result is that the array would contain "Hillo", and ptr will be
 pointing to some unknown memory location.

 The array is considered a constant pointer to a block of memory, and
 as such, any operations on it can only affect the block of memory.
 However, ptr is a variable; therefore, any operations on it affect the
 value of ptr, which happens to be a two- or four-byte number. That
 number happens to refer to a location in memory.

 If you want to changed the block of memory that ptr points to, you
 must do the following:

    >EA &ptr[0] "Hi"

 Essentially, this takes the address of the character that ptr is
 pointing at, gives a constant address, and thus modifies the block of
 memory there. To clarify, imagine you have a character located some
 place in memory. To move a character, you must make a copy of it to
 some other memory location; it is not possible to take its address and
 modify the address directly to change where the character is located.
 Thus, the address of that character is always a constant value. ptr[0]
 happens to be a character located someplace in memory. As such, the
 address of that specific character is a constant value. Since a
 constant cannot be modified, EA changes the block of memory starting
 at where the constant pointer is pointing.


 14. Debugging of DLLs That Do Not Have the .DLL Extension

 Product Version(s): 2.30   | 2.30
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 21-AUG-1989    ArticleIdent: Q47938

 CodeView Protect (CVP) Version 2.30 has the ability to debug DLLs that
 are called with DosLoadModule(). DosLoadModule() can load DLLs that
 do not have the .DLL extension. However, CVP 2.30 cannot debug DLLs
 that do not have the .DLL extension. If you want to debug DLLs that
 are called with DosLoadModule, they must have the .DLL extension.

 Microsoft is aware of this limitation with CodeView Protect 2.30. We
 are researching this problem and will post new information as it
 becomes available.


 15. Resident Software May Cause "Internal Debugger Error 80"

 Product Version(s): 1.x 2.00 2.10 2.10 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 29-AUG-1989    ArticleIdent: Q47989

 Question:

 Sometimes when I run CodeView, I get an "Internal Debugger Error 80"
 message. What causes this?

 Response:

 Internal Debugger Error messages are usually caused by problems in
 your MS-DOS environment; the most likely cause is the presence of
 memory-resident software, commonly referred to as TSRs (terminate-
 and-stay-resident software).

 For example, running CodeView with Borland's Sidekick loaded has been
 known to cause "Internal Debugger Error 80" and "R6002: Floating Point
 not loaded" error messages. "Internal Debugger Error 80" has also been
 reported when CodeView was run with Software Solutions' "Software
 Carousel" loaded into memory.

 CodeView Versions 2.00 and later have become increasingly more
 sensitive to TSRs. If you receive an Internal Debugger Error message,
 or you are experiencing strange problems within CodeView, make sure
 you are running CodeView with no memory-resident software loaded
 (including, but not limited to, device drivers, screen savers,
 keyboard enhancers, command-line editors, etc.). Disabling your
 resident software, but not rebooting, may not completely remove its
 interference, so be sure to "boot clean" when trying to resolve a
 problem of this type.

 If you continue to receive the error message without memory-resident
 programs, try running CodeView on some other program to see if the
 error is related to particular code. If the error is related to the
 specific code, and you are unable to determine the cause, you may want
 to call Microsoft Product Support for assistance at (206) 454-2030.

 If the error is not dependent on your code, the problem might be the
 particular sequence of CodeView commands you execute. Make a note of
 what operations you performed, i.e., the sequence of Trace, Go, Watch,
 Tracepoint, etc., commands that were issued, and contact Microsoft
 Product Support via phone, letter, or Microsoft OnLine.


 16. CVP Restart Command (Dialog Version) Doesn't Properly Set argc

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified: 28-AUG-1989    ArticleIdent: Q48000

 When using the dialog version of the Restart command, you can restart
 your program with command-line arguments; however, under CodeView
 Protect (CVP) Versions 2.20 and 2.30, argc does not get properly set.

 The Dialog Restart command is often used to restart a program with
 command line arguments. For example, you could use the following:

    L arg1 arg2 arg3

 This example restarts the current executable file, retaining any
 breakpoints, watchpoints, and tracepoints, with arg1, arg2, and arg3
 loaded into argv[1], argv[2], and argv[3], respectively. Argv[0] is
 always set to the name of the current executable file. Argc, at this
 point, should be set to four. The problem presents itself here; argc
 either remains unchanged from the value it was initially set to when
 CodeView was started, or is decremented by one. If, for example,
 CodeView is started with two command-line arguments (argc would then
 be set to three) and then executed, the previous example argc (which
 should then set argc to four) would remain unchanged. When using the
 Dialog Restart command and specifying fewer arguments than were
 specified at start up, argc sometimes is decremented by one.

 Microsoft has confirmed this to be a problem with CodeView Versions
 2.20 and 2.30. We are researching this problem and will post new
 information as it becomes available.


 17. Cannot Load CTRL+Z-Terminated Files with Less than 129 Bytes

 Product Version(s): 1.00 1.10 2.00 2.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00 buglist1.10 buglist2.00 buglist2.10 qfbv
 Last Modified:  4-NOV-1988    ArticleIdent: Q26548

 Problem:

 When using the F(ile) O(pen) command to load a text file which has
 less than 129 bytes and is terminated with a hex 1A (decimal 26,
 CTRL+Z, EOF), CodeView issues the error message "Not a text file." If
 the CTRL+Z character is removed, or if the file size is 129 bytes or
 greater, CodeView has no problem loading it.

 Response:

 Microsoft has confirmed this to be a problem in Version 1.00, 1.10,
 2.00, and 2.10. We are researching this problem and will post new
 information as it becomes available.


 18. Debugging High Resolution EGA or VGA Graphics

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER | TAR61178
 Last Modified: 14-AUG-1989    ArticleIdent: Q23308

 Question:

 I am trying to debug a program that does EGA or VGA graphics. When I
 continue from a breakpoint after the program has painted the screen,
 the screen is not as it was before the breakpoint. I think that all
 colors have been turned to black, but I am not sure.

 I tried this procedure with no switches, with /s, and with /t. The
 program is using the EGA in 640x350 16-color mode. Is this supposed to
 work? If it does not work, why not? What will you do about supporting
 the higher modes for the new machines such as the Personal System 2
 series from IBM?

 Response:

 This behavior is partly related to the size of the buffer that
 CodeView creates for storing screen information. If you are running on
 a CGA, EGA or VGA board, this buffer is by default 16K. If you are running
 on a monochrome board, this buffer is by default 4K. As you are
 finding, 16K is simply not enough memory for a color image using
 640x350 resolution (the maximum resolution supported would be
 640x200).

 One of the reasons why CodeView does not have the ability to handle
 the buffer requirements of an EGA image is that the EGA registers are
 write only. There is no way for CodeView to detect what mode the EGA
 currently is in so it can adjust the size accordingly. Also note that
 with the different resolutions the image is stored in different memory
 locations. The black on black characters may simply be a blank image
 because CodeView cannot tell that the resolution is different and
 therefore the image is located elsewhere.

 With the PS/2 machines this is not an issue because the EGA registers
 have read capability. We are reviewing this with regard to future
 implementations of CodeView.

 The following are some ways to work around this current limitation:

 1. Try writing a routine that will place the display in the desired
    mode before you invoke CodeView. CodeView will be able to judge
    which mode is currently in effect and can locate the image in the
    correct area of memory. Note that the image will not be displayed
    in color. You will only see the higher resolution since the buffer
    is not big enough.

 2. Debug your applications that run in high resolution graphics with a
    second monitor (use the /2 switch). Since the display is going to a
    different screen, CodeView will not have to worry about changing
    the video modes or the buffering.


 19. CodeView Version 2.20 Is Called CVPCK.EXE by DOS Version 2.10

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | CV CVPCK CVPACK 2.x
 Last Modified: 21-SEP-1989    ArticleIdent: Q48689

 Question:

 When trying to invoke CodeView Version 2.20 under DOS Version 2.10 or
 2.11, I get the messages "Cannot Find CVPCK.EXE" and "Please enter new
 program spec:". How can I get CodeView 2.20 to work under DOS Versions
 2.1x?

 Response:

 If you rename CV.EXE to CVPCK.EXE, you can run CodeView Version 2.20
 under DOS Version 2.10 or 2.11. You must also rename CV.HLP to C.HLP
 to make the on-line help accessible.

 CodeView Version 2.20 is included with C Version 5.10, FORTRAN Version
 4.10, Pascal Version 4.00, and Macro Assembler (MASM) Version 5.10.

 Many people mistakenly assume that CodeView is actually looking for
 CVPACK.EXE, which also comes with the software packages listed above.
 If you rename CVPACK.EXE to CVPCK.EXE and then try to run CVPCK.EXE,
 you will receive the error message "overlay not found." If you receive
 this error, delete CVPCK.EXE, copy both CV.EXE and CVPACK.EXE from the
 installation disks, and follow the instructions above.

 Under DOS Versions 3.x, a C program's name is available from argv[0].
 Under DOS Versions 2.x, argv[0] always equals the letter "C", so
 programs that need to find themselves under DOS Versions 2.x also have
 their own names hard coded as the filename to locate. Unfortunately,
 the hard-coded name within CodeView Version 2.20 is "CVPCK.EXE", so
 this is what it looks for under DOS Versions 2.x.


 20. CodeView String Search Length Limited to 19 Characters

 Product Version(s): 2.10 2.20 2.30 | 2.10 2.20 2.30
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | SR# G890810-24574 P_WinSDK
 Last Modified: 19-SEP-1989    ArticleIdent: Q48863

 CodeView Versions 2.20 and 2.30 and CodeView for Windows Version 2.10
 have a 19-character limit in the "Find..." option of the Search menu,
 even though the dialog box is much longer than 19 characters. Entering
 a search string longer than 19 characters results in one of two error
 messages.

 If the search string entered is 20 or 21 characters long, CodeView
 displays the erroneous message "No match of regular expression," even
 if the search string does exist in the file. If the search string is
 22 characters or more in length, CodeView displays the more
 appropriate message "Regular expression too long."

 Although 19 characters sometimes can be limiting, CodeView does
 substring searches so that searching for the following

    AFunctionWithAVeryL

 finds the following string:

    AFunctionWithAVeryLongName

 You will have problems only if you have both of the following and
 you are trying to locate one, but not the other:

    AFunctionWithAVeryLongName()
    AFunctionWithAVeryLongParameterList(a,b,c,d,e,f,g,h,i,j)

 In this case, you won't be able to specify search strings long enough
 to distinguish between the two. However, you can repeatedly use the
 Next command from the Search menu to find the next occurrence of the
 following:

    AFunctionWithAVeryL

 The Next command will find whichever of the above two function names
 that comes next in the source file.


 21. Files, Environment Inaccessible Only While Running under CVP

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q49313

 Due to combined problems in both protected-mode CodeView (CVP) Version
 2.20 and OS/2 Version 1.00 or 1.10, programs that correctly access
 data files and/or system environment information could fail when
 attempting this same access while running under CVP 2.20. This is
 strictly a protected-mode problem and is unrelated to the use of
 CodeView under MS-DOS. The sample program at the end of this article
 can be used to demonstrate this problem.

 The system environment information includes such items as the path and
 other environment variables, as well as the current working directory
 for each disk drive. This information is normally available to an
 executing program, but for a program being debugged with CVP 2.20
 running under OS/2 1.00 or 1.10, most of this environment information
 is inaccessible.

 This inaccessibility is a result of environment handling problems in
 both CVP 2.20 and OS/2 Version 1.00. Since CodeView is run from the
 command prompt, all the current environment information is available
 to CodeView itself, but the program being debugged is given its own
 new screen group in which to run. It is in this new screen group that
 the current environment information is lost because it is not carried
 over by either OS/2 or CodeView.

 Although the OS/2 problem has been corrected in Version 1.10, the
 CodeView problem still prevents access to the environment. Therefore,
 upgrading either CodeView or OS/2 alone does not solve the problem.
 Only with CodeView Version 2.30 running under OS/2 Version 1.10 is the
 problem eliminated.

 There may be some environment information available to the program
 being debugged, but only if it was set in the CONFIG.SYS file at start
 up. Since each new screen group is begun with a copy of the original
 start-up system environment, any SET commands carried out in the
 CONFIG.SYS file will then be duplicated for all subsequent screen
 groups.

 Otherwise, if a program needs access to environment variables that
 were set in the current screen group where CodeView will be invoked,
 then the only way to make the information available while debugging is
 to temporarily hard code the information into the program. After
 debugging, the program can be changed back to using the actual
 environment strings.

 The only other alternative to temporarily hard code the environment
 information into the program is to set the environment variables in the
 CONFIG.SYS file at boot time, rather than setting them in the current
 screen group.

 The only reason a file access will fail only while the program is
 running under CodeView is if the program is assuming the file is in
 the current working directory on the current or another drive.

 If this is the case, then one of the following workarounds may be used
 to gain access to files while debugging:

 1. Use full pathnames for all file accesses, since this alleviates any
    dependency on knowing the current working directory for the drive
    that is being accessed. If it is not feasible to have hard-coded
    pathnames in the completed program, at least adding the full paths
    temporarily will allow debugging.

 2. Put the files to be accessed in the root directory of the boot
    drive. This allows them to be found even under CodeView because
    with no environment information, the current working directory
    defaults to the root of the boot drive.

 3. Use a two-monitor debugging setup and start CodeView with the /2
    option. In this situation, CVP does not need to start a new screen
    group for the program being debugged because it can run it on the
    second monitor. Thus, the current environment information is
    available to both programs because they are both running in the
    current screen group.

    For more information about debugging with a two-monitor setup, query
    on the following:

       CodeView two monitor debugging

 The following C program can be used to demonstrate this environment
 problem:

 Program Example:
 ---------------

     /* TEST.C - shows inaccessible files under CodeView

        Compile with : CL /Zi /Od test.c
        Run with : test <filename>      where <filename> is any file
                        in the current directory.  The file will be
                        opened properly.
        Begin CVP with : CVP test <filename>     where <filename> is
                        the same as before. The file will not be
                        found when the program is run or traced.
     */

     #include <stdio.h>
     void main(int, char *[]);

     void main(int argc, char *argv[])
     {
         FILE *dfile ;

         if ((dfile = fopen(argv[1], "rb")) == NULL) {
             perror ("") ;
             printf ("Cannot open file '%s'.\n\n", argv[1]) ;
         }
         else {
             printf("File %s opened OK.\n\n", argv[1]) ;
             fclose (dfile) ;
         }
     }


 22. COM Port Time-Out Halts Redirection of CVP to Remote Terminal

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 27-OCT-1989    ArticleIdent: Q49376

 When using protected-mode CodeView (CVP) under OS/2, there is a
 problem with the serial communications (COM) ports timing out after 60
 to 90 seconds of inactivity. This time-out makes it essentially
 impossible to do remote terminal debugging with CVP. Once the time-out
 occurs, no further input is accepted from the remote terminal. The
 only workaround is to quit CodeView and begin again, or to do a break
 and then restart the redirection to the COM port.

 The CodeView Debugger allows redirection of input and output to a file
 or device. This procedure is commonly used to set up a remote (dumb)
 terminal for CodeView input and output, while the PC screen is used
 for displaying the program input and output. The terminal is connected
 through a COM port, which eliminates the need for a second video
 adapter as is required when using two monitors with the /2 option.
 Entering "=COM1" at the CodeView command prompt enables input and
 output redirection to the device designated as COM1.

 This debugging arrangement works great with CodeView under MS-DOS, but
 it becomes unworkable with CVP under OS/2 because the internal calls
 that are used to set up the redirection do not account for time-outs
 due to inactivity. Thus, if you are entering commands from the remote
 terminal at a steady pace, everything proceeds smoothly. However, if you
 stop and wait for more than about 60 seconds without doing any input,
 the port will time-out and leave you stranded because the keyboard no
 longer responds.

 In a normal debugging session, it is quite likely that there would be
 many instances greater than 60 seconds where input is not yet needed
 or desired; therefore, this situation quickly becomes intolerable. The
 only way to regain control is to enter CTRL+C at the PC keyboard,
 which ends the redirection. At that point, you could enter "=COM1"
 again on the PC keyboard to restart the redirection if you so desired.


 23. CVP 2.30 Does Not Allow Pathnames for DLLs Specified with /L

 Product Version(s): 2.30
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.30
 Last Modified: 10-OCT-1989    ArticleIdent: Q49377

 Protected-mode CodeView (CVP) Version 2.30 allows debugging of dynamic
 link libraries (DLLs) by specifying their names on the command line
 with the /L switch. Because of a problem exclusive to CVP 2.30, this
 particular version of the debugger does not allow a pathname to be
 used with /L to specify the DLL's location in another directory.
 Therefore, all DLLs to be debugged with CVP 2.30 must reside in the
 current working directory.

 Since DLLs are also required to be in a directory that is on the
 LIBPATH, two copies of the DLL may need to be resident on the disk,
 unless the current working directory is also a LIBPATH directory.

 Microsoft has confirmed this to be a problem with CodeView Version
 2.30. We are researching this problem and will post new information as
 it becomes available.

 When tracing a program under CodeView that calls DLLs, the only way to
 trace into the code of a particular DLL is if the DLL was specified
 ahead of time on the command line with /L when CVP was invoked. If a
 program statement is traced that calls a DLL that was not specified by
 /L, then CodeView executes all the code in the DLL and returns control
 back at the line following the call to the DLL. Thus, the call is
 handled as if the step command, rather than the trace command, had
 been used.

 You can indicate only one DLL with the /L switch, so debugging
 multiple DLLs requires multiple /L switches. Normally, the switch is
 followed by a space and the name of the DLL to be debugged, and if the
 DLL is not located in the current directory, a path may precede the
 DLL name. It is only with CVP 2.30 that this becomes a problem because
 a pathname is not recognized with this version, so tracing into the
 DLL is prevented.

 Unfortunately, CodeView does not display error messages for improper
 use of the /L switch, so if the DLL is not found, there is no message
 indicating this. Instead, CodeView does not allow debugging of the
 improperly specified DLL. Use of a pathname with /L with CVP 2.30
 causes this same behavior.

 The only workaround for DLL debugging with CVP 2.30 is to keep a copy
 of the DLL in the current working directory from which CodeView is
 invoked. Thus, if the current directory is not a directory specified
 on the LIBPATH, there must be two copies of the DLL on the disk. It is
 very important that the two copies are exactly the same because
 differing code makes any attempts at debugging very difficult and
 confusing.

 A common practice is to put a period (.) as the first directory on
 the LIBPATH because this makes the current working directory a LIBPATH
 directory, eliminating the need for two copies of the DLL. More
 information on this practice can be found by querying on the
 following words:

    CodeView DLL debugging and libpath


 24. Label Finding Command Does Whole Word Search, Not Text Search

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 27-OCT-1989    ArticleIdent: Q49378

 In CodeView Versions 2.20 and 2.30, under the Search menu is the Label
 option for searching for a label. Unlike the Find option, which
 searches the source code for any regular expression, the Label option
 searches the executable code for an assembly language label.

 This search is not a text search and does not accept regular
 expressions. The only way to find a label is to specify the entire
 label name as the search string. In addition, if the Case Sense option
 is selected on the Options menu, the label is found only if the case
 of each character matches exactly.

 For example, if you want to find the code for the standard C
 stack-checking function "_chkstk", choose Search Label, and type in
 "__chkstk" (without the quotation marks), and press ENTER. This
 switches you into assembly mode, if you weren't there already, and
 puts the line with the __chkstk label at the top of the window. The
 two underscores are required since C appends an underscore to the
 front of all labels and the original function name is "_chkstk".

 You will receive the error message "Unknown Symbol" if the label
 cannot be found or if you mistype or incompletely type the correct
 name. For example, "_chkstk", "chkstk", "__chk", and "__chkstks" all
 fail to find a match in the above example. If Case Sense is on,
 searching for the label "__CHKSTK" also results in failure.


 25. The Assemble Command with ADD Instructions

 Product Version(s): 2.20 2.30  | 2.20 2.30
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified:  9-AUG-1989    ArticleIdent: Q40225

 Problem:

 In CodeView, I'm using the assemble command to change my ADD
 instruction, and it changes all the code from that point on.

 Response:

 If you had the instruction ADD AL,44, for example, and you wanted to
 change the 44 to 45 (or any other number), you could use the Assemble
 command to do it. The Microsoft Macro Assembler generates a 04 44 for
 that instruction; however, when changing the 44 to 45, CodeView
 generates an 80 C0 45, which is still the correct instruction of ADD
 AL,45. However, it's a 3-byte instruction. Inserting one extra byte
 into your code will cause each op code from that point on to be off by
 one.

 Microsoft has confirmed this to be a problem in Versions 2.20
 and 2.30 of CodeView. We are researching this problem and will
 post new information as it becomes available.



 26. CV Prior to 3.00 Needs /S for Mouse to Appear in OS/2 DOS Box

 Product Version(s): 1.00 1.10 1.11 2.00 2.10 2.20 2.30 2.35
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q23646

 With all versions of real-mode CodeView (CV) earlier than version
 3.00, the mouse cursor does not display when running in a DOS session
 under OS/2 in the DOS compatibility box.

 The situation exists because the mouse draws the pointer only in video
 page zero, while CodeView uses video page one. This problem is caused
 by OS/2 itself because the mouse cursor works normally under DOS.

 To work around this limitation with CV 1.x or 2.x, invoke CodeView
 with the /S switch so screen swapping is used as the method of screen
 exchange. This method forces CodeView to swap in and out of page zero.

 Beginning with version 3.00, CodeView detects whether it is running in
 a DOS session under OS/2, and if so, automatically starts up with /S
 as the default in order to make the mouse visible.


 27. CVPACK /p Causes a More Complete Packing

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 28-MAR-1989    ArticleIdent: Q38020

 When you are unable to load your program into CodeView, try packing
 the program with CVPACK.EXE. If you want a more complete packing of
 your executable, then run CVPACK.EXE with the /p option. This option
 will take longer to run, but it will generate better results.

 The /p option for CVPACK.EXE is documented on Page update-17 in the
 "Microsoft C 5.1 Optimizing Compiler, CodeView and Utilities,
 Microsoft Editor Mixed-Language Programmer's Guide."

 Normally, CVPACK discards unused debugging information and appends
 it to the file. With the /p option, CVPACK discards the unused
 debugging information, then proceeds to sort it throughout the
 executable file.


 28. Mouse Cursor Disappears After Right Click

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 14-AUG-1989    ArticleIdent: Q38021

 Problem:

 I have just clicked my right mouse button to acknowledge a pop-up
 message and my mouse cursor has disappeared. I had just clicked my
 right mouse button before for another operation.

 Note: This also occurs when you hit any button on the three button
 Logitech mouse.

 Response:

 To get your mouse cursor back again, redraw the screen with the "@"
 command.


 29. CVP 2.30 Hangs When /O Is Specified, but Child Is Not Debugged

 Product Version(s): 2.30
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.30
 Last Modified: 27-OCT-1989    ArticleIdent: Q49381

 Beginning with protected-mode CodeView (CVP) Version 2.30, you can
 debug child processes from within a parent process's CodeView session
 by invoking CodeView with the /O switch. When the program is executed
 to the point where the child process is invoked, CodeView displays a
 prompt showing you the child's process ID (PID) and asks, "Do you wish
 to debug (y/n)?". Entering "y" brings up the child process and allows
 you to debug it. Pressing "n" should cause the child to execute
 without any debugging.

 Unfortunately, there is a problem in CVP 2.30 that causes CodeView to
 hang if you answer no to debugging the child. The only workaround is
 to always answer yes when prompted to debug a child process, or to
 invoke CodeView without the /O switch because this prevents the prompt
 entirely.

 Microsoft has confirmed this to be a problem with CodeView Version
 2.30. We are researching this problem and will post new information as
 it becomes available.

 If the program you are debugging is not a Presentation Manager (PM)
 application, you may be able to kill the CodeView session if it should
 hang as a result of answering "n" to the debugging child process. You
 must switch to the Task Manager and use it to close the hung CodeView
 session. If you are working on a PM application, the only workaround
 may be to reboot the computer.


 30. Cannot Debug Code in Overlays in Small or Compact Model

 Product Version(s): 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 14-AUG-1989    ArticleIdent: Q27128

 Question:

 I have a C program, compiled with Microsoft C Version 5.00, which
 consists of several modules linked together as overlays. I am not able
 to trace into code in the overlays. I compiled in the default memory
 model. What is wrong?

 Response:

 The modules must be compiled in medium or large memory model to be
 overlaid. In the default model (small), or in the compact model, there
 is only one code segment, which cannot be overlaid. The main module is
 always resident and cannot be overlaid. You must use the compile
 option /AH, /AL, or /AM.


 31. Code that Will Hang IBM XTs or Compatibles

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR57675 buglist1.00
 Last Modified:  8-NOV-1988    ArticleIdent: Q23856

 Problem:

 The following code will hang IBM XTs or compatibles if specific
 commands are issued when inside of CodeView:

    #include <stdio.h>
    main()
    {
         int n;
         double f;

         while(1)   {
                    scanf("%d",&n);
                f=1.0;
                while (n>1) f=f*n--;
                   printf("%.101g%c",f,'\n');
                    }
    }

 For the program to fail in CodeView, first set a breakpoint at
 instruction f=1.0. Issue the Go command, then the P command.

 Response:

 This is corrected in CodeView version 2.20.

 A workaround is to place a breakpoint at the instruction before or
 after the assignment to f.


 32. /DOSSEG Link Switch Fails to Make CodeView .exe

 Product Version(s): 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-AUG-1989    ArticleIdent: Q38163

 Question:

 CodeView is failing on an .exe produced using the /DOSSEG linker
 switch. CodeView responded to an attempt to run with this .exe
 with a "not enough space" diagnostic. What is the problem?

 Response:

 The modules below demonstrate the problem. In this case, compiling the
 C source module and assembling the MASM source module with the
 appropriate CodeView switches, then linking with the /CO /DO switches
 generates a bad .exe. The problem is that CodeView displays source
 with extended ASCII characters.

 To work around this problem, put .DOSSEG in the MASM modules
 being linked, and omit the /DO switch rather that trying to
 force the linker to do the work. Also, switching the order of
 the linker switches may solve the problem.

 The following example demonstrates the problem:

 #include <stdio.h>
 main ()
   {
   long int getds(void), getdsq(void);
   printf("ds.DATA  = %lX\nds.DATA? = %lX\n",getds(),getdsq());
   }

 **************************************************************
 ;        DOSSEG could be put here
         .MODEL  small
         .DATA
 array   dd      0
         .DATA?
 arrayq  dd      ?
         .CODE
         PUBLIC  _getds,_getdsq
 _getds  PROC
         mov     ax,SEG array
         mov     dx,ds
         ret
 _getds  ENDP
 _getdsq PROC
         mov     ax,SEG arrayq
         mov     dx,ds
         ret
 _getdsq ENDP
         END


 33. 3270 ERMA Emulator

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-AUG-1989    ArticleIdent: Q24200

 Question:
    Does CodeView support the 3270 ERMA emulator?

 Response:
    CodeView does not directly support any other program. In this case,
 the 3270 ERMA emulator would have to accommodate CodeView. CodeView
 performs some hardware specific routines (e.g. checking to see if an
 EGA is present) and makes some assumptions on the state of the
 machine. If another program changes the state of the machine, it may
 not work with CodeView. It has been reported that CodeView will hang
 if the 3270 ERMA emulator is enabled; we recommend you disable the
 emulator before running CodeView.


 34. Flipping and Swapping Screens

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-AUG-1989    ArticleIdent: Q24201

 Question:
    What is the difference between flipping and swapping in CodeView?

 Response:
    Both are ways of maintaining two alternate screens for display on
 one monitor. The difference is in the way the task is accomplished.
    When swapping is selected, CodeView allocates a 16K buffer (a 4K
 buffer for a monochrome adapter) to hold the alternate screen. When
 the other screen is required, CodeView swaps the screen into the
 display buffer and places the other screen into the storage buffer.
 Swapping takes memory and time, but it does not have the limitations
 of flipping.
    Flipping uses the video-display pages of the graphics adapter to
 store each screen of text. When the alternate screen is required, the
 other page is selected. Flipping is much faster than swapping and does
 not require the 16K buffer. However, it cannot be used with a
 monochrome adapter, or with programs that display graphics or use the
 video pages.


 35. CODEVIEW.DOC Incorrectly States /E Uses Extended Memory

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 10-NOV-1988    ArticleIdent: Q27763

 The CODEVIEW.DOC file included in Microsoft C Version 5.10 states that
 the /E switch enables use of extended memory for CodeView's symbol
 table.

 This is a documentation error in the CODEVIEW.DOC file. CodeView uses
 expanded, not extended memory.


 36. WINDOWCOMPAT Directs CodeView to Create a Window

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER | S_C
 Last Modified: 10-NOV-1989    ArticleIdent: Q49423

 The WINDOWCOMPAT directive in a linker definition file can cause
 strange behavior in non-Presentation Manager (PM) programs being
 debugged under CodeView. WINDOWCOMPAT is one of three application
 types that can be specified after the NAME directive. WINDOWCOMPAT is
 used for OS/2 programs that use VIO, MOU, and KBD calls and can be
 used inside a PM window or as a separate screen group.

 Debugging a non-PM application that was linked with the WINDOWCOMPAT
 option instructs CodeView to create a PM window to run the program. In
 some cases this feature could be desirable, but for most debugging, a
 PM window is only cumbersome. The way to work around this feature is
 to relink without the WINDOWCOMPAT directive.


 37. The CodeView Port Input Command Example Is Unclear

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | H_MASM H_FORTRAN S_Pascal
 Last Modified: 27-OCT-1989    ArticleIdent: Q49537

 The CodeView example for port input command is unclear in the
 following manuals:

 1. Page 150 of Microsoft C 5.10 "CodeView And Utilities, Microsoft
    Editor, Mixed Language Programming Guide"

 2. Page 150 of Microsoft Macro Assembler 5.10 CodeView and Utilities

 3. Page 150 of Microsoft Pascal 4.00 CodeView and Utilities

 4. Page 127 of Microsoft FORTRAN 5.10 CodeView and Utilities

 The example assumes the radix is in hexadecimal. To set the radix to
 hexadecimal, type in the following command:

    >n16

 After setting the radix to hexadecimal, the example works properly.

 If the radix is not in hexadecimal, a "0x" must be present for
 CodeView to recognize the value as a hex format. The following example
 shows how to use the port input command if CodeView is not in
 hexadecimal radix:

    >I 0x2f8


 38. The Difference Among Watch, Watchpoint, and Tracepoint

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER |
 Last Modified: 14-AUG-1989    ArticleIdent: Q24225

 Question:

 What is the difference between a watch, a watchpoint, and a
 tracepoint?

 Response:

 A "watch" command will monitor an expression or a range of memory
 addresses, and update the watch window each time the expression or any
 location in the range changes. Using a watch never will cause program
 execution to stop; it simply "watches" unconditionally.

 A "watchpoint" monitors an expression (and an expression only) during
 program execution. It will update its value in the watch window
 whenever it changes. However, when the watchpoint expression becomes
 true (nonzero), program execution is stopped.

 A "tracepoint" monitors an expression or a range of memory addresses
 and displays the expression or the range being monitored in the watch
 window. It will stop program execution when the expression or any
 location in the range changes. Please note that writing over the old
 value at a memory location with the same value is not considered a
 change.

 The following example summarizes this information:

 Command     Object To Watch          Conditionally    Condition To
                                      Stops            Stop On
 -------     ---------------          -------------    ------------

 WATCH       expression or            No               (none)
             range of memory

 WATCHPOINT  expression               Yes             expression becomes
                                                      true (nonzero)

 TRACEPOINT  expression or            Yes             expression or
             range of memory                          in range changes
                                                      location

 Note: the "monitoring" described above is done in only window mode. If
 sequential mode is being used, you must use the Watch List command to
 see the values of any of the three types of watch statements.


 39. Tracking Down a Null Pointer Assignment Error

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER | S_C
 Last Modified: 21-AUG-1989    ArticleIdent: Q24270

 Question:

 I consistently get the error number R6001 "null pointer assignment"
 when I run my program. How can I use CodeView to determine the point
 at which the null pointer assignment is occurring?

 Response:

 Use a tracepoint, which can be set to watch a range of memory up to
 128 bytes. It will halt the execution of the program when any value in
 this range is changed. If you set a tracepoint over the entire range
 of the null segment, the program will halt immediately after the
 instruction that wrote over the null segment.

 The location of the null segment is available in the link maps of
 Microsoft compilers. It starts at DS:0 and is 42H bytes long. The
 Microsoft copyright notice is written there at program startup and
 if this area is written to during the course of the program, the
 error r6001 is generated. The most common cause of this error is
 using a pointer that has not been initialized to point to a memory
 area. Pointers that have not had space allocated for them (using
 malloc for example) or that have not been assigned to a specific
 data element (arrays or structures for example) are considered
 uninitialized.

 An example of using CodeView to determine where an unitialized pointer
 is being used follows:

 g main                  /* go to the beginning of main() */
 n16                     /* switch to hexadecimal (base 16) */
 tpb DS:0 DS:42          /* set a Trace Point of type Byte starting
                               at address DS:0 and extending to DS:42 */

 When any value in the specified range changes, CodeView will stop the
 execution of your program. The previously executed line was probably
 the line that caused the R6001 error.


 40. How to Successfully Debug VioPopUp() Code with CodeView

 Product Version(s): 2.20 2.30 2.35
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 27-FEB-1990    ArticleIdent: Q58647

 Debugging programs that take advantage of OS/2's VioPopUp() call can
 present a potentially dangerous situation. Due to the nature of the
 VioPopUp() call, any attempts to trace into the VioPopUp call will cause
 your machine to hang. The workaround for this difficulty is to set a
 breakpoint outside of the VioPopUp() call [after the VioEndPopUp()], and
 then press F5 to instruct CodeView to execute to the next breakpoint.

 The VioPopUp() call brings forward a temporary pop-up text screen group
 that can be used to display text information without altering the
 context of the foreground screen. When a VioPopUp() call is executed, the
 current foreground screen group loses the keyboard focus to the pop-up
 screen. Therefore, when you trace into a VioPopUp() call, the pop-up
 text comes forward and CodeView, running in the foreground, loses the
 keyboard focus and cannot execute a trace instruction. At this time,
 CTRL+ESC or ALT+ESC will not change the deadlock situation and the
 only alternative is to reboot.

 To work around this problem, it is essential that you do NOT step into
 a VioPopUp call. Instead, press F5 to execute to the next breakpoint.
 Setting the breakpoint AFTER the VioEndPopUp() call is critical.


 41. Capabilities of Real Mode CodeView and the 386

 Product Version(s): 2.00
 Operating System:   MS-DOS
 Flags: ENDUSER | s_c, h_masm, h_fortran, s_pascal
 Last Modified:  1-DEC-1988    ArticleIdent: Q38205

 The information below discusses the CodeView debugger and its use
 of 80386 hardware capabilities.

 The DOS CodeView does not keep track of any of this information because
 DOS does not use any of these features. Essentially, a 386 running DOS
 is just a very fast PC and CodeView treats it as such.

 The OS/2 CodeView does not have the privilege to track many of the
 OS/2 functionality.

 The following is a list of CodeView behaviors:

 1. CodeView does not keep track of task states.

 2. CodeView does not handle privilege levels.

 3. CodeView Version 2.20 makes limited use of the 386 debug
    registers. Previous versions do not use these registers.

 4. CodeView does not keep track of interrupt gates and trap gates.

 5. CodeView cannot operate in both real and Virtual 86 mode.

 6. CodeView cannot trace to protected mode and back to real mode.

 7. CodeView does not handle traces in protected mode.


 42. Flip/Swap Setting Crucial to Debugging PM Apps with Children

 Product Version(s): 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 10-NOV-1989    ArticleIdent: Q50514

 Using protected mode CodeView (CVP) to debug Presentation Manager (PM)
 programs that spawn one or more child processes can be rather
 difficult. CVP works correctly for debugging just the parent PM
 process, but once you begin CodeView with the /O option to specify
 that you also want to debug child processes, you may find that you
 hang the computer quite regularly during your debugging session.

 CodeView itself does not have a problem with PM programs even if they
 do invoke child processes. It is only when you use the /O switch to
 debug the children at the same time that you run into difficulty. This
 is because of problems with CodeView conflicting with the OS/2 kernel
 as you bring a process to the foreground for debugging, while a
 system-dependent process like the PM parent is relegated to the
 background where it can become blocked.

 For example, if the parent gets to a point where it is waiting on a
 message, but it is not in the foreground, there is no way to get the
 focus back to this waiting process and you are essentially hung. The
 parent cannot process the message because it must be in the foreground
 to do so, and CodeView cannot continue until the message is processed,
 so it just waits.

 The key to debugging the parent and child processes of a PM program at
 the same time is the setting of Flip/Swap on the Options menu. Under
 CodeView, Flip/Swap ON forces messaging, Flip/Swap OFF does not.
 Therefore, you must turn Flip/Swap on and off as you go, depending on
 which particular part of the program you are currently debugging. The
 Flip/Swap setting is crucial in determining whether you hang the
 system or not.

 The ability to debug child processes from the parent's CodeView
 session became an available option beginning with CVP Version 2.30. By
 specifying the /O switch on the command line, CVP allows you to trace
 into child processes. (See the CVP 2.30 Note below if you are using
 that particular version of CodeView.)

 As far as actually debugging child processes in PM programs, you must
 proceed in an exacting manner. Unfortunately, the specifics are
 different for every program, so an all-encompassing set of debugging
 procedures cannot be devised. Nevertheless, the following general
 guidelines can be used for debugging most PM applications with their
 accompanying child processes:

  1. It is only with the /O option that any of this becomes critical.

  2. You need to debug in a full screen and not a PM window.

  3. Remember, Flip/Swap ON forces messaging, Flip/Swap OFF does not.
     Therefore, while you begin debugging in the parent program, you
     should have Flip/Swap ON, since you need messaging whenever you
     are doing any of the window initialization routines.

  4. Set a breakpoint in the parent somewhere after the window
     initialization code, but before the call to start the child
     process. It varies, but it usually works to put the breakpoint at
     the "while get message - dispatch message" loop or in the
     ClientWndProc procedure at the main switch statement.

  5. You must make sure that the breakpoint is placed in a position
     where you will stop at it before the prompt appears to ask you if
     you want to debug the child, but after ALL the window
     initialization has been completed. You will also probably need to
     set another breakpoint at the point where the parent program is
     going to begin executing again after you have finished working
     with the child.

  6. Do a GO, and when the breakpoint is reached, turn Flip/Swap OFF.
     Make sure that the prompt to debug the child is not already
     visible or you will lock up.

  7. Do a GO (or some traces) and you should get the prompt to debug
     the child. Answer "Y" and you should be able to debug the child
     process at this point.

  8. Use the Process command (the "|") to gain access to the child.
     Never use CTRL+ESC or ALT+ESC to switch to the other processes
     because these will almost assuredly cause you to hang.

  9. Go ahead and set breakpoints, watches, etc. in the child and do
     your debugging.

 10. After the child process is completed, use the Quit command to exit
     the child process's CodeView screen or use the Process command to
     reselect the parent process.

 11. Once you have returned to the parent process, and before you do a
     Restart (or load), or before you do ANY other window
     initialization, you MUST turn Flip/Swap ON again.

 12. Remember to always be aware of where you are in the program and
     what the current state of Flip/Swap is, since turning Flip/Swap on
     or off at the wrong time will almost always cause you to hang.

 Again, this is only the general outline of steps to follow and each
 application requires different specific steps. Don't be too surprised
 if you still run into occasional lock-ups.

 CVP 2.30 Note: When using the /O switch with CVP Version 2.30, there
 is a bug that may also cause you to hang. The problem involves using
 /O on the command line and then saying "No" when asked if you want to
 debug the child. So, with this version of CodeView, you should always
 answer "Yes" when asked if you wish to debug the child.

 For more information on this problem, use the following query:

    CodeView 2.30 hangs debugging child processes


 43. Can't Debug .COM Files in Source Mode

 Product Version(s): 2.00 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-AUG-1989    ArticleIdent: Q38288

 The .COM format files created with the Microsoft Macro Assembler
 cannot contain symbolic and source-line information for the CodeView
 debugger. You can only debug these files in assembly mode.


 44. CODEVIEW.DOC File Error: Mouse Works with the /2 Option

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-NOV-1988    ArticleIdent: Q27764

 Question:
    The CODEVIEW.DOC file included with Microsoft C Version 5.10 states
 that using the /2 switch disables mouse support on the debugging
 display. Is this true?

 Response:
    This is an error in the CODEVIEW.DOC file.
    CodeView does support the mouse when using the /2 switch. In fact,
 if you are debugging a program which itself uses the mouse, using the
 /2 switch will allow you to use the mouse on CodeView's debugging
 screen as well as your application's output screen.


 45. "?CANNOT DISPLAY" After Column 135 in Command Window

 Product Version(s): 3.00 3.11 | 3.00 3.11 3.50
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q68696

 The code below demonstrates a limitation of the CodeView debugger.
 When the command "?y" is executed in the COMMAND window, the structure
 "y" is displayed. However, CodeView displays the structure only to
 column 135 and then prints "?CANNOT DISPLAY," ignoring the rest of the
 elements in the structure. The output appears as follows:

    --------------------------command----------------------------
   |>?y                                                          |
   |{this_field_01=0x0000, ... ,this_field_07=?CANNOT DISPLAY    |
   |                        ^                 ^                  |
   |                        |                 |                  |
   |                  Fields 2-6 displayed    Column 135         |
   |                                                             |
    -------------------------------------------------------------

                       CodeView Command Window

 To view all elements of a structure, you should use the QUICK WATCH
 function. In the example below, the contents of the whole structure
 can be seen by typing "??y". A dialog box will appear on the screen
 showing the contents of the structure. By scrolling down in the dialog
 box, the contents of every element of the structure can be seen. The
 structure contents are displayed as follows:

           --------------- Quick Watch -----------------
          |                                             |
          |-y                                           |
          |   this_field_01=0                           |
          |   this_field_02=0                           |
          |   this_field_03=0                           |
          |   this_field_04=0                           |
          |   this_field_05=0                           |
          |   this_field_06=0                           |
          |   this_field_07=0                           |
          |   this_field_08=0                           |
          |   this_field_09=0                           |
          |   this_field_10=0                           |
          |   this_field_11=0                           |
          |   this_field_12=0                           |
          |   this_field_13=0                           |
          |   this_field_14=0                           |
          |   this_field_15=0                           |
           ---------------------------------------------

                       Quick Watch of Variable

 Sample Code
 -----------

 struct x {
    int this_field_01;
    int this_field_02;
    int this_field_03;
    int this_field_04;
    int this_field_05;
    int this_field_06;
    int this_field_07;
    int this_field_08;
    int this_field_09;
    int this_field_10;
    int this_field_11;
    int this_field_12;
    int this_field_14;
    int this_field_15;
    int this_field_16;
    int this_field_17;
    int this_field_18;
    int this_field_19;
    int this_field_20;
 };

 main()
 {
     struct x y;
 }


 46. Debugging PM Apps with Two Monitors Does Not Require /2 Switch

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 17-JUL-1990    ArticleIdent: Q49824

 Problem:

 I am using CodeView to debug my Presentation Manager (PM) program and
 I am using the /2 switch to redirect the CodeView screen to a
 monochrome monitor. When I press F5 to start my program, a protection
 violation occurs, but it works correctly when I run it from the OS/2
 command line.

 Response:

 The /2 switch for CodeView is not supported for Presentation Manager
 application debugging. However, you may redirect the CodeView screen to
 a monochrome monitor if you do the following:

 1. Start a full-screen command prompt.

 2. At the prompt, type the following command (this puts the prompt on
    the monochrome monitor):

       mode mono

    Note: You must be in a 25-line screen mode before you attempt the
    mode mono. If you are in a 43- or 50-line mode, the display is
    corrupted.

 3. At the prompt, type the following command, where "appname" is your
    application's name:

       cvp appname

 4. After you are finished debugging, you can return the prompt to your
    primary display by typing the following command:

       mode co80


 47. How CodeView Interprets Values (octal, decimal, hexadecimal)

 Product Version(s): 1.x 2.00 2.10 2.20 | 2.20
 Operating System:   MS-DOS             | OS/2
 Flags: ENDUSER |
 Last Modified: 23-NOV-1988    ArticleIdent: Q38299

 Problem:

 When trying to watch a portion of memory, I have a problem with
 the following command at the dialog prompt:

    WW DS:0050 L 4.

 I thought this should have created a watch on the four words starting
 at offset 0x50. It actually set the watch starting at 0x28, CodeView
 interpreted the number as if it had been in base 8. Using the N
 command to change the radix doesn't make any difference.

 Response:

 In this case, the 0's before the offset cause CodeView to evaluate the
 expression in octal. CodeView provides three different prefixes for
 numbers to use an explicit base: 0 signifies octal, 0n signifies
 decimal, and 0x signifies hexadecimal. The current radix setting will
 have no bearing on numbers entered with these prefixes; however, it
 will affect those without prefixes.

 The lines below have different meanings when setting watches.
 The left column is the command, while the right column is an example
 of the display produced in the watch window. Radix is assumed to be 10.

 The following is an example:

 1. ww 50               50    :  0067:0032  6942

 2. ww 050              050   :  0067:0028  6328

 3. ww 0n50             0n50  :  0067:0032  6942

 4. ww 0x50             0x50  :  0067:0050  6163

 The first command sets the watch at the address specified using the
 current radix. This address will change when you use the N command to
 change the radix; the 50 on the left of the watch remains the same;
 however, the offset in the address will change to watch 50 in the new
 base. This address will always be displayed in hexadecimal, but 50
 will be evaluated differently.

 Examples 2 through 4 show watches being set in octal, decimal, and
 hexadecimal modes, respectively. These addresses will never change
 with a change of radix.

 Notice that watches 1 and 3 match. This is because by default CodeView
 is in base 10, so 50 and 0n50 evaluate to the same thing. Using N 8 will
 cause watches 1 and 2 to match, and N 16 will match 1 and 4.


 48. Interrupt Conflict with Greenleaf Libraries

 Product Version(s): 2.20    | 2.20
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | CV CVP
 Last Modified: 23-NOV-1988    ArticleIdent: Q38314

 The Greenleaf Comm Library, a collection of asynchronous
 communications functions for use with the C compiler, causes severe
 complications with CodeView (e.g. crashes, lockups) due to interrupt
 conflicts. Greenleaf Software is aware of this difficulty and will
 advise customers of the incompatibility.

 No workarounds are available. Greenleaf Software is located in
 Carrollton, TX, and can be reached at (214) 248-2561.


 49. CodeView Gives "Illegal Instruction" on Clone 386

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | CV
 Last Modified: 23-NOV-1988    ArticleIdent: Q38317

 Some clones that are not entirely IBM-compatible under CodeView may
 give an "illegal instruction" message upon executing Go (F5), and then
 hang, requiring a warm boot. If the instruction being called illegal
 is FINIT or FNINIT, the particular ROM BIOS probably has a built-in
 387 emulator. Either turn off the emulator, or set the environment
 variable SET NO87=(some string).



 50. Thirty-Two-Bit Register Not Visible under OS/2

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 23-NOV-1988    ArticleIdent: Q38375

 Thirty-two-bit registers are not viewable (using F2) under CVP even if
 you have an 80386-based machine. This is not a problem with CodeView;
 it is a limitation.

 Real mode CodeView (CV) DOES support viewing 32-bit registers. This
 is because of the unprotected and generally more flexible nature of
 DOS. Using the full 32-bits of the 80386 under OS/2 is considered
 hazard-prone and is not supported by CVP.



 51. CodeView Instruction Pointer Miscounts Very Long Lines

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist2.20
 Last Modified:  1-DEC-1988    ArticleIdent: Q38382

 CodeView may display the "current instruction" highlight on the wrong
 line if the source file contains lines that are very long.

 The compiler counts the long lines as one line, but CodeView counts
 the very long lines as two lines. This makes the line number
 calculations incorrect and causes the "current line" highlight to
 appear on the wrong line. This problem does not occur if the source
 lines are less than 251 characters in length.

 Because the Microsoft Editor breaks lines that are longer than 250
 characters, this problem does not occur if you create and maintain
 your source files with the Microsoft Editor.

 Microsoft has confirmed this to be a problem in CodeView Version 2.20.
 We are researching this problem and will post new information as it
 becomes available.


 52. CodeView Requires PUBLIC to Trace MASM Program in Source Mode

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | H_MASM
 Last Modified:  3-MAY-1989    ArticleIdent: Q44006

 A MASM program that runs perfectly from a DOS prompt refuses to trace
 in source mode inside of CodeView. The program single-steps in
 assembly mode, but an attempt to trace into the code in source mode
 results in the program terminating upon reaching the first data
 declaration.

 In addition, the program does not come up in source mode when CodeView
 is started, but can be changed into source mode with "View" "Source".

 This problem happens when the code and data segments are not declared
 as "PUBLIC". The code is valid and executes perfectly inside of
 CodeView or from a DOS prompt. However, CodeView cannot follow the
 logic at a source level.

 A program constructed in the following manner exhibits the symptoms
 described above:

 TITLE    myprog

 StackSeg Segment STACK
 .
 .
 .
 DataSeg  Segment DATA
 .
 .
 .
 CodeSeg  Segment CODE
 .
 .
 .
 END      myprog

 However, if the following minor changes are made to the program, and
 the segments are declared as "PUBLIC", CodeView can trace through the
 program in source mode:

 TITLE    myprog

 StackSeg Segment STACK
 .
 .
 .
 DataSeg  Segment WORD PUBLIC 'DATA'
 .
 .
 .
 CodeSeg  Segment WORD PUBLIC 'CODE'
 .
 .
 .
 END      myprog


 53. Cannot Use /2 Switch on IBM PS/2 in CodeView

 Product Version(s): 2.10 2.20  2.30 | 2.20 2.30
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# G881031-5515
 Last Modified:  9-AUG-1989    ArticleIdent: Q38865

 To use the /2 switch with CodeView, your computer must be equipped
 with a monochrome display (MDA) and a color display (CGA/EGA/VGA). The
 IBM PS/2 computers aren't currently configurable this way because they
 come with built-in VGAs or MDAs, but not both.

 If a hardware vendor starts selling MDAs that can be added to systems
 with built-in VGAs, this problem will be solved. An MDA card is
 needed that plugs into the PS/2 and works correctly in conjunction
 with the built-in VGA so that PS/2 owners can have a dual-monitor
 system.

 Currently, there is no solution to this debugging restriction other
 than using CodeView through the com port in sequential mode (/T) with
 a debugging terminal.


 54. CodeView Does Not Support Debugging Spawned Process

 Product Version(s): 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 26-FEB-1990    ArticleIdent: Q58653

 The following are several reasons why CodeView doesn't provide
 debugging support for spawned processes under DOS:

 1. DOS is not a multitasking operating system. CodeView cannot start
    another thread/process to watch the execution of the spawned
    process.

 2. DOS does not provide debugging support for the DOS BIOS calls (int
    21h). Since all spawn() and exec() functions under DOS have to go
    through the BIOS to run, CodeView cannot follow the spawned
    program.

 3. DOS only recognizes 640K of memory; therefore, there is
    insufficient memory to debug a large program, since both the parent
    and child processes have to reside in memory at the same time.


 55. Display Settings for Compaq Gas Plasma Screen

 Product Version(s): 1.00 2.10 2.20 | 2.20
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified:  6-DEC-1988    ArticleIdent: Q38866

 The default monitor settings for CodeView do not work properly with
 the Compaq gas plasma display adapter. Invoking CodeView with the /b
 switch corrects the problem.


 56. CodeView: Watchpoints and Tracepoints with Enumerated Types

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_c
 Last Modified: 28-MAR-1989    ArticleIdent: Q42601

 CodeView will not display the members of an enumerated type as they
 are declared in a C program. Only the integer representations of these
 types of variables can be shown. The following is an example:

 /*  Example enumerated type.
  */

 enum e_type
 {
     var1,
     var2,
     var3
 };

 enum e_type foo = var1;

 CodeView will not display "var1", "var2", or "var3" when watching a
 variable of type e_type, such as foo. CodeView will instead show the
 integer values of the variable: 0, 1, and 2, respectively. In order to
 watch the variable foo, you must explicitly display its value as an
 integer. The following command will add the proper watch:

     w? foo,d

 To set a watchpoint or a tracepoint on the same variable, further type
 casts must be made. These lines will produce watchpoints and
 tracepoints on foo, as follows:

     wp? *(int *)&foo == 1
     tp? *(int *)&foo

 Trying to set a watchpoint without the proper type cast will result in
 the following error:

     Operand types incorrect for this operation

 Setting a tracepoint on foo without this type cast will set the
 tracepoint but will only show "?CANNOT DISPLAY" in the watch window.
 Going through the right steps will display the current integer value
 of the variable, as it should.


 57. "?CANNOT DISPLAY" Error Not Documented in CodeView Documents

 Product Version(s): 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER | TAR64267 docerr
 Last Modified: 21-AUG-1989    ArticleIdent: Q24877

 Problem:

 When trying to evaluate (?), a function that returns void, I get the
 error "?CANNOT DISPLAY". I cannot find this error message in the
 "Microsoft CodeView Utilities and Editor" manual.

 Response:

 This error message is not contained in the CodeView manual.

 The "?CANNOT DISPLAY" error message will be displayed in cases where
 the expression evaluator cannot return a value, such as a function
 returning void.


 58. Watch Bytes (wb) Command Can Be Used to Watch a Buffer in HEX

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 17-JUL-1990    ArticleIdent: Q50224

 Question:

 Is there a way to keep tabs on the contents of a buffer via a watch
 command? We want to observe the contents of a 20-character buffer in
 HEX. The buffer is not necessarily null terminated.

 Response:

 The way to watch a buffer in CodeView in hexadecimal with the Watch
 command is to use Watch Bytes (wb) as follows:

    >wb *buffer L 10  ; this will watch the first 10 bytes of
                        buffer in HEX

 For the given example, you should follow the previous command with the
 following:

    >wb *(buffer + 10) L 10  ; this will watch the next 10
                               bytes in HEX.

 Please note that both the length specifier as well as the number 10
 used to offset the pointer in the second command are taken in the
 current radix. The example above assumes a radix of 10. You can
 explicitly specify the base of the number in hex as follows:

    >wb *buffer L 0x0a
    >wb *(buffer + 0x0a) L 0x0a

 For more information on the wb command in CodeView, see the "Microsoft
 CodeView and Utilities, Microsoft Editor, Mixed-Language Programming
 Guide" manual.


 59. Specifying Both /T and /W Disables Mouse

 Product Version(s): 2.20    | 2.20
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified:  6-DEC-1988    ArticleIdent: Q38867

 If you invoke CodeView with the following, the use of your mouse is
 disabled:

    CV /T /W program

 Don't specify the /T switch. Using /T with /W produces mutually
 exclusive modes of operation.


 60. Illegal Instruction in CodeView

 Product Version(s): 1.x 2.00 2.10 2.20 | 2.20
 Operating System:   MS-DOS             | OS/2
 Flags: ENDUSER | S_C h_fortran S_PASCAL
 Last Modified:  6-DEC-1988    ArticleIdent: Q38868

 Question:

 When I compile and link my C program and try to run it under CodeView,
 execution stops on the open curly brace of main. The view then goes to
 assembly, and the message "Illegal instruction" appears in the dialog
 window. Is there something wrong with the startup code?

 Response:

 This error can be produced when the main module of a program is
 compiled for one memory model and is then explicitly linked with a
 library for a different model. When the startup code is linked to the
 entry point of the program, different size instructions are used for
 the different memory models. If the program expects one size and the
 linker links in a different size, the startup instructions will be
 misinterpreted and result in this error.


 61. Entering Double Words at a Prompt Prevents Reloading Program

 Product Version(s): 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER| | S_C S_PASCAL H_FORTRAN H_MASM buglist2.30
 Last Modified: 30-NOV-1989    ArticleIdent: Q50410

 When using the Enter Double word (ED) command within the CodeView
 symbolic debugger and allowing the debugger to prompt, you will
 prevent the debugger from reloading your executable (using the L
 command). This problem occurs only when you allow the debugger to
 prompt you for the double word and you enter a double word.

 This problem can manifest itself in several ways, depending on the
 version and on other unpredictable circumstances. Symptoms of the
 problem include the following:

 1. Giving the message "No such file/directory"

 2. Giving the message "Arg list too long"

 3. Generating an internal debugger error 7

 Valid workarounds consist of entering words (not double words) at the
 prompt, or entering double words on the command line (without being
 prompted).

 Microsoft has confirmed this to be a problem with CodeView Version
 2.30. We are researching this problem and will post new information
 here as it becomes available.


 62. CodeView 2.20 Does Not Allow Routine.Variable Specification

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_PASCAL S_C H_FORTRAN H_MASM DOCERR
 Last Modified: 10-NOV-1989    ArticleIdent: Q50698

 On Pages 91-92 of the "CodeView and Utilities" manual that accompanied
 C 5.10 and Pascal 4.00 for CodeView Version 2.20, the period is
 documented as being useful as a specifier of local variables in parent
 functions. The syntax is stated to be as follows:

    routine_name.variable_name

 However, this feature was not implemented in Version 2.20 of CodeView.
 It was implemented in CodeView Version 2.30 (which accompanied FORTRAN
 5.00).

 This feature is useful in all languages, but particularly helpful in
 Pascal because of the "nested-scoping" (the ability of a function to
 access variables from the routine that called it) that occurs in
 Pascal.

 To use this feature in CodeView 2.30, you must be in either the
 routine where the variable is defined or in a routine that is a child
 (or grandchild, etc.) of that routine. After entering the proper
 routine, any variable name can be referenced with a routine and
 variable name (see example below).

 program first (input, output) ;
 var a: integer ;            { Available throughout the program }

     procedure second ;
     var b: integer ;        { Available in second and third }

         procedure third ;
         var c: integer ;    { Available in third }

         begin
             a := 3 ;
             b := 3 ;
             c := 3 ;
         end ;

     begin
         a := 2 ;
         b := 2 ;
         third ;
     end ;

 begin
     a := 1 ;                { Cannot watch second/third variables }
     second ;
 end.

 When in procedure third, you can place a watch on the variables in
 procedure second in the following manner:

 w? second.b

 This will display the variable in procedure second. This variable
 cannot be displayed from the main program, however.


 63. Using a Debugging Terminal with CodeView

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-JAN-1989    ArticleIdent: Q39179

 It is possible to use either a dumb terminal or another machine (PC or
 Macintosh, running a communications package at 9600 baud) as a
 debugging terminal for CodeView. To take advantage of this option, do
 the following:

 1. Connect the second terminal to the com port (COM1 or COM2).

 2. Initialize the communications package to set up the
    second machine as a dumb terminal. Set the baud rate at
    9600.

 3. Start CodeView in either window or sequential mode.

 4. Redirect either the output ( >COM1 ) or both input and output
    ( =COM1 ) to the second terminal.

    If you redirect just the output to the second terminal, you will
    see the debugging output on the second terminal, and program output
    on the primary terminal. If you redirect input and output, you will
    also be able input program information (responses to prompts,
    input from the keyboard, etc.) on the primary terminal, and input
    CodeView information on the secondary terminal.

 5. Set your options and run the program.


 64. Pascal Version of CodeView Version 2.20

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_PasCal
 Last Modified: 14-AUG-1989    ArticleIdent: Q39181

 CodeView Version 2.20 is different for Pascal then the rest of the
 languages. The Pascal version of CodeView 2.20 is the only version
 that has the Pascal Expression Evaluator. The way you can determine
 whether you are running the Pascal version is that Pascal will appear
 under the Languages menu.

 If you have multiple Microsoft Languages, you do not have to keep
 multiple versions of CodeView on your system. CodeView Version 2.20 is
 compatible with all of our languages. However, there is one exception
 -- if you are using Microsoft Pascal, make sure you use the version
 that came with Pascal. It is the only version that has the Pascal
 Expression Evaluator and all of the other language evaluators.

 To check if the version you have is the Pascal version, invoke
 CodeView and pull down the Languages menu. If it lists Pascal in the
 menu, you are using the Pascal version that is compatible with all of
 the Microsoft languages.


 65. "." on the LIBPATH Eases DLL Debugging, But Not for CVP 2.20

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 10-NOV-1989    ArticleIdent: Q50711

 When debugging OS/2 DLLs with protected mode CodeView (CVP), you must
 specify each DLL on the command line with an /L switch, and the DLL
 must be in the current directory as well as in a directory on the
 LIBPATH as set in CONFIG.SYS.

 For ease of debugging, if you put a period ("."), which means the
 current directory, as one of the directories on your LIBPATH, then a
 DLL in the current directory will also be on the LIBPATH and you won't
 need to have two copies of a DLL present on disk for debugging.

 This method only works for versions of CVP beginning with 2.30. CVP
 Version 2.20 will not recognize DLLs in a "." LIBPATH directory.

 If a copy of the DLL called by the program being debugged is not in
 the current working directory, you will not be able to trace into the
 DLL. If a copy of the DLL is not in a LIBPATH directory, CodeView will
 not be able to find the DLL. In this case, instead of coming up in the
 usual "debugging mode," CodeView immediately exits and returns to the
 command prompt after several seconds.

 Many DLL debugging problems arise from the fact that the copy of a DLL
 that is on the LIBPATH may be inadvertently out of date compared to
 the version in the current directory that is being used for debugging.
 By putting a period on the LIBPATH, the current directory becomes a
 LIBPATH directory and only one copy of the DLL needs to exist, thus
 eliminating any DLL update inconsistencies.


 66. CodeView Trace Skips Statement Following Switch Statement

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified:  7-MAR-1990    ArticleIdent: Q59315

 CodeView incorrectly maps assembly level instructions to source code
 in the first statement following a switch statement with seven or more
 cases.

 As shown in the code sample below, the statement following the switch
 is executed correctly, but CodeView steps over the statement while
 tracing in source mode. In mixed source and assembly mode, the
 statement following the switch may be traced into.

 Sample Code
 -----------

 # include<stdio.h>

 void main(void)
 {

    short tag, marker;

    marker = 0;
    tag = 5;

    switch(tag){
       case 1:
          break;
       case 2:
          break;
       case 3:
          break;
       case 4:
          break;
       case 5:
          break;
       case 6:
          break;
       case 7:
          break;
       default:
          break;
    }

       marker = 2;

 }


 67. Using CodeView to Create Disassembled Program Listings

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 12-APR-1990    ArticleIdent: Q51323

 The following steps can be used to create an assembly listing of a
 program with CodeView:

 1. Begin CodeView in sequential mode by using the /T command-line
    switch.

 2. Specify a listing file to redirect CodeView output to by typing the
    redirection operator ">" followed by a filename at the dialog
    prompt. You may redirect the output directly to a printer by
    specifying the printer after the ">" (e.g., >PRN).

    (Note: From this point on, commands will not be viewable.)

 3. Use the Unassemble command "U" to disassemble the code and send a
    listing of the program to the output file. If you do not specify
    the starting address and the range to unassemble, CodeView will
    unassemble the next eight lines of code. See the CodeView
    documentation for more information on the Unassemble command.

 You can use this method on any files, whether or not they contain
 CodeView information. In this regard, you can create assembly listings
 of programs that were not created with a Microsoft compiler. Please
 also note that you cannot create assembly listings of instructions
 other than 8086 instructions.


 68. Debugging DLLs with Codeview

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 18-DEC-1989    ArticleIdent: Q51764

 To debug most DLLs (Dynamic Link Libraries) in CodeView, CVP
 (protected mode CodeView) Version 2.20 or later is required. For DLLs
 loaded via DosLoadModule(), CVP Version 2.30 or later is required.

 Invoke CodeView with the /L switch as follows:

    cvp /L dll1name /L dll2name main.exe

 Make sure that each DLL you want to trace into is specified by the /L
 option.

 CodeView cannot debug DLLs that have either IOPL or EXECUTEONLY
 specified with the CODE directive in the associated definition (.DEF)
 file. For DLLs that require these controls, the Kernel Debugger
 supplied with the SDK is required.

 Note: With CVP 2.30, pathnames cannot be specified for DLLs;
 therefore, the DLL must reside in the current directory. For more
 information, query on the following:

     CODEVIEW DLL LIBPATH


 69. Debugging Bound Applications

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 | 1.11 2.02.02 2.20 2.30
 Operating System:   MS-DOS                   | OS/2
 Flags: ENDUSER | TAR63888
 Last Modified: 14-AUG-1989    ArticleIdent: Q25219

 CodeView does not support the debugging of bound applications in real
 mode. However, CVP in protected mode will allow you to debug such
 applications.


 70. No Symbolic Information Generated for Pascal Units

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_pascal
 Last Modified: 12-JAN-1989    ArticleIdent: Q39811

 The Microsoft Pascal Compiler Version 4.00 generates no symbolic
 debugging information for Pascal Units. As a result, when tracing
 through a Pascal program Unit, attempting to access any local
 variables by using trace/watchpoints, dumps, examines, etc. yields a
 "symbol unknown" error.

 The only workaround is to transform the program Units into Modules.


 71. "Internal Debugger Error: 0" When Watching Structure Members

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist2.30 cv
 Last Modified: 29-DEC-1989    ArticleIdent: Q51834

 When watching a member of a structure using the "w?" or "?" commands,
 it is possible to get the message "internal debugger error: 0". When
 this happens, the only way to view the contents of the member is to
 use the "D" or "??" commands.

 Code Example
 ------------

 typedef struct {
    char *(*instruction)[];
    } *structype;

 structype mac;

 void main (void)
 {
 }

 If you set a watch on an element of the structure variable in the
 above program such as "w? mac->instruction[0]" (without the quotation
 marks) you'll get the message "internal debugger error: 0." Use the
 dump command "D" or the special "??" structure viewing command to look
 at the contents of the member.

 Microsoft has confirmed this to be a problem in CodeView Version 2.30.
 We are researching this problem and will post new information here as
 it becomes available.


 72. Incorrect Error Generated for Very Small COM Files

 Product Version(s): 2.00 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER | TAR65183 buglist2.00
 Last Modified: 21-AUG-1989    ArticleIdent: Q25365

 Problem:

 If my COM file is less than 8 bytes long and I try to load it into
 CodeView, I get the error message "Invalid executable file format -
 please relink."

 Response:

 This problem occurs only on COM files less than 8 bytes in length.

 Microsoft has confirmed this to be a problem with CodeView Version
 2.00. We are researching this problem and will post new information as
 it becomes available.


 73. Dual-Monitor Setup Requires 8-Bit Data Paths for Both Monitors

 Product Version(s): 1.00 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                   | OS/2
 Flags: ENDUSER | s_c s_pascal h_fortran h_masm b_basiccom
 Last Modified: 21-MAR-1990    ArticleIdent: Q51870

 When writing to a system that has a dual-monitor setup, you must make
 sure that both the monochrome monitor and the color monitor are using
 an 8-bit data path. In any dual-monitor write scheme, both display
 cards must be configured to write to a common data path (either both
 8-bit or both 16-bit mode). Today's monochrome adapters use 8-bit
 paths exclusively.

 Most display cards that use a 16-bit mode can autosense whether they
 are being written to in a dual-monitor mode, but some cards, such as
 the ATI VGA Wonder card, do not sense for this situation; therefore,
 you must set the card to an 8-bit path manually.

 If you are using dual monitors and you experience strange behavior
 such as garbage or blinking characters on the monochrome screen, make
 sure that your 16-bit video card is running in 8-bit mode.

 The most common use for a dual-monitor setup is for debugging graphics
 applications in CodeView.


 74. Retrieving Previously Entered Commands

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER | TAR65921
 Last Modified: 14-AUG-1989    ArticleIdent: Q25539

 Question:

 Is there a method to retrieve commands after typing them in once? For
 instance, if I type "d some_data_area l 40", I would like to retrieve
 the command without having to retype it. A suggested method would be
 to allow the user to scroll on the command, then press a key to make
 the command active.

 Response:

 The only way to retrieve commands is to highlight them with the mouse
 and press the INS key. This method inserts the command into the
 command line. We are considering making an easier way to scroll
 through the commands and may implement it in a future version.


 75. system() Call May Cause CodeView to Terminate Process

 Product Version(s): 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified: 22-JAN-1990    ArticleIdent: Q57867

 Using real-mode CodeView to trace over the system() run-time function
 will cause the debugger to terminate the parent process upon return
 from the child process in certain situations where the child does a
 multiple directory-level traversal.

 Instead of tracing, use the "Go" Command (F5) to run past the system()
 call. This procedure allows the program to run to completion.

 The program below demonstrates this problem, but it requires that
 TREE.COM be somewhere in the path. Compile the code with the /Zi and
 /Od options and use CodeView to trace into the program, using F8.
 After TREE.COM executes, CodeView will display the "Program terminated
 normally" message, preventing the last printf() from being executed.

 Microsoft has confirmed this to be a problem with CodeView Versions
 2.20 and 2.30. We are researching this problem and will post new
 information here as it becomes available.

 Code Example
 ------------

 #include <process.h>
 #include <stdio.h>

 void main (void)
 {
         printf ("This is the beginning of the program\n");
         printf ("Calling TREE.COM\n");
         system ("tree");

         /* This line will never be executed */
         printf ("Back from spawn\n");
 }


 76. CodeView Versions 2.10 to 2.30 Use Four Extra File Handles

 Product Version(s): 2.30 2.20 2.10 2.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-JAN-1990    ArticleIdent: Q25950

 Problem:

 CodeView Versions 2.00 to 2.30 seem to be using four additional file
 handles. The following program attempts to open 20 files, reporting
 its success or failure after each attempt:

     #include <stdio.h>
     #include <string.h>
     #include <stdlib.h>

     main()
     {
             FILE *streams[20];
             int i;
             char buffer[12];
             char *p;

             for (i = 0; i < 20; i++) {
                     p = itoa(i, buffer, 10);
                     p = strcat(buffer, ".dat");
                     streams[i] = fopen(buffer, "w+");
                     printf("streams[%d] = %d\n", i, streams[i]);
             }
     }

 Running outside of CodeView, the call to fopen() fails after 15
 streams have been opened. Running in CodeView Versions 1.x, the call
 fails after 15 files have been opened. However, in CodeView Versions
 2.00 to 2.30, it fails after 11 file handles have been opened.

 Response:

 CodeView Versions 2.00 to 2.30 require four file handles for their own
 use. Remember that MS-DOS itself has five preopened file handles. If
 you want to open more than 15 files, follow the steps specified in the
 C Version 5.10 README.DOC to modify the C start-up code to allow
 opening more than 20 files.


 77. Copying Text from Display Window to Dialog Window

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 12-JAN-1989    ArticleIdent: Q40110

 Question:

 Is it possible to copy text from the display window down to the dialog
 window to use at the command line in Microsoft CodeView?

 Response:

 Yes, if you have a mouse. You can highlight with the mouse the section
 of text you would like to copy and press the INSERT key. The
 highlighted text will appear in the dialog box.

 This is very useful if you have very long variable names that you want
 to watch and don't want to retype the long variable name each time.
 Simply type a w? on the command line, then highlight the variable name
 with the mouse and press the INSERT key.

 Strange behavior can occur if you use the SHIFT key in combination
 with the INSERT key. For example, if you use the INSERT key on the
 extended keyboard along with the SHIFT key, it works the same as using
 INSERT alone. However, if you turn NUM LOCK off on the keypad so you
 can you the INSERT key with the SHIFT key, you will get a zero instead
 of the string of text. To get the string of text, you have to turn NUM
 LOCK on. This seems backwards because with NUM LOCK on you would
 expect to get a zero, but you get the text.

 The workaround is not to use the SHIFT key in conjunction with the
 INSERT key. INSERT alone works correctly.


 78. OS2PATCH for CVP Not Needed in OS/2 Version 1.10.

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 14-NOV-1988    ArticleIdent: Q30976

    The OS2PATCH supplied with CodeView (protected) Versions 2.20 and
 2.30 allows you to use command 7 on machines with math coprocessors.
 This patch works only with OS/2 Version 1.00. The PTRACE feature was
 updated in Version 1.10, so this patch is not needed in OS/2 Version
 1.10.
    This patch only works on IBMs version of OS/2 1.00.  If they have
 a different version have them talk to the people who they received
 OS/2 from.  If it was from us then they need to systems languages
 support.
    Please refer to the file OS2PATCH.DOC for more information.



 79. I/O Redirection Under CV Not Supported Prior to Version 2.30

 Product Version(s): 1.x 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS             | OS/2
 Flags: ENDUSER |
 Last Modified: 23-JAN-1990    ArticleIdent: Q57870
 In versions of CodeView earlier than Version 2.30, it was not possible
 to redirect the input or output of the program being debugged. For
 example, a "filter" program that takes input from a file specified by
 the input redirection operator ("<") is hindered by this limitation
 under pre-2.30 CodeView because there is no way to specify that you
 want the redirection to apply to the application rather than to
 CodeView itself.

 In CodeView (CV) or protected-mode CodeView (CVP) Version 2.30,
 redirection on the command line following the program name is directed
 to the program being debugged. For example, invoking CodeView 2.30
 with the following command line

    CV test < test.dat

 causes all input to the program TEST.EXE to be read from the file
 TEST.DAT.

 Redirecting I/O to CodeView itself is useful for involved debugging
 sessions where many CodeView dialog commands can be put into a
 separate text file that is automatically read by CodeView during
 debugging. For instance, this method will allow a complicated
 debugging scenario to be accurately repeated any number of times.
 Prior to CV and CVP 2.30, this was the only type of redirection
 supported while debugging.

 Starting with CodeView 2.30, you can redirect I/O to both the
 application being debugged and to CodeView. The CodeView redirection
 is done with the /C command-line option, or from within CV itself with
 the redirection dialog commands ("<" and ">"). Since the /C switch
 allows you to specify CV dialog commands on the command line, you can
 specify the redirection at this point. For example, the following
 command line

    CV "/C<cv.dat" test < test.dat

 brings up CodeView with TEST.EXE as in the example above (with the
 TEST.EXE input coming from TEST.DAT), but this time CodeView also
 reads the debugging instructions to perform from the file CV.DAT.


 80. /2 and /O Switches Not Compatible

 Product Version(s): 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  9-NOV-1988    ArticleIdent: Q30978

    The UTILITY.DOC states that the /O switch is not compatible with
 the /2 switch. However, the SDK Installation Notes file uses the
 following code as the example of how to debug child processes:

     cvp /2 /O <program> <program arguments>

    This file recommends that the /2 switch be used when debugging PM
 applications. The UTILITY.DOC file is correct. You cannot use the /2
 and /O switches at the same time.


 81. CVP Prompts "SYS0197 OS/2 Not Configured..." Error Message

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  9-NOV-1988    ArticleIdent: Q31658

    When loading CodeView protected mode (CVP), the "SYS0197 OS/2 not
 configured to run this application" error message may appear. A
 request for help on 0197 prompts the "requires input/output privilege"
 message. You need to set IOPL=YES in CONFIG.SYS to run CVP.

    The following information is from the section titled "Microsoft(R)
 CodeView(R) Debugger" of the Microsoft C Version 5.10 UTILITY.DOC
 file, the FORTRAN Version 4.10 CVREADME.DOC file, and the Microsoft
 Macro Assembler Version 5.10 README.DOC file.

 CONFIG.SYS Setting for CVP
    To run the protected-mode CodeView debugger (CVP.EXE), you must
 have the following line in your CONFIG.SYS file:

    IOPL=YES



 82. Methods for Debugging Large Programs within the 640K DOS Limit

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-FEB-1990    ArticleIdent: Q57941
 Because of the 640K limit under DOS, it is common to run out of memory
 when trying to debug large programs with CodeView. CodeView requires
 over 200K of RAM, not including the program being debugged. In
 addition, the symbolic information added by compiling with the /Zi
 switch greatly increases the executable size of the program you are
 trying to debug.

 The following is a list of the possible ways of getting around the
 limited memory problems for debugging:

 1. Include full symbolic information only in those modules that
    contain source code that you are currently trying to debug. In
    other words, compile only those modules with the /Zi switch. For
    the other modules, compile with the /Zd option, to put only line
    number information in the object files.

 2. Use overlays to swap parts of your code in and out, even if it is
    just during the development process. You can always link without
    overlays once your application is debugged.

 3. If you have expanded memory, use it by invoking CodeView with the
    /E switch. To work properly with CodeView, you should have LIM EMS
    3.2 or (preferably) 4.0. Expanded memory is used for storing the
    symbolic information, which can be a great percentage of your .EXE
    size.

 4. Use the CVPACK utility, which is documented in the Update Section
    of the C 5.1 "Microsoft CodeView and Utilities Software Development
    Tools for MS OS/2 and MS-DOS Operating Systems Update" manual.
    CVPACK will compress the debug information in the file by removing
    duplicate references. Use the /p option to achieve maximum
    compression.

 In trying to obtain a workable solution, you can use any combination
 of the above methods. If adequate debugging is still impossible, then
 you might look into the following possibilities:

 5. Switch to the OS/2 operating system. This may be limited as far as
    how much real mode program debugging you can do, depending on how
    compatible your application is with protected mode requirements.

 6. You might look into MagicCV from Nu-Mega Technologies of New
    Hampshire. MagicCV requires a 386-based computer because it uses
    virtual-86 mode of the processor to run CodeView in extended
    memory. This method reportedly allows CodeView to use only about 8K
    of conventional DOS memory. It should be noted that Microsoft does
    not endorse MagicCV or make any claims as to its usage. The
    information is offered only as a potential option. Nu-Mega can be
    reached at (603) 888-2386.


 83. Problems with CodeView and Logitech Mouse with Older Drivers

 Product Version(s): 2.00 2.10 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 23-JAN-1990    ArticleIdent: Q31918

 Incompatibility problems have been reported with Logitech's mouse and
 CodeView. Some of the problems encountered are as follows:

 1. The Logitech mouse fails to function correctly with CodeView
    Version 2.20 when in 43-line mode. The characters within
    highlighted cells are incorrect until they are unhighlighted.

 2. When in either 43-line or 25-line mode, garbage characters are
    occasionally found at the DOS prompt following an exit from
    CodeView.

 The problems seem to be with Versions 3.20 and earlier of the Logitech
 mouse driver. An update of the mouse driver is available that corrects
 these problems. Logitech can be reached at (415) 795-0427. Logitech
 also has a bulletin board service, which may contain the latest driver
 and can be reached at (415) 795-0408.

 A Microsoft Mouse or 100 percent Microsoft-compatible mouse is
 required for use with CodeView. In addition, you must use Microsoft's
 mouse driver Version 6.00 or later, or a driver that exactly emulates
 these Microsoft drivers.


 84. Using the T Command to Echo CodeView Output

 Product Version(s): 2.00 2.10 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 16-NOV-1988    ArticleIdent: Q31919

    To generate and record a history of the source lines stepped
 through in the course of a debugging session, do the following:

    1. Start CodeView in sequential mode using the /T option.
    2. While in sequential mode, enter the Redirect Output (>) command,
 followed by a filename. If no filename is specified, then stdout will
 be assumed.
    3. If you wish to view the output as it is redirected, precede the
 redirection operator with the echo command (T).
    4. If a second redirection operator is specified, the redirection
 file is appended to rather than truncated before output.

    For more information on output redirection, refer to the "System
 Commands" section of the "Microsoft CodeView and Utilities" manual.

    The following example demonstrates this process:

 CV> T > log.dat  or T >> log.dat
 CV> t
 CV> t
 CV> t
 CV> .
 CV> .
 CV> .
 CV> q

    The lines traced will be written both to the console and to the log
 file.


 85. CHAIN Statement in Compiled BASIC Not Supported by CodeView

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | B_QuickBas B_BasicCom
 Last Modified: 16-NOV-1988    ArticleIdent: Q32265

    In Microsoft CodeView, when debugging compiled BASIC programs that
 CHAIN, you can view only the first program executed (the one given in
 the CV command line). The modules that are CHAINed-to cannot be viewed
 or stepped through, and their variables cannot be looked at, even if
 these modules are successfully executed. In fact, you cannot gain any
 information about the CHAINed modules, other than whether or not they
 execute correctly, unless you execute them separately in CodeView.
    This information applies to QuickBASIC Versions 4.00 and 4.00b,
 and the Microsoft BASIC Compiler Version 6.00 for MS-DOS and OS/2.



 86. CodeView Cannot Debug Source Code in Include Files

 Product Version(s): 1.00 1.10 1.11 2.00 2.02.02 2.10 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  9-NOV-1988    ArticleIdent: Q34922

 CodeView cannot debug source code in include files. This information
 is documented on Page 7 of the "Microsoft CodeView and Utilities"
 manual. The explanation for the restriction on include files says "You
 will not be able to use the CodeView debugger to debug source code in
 include files."

 This information means programs with include files that contain
 executable statements cannot be debugged with CodeView.

 The usual symptom of this problem is that after tracing or otherwise
 trying to execute your program, you will be viewing one of your
 include files instead of your normal source code. Repeated attempts
 to view the main or other source files will result in viewing the
 include file again.

 This is program design for the product. Microsoft's compilers do not
 generate symbolic information for code in include files. As a result,
 CodeView is confused by the discrepancies, and the subsequent behavior
 is unpredictable. Include files only can contain prototypes,
 declarations, #defines or #includes, etc.

 (Note that these items are all "nonexecutable" statements )

 Although it is valid C code, include files must not contain
 initializations or function definitions or other executable statements
 for CodeView to be able to debug your programs properly.


 87. No Symbolic Information Generated for Pascal Units

 Product Version(s): 2.10 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | s_pascal
 Last Modified:  8-MAR-1990    ArticleIdent: Q57943

 The Microsoft Pascal Compiler Version 4.00 does not generate symbolic
 debugging information for Pascal units. As a result, when tracing
 through a Pascal program unit, any attempt to access local variables
 by using trace/watchpoints, dumps, examines, etc. yields a "symbol
 unknown" error.

 The only workaround is to transform the program units into modules.


 88. CVP Accessing I/O Ports

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified: 14-AUG-1989    ArticleIdent: Q36885

 In the "Microsoft CodeView and Utilities Software Development Tools
 for the MS-DOS Operating System," Sections 6.6 and 10.5 discuss the
 Port Input and Port Output commands respectively. These commands
 function correctly in CV under MS-DOS. However, CVP under OS/2
 generates a protection violation when trying to access a port. The
 port input and output commands do not function in CVP Version 2.20
 under OS/2.

 Microsoft has confirmed this to be a problem in Version 2.20. We are
 researching this problem and will post new information as it becomes
 available.


 89. Using CodeView to Examine FORTRAN Arrays

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 14-AUG-1989    ArticleIdent: Q37548

 Question:

 I have allocated memory for a three-dimensional array in FORTRAN. How
 can I examine the contents of a row using CodeView?

 Response:

 You can use CodeView to display a single element of the array using
 ?arrayname(x,x,x), where "arrayname" consists of the first six
 characters of the array name and "(x,x,x)" must be a valid cell in the
 array.

 There is no way to display more than one cell of the array using this
 command. To display many cells, you must do a memory dump of the
 addresses where the array is stored. Use the examine command (X) to
 get the starting address of the array, and dump (D) to dump the
 elements.

 FORTRAN stores array elements in column-major order. Use the following
 formula to determine the address where any cell (i,j,k) is stored,
 where Max_Row is the maximum i possible and Max_Col is the maximum j
 possible:

     MemAddr = start_addr+(size of elements)*
                      (Max_Row((k-1)(Max_Col)+(j-1))+(i-1))

 "Size of elements" is the number of bytes of each element in the
 array.


 90. CodeView Unexpectedly Exits to DOS

 Product Version(s): 2.10 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  8-APR-1990    ArticleIdent: Q37566

 When debugging a program with CodeView, certain operations cause it to
 exit to DOS without giving any warning or error message. Some of the
 things that cause this behavior are trying to access help, setting a
 watch variable, and returning from a DOS shell.

 This problem occurs because not enough file handles are being
 allocated at boot time with "files=XX" in CONFIG.SYS. An error message
 is printed, but then over written before most people can see it.

 The solution is to make sure files are set to 20 in CONFIG.SYS.


 91. How CodeView Handles DosExitList Routines

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 12-JAN-1989    ArticleIdent: Q40270

 Question:

 CodeView does not seem to be executing my DosExitList. What should I
 do to execute the exit list?

 Response:

 If you are in your program and issue the GO command, your program
 executes to the end of your application, giving the message "Thread
 terminated normally." At this point, you can use the GO command or
 trace into your exit routine. However, if you would like to quit your
 program and go to your exit handler in the middle of executing your
 program, you have two choices.

 When you quit CodeView ("q"), your code including your DosExitList
 will not be executed. The first method to execute your DosExitList is
 the safest, but you are not able to trace through your exit routine.
 When you want to exit, type the following:

    ? myexithandler()

 This command executes the function "myexithandler", which is your
 DosExitList routine. After this command has been performed, you can
 quit CodeView ("q") because all of your cleanup has been accomplished.

 The second method, which is less reliable, is to modify the instruction
 pointer (IP) so that you can effectively jump to the end of your
 program. Before you do this, make certain that you are not in a
 subfunction. If you are not in main(), jumping to the end of the
 program causes problems with the stack. While in your main() routine,
 enter the following at the CodeView command line, where XXXX is the
 value of the IP when you are at the last curly brace at the end of
 your program:

    R IP XXXX

 This command causes a jump to the last curly brace; you can step
 through your program from there. This method allows you to step
 through your exit routine, but it is a little more risky.


 92. You Cannot Display Past Column 71 in CodeView

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-JAN-1989    ArticleIdent: Q40428

 Can I view my code beyond column 71 in CodeView like I can in the
 Microsoft editor?

 In CodeView Version 2.20, you cannot scroll your code to the right.
 You should either rewrite the source code or, if you used tabs in the
 source code, reduce the tab size with the # dialog command, as
 described on Page 240 of the "Microsoft CodeView and Utilities"
 manual.



 93. Display Command Returns Incorrect Result for FORTRAN Function

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified: 14-AUG-1989    ArticleIdent: Q40586

 The display command does not return correct values for the
 user-defined FORTRAN real functions in Microsoft CodeView.

 The display command calls integer functions and returns correct
 results.

 Microsoft has confirmed this to be a problem in Version 2.20. We are
 researching this problem and will post new information as it becomes
 available.

 The display command is discussed in Chapter 6 of the "Microsoft
 CodeView and Utilities" manual. The valid FORTRAN expressions for
 CodeView are discussed in the Chapter 4 of the same manual.


 94. CodeView Does Not Work with Grouped Code Segments

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | H_MASM
 Last Modified:  9-FEB-1989    ArticleIdent: Q40784

 When using MASM it is possible to associate various segments into a
 group; DGROUP is an example of this technique. Grouped data or stack
 segments do not affect CodeView, but CodeView does not recognize
 grouped code segments. The program will execute correctly under
 CodeView, but none of the CodeView functions will be available on the
 second and subsequent segments in the code group.

 The following code segment illustrates this behavior:

 codegroup  GROUP ASEG,BSEG
         assume cs:codegroup

 ASEG    SEGMENT WORD PUBLIC 'CODE'
 A:
         mov ax,1
         mov ax,1
         JMP B
 ASEG    ends

 ;   Will not be able to single step through this section
 BSEG    SEGMENT WORD PUBLIC 'CODE'
 B:      mov ax,1
         mov ax,1
         mov ax,1
         int 21h
 BSEG    ends
         end A

 Once the program executes into the BSEG segment, all CodeView
 functionality will be lost. You cannot set any breakpoints or single
 step through the BSEG segment of code. It appears that CodeView does
 not store any symbolic information for the BSEG segment. Any attempt
 to single step through this section of code will result in CodeView
 executing the BSEG segment of code until the program is completed.

 Microsoft is researching this problem and will post new information as
 it becomes available.


 95. CodeView and Video Pages

 Product Version(s): 2.00 2.10 2.20 | 2.20
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified:  2-MAR-1989    ArticleIdent: Q41101

 Question:

 Is there anyway to specify which video page CodeView uses? I have an
 application that uses video page one; I am not able to use CodeView
 with it because CodeView also uses video page one.

 Response:

 CodeView does not allow you to specify which video page it will use.
 As a result, any application that uses video page one conflicts with
 CodeView and the screen becomes corrupted.

 The recommend work around in this situation is to use the two monitor
 option for CodeView. This option allows CodeView to send the
 application's output to one screen while using the first screen for
 its own output.

 Another less desirable workaround would be to avoid the use of video
 page one in programs that will be used under CodeView.



 96. Removing CodeView Information from .LIBs and .EXEs

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | SR# G890207-11424
 Last Modified:  2-MAR-1989    ArticleIdent: Q41371

 Question:

 Is there a way to remove CodeView symbols from a .LIB or .EXE file?

 Response:

 Although there is no utility that removes CodeView information from
 libraries, EXEPACK will remove CodeView information from .EXE files in
 the course of packing them. You can also remove information from an
 .EXE file by relinking it without the /CODEVIEW option.

 The only way to remove CodeView information from a library is to
 recompile the source modules and use the LIB utility to rebuild the
 library.


 97. CodeView: Debugging Presentation Manager Printer Drivers

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 28-MAR-1989    ArticleIdent: Q42780

 To debug OS/2 Presentation Manager (PM) printer drivers, you must use
 the kernel debugger. Currently, PM printer drivers fall under the same
 category as lower-level device drivers. These device drivers cannot be
 debugged using the current version of CodeView.


 98. Dump Command on Arrays in FORTRAN Gives Syntax Error

 Product Version(s): 1.10 2.20 | 2.20
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | H_FORTRAN buglist2.20 buglist2.30
 Last Modified: 21-AUG-1989    ArticleIdent: Q42942

 Microsoft CodeView Versions 2.20 and 2.30 gives a "Syntax error" when
 attempting to use the Dump command on an array of dimension greater
 than 1.

 For example, issuing the DI i(1,3) command to dump the contents of an
 array element fails.

 To work around this problem use one of the following methods:

 1. Use the "?" command, as follows:

       ? i(1,3)

 2. Enclose each dimension index within parentheses and omit the comma,
    as follows:

       DI i((1)(3))

    DI i(1(3)) and DI i((1)3) are also acceptable.

    A three dimensional example would look like the following:

       DI j(1(2)3)

    Any permutation of the parenthesis around the index is sufficient.

 Microsoft has confirmed this to be a problem in Versions 2.20 and
 2.30. We are researching this problem and will post new information as
 it becomes available.


 99. CodeView Protect: /43 Switch Doesn't Work on VGA Adapters

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.20
 Last Modified: 18-APR-1989    ArticleIdent: Q43043

 The /43 switch for CodeView, used to debug in 43 line mode, is ignored
 when a VGA video adapter is being used under OS/2. This switch works
 properly as documented in DOS, or when an EGA adapter is being used.
 The /50 switch, used to debug in 50 line mode, also works properly as
 documented.

 If you wish to use CodeView Version 2.20 in 43 line mode under OS/2,
 the MODE command can be used first to set the entire screen group into
 43 line mode. Using MODE 80,43 at the OS/2 prompt will accomplish this
 result. Starting CodeView without any switches will then cause it to
 use the current video mode.

 Microsoft has confirmed this to be a problem in CodeView Protect
 Version 2.20. This feature is under review and will be considered for
 inclusion in a future release.


 100. CV: K Command in Secondary Module Sets Breakpoints in Main

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist2.20
 Last Modified:  6-APR-1989    ArticleIdent: Q43170

 In some cases the K (call stack) command will cause CodeView to become
 uncertain as to where to set breakpoints.

 If an attempt to set a breakpoint is made in a module of a
 multi-module program immediately after using the K command then the
 breakpoint will be set in the module containing main() instead of in
 the current module.

 If the corresponding line in the first module is not an executable
 line then CodeView will issue the expected beep to indicate that the
 breakpoint could not be set.

 If the corresponding line is an executable line then there will be no
 indication at all that the breakpoint has been set until that module
 is again in view. At that point the breakpoint will be highlighted as
 usual. This behavior will occur in any module accessed after the one
 containing main().

 Breakpoints will be set properly after using the K command if any
 stepping is performed, the view is changed, or the Calls menu is
 accessed.

 Microsoft is researching this problem and will post new information as
 it becomes available.


 101. Vertical Scroll Inactive with MODE CO40 and Dual Monitors

 Product Version(s): 2.x
 Operating System:   MS-DOS
 Flags: ENDUSER | S_C buglist2.20
 Last Modified: 18-APR-1989    ArticleIdent: Q43260

 While debugging a program using Microsoft CodeView and dual monitors,
 the vertical scroll bar is disabled when the video mode is set to
 40-line color text. This occurs if the mode is set either at the
 command line

    MODE CO40

 or from within a program as follows:

    _setvideomode(_TEXTC40);

 The scroll bar remains inactive until the mode is changed. This
 problem does not occur on a single monitor system or in any other
 video modes.

 Microsoft has confirmed this to be a problem in Version 2.20. We are
 researching the problem and will post new information as it becomes
 available.

 The following program demonstrates the problem:

 #include <graph.h>

 void main (void)
 {
   _setvideomode(_TEXTC40);
   _setvideomode(DEFAULTMODE);
 }



 102. Selecting Text for Use with Commands

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | docerr insert
 Last Modified:  9-APR-1990    ArticleIdent: Q59408

 In CodeView Versions 2.20 and 2.30, you supposedly can press the left
 mouse button to highlight the command to be copied, and then press the
 INS key to copy the command. However, this method works only with the
 mouse and not with the keyboard.

 On Page 64 of the "Microsoft FORTRAN CodeView and Utilities User's
 Guide" Version 5.0 manual, it incorrectly states that you can copy any
 text that appears in any window. This is incorrect because you can
 only copy text in the command window.


 103. CodeView: View Command Fails with Underscore in Filenames

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist2.20
 Last Modified:  3-MAY-1989    ArticleIdent: Q43508

 Assume that two source files, MAINPROG.C and FILE_NAM.C, have been
 compiled with CodeView information. The main function in MAINPROG.C
 calls a function in FILE_NAM.C.

 When the following command is executed in CodeView, CodeView responds
 with "syntax error":

    V.FILE_NAM.C

 When FILE_NAM.C is renamed and recompiled as FILENAM.C, the following
 command works properly, and the source code in FILENAM.C is displayed:

    V.FILENAM.C

 Attempts to open a file with an underscore character will work
 correctly through the "Open" menu in CodeView, but will fail with the
 View command.

 Microsoft has confirmed this to be a problem in Version 2.20. We are
 researching this problem and will post new information as it becomes
 available.


 104. Cannot Set Breakpoint on an Executable Line with CodeView 3.00

 Product Version(s): 3.00   | 3.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 19-APR-1990    ArticleIdent: Q60338

 If you cannot set a breakpoint on a particular line of code, make sure
 you have used the -Zi and -Od options to create executable code that
 has full CodeView debugging capabilities.

 Some code in the executable is concatenated if the -Od option is not
 used.

 Sample Code
 -----------

 #include <stdio.h>

 int foo();

 void main (void)
 {
    int a,b,c;

    a = foo();/* this line would be concatenated into the next */
    b = a + c;/* line to look like b=(a=foo())+c.              */
 }

 int foo()
 {
    return(10);
 }


 105. Commands Invoked with "?" Command Must Be Compiled with /Zi

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  3-MAY-1989    ArticleIdent: Q43556

 Invoking C functions in CodeView using the "?" command works as
 expected as long as the function is contained in a module that was
 compiled with /Zi for the CodeView information. However, if you invoke
 a run-time library function, CodeView returns the error message
 "syntax error."

 The reason for the error message is that the module containing the
 library function is not compiled with the CodeView option /Zi. The
 error message is not dependent on the fact that the function is in the
 library rather than being user-defined. If a user-defined function is
 contained in a module that is compiled without /Zi for the CodeView
 information and you try to invoke it with the "?" command, CodeView
 will return the same error message.

 The "?" command is formally referred to in the CodeView Utilities
 menu as the Display Expression command.


 106. CodeView May Single Step onto a Comment Line

 Product Version(s): 2.20   | 2.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist2.20
 Last Modified:  2-JUN-1989    ArticleIdent: Q43601

 When using CodeView to single step the following program, the current
 execution line will be put on the first comment line. CodeView should
 always skip over the comment line.

 The program is compiled as required for running in CodeView. The
 compiling command used could be the following:

    cl /Zi /Od test.c

 Microsoft has confirmed this to be a problem with CodeView Version
 2.20. We are researching the problem and will post new information as
 it becomes available.

 This problem has no effect on the application program's performance.

 The following is the program:

 /*   test.c   */
 #include <stdio.h>
 int i = 1 ;
 void main (void)
 {
 if ( i )
      i = 0 ;
      /* first comment line */
 else
      /* more comment */
      i = 1 ;
 }


 107. Returning Control to CodeView

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | CONTROL-C CONTROL+C CONTROL+BREAK CONTROL-BREAK ^C ^BREAK
 Last Modified:  3-MAY-1989    ArticleIdent: Q43648

 The following are two software methods of returning control to
 CodeView during program execution:

 1. Use the debug interrupt, interrupt 03, in your code. Interrupt 03
    is called a microprocessor (or logical) interrupt. It is the
    interrupt that CodeView uses to make breakpoints. Hard code
    interrupt 03 into your code in selected places where you want to
    return control to CodeView. The following sample program will
    demonstrate the technique. Note that a macro could easily be
    constructed to insert breakpoints where desired.

         #include <dos.h>
         #include <stdio.h>

         void main()
         {
             union REGS    inregs;
             int           i = 1;

             for( ;; )
             {
                 printf( "Loop iteration: %d\n", i++ );
                 int86( 0x03, &inregs, &inregs );
             }

 2. Use CTRL+C and CTRL+BREAK to return control to CodeView. This is
    a useful method for breaking out of a program is currently running
    or that has locked up.  The position in the source code to which
    you are returned depends on when you hit the ^C and what caused
    the system to hang, e.g. an infinite loop, a bad pointer, etc.
    Execution may be continued from this point in the usual manner
    (F5, F8, F10, etc.).

    Under OS/2 CTRL+BREAK does not return control to CodeView. CTRL+C
    may be used to abort a normally executing program but you cannot
    continue to debug from that point as you can in DOS.

 There is no hardware interrupt that will return control to CodeView.


 108. Cannot Open Source File Under CVP

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30 buglist2.4.1
 Last Modified: 18-SEP-1989    ArticleIdent: Q45135

 Problem:

 When using CodeView Protect (CVP) Version 2.20, I trace my program
 through a number of source files and after some number of files CVP is
 no longer able to open source files. When CVP gets into this
 situation, it automatically goes into mixed mode -- displaying line
 numbers but no source text. In this state, trying to use the "v"
 command to look at another (not previously looked at) file results in
 a red message box telling me that CVP can't open the file.

 Response:

 This is a problem with CVP Version 2.20 and 2.30. CVP is running into a
 file limit. To work around this problem, before you step out of the first
 module, open the source file containing the code you wish to debug and
 set a breakpoint there. Now "go" to this location by pressing the F5
 key. This procedure allows you to start debugging at a location deep
 into the file without opening multiple source files.

 Microsoft has confirmed this to be a problem with CodeView versions
 2.20 and 2.30. We are researching this problem and will post new
 information as it becomes available.


 109. Incorrect Handling of SP Can Cause CodeView to Corrupt Stack

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  7-JUN-1989    ArticleIdent: Q45183

 CodeView will use your program's stack for temporary variables in
 between assembly instructions. Thus, when writing an assembly language
 program, if you forget to increase the stack pointer (SP) to point
 beyond the memory locations you are using on the stack, CodeView will
 overwrite that memory.

 This is expected behavior. Even if CodeView did not use the stack, you
 would still have to increment the stack pointer to keep your program
 from overwriting your variables when you make a call, or with any
 operation that pushes values on the stack.


 110. Switching Out of PM Application Hangs System under Codeview

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 16-MAY-1989    ArticleIdent: Q44418

 Question:

 I am using CodeView to debug my Presentation Manager (PM) application.
 Why does my machine sometimes hang when I use CTRL+ESC to switch to
 the OS/2 program selector?

 Response:

 Presentation Manager applications require the use of the Presentation
 Manager shell. To debug PM applications, CodeView must put hooks into
 the Presentation Manager before the PM application is executed. This
 process works properly while inside CodeView, but if you try to switch
 back to the program selector, PM is in an unknown execution state.

 Therefore, to switch out of CodeView while debugging a PM application,
 you must first restart or end the program inside CodeView. This tells
 CodeView to restore the Presentation Manager to its original
 condition.


 111. SYS0317 Caused by Running CVP on a DOS Application

 Product Version(s): 2.20
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 31-MAY-1989    ArticleIdent: Q44707

 The following message results from running a DOS application under
 Microsoft CodeView Version 2.20 or 2.30 for protected mode:

    SYS0317: The system cannot find message 0491
    in message file OSO001.MSG

 The screen is then cleared and the OS/2 prompt returns.


 112. /43 Starts CodeView with Screen Swapping Enabled

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified:  7-JUN-1989    ArticleIdent: Q45185

 When CodeView is started with the /43 switch to bring it up in 43-line
 mode, screen swapping is automatically enabled. This behavior is by
 design, although it is not stated in the documentation for the
 product.


 113. Setting a Breakpoint Highlights More Than One Line

 Product Version(s): 2.20
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist2.20
 Last Modified:  7-JUN-1989    ArticleIdent: Q45241

 When setting a breakpoint, CodeView may highlight two or more lines of
 code when you do the following:

 1. Compile C program (e.g., "Hello, world") with /Zi /Od.

 2. Load CodeView with 50 line mode (in VGA mode) as follows:

       cv /50 hello.c).

 3. Display mixed source and assembly.

 4. Move the cursor to the edit window and scroll down two or three
    pages of start-up assembly code.

 5. Set and remove breakpoints at arbitrary locations. In some cases,
    multiple lines will be highlighted and the display altered. The
    code itself is not changed. To restore the altered display, page
    down and then page up to the altered location.

 CVP does display this problem.

 Microsoft has confirmed this to be a problem in CodeView Version 2.20.
 We are researching this problem and will post more new as it becomes
 available.

 After setting a breakpoint that highlights more than one line of code,
 using the BL command will list only the one breakpoint you set.


 114. "No Symbolic Information" May Be Caused by Using Wrong Linker

 Product Version(s): 1.00 1.10 2.00 2.10 2.20 2.30 2.35 | 2.20 2.30 2.35
 Operating System:   MS-DOS                             | OS/2
 Flags: ENDUSER | S_LINK
 Last Modified: 19-SEP-1990    ArticleIdent: Q59540

 To debug programs at the source level with CodeView, it is critical
 that a proper version of LINK be used. Particular versions of CodeView
 are matched to particular versions of LINK and using a version of LINK
 newer than the versions matched to a particular version of CodeView
 will prevent CodeView from recognizing the symbolic information in the
 .EXE file.

 This mismatch will cause CodeView to come up in assembly mode and
 produce the message "No Symbolic Information," even though the source
 files may have been compiled and linked with the correct options for
 CodeView symbolic debugging.

 The difference between the linkers is in the way they store symbolic
 information in .EXE files. A newer version of CodeView generally can
 always display symbolic information for programs produced with
 previous versions of LINK, but the opposite is NOT true. Using a more
 recent linker with an older version of CodeView is where potential
 problems arise.

 The following information applies to both real-mode CodeView (CV) and
 protected-mode CodeView (CVP).

 Versions of CodeView prior to Version 3.00 cannot display symbolic
 information for .EXE files produced with LINK 5.10. In other words,
 if LINK 5.10 (supplied with C 6.00) is used for linking, then
 CodeView 3.00 is the ONLY matched version of CodeView that can
 display the program's symbolic information.

 CodeView Version 2.35 is matched to LINK 5.05 (both were released with
 BASIC 7.00). Therefore, CodeView 2.35 is the ONLY version of CodeView
 that can display symbolic information for a program linked with LINK
 5.05.

 For CodeView Versions 2.00, 2.10, 2.20, and 2.30, any linker with a
 version number from 3.60 to 5.03 is acceptable.

 For CodeView Versions 1.00 and 1.10, LINK versions later than or equal
 to 3.51, but earlier than 3.60, must be used.


 115. Mouse Disabled When Single-Stepping over Video Mode Change

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.20 buglist2.30
 Last Modified: 21-JUN-1989    ArticleIdent: Q45617

 When CodeView is run in the OS/2 compatibility box with screen
 swapping enabled (started with either /s or /43), single-stepping (F8)
 over a _setvideomode() call or an INT 10 call to change the video mode
 to a graphics mode causes the mouse cursor to disappear. Exiting
 CodeView and running another mouse-driven program reveals that the
 mouse has been completely disabled in the compatibility box. The only
 way to regain the mouse is to reboot the computer. Attempting to
 reload the mouse by typing "mouse" at a prompt results in the
 following message:

    Session Title: DOS Command Prompt

 This error occurs because a DOS mode program changes an interrupt
 vector that is owned by the system causing the program to end.

 The behavior described above applies to tracing in SOURCE mode.
 Attempting to trace in assembly language or mixed mode through the
 code that changes the video mode produces erratic results, which range
 from hanging the DOS box to halting the entire system with an
 "internal processing error."

 Microsoft has confirmed this to be a problem in CodeView Versions 2.20
 and 2.30. We are researching this problem and will post new information
 as it becomes available.

 The following program illustrates the problem:

 #include <graph.h>

 void main(void)
 {
   _setvideomode(_ERESCOLOR);    /* when this line is executed, the  */
                                 /* mouse cursor will disappear.     */
   _setvideomode(_DEFAULTMODE);

 }


 116. CodeView "??" Command Can't Show All of Large Structures

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | SR# G890607-19918
 Last Modified:  8-AUG-1989    ArticleIdent: Q45624

 Question:

 How can I view structures with many members in CodeView with the "??"
 command? It shows only those members that fit on the screen. Is there
 some trick I haven't found?

 Response:

 Unfortunately, the "??" command is limited in this respect -- there is
 no way to view the last members of a large structure with this
 command. This feature is under review and will be considered for
 inclusion in a future release.

 Instead, however, you can view each element of the structure by itself
 by dereferencing the struct and element, i.e., "?structname.field".

 There are at least two ways to work around the problem in CodeView
 Versions 2.20 and 2.30. One way is to shrink or nest the structures.
 Another workaround is to use the "?" or Watch command to look at the
 individual member(s) you want to see.


 117. Problem Debugging StartSession from a Child Process

 Product Version(s): 2.30
 Operating System:   OS/2
 Flags: ENDUSER | buglist2.30
 Last Modified:  9-AUG-1989    ArticleIdent: Q45707

 When a program spawns another program that starts a new session,
 CodeView has difficulty stepping into that new session. This process
 is shown graphically in the following diagram:

        --------------        -------------------
    A --| DosExecPgm |--> B --| DosStartSession |--> C
        --------------        -------------------

 The following describes how to duplicate this process and re-create
 the problem:

 1. Invoke CodeView on Program A with offspring debugging enabled, as
    follows:

       CVP /O A

 2. Program A calls DosExecPgm to spawn Program B. Trace into Program B
    by pressing F8 on the DosExecPgm function. You will be informed
    that a new process has begun and you will be asked if you wish to
    debug it. Answer yes and switch to the newly created CodeView
    session.

 3. Program B calls DosStartSession to begin a new session. The program
    that will execute in that session is Program C. Attempt to trace
    into the new session by pressing F8 on the DosStartSession function.

 The problem is demonstrated in Step 3. CodeView does not give you the
 opportunity to debug Program C as it should. Further, when Program B
 has completed execution and CodeView returns back to Program A, the
 first single step will inform you that a new process has been started.
 This message should have been presented on the call to
 DosStartSession.

 CodeView has no difficulty stepping into a new session when the
 initial program being debugged is Program B. To work around this
 problem, invoke CodeView on Program B with the /O switch.

 Microsoft has confirmed this to be a problem with CodeView Version
 2.30. We are researching this problem and will post new information
 as it becomes available.

 The following three modules demonstrate this problem:

 //***********************************************************
 // A.C - spawn a child from here.

 #define INCL_BASE
 #include <os2.h>

 void main (void)
 {
   char        failbuf[80];
   RESULTCODES ExecCode;

   DosExecPgm (failbuf, 40, EXEC_ASYNC, NULL, NULL, &ExecCode, "B.EXE");
   VioWrtTTY ("End of A.\r\n", 11, 0);
 }

 //***********************************************************
 // B.C - start a new session from here.

 #define INCL_BASE
 #include <os2.h>
 #include <string.h>

 void main (void)
 {
   USHORT    Disk;
   ULONG     Drives;
   BYTE      SessionProg [80];
   USHORT    MaxLen = sizeof(SessionProg)-14;
   STARTDATA StartData;
   USHORT    Session;
   USHORT    Process;

   // Build program name to run in new session.
   DosQCurDisk (&Disk, &Drives);
   strcpy (SessionProg, "*:\\");
   SessionProg[0] = (char) ('A' + Disk - 1);
   DosQCurDir (0, SessionProg + strlen(SessionProg), &MaxLen);
   strcat (SessionProg, "\\C.EXE");

   StartData.Length      = sizeof(STARTDATA);
   StartData.Related     = 1;
   StartData.FgBg        = 0;
   StartData.TraceOpt    = 0;
   StartData.PgmTitle    = "Test Session";
   StartData.PgmName     = SessionProg;
   StartData.PgmInputs   = "sample param";
   StartData.TermQ       = NULL;
   StartData.Environment = NULL;
   StartData.InheritOpt  = 0;
   StartData.SessionType = 1;
   StartData.IconFile    = NULL;
   StartData.PgmHandle   = 0;

   DosStartSession (&StartData, &Session, &Process);
   VioWrtTTY ("End of B.\r\n", 11, 0);
 }

 //***********************************************************
 // C.C - the test session.

 #define INCL_VIO
 #include <os2.h>

 void main (void)
 {
   VioWrtTTY ("In test session", 15, 0);
 }


 118. CodeView Skips Over a Line of Source Code

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | S_QuickC
 Last Modified: 14-AUG-1989    ArticleIdent: Q46010

 After setting a breakpoint on the indicated line in the program below
 and executing the program, CodeView executes that line without
 stopping. Likewise, if you single step through the code, CodeView
 steps past that line. This problem also occurs in the QuickC
 integrated debugger.

 The workaround is to flip your source into mixed mode and set the
 breakpoint on the correct assembly line.

 This is due to the fact that CodeView is line-based and the C compiler
 is token-based. This will not be corrected; it is a restriction.

 Sample Program
 --------------

 int i, j, k, l;

 void main(void)
 {
     for(i = 0; i < 20; i++)
     {
         j = 0;
         for(k = 0; k < 20; k++)
             if(j == 0)
                 break;

         j = 1; /*** set breakpoint here ***/
     }

     l = 0;
 }


 119. Capabilities and Limits of the /R switch on 80386 Machines

 Product Version(s): 2.20 2.30 2.35 3.00 | 2.20 2.30 2.35 3.00
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER | 386
 Last Modified: 12-APR-1990    ArticleIdent: Q46448

 The /R command line switch for CodeView beginning with Version 2.20 is
 used only on 80386 machines. The /R switch tells CodeView to use the
 four debug registers available on the 80386 chip, and also allows
 hardware breakpoints. This causes CodeView to run faster when
 performing debugger-intensive steps such as monitoring a tracepoint.

 The /R switch works under DOS and OS/2's DOS compatibility box. It is
 an unrecognized switch under OS/2. The /R switch speeds operation of
 Tracepoint but not Watchpoint or Breakpoint commands.

 Note: because there are only four debug registers, only four
 tracepoints (of up to 4 bytes each) may be specified when utilizing
 these registers. Specifying any combination of tracepoints greater
 than 16 bytes will require CodeView to use software tracepoints rather
 than the debug registers and all performance gains will be lost.


 120. Using CodeView /2 with Hercules Graphics Cards and Libraries

 Product Version(s): 2.20 2.30
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 16-OCT-1990    ArticleIdent: Q46949

 Using CodeView in the dual-monitor mode with a Hercules graphics card
 as the primary (application) monitor requires the Hercules card to be
 configured in the half mode. Using the Hercules graphics library, the
 monitor must be configured using the config(0) function call. This
 function call is a part of the Hercules graphics library and does not
 use Microsoft graphics library or the MSHERC.COM program. Therefore,
 this information applies only if you are using the Hercules graphics
 libraries. This is NOT the same as using the /h switch with CodeView.

 The first page of the Hercules graphics display card is mapped to
 memory location B0000 (same as MDA), and the second page is mapped to
 B8000. The CGA/EGA/VGA also use B8000 as the beginning of their video
 memory. CodeView uses these two different address to run in the
 dual-monitor mode, sending the application output to the primary
 address, usually located at B8000, and the CodeView information to the
 secondary monitor, usually located at B0000.

 This works well until a Hercules graphics card is used as the primary
 monitor (in graphics mode) and the CGA/EGA/VGA card is used as the
 secondary monitor. The Hercules graphics card uses both pages (one at
 B0000 and the other at B8000) in the full mode. Therefore, use
 config(0) and only the first page (B0000) will be used and CodeView
 will function properly in dual-monitor mode.


 121. DEF File Entry of EXECUTEONLY Causes Problems with CVP

 Product Version(s): 2.20 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 30-AUG-1989    ArticleIdent: Q47103

 Question:

 When I step into my DLL, I can see and step through the source code
 correctly. I also can look at local variables. However, I cannot set
 breakpoints in the DLL. Also, when I try to look at the disassembled
 code I see the following:

    ??? No Code ???

 I am using the correct Compile and Link options. Why is CodeView
 acting strangely?

 Response:

 In the .DEF file for the DLL, you had the EXECUTEONLY attribute as
 opposed to the default EXECUTEREAD. When you choose EXECUTEONLY,
 CodeView cannot read the code segment as it must to work correctly.
 Removing the EXECUTEONLY attribute corrects the problem.


 122. OS/2 SDK Version of CVP 2.30 Won't Debug DosLoadModule DLLs

 Product Version(s): 2.30
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 11-JUL-1990    ArticleIdent: Q59610

 The OS/2 version 1.10 Software Development Kit (SDK) includes a
 prerelease version of protected-mode CodeView (CVP) version 2.30. This
 version is identical to the regular retail release of CVP 2.30, except
 that it does not allow the debugging of DLLs loaded with
 DosLoadModule. The regular retail version of CVP 2.30 is included with
 FORTRAN 5.00 and the OS/2 Presentation Manager Toolkit for OS/2
 version 1.10. This release DOES support debugging DLLs loaded at run
 time with DosLoadModule.

 The prerelease version of CVP 2.30 released in the OS/2 SDK may be
 identified by a file date of 2-24-89. The regular release version is
 dated 3-21-89. The file date is the only discernible difference
 between these two versions since the files themselves are exactly the
 same size.


 123. Minimum Extended Memory (384K) Causes CV 3.00 to Use Extra RAM

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr HIMEM
 Last Modified: 27-SEP-1990    ArticleIdent: Q59890

 Real-mode CodeView (CV) Version 3.00 is documented as being able to
 run in extended memory as long as there is at least 384K of extended
 memory available. This 384K minimum is accurate as far as CV being
 able to utilize the extended memory, but it is not enough for CodeView
 to remove all of itself from conventional RAM. In fact, a system
 configuration with only 384K extended memory will result in LESS
 memory being available for the debuggee (the program being debugged)
 than if no extended memory is utilized at all.

 The CodeView 3.00 documentation states that "if HIMEM.SYS or another
 extended-memory driver is installed, all but 16K of CodeView, plus all
 of the symbolic information for the program you are debugging, are
 placed in extended memory." But, for CodeView to truly work with this
 16K "footprint" in conventional memory, a minimum of approximately
 600K extended memory must be available.

 When no extended memory is available, CodeView normally utilizes
 overlays to keep as much of itself out of memory as possible, so that
 the debuggee can have more space to load. (The new /Dnnn option
 actually allows you to specify the size of the overlays -- a bigger
 overlays means CV runs faster, but a smaller overlays mean a bigger
 program can be loaded for debugging.)

 Once CodeView detects extended memory, it assumes that overlays are no
 longer needed, since CV itself and the debuggee's symbolic information
 will both (supposedly) be loaded into extended memory. However, the
 result may be that CodeView seems to get bigger because what Codeview
 can't fit into extended memory is loaded into conventional memory.

 Since no overlays are used, this can result in a much larger
 footprint. For instance, if the minimum of 384K extended memory is all
 that is available, then the footprint will be well over 200K.
 Obviously, as the amount of extended memory is increased from 384K,
 the footprint will shrink accordingly.

 The /X command-line option instructs CodeView to use extended memory.
 However, CV will automatically detect extended memory and use it if it
 is available. Consequently, if the /X option is not specified, CodeView
 will still use extended memory.

 Thus, if you have a limited amount of extended memory and decide to
 run CodeView in conventional RAM only, you have two options. You can
 explicitly specify /D (for example, /D16) to tell CodeView to use
 overlays, or you can remove (or comment out) the line in your
 CONFIG.SYS file that loads the extended memory driver (HIMEM.SYS) and
 reboot.


 124. If COMSPEC Is Invalid, Invoking DOS Shell May Hang Machine

 Product Version(s): 2.x 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | s_quickc s_pwb s_quickasm s_editor
 Last Modified: 19-APR-1990    ArticleIdent: Q60748

 If you set your COMSPEC environment variable to point to an invalid
 command interpreter, and then shell out of any DOS application, your
 machine will hang. This problem occurs because the file that COMSPEC
 points to is assumed to be a valid command interpreter and cannot be
 checked for validity.

 This is expected behavior. Because .COM files have no standard file
 header structure, they cannot be checked for validity. Therefore, DOS
 must assume that whatever the COMSPEC environment variable points to
 must be a valid command interpreter, and can do no further error
 checking.

 This behavior can easily be demonstrated in any program that allows
 you to access a DOS shell, including CodeView, Programmer's WorkBench
 (PWB), the Microsoft Editor (M), and the Quick environments. Type the
 following line at the DOS prompt:

    set comspec=a:\foo.c ; Invalid command.com file

 Then enter a DOS application and shell out. Your machine will hang,
 and you may receive strange error messages.

 If you are running under OS/2, you will be warned about an invalid
 command interpreter when you attempt to shell to the operating system.
 Under OS/2, the system expects an .EXE file to be the command
 interpreter, and .EXE files have a standard, recognizable structure
 that can be checked.


 125. /I Documented Incorrectly in "Advanced Programming Techniques"

 Product Version(s): 3.00   | 3.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 19-APR-1990    ArticleIdent: Q60829

 In Section 9.7, "Controlling CodeView with Command-Line Options," on
 Page 204 of the "Microsoft C Advanced Programming Techniques" manual,
 it incorrectly states that the /I switch (used to turn the nonmaskable
 interrupts and 8259 interrupts on or off) is followed by either a 1 or
 a 2 (either /I1 or /I2).

 The correct switch options are /I0 to trap these interrupts, or /I1 to
 ignore these interrupts. Both the online documentation and the
 "Microsoft C Reference" give this correct usage of the /I switch.


 126. OS/2 1.20 Requirements for Dual-Monitor Debugging

 Product Version(s): 2.x 3.00
 Operating System:   OS/2
 Flags: ENDUSER | PM
 Last Modified: 17-JUL-1990    ArticleIdent: Q60866

 To do dual-monitor debugging under OS/2 Version 1.20 with CodeView,
 make sure that you have the correct display DLLs specified in your
 CONFIG.SYS file.

 For example, the following three lines in your OS/2 CONFIG.SYS file
 specify the device drivers needed to use a VGA and a monochrome
 adapter:

    set video_devices=bvh_vga,bvh_mpa
    set bvh_vga=device(bvhvga)
    set bvh_mpa=device(bvhmpa)

 If you have a CGA or an EGA monitor and adapter for your primary
 (color) display, replace device(bvhvga) with device(bvhcga) or
 device(bvhega), depending on your adapter type.

 Next, make sure that both of the BVH*.DLL files (in the above case,
 BVHVGA.DLL and BVHMPA.DLL) specified in the device(name) section are
 in your LIBPATH. OS/2 setup places these files in your C:\OS2\DLL
 directory by default.

 Note: You can substitute any name for bvh_vga or bvh_mpa, as long as
 those two placeholders match up with the name tab in the set
 <name>=device... lines.

 Remember, the two monitors must be unique for OS/2 to determine which
 monitor is which. For instance, debugging with two VGA monitors will
 not work because OS/2 and, therefore, CodeView will be unable to
 determine which adapter/monitor is the primary adapter/monitor and
 which is the secondary adapter/monitor.

 This point is critical to remember when considering dual-monitor
 debugging on a microchannel machine (for example, an IBM PS/2 Model 50
 and above). Since there are currently no microchannel monochrome
 adapter cards on the market, the only alternative is to use a VGA and
 an 8514 as the two monitors. The following are the matching three
 lines for your OS/2 CONFIG.SYS file for that scenario:

    set video_devices=bvh_vga,bvh_8514
    set bvh_8514=device(bvh8514)
    set bvh_vga=device(bvhvga)

 Using this setup, the 8514 monitor displays the graphics output (or
 the Presentation Manager screen) and the VGA is the debug monitor and
 displays all text output.


 127. Debugging Large DOS Applications in CodeView 3.0 with /X /E /D

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-MAY-1990    ArticleIdent: Q61473

 CodeView version 3.00 includes enhanced support for debugging
 applications under DOS. CodeView 3.00 may access extended memory or
 expanded memory, or the size of the overlay swap area that CodeView
 uses may be adjusted.

 CodeView 3.00 offers three command-line parameters (/X, /E, and /D)
 for specifying memory utilization. If you DO NOT specify the /X, /E,
 or /D options when you start a CodeView session, CodeView will
 automatically search for extended memory. If CodeView finds extended
 memory, it will place the symbolic information and most of itself into
 extended memory (as long as enough extended memory is available).

 If there is no extended memory on your system, Codeview will search
 for expanded memory. If there is expanded memory, Codeview will place
 the symbolic information for your program in expanded memory.

 If there is no extended or expanded memory on your machine, CodeView
 will load itself, your application, and symbolic information for your
 program in base memory.

 Since CodeView does this automatic scan for extended and expanded
 memory, the /X and /E switches are needed only if you explicitly want
 to specify the use of one form of memory or the other and you do not
 want to enter CodeView if this memory type is not available.

 CodeView's /X option tells the debugger to load into extended memory
 ONLY, and to return an error message if extended memory is not
 available on your system. This message has the following form:

    CV1302 Error: /X : HIMEM.SYS not loaded

 CodeView's /E option tells the debugger to access expanded memory
 ONLY, and to return an error message if there is no expanded memory on
 your machine. This message has the following form:

    CV1304 Error: /E : EMM driver not loaded

 CodeView's /D option specifies that CodeView should use disk overlays.
 When you use this option, you can also specify a decimal size in
 kilobytes between 16K and 128K to explicitly set the overlay swap area
 size. The default size of the swap area is 64K if /D is used but no
 size is explicitly specified. If extended and expanded memory are not
 available, /D will not need to be specified for the default 64K
 overlay swap area to be used.

 A larger overlay swap area allows CodeView to run faster because it
 doesn't have to swap to disk as frequently as with a smaller swap
 area, but it means more memory is used up by CodeView itself. A
 smaller swap area allows you to debug larger applications under DOS,
 but CodeView runs slower because of the more frequent need to swap
 code from disk to memory.


 128. P70 Display Creates Problems Under CodeView and PWB

 Product Version(s): 3.00
 Operating System:   OS/2
 Flags: ENDUSER | buglist3.00 S_PWB S_Editor
 Last Modified: 15-AUG-1990    ArticleIdent: Q61557

 CodeView version 3.00 and Programmer's WorkBench (PWB) version 1.00
 have problems recognizing the built-in monitor of IBM P70 portables
 under OS/2. Symptoms of this problem include the following error
 messages:

    Product     Error Message
    -------     -------------

    CodeView    Internal Debugger Error 0 at load time
    PWB         Inability to change from 43-line mode

 Microsoft has confirmed this to be a problem with CodeView version
 3.00. We are researching this problem and will post new information
 here as it becomes available.

 This problem is directly related to the video configuration of the IBM
 P70. In its documentation, IBM mentions briefly that it might be
 necessary to type MODE CO80 to make some software recognize the
 built-in plasma display. An added condition for PWB and CodeView is
 the necessity of being in 43-line mode. PWB automatically places you
 in 43-line mode no matter what you previous mode was and thus gets
 around this limitation. If you attempts to change the height switch
 while editing, PWB doesn't complain but still stays in 43-line mode.

 CodeView cannot make the mode change in the same way that PWB can. If
 invoked without the above considerations, CodeView will crash with an
 Internal Debugger Error 0. The following are several ways to work
 around this problem if want to use CodeView with this type of
 configuration.

 1. Type MODE CO80 or BW80 and invoke CodeView with the /43 switch.

 2. Type MODE CO80,43 or BW80,43 before invoking CodeView.

 3. Use an external monitor with the built-in VGA port.

 4. Invoke CodeView from PWB, which makes the change automatically.


 129. CodeView Does Not Reset Initial Graphics Mode on Exit

 Product Version(s): 2.x 3.00    | 2.x 3.00
 Operating System:   MS-DOS      | OS/2
 Flags: ENDUSER |
 Last Modified: 29-MAY-1990    ArticleIdent: Q61611

 When CodeView exits, it leaves the screen in the current video mode
 and does not reset the mode to the mode that was active when CodeView
 was initially loaded.

 This behavior is by design. However, if you start CodeView with the /s
 option to enable screen swapping, the video mode that was active when
 CodeView was loaded will be reset because CodeView has separate
 swappable video memory pages to hold the output screen as well as the
 CodeView screen.


 130. CV 3.00 Gives R6000, Hangs When Accessing Help During Start-Up

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 fixlist3.10
 Last Modified:  5-FEB-1991    ArticleIdent: Q61919

 Accessing help in the "Enter directory for filename.c (cr for none)?"
 window results in the following error in CodeView version 3.00:

    run-time error R6000
    -stack overflow

 Then, the machine hangs requiring a cold reboot.

 To reproduce the error, do the following:

 1. Compile and link a program with symbolic information for CodeView.

 2. Delete or rename the source file and then go into CodeView. A
    window will appear asking you to "Enter directory for filename.c
    (cr for none)?".

 3. Choose the Help option at the bottom of the window. The run-time
    error message will be printed over the CodeView screen and the machine
    will be hung.

 The problem does not occur under OS/2.

 Microsoft has confirmed this to be a problem in CodeView version 3.00.
 This problem was corrected in CodeView version 3.10.


 131. CodeView 3.00 Fades with Monochrome VGA

 Product Version(s): 3.00   | 3.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 11-JUL-1990    ArticleIdent: Q61970

 If you invoke CodeView version 3.00 on certain machines with
 monochrome VGA monitors and then trace through several lines of code,
 the screen will fade and become unreadable. Exiting and re-entering
 CodeView refreshes the screen, but the screen immediately starts to
 fade again.

 This problem is caused by an error in the video ROM BIOS and has been
 verified to occur on the following machines:

 l. PS/2 Model P70 with monochrome VGA

 2. Siemens with Video 7 monochrome VGA

 3. Northgate 386 with Video 16 monochrome VGA

 The following are different methods of working around this problem:

 1. Switch into color mode using the mode CO80 command (may not have
    any effect).

 2. From the options menu inside Codeview, turn flip/swap off using
    the screen-swap option.

    If you don't want to give up flip/swap functionality, try option 3.

 3. If the video BIOS is replaceable, replace it with an updated video
    BIOS.

 4. If the video BIOS is not replaceable, replace the card.


 132. CodeView 3.00 Hangs on gets() with Screen Swap Off

 Product Version(s): 3.00   | 3.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_c s_quickc s_quickasm
 Last Modified: 25-JUL-1990    ArticleIdent: Q62663

 CodeView 3.00 will hang if you step or execute past a call to the
 gets() run-time routine if the Screen Swap option is turned off.

 Sample Code
 -----------

 #include <stdio.h>

 char string[256];

 void main (void)
 {
     printf ( "Enter a string: ") ;
     gets ( string ) ;
     printf ( "Echoing : %s\n", string) ;
 }

 Compile the above file with the following:

    cl /Od /Zi test.c

 Bring the file up in CodeView, then select the Options.Screen Swap
 option. Next, step past the gets() call. Under DOS, your machine will
 hang, and under OS/2, the current screen group will be hung.


 133. DosSetMaxFH Between 0-39 Fails Under CodeView 3.00

 Product Version(s): 3.00
 Operating System:   OS/2
 Flags: ENDUSER | buglist3.00
 Last Modified: 25-JUL-1990    ArticleIdent: Q62666

 OS/2's DosSetMaxFH routine can be called to reset the OS/2 default
 limit of a maximum of 20 open file handles to a larger number. By
 definition, DosSetMaxFH fails when trying to set the number smaller
 than the current maximum amount of handles. Under OS/2, the default
 maximum number of files is 20, so a DosSetMaxFH to a number between
 0-19 should fail.

 However, under CodeView 3.00, calling DosSetMaxFH with a number
 between 0-39 will return a fail value.

 Sample Code
 -----------

 /* compile with : cl /Od /Zi file.c */

 #define INCL_DOSFILEMGR

 #include <stdio.h>
 #include <os2.h>

 void main(void)
 {
    int i;
    for ( i = 0 ; i < 1000 ; i ++ )

    if ( DosSetMaxFH ( i ) )
    {
       printf ( " DosSetMaxFH to %d failed!\n ",i ) ;
    }
 }

 This program prints the error message on parameters from 0 to 39.

 You can call the DosSetMaxFH routine to set at least 40 file handles
 to work around this problem.


 134. CV Limits Input of Period Character (2Eh) into Memory Window

 Product Version(s): 3.00 3.10 | 3.00 3.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist3.00 buglist3.10 decimal point dot
 Last Modified: 31-AUG-1990    ArticleIdent: Q65241

 When viewing memory in byte format in a memory window in CodeView
 version 3.00 or 3.10, you cannot change the value of a byte in memory
 to the hexadecimal value 2E. The hex value 2E has an ASCII character
 equivalent of the period ("."). In CodeView, a period is used to
 display any nondisplayable character (for example, null, a carriage
 return, control characters, etc.), which means the period character
 can sometimes have special meaning to CodeView when it appears in a
 memory window.

 Because of the special usage of the period character in a memory
 window, CodeView does not allow periods to be typed directly into
 memory. In CodeView 3.00, attempts to change a byte value to 2E
 results in either the 2 or the E being entered and the other digit
 being ignored, depending on which value you enter first. In CodeView
 3.10, both the 2 and the E are returned to their original values once
 they have both been entered. If you move to the right side of the
 memory window where the ASCII equivalents are shown and you try to
 type in a period there, CodeView will also ignore that input.

 If you switch the memory window so that you are viewing memory in
 ASCII mode, actual periods can be typed in to any memory location.
 However, there is a problem with this because ALL other periods on the
 same line, which really represent various nondisplayable ASCII
 characters, are all converted to 2Es.

 If you use are viewing memory in a format other than bytes or ASCII,
 CodeView will allow a 2E to be entered. The workaround, then, if a
 period needs to be entered into memory, is to choose a different
 viewing mode other than ASCII or byte-mode, and then enter the period
 in the desired location as the value 2E. You can cycle through the
 available memory viewing modes by repeatedly pressing SHIFT+F3, or you
 can select the desired mode from the Memory Window option on the
 Options menu.

 Microsoft has confirmed this to be a problem in CodeView versions 3.00
 and 3.10. We are researching this problem and will post new
 information here as it becomes available.


 135. CV 3.00 Incorrectly Documents helpbuffer Switch as helpbuffers

 Product Version(s): 3.00   | 3.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 25-FEB-1991    ArticleIdent: Q63236

 In the "Configure CodeView" section of the online help for CodeView
 version 3.00, the "helpbuffer" switch is incorrectly listed as
 follows:

    helpbuffers:<size>

 This switch should be spelled as follows:

    helpbuffer:<size>

 CodeView will not recognize the first spelling. The correct spelling
 was incorporated into the online help beginning with CodeView version
 3.10.


 136. CodeView Crashes in DOS on "Drive Not Ready" Error

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00
 Last Modified: 25-JUL-1990    ArticleIdent: Q64026

 CodeView version 3.00 may hang after encountering a "Drive Not Ready"
 error. This error may occur if a file is opened on Drive A and a disk
 is not in the drive.

 To reproduce this problem, compile the following program with CodeView
 options (cl /Zi /Od):

    main () {
      FILE *fp;
      fp = fopen("a:\readme.doc","r");
    }

 If you run the program in CodeView version 3.00 without a disk in
 Drive A and press F5 to run the program, the following error will
 appear:

    Not ready reading drive A
    Abort, Retry, Fail?

 Regardless of what is typed, the machine will hang and you must do a
 cold reboot to remedy the crash.

 Note: CodeView versions 2.20 and 2.30 do not hang the machine if the
 above steps are executed. The fopen() just returns a NULL. OS/2 also
 handles the error correctly in versions 2.20, 2.30, and 3.00 of
 CodeView.

 Microsoft has confirmed this to be a problem with CodeView version
 3.00. We are researching this problem and will post new information
 here as it becomes available.


 137. CV1319 Error May Be Caused by CodeView DOS Extender

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 fixlist3.10
 Last Modified: 31-AUG-1990    ArticleIdent: Q65242

 Real-mode CodeView (CV) version 3.00 (shipped with Microsoft C 6.00)
 may encounter problems on certain computers when extended memory is
 utilized for debugging programs. These problems involve the processing
 of interrupts while CodeView 3.00's internal DOS extender is being
 used to run CodeView in protected mode in conjunction with HIMEM.SYS,
 the extended memory (XMS) driver.

 The problems manifest themselves in various ways, due to both the
 varied interrupt handling speeds of different machines and the varied
 interactions of CodeView itself running in protected mode while the
 DOS program being debugged is still being run in real mode. The most
 common error is a protection violation, which shows up in CodeView as
 either a CV1319 error (internal error - unrecoverable fault) or as a
 system hang. The errors usually occur when you are paging through the
 code or manipulating the mouse.

 Registered Microsoft C 6.00 owners who are experiencing any of these
 problems with CodeView version 3.00 are encouraged to call Microsoft
 Technical Support at (206) 637-7096 to obtain information concerning a
 possible correction for these errors. However, there may be some cases
 where the only solution is to obtain a newer computer BIOS or to use
 CodeView without extended memory.
 Most reported problems have involved IBM PS/2 computers, but a number
 of these problems have also been reported on computers with an AMI
 BIOS. Note that CodeView version 3.10 includes modifications that are
 expected to eliminate most of these interrupt problems, but in some
 instances (especially with older AMI BIOS machines), an update of the
 BIOS may be the only solution.

 The easiest workaround to these protected-mode errors is to start
 CodeView without the use of extended memory. This can be done by
 removing the line in CONFIG.SYS that loads the HIMEM.SYS driver (and
 then rebooting the computer). Another option, if HIMEM is already
 loaded, is to start CodeView with the /D command-line option to
 specify explicitly that CodeView should use disk overlays, rather than
 extended or expanded memory. (Otherwise, if extended memory is
 available, CodeView will use the /X option by default.)

 Because these problems can occur only when CodeView is running in
 protected mode in extended memory, and because CodeView 3.00 requires
 HIMEM.SYS in order to run in protected mode, the problems are often
 mistakenly attributed to HIMEM.SYS. In reality, HIMEM.SYS is not
 responsible for the errors because it is just the memory manager that
 CodeView utilizes to get at extended memory. The errors are the result
 of an interrupt handling incompatibility between certain hardware
 configurations and the DOS extender built into CodeView.

 Microsoft has confirmed this to be a problem in CodeView version 3.00.
 This problem has been corrected in version 3.10.


 138. Label/Function Search Command Fails Under Codeview 3.00/3.10

 Product Version(s): 3.00 3.10 | 3.00 3.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist3.00 buglist3.10
 Last Modified: 31-AUG-1990    ArticleIdent: Q65312

 Under CodeView versions 3.00 and 3.10, the Label/Function search
 command is described in the online help as performing a search of the
 current source window for an assembly-language label or function name.
 If the label is found, the debugger should switch from source to
 assembly mode to display a label in a library routine or assembly
 language module.

 In reality, this command fails with a message "Error - Unknown
 Symbol". The debugger does not switch into assembly mode. This problem
 can be reproduced by selecting Search from the CodeView menu, then
 selecting Label/Function and typing in "__chkstk" (without the
 quotation marks).

 Microsoft has confirmed this to be a problem with CodeView Versions
 3.00 and 3.10. We are researching this problem and will post new
 information here as it becomes available.


 139. Cannot Enable A20! with Orchid 386s

 Product Version(s): 3.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-DEC-1990    ArticleIdent: Q65360

 Using HIMEM.SYS version 2.50 with Orchid 386/25 motherboards with the
 caching controllers can cause the following error message:

    Cannot enable A20!

 Orchid Technology has verified that this is a problem with the PAL
 chip on these motherboards. Customers who are experiencing this
 problem should call Orchid Technology at (415) 683-0300 for an update
 of their PAL chip. Please have the revision of the motherboard on hand
 when calling.


 140. Mouse Cursor on Wrong Monitor During Dual-Monitor Debugging

 Product Version(s): 3.00 3.10
 Operating System:   MS-DOS
 Flags: ENDUSER | H_MOUSE
 Last Modified: 17-SEP-1990    ArticleIdent: Q65528

 Under certain conditions, when invoking real-mode CodeView (CV) in
 dual-monitor mode with /2, the mouse cursor appears on the wrong
 monitor. When this occurs, a "sprite" mouse cursor appears on the
 monitor that the application is to run on, while the secondary monitor
 where CodeView is running does not have a mouse cursor. Several
 workarounds to this problem are given below.

 The sprite mouse cursor is a "graphic" arrow cursor similar to that in
 Windows 3.00 or OS/2 Presentation Manager (PM), as opposed to the
 traditional "text" block cursor that usually appears when running
 CodeView or the Programmer's WorkBench (PWB).

 The problem of the mouse appearing on the wrong monitor occurs only on
 computers that have "extended register" video boards, such as some of
 the Video 7 VGA cards. Certain mouse drivers enable the sprite cursor
 when they detect these extended video registers. Because a monochrome
 monitor cannot support this extended mode mouse cursor, the cursor
 fails to switch to the secondary monitor when focus is switched to
 that monitor after CodeView is invoked with the /2 switch.

 The following are three possible workarounds to this problem:

 1. Upgrade to mouse driver version 7.04 or later. This version
    provides a new switch, /Y, which can be used with either the
    MOUSE.COM program or the MOUSE.SYS device driver. The /Y switch
    tells the mouse driver to disable the sprite cursor. The mouse
    driver update can be obtained free of charge by contacting
    Microsoft Product Support Services at (206) 637-7096.

 2. If a mouse driver earlier than version 7.04 is used, the problem
    may be worked around by creating a batch file or adding the
    following commands to the AUTOEXEC.BAT file:

       mode mono
       mouse
       mode co80

    These commands will switch focus to the monochrome monitor while
    the mouse is being invoked and then will switch the focus back to
    the color monitor. This method will prevent the mouse driver from
    detecting the extended registers and using the sprite cursor.

 3. Disable the extended video registers. Check the video card
    documentation to see if this method is possible with your
    particular card.


 141. CV May Come Up Only in Monochrome with 8514/A Display Adapter

 Product Version(s): 3.00 3.10
 Operating System:   MS-DOS
 Flags: ENDUSER | appnote SV0337.ARC B_QuickBas
 Last Modified: 16-OCT-1990    ArticleIdent: Q65701

 Real-mode CodeView (CV) may display only in monochrome (black and
 white) mode on some systems with an 8514 or color VGA monitor attached
 to an 8514/A display adapter. On these systems, the installation of an
 8514/A video card causes the BIOS video functions to return an
 incorrect value indicating that a monochrome VGA monitor is attached,
 rather than a color monitor.

 This same BIOS information contributes to the way in which these
 versions of CodeView (and various other programs) detect the type of
 video adapter present; thus, CodeView may incorrectly determine that
 it is running on a monochrome system and may display the screen only
 in black and white.

 Workaround
 ----------

 As a workaround, an application note titled "8514/A Monochrome to
 Color Patch" is available from Microsoft Product Support Services by
 calling (206) 637-7096. This application note contains a program,
 which may be run before CodeView is invoked and which will configure
 the BIOS information correctly for CodeView to come up in color.
 The program is also available in the Software/Data Library by querying
 on SV0337, the Q number of the article, or S12719. SV0337 was archived
 using the PKware file-conversion utility.

 This monochrome video problem is specific to DOS, and therefore, does
 not occur with protected-mode CodeView (CVP) under OS/2. However, the
 problem may appear if real-mode CodeView is run in the DOS
 compatibility box under OS/2. In addition, the problem may occur with
 other software, such as Microsoft QuickBASIC.

 With CodeView, another symptom of this problem is that the program
 output screen (which can be accessed by pressing F4) will usually
 appear as dark blue characters on a black background. This screen is
 essentially unreadable and remains this way even after CodeView is
 terminated. Typing MODE CO80 at the DOS prompt after exiting CV should
 restore the system to the default colors.

 Microsoft intends to change the video detection routine in future
 software releases in order to circumvent this problem. Although the
 problem is not specifically caused by CodeView, a more sophisticated
 video detection routine will determine what video adapter and monitor
 are present without relying on the possibly inaccurate BIOS data.


 142. CV /E Avoids Windows 3.00 386 Enhanced Mode Protection Error

 Product Version(s): 2.35 3.00 3.10
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# S900919-57 B_QuickBas B_BasicCom W_Win3
 Last Modified: 24-OCT-1990    ArticleIdent: Q65934

 When you start Microsoft CodeView under Windows 3.00 in a 386 enhanced
 mode DOS box, the following error message is displayed:

    You have attempted to run protected-mode application under 386
    enhanced mode. To run the application, exit and run Windows using
    either the WIN /s or the WIN /r command.

 However, using WIN /s or /r is unnecessary. To avoid the error
 message, start CodeView with the /E option to tell CodeView that
 expanded memory is available, as follows:

    CV /E

 This information applies to Microsoft CodeView versions 2.35, 3.00,
 and 3.10 for MS-DOS.
 Note that CodeView version 2.35 is shipped with Microsoft BASIC
 Professional Development System (PDS) version 7.00; CodeView version
 3.00 is shipped with Microsoft C Compiler PDS version 6.00; and
 CodeView 3.10 is shipped with Microsoft BASIC PDS version 7.10.

 You may find that after the error message is generated, if you return
 to the DOS box and wait a few seconds, CodeView will start up. To
 avoid the error message, start CodeView as follows with the expanded
 memory (/E) switch (where <filename.exe> is the name of the program
 you want to debug):

    CV /E <filename.exe>

 To increase the size of programs that can be loaded into CodeView in
 conjunction with the /E switch, you can create a PIF file for CodeView
 and specify -1 for the Expanded Memory KB Limit, which instructs
 Windows to give the program all the EMS that it needs.

 CodeView will run without the above error message in a Windows 3.00
 DOS box in standard mode, WIN /S.


 143. CV1319 Error May Be Caused by Generic Breakpoints

 Product Version(s): 3.00   | 3.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 24-OCT-1990    ArticleIdent: Q66215

 In some situations a program will hang with the CodeView
 initialization error CV1319 even though the program runs correctly
 outside of CodeView. Deleting any generic breakpoints in the
 CURRENT.STS file may resolve this problem. The following is an
 example:

    [debug-]
          genericbp='E 0x47:0x0007

 The problem is that when you recompile your program, the code moves
 and the absolute breakpoint may now be set in the middle of a
 multibyte instruction rather than the beginning of the instruction.

 Additional Workaround
 ---------------------

 Invoke CodeView with the /TSF ("Toggle StateFileread") option. This
 option will either read or ignore the CURRENT.STS file based on what
 the statefileread switch is set to in the TOOLS.INI file.

 For example, if the statefileread switch is set to "yes" (the default)
 and CodeView is invoked with the /TSF option, the CURRENT.STS file
 will be ignored.


 144. Running Out of Memory in CodeView with /X

 Product Version(s): 3.00 3.10 3.11
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 24-OCT-1990    ArticleIdent: Q66230

 Under some circumstances, CodeView may still run out of memory while
 debugging large applications with the /X switch invoked to take
 advantage of extended memory with HIMEM.SYS. The debug information
 gets expanded when CodeView loads the program, so the following
 suggestions may help the problem:

 1. Don't use the quick compile (/qc) option. The symbolic information
    created by the quick compiler may expand much more when loaded by
    CodeView than the symbolic information created by the standard
    compiler. In addition, the quick compiler may create some duplicate
    debug references in the executable file. These duplicate references
    can take up significant memory when CodeView loads the program.

 2. Use the CVPACK utility, which is documented in the online
    documentation and on Page 21 of the "Microsoft C Reference" manual.
    CVPACK will compress the debug information in the file by removing
    duplicate references. Use the /P option to achieve maximum
    compression.


 145. CodeView Fails to Return Value in ES

 Product Version(s): 3.00 3.10 3.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist3.00 buglist3.10 buglist3.11
 Last Modified:  9-NOV-1990    ArticleIdent: Q66507

 When CodeView is running in extended memory and a call is made to
 interrupt 15h function C0h, the value in the ES register is not
 changed. This interrupt call should return the segment of the system
 configuration table in the ES register. If CodeView is run with the /D
 or /E option, a value is returned in the ES register as it should be.

 Microsoft has confirmed this to be a problem in CodeView versions
 3.00, 3.10, and 3.11. We are researching this problem and will post
 new information here as it becomes available.

 Sample Code
 -----------

 main ()
   {
    _asm mov ah, 0xC0
   _asm int 0x15
   }


 146. Memory Requirements for Real-Mode CodeView (CV.EXE)

 Product Version(s): 3.00 3.10 3.11 | 3.00 3.10 3.11
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified: 11-NOV-1990    ArticleIdent: Q66513

 Real-mode versions of CodeView (CV) beginning with version 3.00 offer
 a number of ways to utilize available memory in order to make the
 greatest amount of conventional memory available to the program being
 debugged. The amount of memory actually used depends on the
 command-line options specified as well as the configuration of the
 system used for debugging.

 The following table shows the size of CodeView in standard DOS memory
 with each of the memory-specific command-line options (see the "More
 Information" section below for further details):

    Option  RAM Usage                   Option  RAM Usage
    ------  ---------                   ------  ---------

     /X       16K                       /D16     210K
     /E      192K                       /D32     225K
     /D      256K (same as /D64)        /D128    320K

 The following descriptions of the three memory-related CodeView
 options explain the ways in which each option affects memory
 utilization in addition to the respective amounts of conventional
 memory that CodeView requires with each. (This information pertains
 only to CodeView versions 3.00 and later -- versions of CodeView
 earlier than 3.00 require approximately 230K of RAM specifically for
 CodeView.)

 /X - Specifies that CodeView should utilize extended memory. Assuming
      that enough extended memory is available, this option moves both
      the symbolic information and most of CV itself into extended
      memory. Allowing CV to be loaded into high memory requires that
      approximately 16K to 19K of "control" code remain in conventional
      memory, thus all free conventional RAM over 19K is available to
      load the program to be debugged (the "debuggee").

 /E - Specifies that CodeView should utilize expanded memory. Assuming
      that enough expanded memory is available, this option moves both
      the symbolic information and CodeView's own overlays into
      expanded memory. The size of the CV "root" without the extra
      overlayed code is approximately 192K. Since the overlays do not
      cause any additional overhead with /E, all free conventional RAM
      over 192K is available to load the debuggee.

 /D - Specifies that CodeView should utilize disk overlays in
      conventional memory. By default, this option creates a 64K buffer
      area for loading disk overlays. With the 192K root, the 64K
      buffer means CV will take about 256K of conventional memory with
      /D. In addition, the symbolic information must also be loaded
      into conventional memory; therefore, since symbolic data varies
      with each program, it is not possible to specify the amount of
      memory available for the debuggee alone.

      The /D option can also be specified with a value that indicates
      the size of the overlay buffer area. This parameter can be any
      value from 16 to 128, which represents an overlay buffer size
      from 16K to 128K. Specifying /D16 will minimize CodeView's size
      with disk overlays to approximately 210K. This maximizes the
      amount of conventional memory that will be available to load the
      debuggee and the symbolic information. At the other extreme,
      /D128 causes CV to use approximately 320K of conventional RAM.
      This provides faster CodeView execution speed, but it will only
      work with smaller debuggees.

 Note: CodeView will default to the best memory usage possible. In
 other words, if NO memory usage option is specified, CV will try to
 use extended memory. If extended memory is unavailable, CV looks for
 expanded memory. CV will use disk overlays on its own only if expanded
 memory is not found.


 147. CV2206 Warning: Corrupt OMF Detected in <filename>

 Product Version(s): 2.x 3.00 3.10 | 2.x 3.00 3.10
 Operating System:   MS-DOS        | OS/2
 Flags: ENDUSER | S_MASM H_MASM
 Last Modified: 11-NOV-1990    ArticleIdent: Q66702

 When trying to debug a Macro Assembler program with CodeView, the
 following message may appear:

    CV2206 Warning: Corrupt debug OMF detected in <filename>,
       discarding source line information

 The error occurs when code segments are not of class "CODE". Page 104
 of the "Macro Assembler 5.10 Programmer's Guide" states the following:

    The CodeView debugger also expects code segments to have the class
    name 'CODE'. If you fail to assign a class type to a code segment,
    or if you give it a class type other than 'CODE', then labels may
    not be properly aligned for symbolic debugging.

 This is also mentioned in the "CodeView and Utilities" manual under
 section 1.3.8 titled "Preparing Assembly Programs."

 The following is an example of the problem:

 _text segment para public   ; 'CODE' should be added to this line

 begin    proc
       mov ah, 4ch
       int 21h
 begin    endp

 _text ends
       end begin


 148. How to Execute a Function From the Command or Watch Window

 Product Version(s): 2.x 3.00 3.10 3.11 | 2.x 3.00 3.10 3.11
 Operating System:   MS-DOS             | OS/2
 Flags: ENDUSER | docerr s_c 6.00 6.00a
 Last Modified:  4-DEC-1990    ArticleIdent: Q67007

 Page 201 of the "Advanced Programming Techniques" (APT) manual that
 accompanies Microsoft C versions 6.00 and 6.00a states that "any C
 function in your program (whether user-written or from the library)
 can be called from the Command window or the Watch window."

 This statement is not completely true. Actually, only functions
 compiled with full CodeView symbolic information can be called. This
 restriction eliminates all of the C run-time functions from being
 executed in this manner because they contain no symbolic information.
 A simple example of how to call a C run-time function is shown below.

 If an attempt is made to execute a function that has not been compiled
 with symbolic information via the Command window, the following error
 will be displayed in the Command window:

    CV1017 Error: Syntax error

 In CodeView versions 2.x, an "unknown symbol" error is displayed in
 the Command window.

 If an attempt is made to add the function to the Watch window via the
 Watch menu and the "Add Watch" command, CodeView will ignore the entry
 and beep. In versions 2.x, CodeView will give an "unknown symbol"
 error.

 The APT gives an example of calling a C function from the Command
 window via the following command:

    ?funcname (varlist)

 This command will only invoke the function and display its return
 value in the Command window. To add the function to the Watch window,
 a slightly different command must be used, as follows:

    w?funcname (varlist)

 The function name can also be added to the Watch window by choosing
 the Watch menu and the "Add Watch" command, and typing only the
 function name plus its variable list enclosed in parenthesis. Neither
 the "w" or the "?" are needed in this situation.

 It is important to note that you should be sure that the screen
 flip/swap option on the Options menu is turned on if the function you
 execute performs any screen input or output.

 For example, if you want to call a C run-time function or any other
 function that does not contain CodeView symbolic information, you must
 create a shell function that calls the desired function itself and
 gives the same return value.

 Therefore, if you wanted to call the C run-time function sqrt()
 directly from the CodeView Command window or Watch window, you would
 create a shell function that resembles the following:

 1. #include <math.h>
 2. double my_sqrt(double x)
 3. {
 4.    return(sqrt(x)) ;
 5. }

 You would then compile this function with CodeView information by
 compiling with the /Zi switch, and then link it into your program
 being sure to include /CO in your link command. Note that your program
 does not need to make a call to the function in order for it to be
 available for direct execution.

 To execute this function from the Command window, enter the following
 command:

    ?my_sqrt(4.0)

 The return value should be displayed on the next line in the Command
 window. In this example, 2.0000000000000 should be displayed as a
 result of the square root of 4.0.

 To add the function to the Watch window via the Command window, you
 would enter the following command:

    w?my_sqrt(4.0)

 The function could also be added to the watch window by choosing the
 "Add Watch" command from the Watch menu and entering the following at
 the Add Watch prompt:

    my_sqrt(4.0)

 When a function is added to the Watch window, that function is
 executed any time the Watch window is updated.

 Although these examples show a constant value as the parameter to the
 function, any variable that is in scope at the time could be entered
 as a parameter.


 149. Syntax Error When Watching Variables That Begin with "P"

 Product Version(s): 2.20 2.30 | 2.20 2.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist2.10 buglist2.20 fixlist3.00
 Last Modified: 18-NOV-1990    ArticleIdent: Q67008

 When the following command is entered in the Command window to watch a
 variable that begins with the letter "p", the result is a syntax
 error:

 > W pvariable

 The syntax for watching a memory location is W[type] range, where the
 type and range specify the format and length of memory to be
 displayed, respectively.

 When no type is declared, as in the above example, the default type is
 used. The default type will be the last type used by a Dump, Enter,
 Watch Memory, or Tracepoint Memory command. If none of these commands
 has been used during the session, the default type is byte.

 The workaround for this problem is to explicitly declare a type in the
 watch statement, for example:

 > WB pvariable.

 Microsoft has confirmed this to be a problem in Microsoft CodeView
 versions 2.x. This problem has been corrected in Microsoft CodeView
 version 3.00.

 Additional keywords: buglist2.30 buglist2.35


 150. CV1017: Syntax Error Can Be Caused by a Leading Zero

 Product Version(s): 3.00 3.10 3.11 | 3.00 3.10 3.11
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified:  4-JAN-1991    ArticleIdent: Q67160

 Since CodeView treats all values with a leading zero as octal numbers,
 the following error is reported when the value is not a valid octal
 number:

    CV1017: syntax error

 To enter a number in hexadecimal form, the value must be preceded with
 "0x" (without the quotation marks). If the value is a number in
 decimal form, any leading zeros should be dropped.

 You can also use the "0n" prefix to specify decimal numbers,
 independent of the current radix.


 151. CodeView Asks for Path to a Source File Without Extension

 Product Version(s): 2.x 3.00 3.10 3.11 3.50
 Operating System:   MS-DOS
 Flags: ENDUSER | s_lib s_utility
 Last Modified:  4-DEC-1990    ArticleIdent: Q67271

 If an old version of the LIB utility is used to store OBJ modules in a
 library, the extension may not be stored. This can cause a problem if
 a module is compiled with debug information and an .EXE is built for
 CodeView to debug. When CodeView attempts to open the source file for
 the module in the library, it will fail because there is no extension.
 It will then prompt you for the filename.

 This is a problem with the Microsoft LIB utilities earlier than version
 3.08 and some third-party library managers. Beginning with LIB version
 3.08, the full filename is stored in the library.


 152. CodeView Does Not Debug kbhit() Correctly

 Product Version(s): 3.00 3.10 3.11  | 3.00 3.10 3.11
 Operating System:   MS-DOS          | OS/2
 Flags: ENDUSER | buglist3.00 buglist3.10 buglist3.11
 Last Modified:  4-DEC-1990    ArticleIdent: Q67360

 When setting a breakpoint between the kbhit() function and a function
 to read a character from the input stream, CodeView will grab the
 character from the input stream when the breakpoint is executed.

 The following code example demonstrates the problem. If a breakpoint
 is placed on the line containing the getch() function, the character
 input from the keyboard will be placed in CodeView before the getch()
 function is actually stepped over. You will not be prompted for the
 character when you step over the getch() function. The character you
 typed to stop the kbhit() loop will be used for the getch() function
 call when that line is executed.

 Microsoft has confirmed this to be a problem in CodeView versions
 3.00, 3.10, and 3.11. We are researching this problem and will post
 new information as it becomes available.

 Sample Code
 -----------

 #include <stdio.h>
 #include <conio.h>

 void main(void)
 {
         int a;

         do {
                 printf(".");
         } while(!kbhit());

         a = getch();         // put breakpoint here

         printf("%c\n", a);
 }






 Microsoft Linker
 =============================================================================


 1. Corrupted Library Causes Error L1102

 Product Version(s): 3.61 3.64 3.65 | 5.01.20 5.01.21
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified:  6-DEC-1988    ArticleIdent: Q38201

 The link error "L1102: unexpected end-of-file" is generated when the
 linker attempts to resolve externals in a corrupted or null-length
 library.

 This error most commonly occurs with a combined library, mlibx.lib,
 that is corrupted during the library creation stage of SETUP. Make
 sure to check the \LIB subdirectory for odd or null size libraries.
 Library rebuilding is needed if insufficiently-sized libraries are
 found.

 The L1102 error can also be generated if you inadvertently type in the
 name of a used library at the "list file" prompt, as follows:

    Run File  [SPUD.EXE]:      main.exe
    List File [NUL.MAP]:       libname.lib    (generates faulty library)
    Libraries [.LIB]:          libname.lib
    Definition File [NUL.DEF]: main.def

 This process creates a map listing with the specified library name in
 the current working directory. Because this directory is searched
 before the directory specified in the LIB environment variable, the
 incorrect library containing the map listing is used during linkage,
 causing the error L1102.


 2. /I Linker Option Should Read /INF

 Product Version(s): 3.61 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 18-OCT-1988    ArticleIdent: Q30515

 Pages 266 and 267 of the "Microsoft C Optimizing Compiler CodeView and
 Utilities" manual for Versions 5.00 and 5.10 incorrectly list the
 shortened name of the /INFORMATION option as /I.

 If /I is given as an option, the result is an error stating that /I is
 an unrecognized option.

 The correct shortened name for /INFORMATION is /INF.


 3. Maximum Libraries LINK Can Handle

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 18-OCT-1988    ArticleIdent: Q31986

    LINK can handle no more than 32 libraries, i.e., on the LIBRARY
 prompt, you can specify up to 32 libraries.
    If you have more libraries, you have two choices: combine libraries
 or specify some of them at the object modules prompt. In the second
 case, LINK will treat the library as a collection of object modules,
 all of which should be included in your .EXE file.


 4. Maximum Number of Object Modules LINK Allows

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 18-OCT-1988    ArticleIdent: Q31987

    There is no limit to the number of object modules LINK allows;
 however, LINK can operate only in certain limits imposed by the amount
 of available resources.


 5. The Meaning of an Invalid Object Module

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 13-OCT-1988    ArticleIdent: Q31988

 An invalid object-module error message means that an object module
 does not conform to Microsoft object format. The description of object
 format can be found in "MS-DOS Encyclopedia Part E: Programming Tools
 Article 19: Object Module."


 6. Object Modules Handled by LINK

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-JUL-1988    ArticleIdent: Q31989

    Successive versions of LINK always are backward compatible, but not
 necessarily upward compatible, i.e., the most recent versions should
 link any existing object module, but not necessarily any future object
 module.
    To solve this problem, update to the latest version of LINK.



 7. How LINK Orders and Combines Segments

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-JUL-1988    ArticleIdent: Q31991

    Every segment belongs to a named class such as 'CODE', 'DATA', or
 'BSS'. LINK orders all segments with the same class name contiguously.
    Within each class, segments are placed in the same order as LINK
 encounters them. Segment classes are placed in the order they appear.
 If you do not give a class name when you define a segment in assembly,
 the segment gets the null class, which is treated like any other segment.
 If the /DOSSEG option is given, or one of the Microsoft language run-time
 libraries is used, LINK imposes the following additional order:

       code (class ending in 'CODE')
       far data (everything but DGROUP and 'CODE')
       DGROUP - the default data segment
           class 'BEGDATA' (special runtime segment)
           near initialized data (everything but 'BSS' and 'STACK')
           near BSS--uninitialized data  (class 'BSS')
           stack



 8. Link Error L1053 Symbol Table Overflow

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 13-OCT-1988    ArticleIdent: Q31992

 Question:

 I am receiving link error L1053: symbol table overflow. What is the
 limit of the symbol table?

 Response:

 Under MS-DOS, this limit using the DOS-only linker (Versions
 3.x) is dependent on the amount of available memory in your computer.
 LINK can use all conventional memory available under DOS (up to 640K).

 Under OS/2, the segmented-executable linker (Versions 5.x and above)
 has no limit on the size of the symbol table because it extends the
 symbol table in virtual memory.


 9. Temporary Files Created at Link Time

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 22-JUL-1988    ArticleIdent: Q31993

    The linker creates a temporary file when it runs out of memory to
 hold the symbol table or the load image and run-time relocations of
 the program being linked.



 10. How Overlays Are Set Up By the Linker

 Product Version(s): 3.x 4.06 4.07 5.01.20 5.01.21 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 26-JAN-1990    ArticleIdent: Q31994

 The overlay linker uses an interrupt to call in overlaid files. By
 default, the interrupt number used for passing control to overlays is
 63 (3f hex).

 The linker links the Microsoft overlay manager from the standard
 Microsoft language run-time libraries. The linker assigns segments to
 overlays based on the grouping you indicate. It replaces
 overlay-to-overlay far calls and root-to-overlay far calls with an
 interrupt sequence that calls the overlay manager. The overlay manager
 swaps overlays if necessary and returns control to the program.

 The linker replaces root-to-overlay and overlay-to-overlay far calls
 with the following sequence:

    INT     3Fh         ; can change # with /OVERLAYINTERRUPT:#
    DB      ?           ; target overlay segment number, where
                        ; every non-root code segment is numbered
                        ; starting at 1
    DW      ?           ; target offset within segment

 The interrupt handler is set to the overlay manager code that swaps
 out the resident overlay if necessary and swaps in the target overlay,
 then jumps to the target address. The overlay manager does nothing
 unusual in servicing the interrupts; it does not disable interrupts.
 However, it may issue INT 21h calls to swap overlays.

 The overlay manager assumes that once your initialization code has
 been executed, DS and SS will always be the same. Furthermore, it
 assumes you will initialize DS and SS to the value of DGROUP (the
 default data segment defined by Microsoft languages). Note that your
 program also must have a stack segment.

 A more detailed description of the overlay manager can be found on
 Page 715 of the "MS-DOS Encyclopedia," "Article 20: The Microsoft
 Object Linker."


 11. Why the First Module in the Code Segment Starts at Offset 16

 Product Version(s): 3.x 4.06 4.07 5.01.21 5.03 | 5.01.21 5.03
 Operating System:   MS-DOS                     | OS/2
 Flags: ENDUSER | s_c s_quickc s_quickasm h_masm h_fortran
 Last Modified: 14-FEB-1990    ArticleIdent: Q58688

 Question:

 Under some circumstances, I get 16 zero bytes at the beginning of my
 code segment. I'm linking with my own replacement C library with
 start-up code. The entry point to this start-up module is the first
 item in the module, and it always ends up at offset 16. Why is this?

 Response:

 The linker will insert 16 bytes at the beginning of the code segment
 if it determines that you are using standard segment naming
 conventions (/MS-DOSSEG) and the NULL segment is not explicitly
 removed (/NONULLSMS-DOSSEG). In your case, the linker assumes that you
 need support for signal() and allocates the first 16 bytes for it.

 Note: This will always be done for C programs by the compiler.


 12. Linker Outputs Information with Invalid Object Module

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-JUL-1988    ArticleIdent: Q31999

    When an invalid object-module error message occurs, some
 information about the record and the position is printed.
    This information includes the object record type and the relative
 position of the record in the .OBJ file. There is little you can do
 with this information; it is mainly for compiler and assembler
 developers to point to the wrong object record.


 13. Incremental Linking

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-JUL-1988    ArticleIdent: Q32000

    The following is a description of the incremental-linking process.
    Your file is built from a set of .OBJ files. Each .OBJ file is
 produced by the compiler or assembler from a source file. If a set of
 .OBJ files is large, then linking time can be long. If you change only
 one source file (i.e., in your set of .OBJ files you have one new .OBJ
 file), you can link all .OBJs one more time, or patch your .EXE file
 with the new .OBJ file. This patching is called incremental linking.
    Incremental linking only is supported for OS/2 and Windows
 programs.



 14. Explanation of a MAP File

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-JUL-1988    ArticleIdent: Q32001

    A MAP file gives you a picture of how your code and data are
 arranged in memory when the program is loaded.
    First you get the list of segments in the order in which they will
 be loaded into memory. For each segment, you have its starting
 address, length, name, and class. Following the segments are groups,
 each specifying the starting address of the group.
    If you specify the /MAP switch and list filename, in the MAP you
 will get two lists of public symbols in your program. The first list
 will be sorted alphabetically, the second by addresses.
    If you specify the /LINENUMBERS switch, then in the MAP, you will
 get line numbers and the associated addresses of your source program.
 To produce line numbers in the MAP, give LINK an object file with
 line-number information. Use the /Zd option with any Microsoft
 compiler to include line numbers in the object file.
    Information from the MAP will help you debug your program and
 understand how the program is loaded into memory.


 15. L1087: "Unexpected End-of-File on Scratch File"

 Product Version(s): 3.x 5.x  | 5.10
 Operating System:   MS-DOS   | OS/2
 Flags: ENDUSER |
 Last Modified: 13-OCT-1988    ArticleIdent: Q34669

 The Link Utility generates the error message L1087: "unexpected
 end-of-file on scratch file" when a disk with the temporary linker
 output file has been removed. This information is documented in the
 "Microsoft Macro Assembler CodeView and Utilities Guide."

 The error message L1087 also can be caused by insufficient memory
 available on the disk that contains the temporary linker output file.
 The disk can be a hard disk, floppy disk, or RAM disk.


 16. Assigning Addresses to Overlay Segments

 Product Version(s): 3.x 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-JUL-1988    ArticleIdent: Q32003

    The linker assigns only code segments (identified by class names
 ending in "CODE") to overlays. Data segments go in the root. The
 particular overlay the segment goes in is determined by the module
 that first defines the segment.

    Note that the linker assigns segments, not object modules, to
 overlays. Therefore, if you have the following command

     LINK A+(B+C)

 where

     A   defines public SEG1
     B   defines public SEG2
     C   defines public SEG1

 then C's contribution to SEG1 goes in the root, not in the first
 overlay, because SEG1 was first defined in a root module.
    The linker orders all segments as it normally would, ignoring the
 overlays and using the class and combine-type rules described
 elsewhere. The linker then assigns addresses for every segment in the
 root up to the first overlay segment. Before the first overlay
 segment, it defines a special empty segment called OVERLAY_AREA. Then
 for each overlay it assigns addresses for every segment in the overlay
 so that the first segment in the overlay starts at OVERLAY_AREA. One
 particular overlay will end at a higher address than all the others;
 at this address, the linker defines a special empty segment called
 OVERLAY_END. Finally, the linker assigns addresses for all remaining
 segments in the root so that the first one starts at OVERLAY_END. The
 load image looks like the following:

         ------------+-> 0000
         |           |
         |  root     |
         |           |
         +-----------+-> OVERLAY_AREA
         |  overlay  |
         |  area     |
         |           |
         +-----------+-> OVERLAY_END
         |  root     |
         +-----------+

    The resultant MAP file has some different contents than the
 pre-overlay file. All items listed are declared as "res", meaning
 resident. The items contained within the overlay modules are also
 declared as "res".
    At the top of the MAP file, the segments are listed in the exact
 order in which they will be in the load image, and each segment is
 identified as being in a particular overlay or the root.
    Every symbol marked "res" is in a root segment and every symbol
 marked "ovl" is in an overlay segment. If symbols are not where you
 think they ought to be, remember the linker assigns segments, not
 modules, to overlays.
    For more information on overlays, refer to the 1988 "MS-DOS
 Encyclopedia."


 17. Link Error L1089

 Product Version(s): 3.51 3.55 3.60 3.61 3.64 3.65 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 22-JUL-1988    ArticleIdent: Q32829

    If you are receiving the following error message, check to see if
 the TMP environment variable is set correctly:

    L1089   'filename' : cannot open response file

   If the TMP variable is not set, temporary files cannot be created
 and this error may occur.



 18. Cannot Overlay Small-Model Code

 Product Version(s): 3.60 3.61 3.64 3.65 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-OCT-1988    ArticleIdent: Q34294

 Problem:

 I have specified overlays for my small-model code, but the link map
 shows that no overlays are produced.

 Response:

 You cannot overlay small-model code. You must change the memory model
 to medium, large, or huge. Page 285 of the "Microsoft CodeView
 Utilities" manual that comes with C Versions 5.00 and 5.10, MASM
 Versions 5.00 and 5.10, and Pascal Version 4.00, and Page 135 of the
 "Microsoft FORTRAN Optimizing Compiler User's Guide" states that you
 can overlay only modules to which control is transferred and returned
 by a standard 8086 long (32-bit) call/return instruction.


 19. Link Error 4051

 Product Version(s): 3.60 3.61 3.64 3.65 5.01.20 5.01.21
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 22-JUL-1988    ArticleIdent: Q32831

    If you receive link error 4051, check the following:

    1. Is the LIB environment variable set correctly? Check
       for spaces around the equal sign or any extra characters
       at the end of the line.
    2. Which version of the linker is being used? Old versions of
       the linker do not recognize the LIB environment variable.
          Make sure the linker being used is the one that came with
       the product.
    3. Are the library names being asked for component libraries or
       combined libraries? Libraries compiled under C Version 4.00 or
       earlier have component library names embedded in the .OBJ files.
       With later versions of the C compiler, combined libraries are used
       and the component libraries will not be found.
          This behavior also exist when upgrading from Pascal Versions 3.32
       or earlier to Pascal Versions 4.00 or greater.
          The work-around for this behavior is to recompile all .OBJ file
      (and libraries) with the new compiler or to use the /NOD switch
      when linking, and specify all the libraries (combined and otherwise)
      to be used. The following is an example:

             link /NOD  test,,,llibce.lib;

    4. Is the correct library available for the math option chosen?
    FORTRAN defaults to the co-processor library (e.g. LLIBFOR7.LIB).
    C and Pascal default to the emulator math library (e.g. SLIBCE.LIB
    and LIBPASE.LIB)



 20. LINK /CO /DO in OS/2 Gives Protection Violation

 Product Version(s): 5.01.21 | 5.01.21
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | buglist5.01.21
 Last Modified: 13-OCT-1988    ArticleIdent: Q34374

 The Microsoft Segmented Link Utility Version 5.01.21 will
 incorrectly generate a protection violation under OS/2 when the
 command line uses the options /CO /DO, respectively.

 OS/2 gives the message SYS1943: "A program caused a protection
 violation." The SYS1811 violation follows, indicating the process has
 stopped.

 The work around for this problem is to order the switches differently.
 Instead of including /CO /DO in the command line, the command line can
 be reorder to /DO /CO.

 Microsoft has confirmed this to be a problem in Version 5.01.21. We are
 researching this problem and will post new information as it becomes
 available.


 21. /NOE Option for Redefinition Error L2044

 Product Version(s): 3.x 5.x | 5.10
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 13-OCT-1988    ArticleIdent: Q34502

 The /NOEXTDICTIONARY switch tells the linker NOT to take advantage of
 additional information recorded in Extended Dictionary in the library
 file. This additional information describes which module in the library
 calls any other module from the same library, saving linker number
 of passes through the library file to pick up all required modules.

 If you have a call in your code to the library function FOO and FOO
 calls another function BAR from the same library, then at processing
 time of FOO, the linker will pull out BAR. This process occurs because
 the extended dictionary has a link between FOO and BAR.

 Linking without /NOE causes the following error if you want to pull
 FOO in from the library but you want to provide its own BAR:

 L2044 BAR : symbol multiply defined, use /NOE

 This error resulted from the linker pulling FOO and BAR from the
 same library, then later it sees BAR coming from user .OBJ file.

 Using /NOE in this case prevents the linker from pulling out
 BAR from the library, so your BAR routine is used instead.

 If you have genuine symbol redefinition, then when linking with /NOE
 you will see the following error:

 L2025 BAR : symbol defined more than once


 22. L2001 Fixups without Data

 Product Version(s): 3.65 5.01.21 | 5.01.21
 Operating System:   MS-DOS       | OS/2
 Flags: ENDUSER |
 Last Modified: 12-OCT-1988    ArticleIdent: Q35155

 The Link Utility can generate the linker error message L2001:
 fixup(s) without data. In the manual, the linker error is described
 as follows:

 A FIXUPP record occurred without a data record immediately
 preceding it. This is probably a compiler error. (See
 the "Microsoft MS-DOS Programmer's Reference" for more information
 on FIXUPP.

 In most cases, the error message is generated from an
 assembly-language program that doesn't make sense from the linker's
 point of view, but is convenient for users. The following is an
 example:

     extrn   foo:word

     ABSEG   segment at 123          ; absolute segment

     dw      offset DGROUP:foo       ; offset portion of address of "foo"

     ABSEG   ends

 This tells the linker to fix up a location in ABSEG with the address
 of foo. But ABSEG is an absolute segment and has no data to be fixed
 up.

 Another example is when you include the same STRUC definitions in both
 absolute and non-absolute segments, so that the STRUC definitions
 contain relocatable addresses.



 23. Setting the Overlay Interrupt (/O) in LINK

 Product Version(s): 3.61 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 20-JAN-1989    ArticleIdent: Q40408

 Question:

 Page 272, Section 12.2.12, of the "Microsoft CodeView and Utilities
 Software Development Tools for the MS-DOS Operating System" manual
 states that you can change the default overlay interrupt. The default
 interrupt is 3F hexadecimal. Is the manual correct? Do you have to
 change the interrupt if you have a program that uses overlays and it
 spawns a program that also uses overlays?

 Doesn't the compiler save interrupts? Suppose both Programs A and B
 use overlays and A spawns B. If B is a Microsoft C Version 5.00 or
 5.10 program, shouldn't it restore the original INT 3F address when it
 exits? Thus, everything should work correctly without
 /OVERLAYINTERRUPT.

 Response:

 You are correct; the C Versions 5.00 and 5.10 compiler saves and
 restores the interrupt so there should be no conflict. The C Versions
 5.00 and C 5.10 manual is incorrect. This switch need only be used if
 you are linking a program with overlays, and INT 3F is being used by
 something else when you run the program. For example, INT 3F might be
 used to communicate with a hardware board or a TSR might use it;
 however, this is unlikely.

 This option is for advanced users who know their configurations well
 enough to know who is using which interrupt vectors and know there is
 a conflict.


 24. LINK Environment Variable Ignored When Linking Through CL

 Product Version(s): 5.00 5.10 | 5.10
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | S_C S_QuickC
 Last Modified: 15-AUG-1989    ArticleIdent: Q47503

 Problem:

 To increase the size of my stack, when I set an environment variable
 called LINK equal to /ST:4096, it doesn't work correctly when I link
 using CL.

 Response:

 Before CL spawns the linker, it clears the environment of all
 variables except LIB. Consequently, the LINK environment variable
 doesn't exist when the linker is invoked, and any options that were
 specified by it are not seen. When linking with CL, any desired linker
 options should be specified on the CL command line after the /link
 switch.

 The same behavior is seen with the command line compilers from QuickC
 Version 1.00 and 1.01, but not with QuickC 2.00 or QuickAssembler.


 25. Why Unitialized Global Variables Don't Appear in C 5.10

 Product Version(s): 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G881021-5044
 Last Modified:  6-DEC-1988    ArticleIdent: Q38725

 Questions:

 Why don't uninitialized global variables show up in the library
 listing when the module containing them has been placed in the
 library? It appears that the librarian does not "see" uninitialized
 global variables.

 If my main program declares an extern, and an .OBJ with which its
 linked declares it globally (without extern), but doesn't initialize
 it, the symbol appears in the link map and space is allocated for it
 in the .EXE. This behavior seems different from previous versions of
 the compiler. If the .OBJ file is placed as a library rather than
 linked explicitly, the symbol does not appear in the .EXE. Why does it
 behave differently?

 Response:

 In Version 5.00 of the C Compiler, we introduced a new concept into
 our linking process called "communal data." Communal data can be
 declared in many modules, but only one copy of the data will exist
 in the linked .EXE file. (It is similar to the concept of COMMON
 blocks in FORTRAN.)

 In C, data declared outside of a function without a storage class is
 now considered to be communal data. (This is a change from previous
 versions.) Communal data declarations generate no definitions, just
 declarations; whereas initialized, or global, data declarations
 generate both definitions and declarations.

 Communal declarations may refer to a global definition. If they do,
 the linker simply adjusts the address as necessary. However, if
 there is no global definition of the variable, the linker combines
 the declarations into one definition and allocates the appropriate
 amount of space. For example, it is legal to declare

    int x;

 in several different modules without a corresponding

    int x = 0;

 Communal declarations are NOT copied into libraries. (This is
 documented on Page 84 of the "Microsoft C Language Reference Manual.")
 If you want the variable to appear in a library, it MUST be
 initialized so that it is global rather than communal. Communal
 variables are not included in libraries because they can cause
 strange conflicts. For example, let's suppose you
 unwittingly used a variable name that was also the name of a communal
 variable in your library. At link time, the linker would allocate
 only ONE copy of that variable without generating any warning.

 The symptom would be that your variable would mysteriously change
 every time you called the library function that used the communal
 variable. This problem would be a very difficult to trace.

 Now that we understand communal variables and how they interact with
 libraries, we can answer your questions.

 The first question was basically, "Why don't my communal variables
 show up in the library listing?" Because communal data is not placed
 into the library, it won't show up in the listing.

 The second question was, "How come the communal variable shows up in
 the .EXE file if I link it from an .OBJ file but not from a .LIB
 file?" It shows up from the .OBJ file because the communal variable
 is allocated space by the linker if it doesn't resolve to a global
 definition. It does NOT appear in the link produced by the .LIB file
 because it does not appear in the library dictionary.

 Note: this behavior is the result of doing something we ask you not to
 do; namely, putting communal data in a library. Data intended to be
 placed in a library must be initialized.


 26. Example of Using a Response File with LINK

 Product Version(s): 3.65   | 5.01.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-JAN-1989    ArticleIdent: Q40429

 The following is a small example of using a response file with LINK.

 A response file contains responses to the LINK prompts. The responses
 must be in the same order as the LINK prompts.

 LINK treats the input from the response file just as if you had
 entered it in response to prompts or in a command line. It treats any
 carriage-return-linefeed combination in the response file the same as
 if you had pressed the ENTER key in response to a prompt or included a
 comma in a command line.

 Note: You cannot put comments in response files.

 The following is an example of a file named RESPONSE.ONE:

 file1 file2 file3 file4
 /pause /map
 filelist
 graphics.lib

 Type the following at the command line:

    LINK @response.one


 27. Error L2025: Symbol Defined More than Once

 Product Version(s): 5.10   | 5.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-JAN-1989    ArticleIdent: Q40485

 Problem:

 I cannot link a function name in my object file with a library
 containing that same function name and have the resulting EXE call my
 function and not the library's.

 I am using /NOE; however, I receive the following error:

 (...): error L2025: (my function name) : symbol defined more than once
  pos: (some number) Record type: 53E8

 Response:

 You can only perform this task if the function name is an individual
 module. The following procedure demonstrates the error:

 1. Create a file CALL.C that calls functions A() and B().

 2. Create functions A() and B() in fileA.c and fileB.c, and compile
    them to objects.

 3. Do the following to create TEST.LIB:

       LIB TEST +fileA +fileB, test.lst

 4. Change B() in fileB.c and compile the following:

       cl call.c fileB.c test.lib /link /NOE /INF

    You will have an EXE that calls A() from the library and B() from
    your modified fileB.c.

 5. Combine fileA.c and fileB.c into one file called TEST.C.

 6. Compile to object code.

 7. Delete the old TEST.LIB, and do the following:

       LIB TEST +test, test.lst

    (Normally you would change fileB.c, but this is not necessary here.)

       cl call.c fileB.c test.lib /link /NOE /INF

 You will receive the following error:

 TEST.LIB(test.c) : error L2025: _B : symbol defined more than once
  pos: 13E Record type: 53E8
 There was 1 error detected

 When you encounter this error, it is usually because the function you
 are trying to overwrite is part of a set appearing in one module.

 The library listing looks as follows in the first case:

 _A................fileA             _B................fileB

 fileA             Offset: 00000010H  Code and data size: 95H
   _A

 fileB             Offset: 000002a0H  Code and data size: 92H
   _B

 You will be able to replace A() or B(). The listing in the
 second example looks as follows:

 _A................test              _B................test

 test              Offset: 00000010H  Code and data size: deH
   _A                _B

 You will not be able to replace either A() or B() without removing the
 TEST module with the LIB utility. You may have to provide replacements
 for both functions and not just the one you want to change. For more
 information, query on the following words in this KnowledgeBase:

    L2029 unresolved externals


 28. Default for NODATA When Using the _export Keyword

 Product Version(s): 5.01.21 | 5.01.21
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | buglist5.10.21 buglist5.02 fixlist5.03
 Last Modified: 21-AUG-1989    ArticleIdent: Q47826

 Question:

 What is the default for NODATA when using the _export keyword? The
 _export keyword is used to mark functions in DLLs for export. It
 appears that for real-mode windows, for normal applications, _export
 does not use NODATA. However, for DLLs (also for real-mode windows)
 _export marks the function NODATA. How does the keyword _export mark
 functions (NODATA or not).

 Response:

 The default as issued by the compiler is not NODATA, i.e., the
 exported routine is assumed to use the shared data segment.
 Unfortunately, the linker has a problem that causes it to mistakenly
 assume NODATA for all exports declared from the .OBJ file.

 Microsoft has confirmed this to be a problem with LINK Version 5.01.21
 and 5.02. The problem was corrected in LINK Version 5.03 and later.

 In OS/2 this should not make any difference. In Windows, the program
 loader looks for the -Gw sequence in the prolog of the exported entry
 and replaces it with a sequence to load DS. The _loadds keyword will
 generate the load-DS sequence in the first place.

 In any case, a workaround is to not use the _export keyword and
 declare the routine in EXPORTS in the .DEF file.


 29. No Default Extension for a Linker Response File

 Product Version(s): 3.55 3.60 3.61 3.64 3.65  | 5.01.21 5.01.21
 Operating System:   MS-DOS                    | OS/2
 Flags: ENDUSER |
 Last Modified:  2-MAR-1989    ArticleIdent: Q41611

 The Microsoft Overlay Linker does not have a default extension for a
 response file; unlike Phoenix's PLINK, which uses a default .LNK
 extension.

 This information also applies to the Microsoft Segmented-Executable
 Linker.


 30. Ambiguous Switch /PAC with QuickC 2.00 Linker

 Product Version(s): 4.06
 Operating System:   MS-DOS
 Flags: ENDUSER | s_quickc b_quickbas docerr
 Last Modified: 22-JAN-1990    ArticleIdent: Q42027

 Using the /PAC switch with LINK Version 4.06 results in the
 following error:

    fatal error L1001: PAC : option name ambiguous

 This same option works correctly on Versions 3.65 and 5.01.21, and is
 documented as being a valid shorthand name for /PACKCODE on Page 131
 of the "QuickC Tool Kit."

 The problem is due to a conflict with an option that is not documented
 in the Tool Kit, but is displayed when LINK is invoked with /HELP. The
 option that causes the ambiguity is /PACKDATA, which causes data
 segments to be combined.

 The shortest version of /PACKCODE that can be used is /PACKC.
 Similarly, /PACKD is the shortest version of /PACKDATA that can be
 used.


 31. /CO before /DO Causes Problems in LINK

 Product Version(s): 3.65 4.06 5.01
 Operating System:   MS-DOS
 Flags: ENDUSER | h_masm s_pascal h_fortran buglist3.65 buglist5.01
 Last Modified: 28-MAR-1989    ArticleIdent: Q42212

 When compiling or assembling with the /Zi switch to include CodeView
 symbolic information and linking with /CO to preserve it, the
 placement of the /DO switch is crucial. If the /CO switch is specified
 before /DO, the following behavior may occur when running CodeView:

    Message                                Behavior

    Enter directory for  (cr for none)?    When CodeView is executed,
                                           no source code will appear.

    Unable to open file

    Internal debugger error: 13            When attempting to change
                                           from assembly view to source
                                           CodeView. Hanging of the
                                           machine when executing
                                           CodeView.

 If switching the order of the /CO and the /DO switches does not
 take care of the problem then you have to put the .DOSSEG into
 your MASM routines and not use the /DO switch.

 Microsoft has confirmed this to be a problem in Versions 3.65 and
 5.01. We are researching this problem and will post new information as
 it becomes available.

 While LINK Version 5.01 may be used in OS/2, the /DO switch has no
 meaning. Using it, however, causes the linker to GP fault if /CO
 precedes /DO.



 32. Unimplemented Switch /BI with QuickC 2.00 Linker

 Product Version(s): 4.06
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QUICKC
 Last Modified: 24-JAN-1990    ArticleIdent: Q42849

 The /BINARY switch for Link Version 4.06 is documented on Page 122 of
 the "Microsoft QuickC Tool Kit" as a switch used to create .COM files
 for assembly-language programs. Its shorthand version is /BI. This
 switch is an alternative to creating .EXE files and then running them
 through EXE2BIN.

 This switch is currently not implemented, a fact documented in the
 README.DOC on line 665, "Creating a .COM file." Using it will result
 in the following error:

     fatal error L1002: BINARY : unrecognized option name


 33. How /NOE (No Extended Dictionary) Is Used by the Linker

 Product Version(s): 3.65 4.06 5.01 | 5.01
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | S_C H_FORTRAN S_QUICKC
 Last Modified:  6-APR-1989    ArticleIdent: Q43009

 This article contains information about the LINK option /NOE and how
 it relates to the three following topics:

 1. The Extended Dictionary and how LINK uses it

 2. The definition of genuine redefinition

 3. Why redefinitions are not detected in some situations

 The LINK option /NOE stands for No Extended Dictionary.

 What is the extended dictionary and how does LINK use it? How does
 LINK use the extended dictionary?

 LINK uses the extended dictionary to speed up library searching. For
 example, if the library module A calls functions in module B and
 module C, the extended dictionary tells LINK that, if your program
 requires module A from library, it will also require modules B and C.
 According to this information, LINK pulls in the three modules A, B,
 and C all at once. This way, LINK doesn't have to search the library a
 second time to resolve references from module A to modules B and C.

 What is a genuine redefinition?

 The ERRMSG.DOC file states that when linker error L2044 occurs, the
 /NOE switch should be used. When linker error L2025 occurs, the
 program has a genuine redefinition problem.

 A genuine redefinition is any redefinition that has nothing to do with
 the extended dictionary. A redefinition error that occurs when you
 specify the /NOE switch indicates a genuine redefinition, as in the
 following example:

     FOO.OBJ:
         defines "_foo"
         calls "_libfunc"

     Module A: (in XYZ.LIB):
         defines "_libfunc"
         defines "_foo"

 If you run "LINK foo /NOE,,,xyz.lib", the L2025 error will be produced
 because module A is pulled in and redefines the symbol "_foo".

 When LINK encounters the redefinition while processing a library
 module, it assumes that the error might go away if you were to add the
 /NOE switch. This would be true if the symbols were defined like this
 as follows:

     FOO.OBJ:
         defines "_foo"
         calls "_libfunc"

     Module A (in XYZ.LIB):
         defines "_libfunc"
         calls "_foo"

     Module B ( in XYZ.LIB ):
         defines "_foo"

 The extended dictionary tells LINK to link modules A and B, even
 though module B should not be linked because "_foo" is already
 defined. In this case, the /NOE switch will eliminate the error.

 LINK cannot figure out when the error is due to the extended
 dictionary and when it is not; therefore, it assumes that the extended
 dictionary will cause a redefinition error when processing a library
 module.

 Please note that redefinitions not detected in some situations. For
 example, when the function 'printf' is redefined in a program module
 and the module is linked with SLIBCER.LIB without using the /NOE
 switch, LINK does not complain about the redefinition at all. LINK
 does not detect a redefinition because the module that defines printf
 in the library is not pulled in; thus, there is no redefinition.

 If your program module redefines a library function that is also
 called by other library functions used by your program, you will get a
 redefinition error. The extended dictionary specifies which library
 modules call routines in other library modules. Consider a
 "second-level" function to be any library function called by a library
 function in another module. For example, spawnve and _setargv are
 second-level functions because they are called by other library
 functions; printf is not. You can get a redefinition error only if you
 redefine a second-level library function called by some first-level
 routine being linked into your program.


 34. Producing an _TEXT Segment for Multiple Object Modules

 Product Version(s): 3.x 4.06 | 5.01.20 5.01.21
 Operating System:   MS-DOS   | OS/2
 Flags: ENDUSER | S_C
 Last Modified:  6-APR-1989    ArticleIdent: Q43128

 In a map file, a <modulename>_TEXT will be produced for each logical
 code segment in your program. Since small and compact model programs
 have only one code segment, you only get one logical segment, _TEXT.
 Medium- and large-model programs, however, will have a separate
 logical segment for each object module in the program, and thus produce
 a <modulename>_TEXT for each logical segment.

 To generate a map file, use the /M option with LINK or the /Fm option
 with CL.

 The following is an example map file generated when compiling a
 program with two object modules in small-memory model:

  Start  Stop   Length Name                   Class
  00000H 016EAH 016EBH _TEXT                  CODE
  ...

 The following is an example map file generated when compiling the same
 program with two object modules in large-memory model:

  Start  Stop   Length Name                   Class
  00000H 0000DH 0000EH MAPL_TEXT              CODE
  0000EH 00023H 00016H MAP2_TEXT              CODE
  00024H 01B2CH 01B09H _TEXT                  CODE
  ...

 MAPL_TEXT and MAP2_TEXT come from the files MAPL.OBJ and MAP2.OBJ,
 respectively. The _TEXT is the Microsoft run-time library and any
 third-party libraries.



 35. LINK: Renaming Overlayed Executables Will Cause Problems

 Product Version(s): 5.01.21
 Operating System:   DOS
 Flags: ENDUSER | s_C s_Pascal h_FORTRAN
 Last Modified:  6-APR-1989    ArticleIdent: Q43139

 When the Microsoft linker creates an executable file with overlays,
 the name of that EXE is hard coded into the file for use by the overlay
 manager. The Microsoft linker only creates internal overlays, i.e.,
 rather than producing FOO.EXE, FOO1.OVL, and FOO2.OVL, the two
 overlays are contained in FOO.EXE.

 If the executable is renamed at any point after linking, the overlay
 manager will still use the hard-coded name found in the EXE to locate
 the overlays, and will fail with the following prompt:

    Cannot find <oldname>
    Please enter new program spec:

 In order to change the name of the executable without receiving this
 error, it must be relinked and given the new name at that time.


 36. LINK: Creating and Accessing _edata and _end

 Product Version(s): 3.X 4.06 | 5.01.20 5.01.21
 Operating System:   MS-DOS   | OS/2
 Flags: ENDUSER | s_c
 Last Modified:  6-APR-1989    ArticleIdent: Q43165

 LINK creates the two symbols _edata and _end when the LINK option
 /DOSSEG is used. If a program is compiled by a Microsoft high-level
 language compiler, or if an assembly program written in Microsoft MASM
 uses .DOSSEG directive, LINK uses this option automatically.

 LINK gives _edata the address of the beginning of BSS segment and
 gives _end the address of the end of BSS segment. Since the STACK
 segment is directly above the BSS segment, the address of _end also
 marks the lowest address of the STACK segment.

 To obtain the addresses for these two symbols, declare the following
 in your C program:

 unsigned char edata, end ;

 The addresses, &edata and &end, can now be used to locate _BSS and
 STACK. They can also be examined in CodeView. Modifying these two
 variables is not recommended.

 Note: The segment BSS referred to in this article actually includes
 the segment C_COMMON. However in a map file created by LINK, BSS and
 C_COMMON are listed as two separate segments.



 37. Linker Options /PADDATA and /PADCODE

 Product Version(s): 4.06
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QuickC docerr
 Last Modified: 18-SEP-1989    ArticleIdent: Q44928

 Question:

 I ran the linker Version 4.06 that comes with the Microsoft QuickC
 Compiler Version 2.00 with the /help option as follows:

    LINK /HELP

 I noticed two switches for which I couldn't find documentation:
 /PADDATA and /PADCODE. What are these options for?

 Response:

 The /PADC[ODE]:padsize option causes LINK to add filler bytes to the
 end of each code module. The option is followed by a colon and the
 number of bytes to add. (Decimal radix is assumed, but you can specify
 special octal or hexadecimal numbers by using a C-language prefix.)
 Thus, the following adds an additional 256 bytes to each code module:

    /PADCODE:256

 The default size for code-module padding is 0 bytes.

 The /PADD[ATA]:padsize option performs a function similar to
 /PADCODE, except that it specifies padding for data segments (or data
 modules, if the program uses small or medium-memory models). Thus,
 the following adds an additional 32 bytes to each data module:

    /PADDATA:32

 The default size for data-segment padding is 16 bytes. Note that if
 you specify too large a value for padsize, you may exceed the 64K
 limitation on the size of the default data segment.

 These two options are quite useful when used in conjunction with
 QuickC Version 2.00's incremental linking option. Using them correctly
 increases the incremental linking speed of a program.

 These two options are documented on Page 64 in the update section of
 the Microsoft C Optimizing Compiler Version 5.10 "CodeView and
 Utilities, Microsoft Editor, Mixed-Language Programming Guide" manual.


 38. Linker Error L2013 May Be a Result of a Problem in MASM 5.10

 Product Version(s): 3.x 4.06 4.07 5.01.21 5.02 5.03 5.05
 Operating System:   MS-DOS
 Flags: ENDUSER | h_masm
 Last Modified: 27-DEC-1990    ArticleIdent: Q59894

 The error message for linker error L2013 is as follows:

    error L2013 LIDATA record too large
       pos: xxx Record type: 743C

 In the README.DOC file that comes with MASM version 5.10, Microsoft C
 version 5.10, and the "Microsoft FORTRAN CodeView and Utilities User's
 Guide" version 5.00 manual, the recommended course of action is to
 call Microsoft Product Support at (206) 637-7096.

 The error is a result of an invalid object module. This is a known
 problem in MASM 5.10. The most likely cause is a duplication of some
 large data item, such as a structure.

 The easiest workaround is to break up the duplication(s) into smaller
 parts.


 39. LINK 5.02 Should Not Be Used with ILINK 1.10

 Product Version(s): 5.02
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QuickC
 Last Modified: 30-AUG-1989    ArticleIdent: Q45536

 LINK Version 5.02, which comes as a secondary linker for QuickC 2.00,
 should not be used with ILINK Version 1.10, which also comes with
 QuickC 2.00.

 Inside the QuickC environment, this combination has caused problems
 with floating point-values being printed with printf. Outside of the
 environment, the same executable results in math error M6104.

 The source code below prints "FP = 0.00000" instead of "FP =
 5.020000". Running from the DOS prompt, in this case, produces the
 same results.

 Source Code
 -----------

     #include <stdio.h>

     void main( void )
     {
         float fp = 5.02F;

         printf( "FP = %f\n", fp );
     }

 LINK Version 4.06 should be used if ILINK is also to be used. If it is
 necessary to use Version 5.02 of the linker, incremental linking
 should be disabled from within the environment.

 Microsoft is researching this problem and will post new information as
 it becomes available.


 40. Linker Errors L4013, L2048, and L4038: Overlaying in OS/2

 Product Version(s): 5.01.20 | 5.03
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | S_C H_Fortran
 Last Modified: 21-JUN-1989    ArticleIdent: Q45619

 The linker does not overlay files when linking with protected mode
 run-time libraries. If told to overlay a program that is being linked
 with a protected mode run-time library, the linker responds with one
 or more of the following errors:

    LINK : warning L4013: invalid option for new-format executable file
    ignored
    LINK : error L2048: Microsoft Overlay Manager module not found
    LINK : warning L4038: program has no starting address

 possibly followed by (in DOS):

    run-time error R6001
    - null pointer assignment

 or possibly followed by (in OS/2):

    A general protection (GP) fault. It may also go into an infinite
    loop after creating the temporary file (for large executables).

 The workaround is to create two versions of the executable, an
 overlayed DOS version and a non-overlayed OS/2 version.

 Microsoft is researching this problem and will post new information as
 it becomes available.


 41. Link Error L1005: /PACKCODE: Packing Limit Exceeds 65,536

 Product Version(s): 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 21-JUN-1989    ArticleIdent: Q45724

 The Microsoft Overlay Linker Version 3.65 presents the following error
 message when the /PACKCODE: switch is used with a value greater than
 65,536 (64K):

    Link Fatal Error L1005:

 No error message text is supplied, and the error cannot be referenced
 in the Microsoft C 5.10 "CodeView and Utilities, Microsoft Editor,
 Mixed-Language Programming Guide." The error message should read as
 follows:

    Link Fatal Error L1005: /PACKCODE: Packing Limit Exceeds 65,536

 The error is reported correctly by the Microsoft QuickC Linker Version
 4.06 and all 5.0x versions of the Microsoft Segmented-Executable
 Linker. It is correctly documented in the Version 2.00 "Microsoft
 QuickC Tool Kit," on Page 278, and on Page 373 of the Version 5.00
 "Microsoft FORTRAN, Microsoft CodeView and Utilities User's Guide"
 manual, as follows:

    The value supplied with the /PACKCODE option exceeds the limit of
    65,536 bytes.


 42. What the /HIGH and /DS Linker Options Do

 Product Version(s): 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G890607-19979
 Last Modified: 13-JUL-1989    ArticleIdent: Q46745

 Question:

 I would like information on the /HIGH and /DS options of the linker.
 Specifically, what changes are needed in the .EXE file to tell the
 loader to put it high?

 Response:

 Basically, these are hold-over features from DOS Version 1.00 and from
 the original Microsoft/IBM Pascal and FORTRAN Compilers -- they're of
 little or no use under DOS 2.00 and later. Specifically, programs
 linked with the /HIGH switch are allocated all of the memory in the
 machine and cannot release unneeded memory back to DOS; therefore, no
 other program can be loaded into memory.

 The /HIGH switch sets both the minalloc and maxalloc fields in the .EXE
 header to zero. This combination of values causes the loader to load
 the program in high memory.

 /DSALLOCATE (or /DS) causes DGROUP to be "shifted" upwards so that the
 high address in the group is always FFFFh. Offsets into DGROUP are
 adjusted appropriately.

 These switches are strictly incompatible with our current high-level
 languages -- the only possible use for them is in a MASM program.
 Microsoft doesn't recommend using them at all unless you know
 precisely what you're doing.

 There is good documentation on what the /HIGH and /DSALLOCATE switches
 do, as well as how the loader works, in the "MS-DOS Encyclopedia,"
 starting on Page 719. (This excellent reference manual is now less
 expensive and available in paperback).


 43. How Minimum Load Size Is Calculated

 Product Version(s): 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER | SR# G890607-19979
 Last Modified: 13-JUL-1989    ArticleIdent: Q46774

 The MS-DOS program loader uses the following formula to calculate the
 number of 16-byte paragraphs to use when loading a program:

    TotPages * 20h - NumHeader + 10h + MaxAlloc

 The formula calculates the number of 16-byte paragraphs, unless
 there's not enough memory, in which case all the available memory is
 used. If there are not at least

    TotPages * 20h - NumHeader + 10h + MinAlloc

 paragraphs available, DOS cannot and will not load the program.

 The 20h is the size of a page in paragraphs, which is the size of a
 page (512 bytes) divided by the size of a paragraph (16 bytes).

 The 10h is the size in paragraphs of the 256-byte Program Segment
 Prefix that precedes all programs in memory.

 All of the values used in the formulae shown above are words (shown in
 the following) that are stored in standard Intel low-byte-first format
 in the .EXE file header:

    Value           Name used by EXEHDR             Offset in .EXE header
    -----           -------------------             ---------------------

    TotPages        Pages in file                   4 - 5
    NumHeader       Paragraphs in header            8 - 9
    MinAlloc        Extra paragraphs needed         0Ah - 0Bh
    MaxAlloc        Extra paragraphs wanted         0Ch - 0Dh

 For more information, refer to a good MS-DOS reference such as the
 "MS-DOS Encyclopedia."


 44. L1074 Name: Group Larger Than 64K Bytes

 Product Version(s): 4.06
 Operating System:   MS-DOS
 Flags: ENDUSER | S_C S_QuickC
 Last Modified: 24-JUL-1989    ArticleIdent: Q46996

 The Microsoft QuickC Compiler Version 2.00 returns the following
 linker error message when the size of DGROUP (the default data
 segment) exceeds 64K:

    L1074 name: group larger than 64K bytes

 This error is documented on Page 282 of the "Microsoft QuickC Tool
 Kit" manual as follows:

    The given group exceeds the limit of 65,536 bytes.

    Reduce the size of the group, or remove any unneeded segments from
    the group (refer to the map file for a listing of segments).

 There are four ways to resolve this data segment overflow when using
 QuickC:

 1. Reduce the stack size in order to reduce the size of DGROUP. In the
    environment this can be done in the Options.Make.Linker Flags menu.
    Outside the environment this can be done at compile time with the
    "/F hexnum" switch, where hexnum is the size of the requested stack
    in hexadecimal format. Outside the environment, at link time, this
    can be done with the "/ST:decnum" switch, where decnum is the size
    of the requested stack in decimal format.

 2. Declare data with the FAR keyword to move it out of DGROUP.

    Note: In the small and medium memory models the Microsoft run-time
    library functions can no longer be used with this data. You must
    copy this far to a near heap location, before you use the run-time
    routines on this data.

 3. Outside the environment, compile in the compact, large, or huge
    memory models with the "/GtX" switch, where X is a data threshold.
    All data items larger than X bytes are moved out of DGROUP into a
    far data segment.

 4. Reduce the amount of data declared in the program. In the compact,
    large, and huge memory models, try dynamically allocating space for
    the data. Memory can also be dynamically allocated outside DGROUP
    in the small and medium memory models by using _fmalloc() but, as
    stated in Number 2, the run-time library functions do not work with
    this data.

    Reduce the amount of string literals in this default data segment by
    reading from a data file at run time, or in C 5.00, by using the
    /Gt patch to allow string literals to be moved from the _CONST
    segment in DGROUP into a far segment.


 45. /CP:X Is Not Valid When Linking Protected-Mode Programs

 Product Version(s): 5.01.21 | 5.01.21
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 26-JUL-1989    ArticleIdent: Q47036

 Question:

 I cannot seem to get the /CPARMAXALLOC linker option to work when I
 link for OS/2 protected mode. When linking a real-mode application, it
 works correctly. Also, when I type "link /help" in protected mode, the
 output indicates that this is a valid option. However, when I try to
 use this option for a protected-mode application, the linker produces
 the following warning:

    LINK : warning L4013: invalid option for new-format executable file
                          ignored

 What am I doing wrong and what does this error message mean?

 Response:

 As documented on Page 27 in the update section of the Microsoft C
 Optimizing Compiler Version 5.10 "CodeView and Utilities, Microsoft
 Editor, Mixed-Language Programming Guide" manual, the /CPARMAXALLOC
 option is for real-mode applications only. The "link /help" indicates
 that this is a valid option because this option IS valid whenever
 you're linking real-mode applications, regardless of whether the
 linker is running under OS/2 or DOS. (By the same token, it is invalid
 when you're linking a protected-mode application, regardless of which
 operating system you're using.)

 This error message was omitted from the documentation. It indicates
 that one of the options that the linker was passed is invalid.

 This option is not supported in a protected-mode application because
 the functionality of it is done automatically by the linker.
 Protected-mode applications are not given a 64K default data segment;
 they are only allocated the space that they need. This is documented
 on Page 33 of the same section and manual listed above.


 46. Cannot Use Overlays in a Bound Application

 Product Version(s): 5.01.21 5.03 | 5.01.21 5.03
 Operating System:   MS-DOS       | OS/2
 Flags: ENDUSER |
 Last Modified: 30-AUG-1989    ArticleIdent: Q47104

 Question:

 How can I incorporate overlays into my bound application?

 Response:

 You cannot use overlays in a bound application. To bind an
 application, you must first have a runnable OS/2 executable; then, you
 use the BIND utility to make it run in both OS/2 and DOS. OS/2
 executables do not understand overlays so you cannot incorporate them
 into an OS/2 executable. Hence, you cannot use overlays in a bound
 program.


 47. Linker Error L1063 and Linking Over 1000 Object Modules

 Product Version(s): 5.01.21 5.03
 Operating System:   OS/2
 Flags: ENDUSER | S_C S_CodeView
 Last Modified: 16-AUG-1989    ArticleIdent: Q47931

 Question:

 When attempting to link a large OS/2 application consisting of over
 1500 object modules with C 5.10's Link 5.01.21 or FORTRAN 5.00's Link
 5.03 by using the options /co /map:2078 /noe /se:2078 /packcode, I get
 the link error "L1063 out of memory for CodeView information." Only
 one of the .C source files was compiled with /Zi. All were compiled
 with /AL. Linking without /co (CodeView information) successfully
 produces a 700K executable file (.EXE), but I need to do some
 debugging with CVP.

 What is the L1063 error, and how can I work around it?

 Response:

 Information on L1063 is not in the C 5.10 text files or documentation,
 but it is in Pascal 4.00's README.DOC and in FORTRAN 4.10's
 CVREADME.DOC as noted in another article in this knowledge base. The
 following reiterates the error message and its description:

    L1063 out of memory for CodeView information

    The linker was given too many object files with debug information,
    and the linker ran out of space to store it. Reduce the number of
    object files that have debug information.

 In this case, it is not the number of modules with CodeView
 information that is causing the problems exactly; it is the great
 number of modules and trying to link in any CodeView information.

 The following are ways to workaround this linker limitation:

 1. The most effective method is to demodularize your application. That
    is, put more functions into fewer .C source files.
 2. Reduce the linker option /se: value to as low as possible for the
    number of logical segments in the application.
 3. Link the object files from the current working directory. If you
    must use different directories for your .OBJs, make the pathnames
    as short as possible.


 48. Description of a Linker .MAP File

 Product Version(s): 3.60 3.61 3.64 3.65 5.01.20 5.01.21 5.03  | 5.01.20 5.01.
 Operating System:   MS-DOS                                    | OS/2
 Flags: ENDUSER | S_C S_PasCal H_FORTRAN
 Last Modified: 19-SEP-1989    ArticleIdent: Q47960

 A .MAP file generated by the linker is a listing of the addresses and
 names of a program, as follows:

    Logical Segments
    Groups (defined collections of logical segments)
    Public Symbols listed by name
    Public Symbols listed again by their relative address
    Entry Point address (first executable instruction)

 A linker .MAP file (with a .MAP file extension) contains the address,
 size, name, and class of logical code and data segments. (One or more
 logical segments of either code or data can be combined into a
 physical segment of either code or data, respectively, by the linker.)

 In DOS or real-mode OS/2, the addresses are 20-bit hex addresses that
 are RELATIVE to the beginning of the program's load image. In
 protected-mode OS/2, the hex addresses are in 32-bit segment
 selector:offset notation (16 bits for the segment selector and 16 bits
 for the offset) starting with segment selector 1.

 The _TEXT segment names of class CODE are the code in your object
 files. The various forms of near logical data segments are described
 in the DGROUP diagram, which you probably already have. (Briefly,
 _DATA is initialized near global data, _BSS is uninitialized near
 "static" data, C_COMMON is uninitialized near data, and CONST is for
 floating point constants. FAR_DATA and HUGE_DATA are global
 initialized far and huge data, respectively, and FAR_BSS is global
 unitialized far or huge data.)

 Next in the .MAP is the ORIGIN (address) and name of the defined
 groups of logical segments, notably DGROUP, which is used in our
 high-level languages for grouping many logical data segments into the
 "default" physical data segment. The name "default" data segment
 refers to the fact the the DS register will point to this segment by
 default so that offset (near) addressing can be used without loading
 the DS register. Groups allow multiple logical segments to be
 associated with the same starting address, so near (non-far) data in
 Microsoft high-level languages is addressed relative to DGROUP.

 Following the segment descriptions, under the heading of "Publics by
 Name", the names of Public symbols (i.e., global or extern functions,
 including numerous internal C library functions, and variables) are
 listed in ASCII order (capital letters first, then lowercase letters,
 and finally underscores) along with their hex relative segment:offset
 addresses (or segment selector:offset in protected-mode OS/2). Public
 symbols are then listed again, in order of their relative
 segment:offset addresses under the heading "Publics by Value".

 Only Public (e.g. global) symbols such as function and variable names
 appear in the .MAP. No "static" functions or data, "auto" storage
 class data (e.g. local function data), or data types are listed in the
 .MAP.

 A high-level language such as C creates many logical segments in
 DGROUP for "internal" (e.g. undocumented) purposes, calls numerous
 internal library functions, and refers to variables for the main
 program initialization and start-up code. C refers to additional
 initialization functions and variables for the library functions that
 your program explicitly calls, still more for floating point
 functions, as well as termination functions.

 To get an idea of the functions automatically linked in from the C
 library, generate and compare .MAP files for simple source modules
 such as foo(){} or main(){}, main(){puts("hi");}, and a small program
 that performs floating point arithmetic or calls a C library floating
 point math function that calls "fp..." routines.

 The "Program entry point" is the last item in the .MAP file. It refers
 to the segment:offset address of the first instruction of the program
 to be executed, relative to the lowest memory address in the .EXE load
 image.

 For more information on the entry point, please use the following
 query:

    .map file's program entry point


 49. Linker Can Indiscriminately Bind Different Types

 Product Version(s): 1.x 2.x 3.x 4.x 5.01 5.02 5.03 | 5.01
 Operating System:   MS-DOS                         | OS/2
 Flags: ENDUSER | S_C S_QuickC S_QuickASM S_Pascal S_QuickPas
 Last Modified:  2-AUG-1990    ArticleIdent: Q48204

 The object module format used by the Microsoft languages contains a
 record type that is used to bind symbol definitions to symbol
 references in other modules. This record is known as a "fixup." As
 defined by Intel, the fixup record type contains no information as to
 the type of data that is to be fixed up. Under certain circumstances,
 this can cause unexpected and undesired binding at link time. The code
 below demonstrates such an instance:

     /*----- FILE1.C -----*/

     void bar( void );

     void main( void )
     {
         bar();
     }

     /*----- FILE2.C -----*/

     int bar;

 These files both compile without error. When compiled for a model with
 a single code segment, linker error L2003 is produced saying that an
 intersegment self-relative fixup was attempted. If a multiple code
 segment model is used, no link errors are produced. Although a clean
 link can be obtained, the resultant EXE does not perform as expected
 due to the fact that the function reference of bar in FILE1.C has been
 bound to the integer definition of bar in FILE2.C.

 The linker has no way of determining the types of the reference to,
 and definition of, bar. This is a limitation of the object file
 format. If an include file was used to prototype bar and was then
 included in both files, the compiler could have detected the
 redefinition of bar.

 This information applies to all 1.x, 2.x, and 3.x versions of LINK
 including 3.60, 3.61, 3.64, and 3.65, as well as LINK Versions 4.06,
 4.07, 5.01, 5.02, and 5.03.


 50. Novell Network Software May Cause L1084 Error

 Product Version(s): 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER | h_fortran h_masm s_c s_pascal
 Last Modified: 23-JAN-1990    ArticleIdent: Q57304

 The resident software used to access a Novell network may cause the
 following error when linking large programs:

    L1084:  Cannot create temporary file

 This problem was observed with Netware versions 2.10 SFT and 2.15 of
 the Novell network software.


 51. Relationship between Map File Addresses and Location in Memory

 Product Version(s): 3.61 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 19-SEP-1989    ArticleIdent: Q48241

 In situations where memory is very short or where CodeView interacts
 with your program, it is sometimes necessary to use the DEBUG.COM
 program supplied with DOS.

 Using DEBUG is more difficult than using SYMDEB or CodeView because
 DEBUG has no symbolic features. You must use the map produced by the
 /M option when you link with a standard DOS overlay linker (i.e., not
 a segmented executable linker) to locate specific parts of your
 program.

 However, since DOS relocates programs when it loads them, the
 addresses given in the map need conversion before you can use them.

 This conversion is simple: DOS adds the address of the start segment
 (defined below) to each segment address in the load map. The offsets
 never change from the values shown in the link map -- only the
 segments change.

 The start segment is the base address of the Program Segment Prefix
 (PSP) plus the size of the PSP in paragraphs. Since the PSP is always
 100h (256) bytes long, the size of the PSP is 10h paragraphs.

 Note: DOS puts the base segment address of the PSP in DS and in ES
 when a program begins execution.

 For example, assume that the link map says that the function _funct is
 at 0004:05A0 (all values in hex) and that the global variable _errno
 is at 0192:00E3. Suppose further that when the program is loaded into
 DEBUG, the DS and ES registers contain 2BA5 -- the segment address of
 the PSP. (Use the R command to display the values of the registers.)

 The start segment for loading the program will be 2BB5 -- the value of
 the PSP base address (2BA5) + 10h to allow for the 10h paragraph
 length of the PSP (100h bytes).

 Thus, the function _funct will be located as follows:

    0004:05A0   -- address of _funct in the link map
    2BB5        -- start segment address (PSP + 10h)
    ---------
    2BB9:05A0

 And _errno will be located as follows:

    0192:00E3   -- address of _funct in the link map
    2BB5        -- start segment address (PSP + 10h)
    ---------
    2D47:00E3

 Use this calculation on any address in the link map to find where the
 symbol is located in memory when actually loaded.

 The H (Hex Arithmetic) command in DEBUG can be helpful when performing
 these calculations, as can a hex calculator with constant feature.


 52. Warning L4014: /PACKDATA: Option Ignored for Real Mode

 Product Version(s): 4.06 4.07 5.02 5.03 | 5.02 5.03
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER |
 Last Modified: 21-SEP-1989    ArticleIdent: Q48839

 /PACKDATA is incorrectly listed as an available switch for LINK
 Versions 4.06 and 4.07. LINK Version 4.06 comes with the QuickC
 compiler, and LINK Version 4.07 comes with the QuickAssembler.

 The /PACKDATA option is valid ONLY for segmented-executable files --
 OS/2 or Windows; it has no meaning for DOS. Real mode executable means
 a DOS-only program. To use the /PACKDATA switch, create a .DEF file
 with at least the following statement:

    NAME    MyProtectModeProgram

 This switch is implemented in segmented-executable LINK Versions 5.02
 and later.


 53. /NOI Switch May Cause L2022 and L2029 in PM Programs

 Product Version(s): 5.10   | 5.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 27-OCT-1989    ArticleIdent: Q49008

 I am compiling and linking a Presentation Manager (PM) program from
 Charles Petzold's "Programming the OS/2 Presentation Manager" and I
 get the following link errors:

    LINK : error L2022: ClientWndProc (alias ClientWndProc) : export
           undefined

         : error L2029 : 'ClientWndProc' : unresolved external

 I get the same errors when compiling WELCOME1.C from the companion
 disk to "Programming the OS/2 Presentation Manager."

 The /NOI switch instructs the linker to preserve case. If you are
 using the /NOI switch, the linker will generate these errors because
 EXPENTRY (the export entry point) is defined in OS2DEF.H as follows:

    #define EXPENTRY far pascal

 The "pascal" keyword instructs the compiler to use the left-to-right
 calling sequence for the functions that it modifies. The keyword also
 causes the conversion of the function's name to uppercase letters.

 All window procedures are defined as EXPENTRY. Thus, the name of your
 window procedure is converted to uppercase letters. In your .DEF, you
 export your window procedures as follows:

    EXPORTS         ClientWndProc

 Because of the /NOI switch, the linker does not view ClientWndProc and
 CLIENTWNDPROC as being equal. Consequently, you get the first error
 message "export undefined."

 The second error message is generated because ClientWndProc (mixed
 uppercase and lowercase letters) is not recognized as being defined,
 so the linker considers it an "unresolved external."

 Removing the /NOI switch from your link line corrects both errors.


 54. LINK 5.03 and Later Require EXETYPE WINDOWS in .DEF File

 Product Version(s): 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 17-JUL-1990    ArticleIdent: Q49445

 Microsoft LINK (LINK.EXE) versions 5.03 and later require that the
 WINDOWS descriptor be placed in the EXETYPE section of your project's
 .DEF (definitions) file if you are developing a Windows' application.

 This marks a change from previous linkers' behavior, which would allow
 the programmer to fail in specifying the type of executable to be
 created, but still produce a Windows-compatible .EXE file. This
 failure is no longer acceptable to LINK Versions 5.03 and later.

 If you fail to inform the linker (via the .DEF file) that you are
 creating a Windows executable, the linker reaches completion but the
 resulting .EXE does not execute.

 To specify the executable type, you must create a .DEF file and submit
 this to the linker at link time. For example, if you had a project
 called WINTEST.C, you must modify WINTEST.DEF so that it contains the
 following line:

    EXETYPE   WINDOWS

 The default EXETYPE is OS/2, as stated in the "Microsoft FORTRAN,
 CodeView and Utilities User's Guide" packaged with FORTRAN Version
 5.00.

 For further information regarding the definitions file and other
 descriptors, consult Section 7, "Using Module-Definition Files," in
 the "CodeView and Utilities, Microsoft Editor, Mixed Language
 Programming Guide" (Update Section) for C 5.10.

 LINK Version 5.03 is shipped with the FORTRAN version 5.00 package.


 55. Long TMP Environment Variable Causes L1089

 Product Version(s): 5.03   | 5.03
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | h_fortran
 Last Modified:  6-DEC-1989    ArticleIdent: Q48869

 L1089 occurs when the LINK Utility Version 5.03 is called from FORTRAN
 Version 5.00 and the TMP environment variable is set to a long
 pathname.

 Normal troubleshooting indicates that the TMP variable is corrupt, but
 this is not the case. It seems that the temporary filename is being
 truncated.

 The following sequence produces the error if the subdirectory
 D:\COMPILER\FORTRAN5\TMP\ already exists:

 SET TMP=d:\compiler\fortran5\tmp
 fl sieve.for

 LINK : fatal error L1089: D:\COMPILER\FORTRAN5\TMP\000054l
 : cannot open response file

 This problem occurs in FORTRAN 5.00 and Link 5.03.


 56. L2041: Stack Plus Data Exceeds 64K -- Documentation Supplement

 Product Version(s): 3.65 4.06 | 5.01.21
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER  | s_pascal h_fortran h_masm s_c s_quickc s_quickasm s_error d
 Last Modified: 30-NOV-1989    ArticleIdent: Q50130

 The following indicates that there is more than 64K of stack and data
 to be put into the 64K DGROUP (default data segment):

    L2041    stack plus data exceeds 64K

             The combined size of the program stack segment plus DGROUP
             was greater than 64K; as a result, the program will not
             load up correctly.

 To correct this problem, do the following:

 1. If the file(s) was compiled with C 5.00, a large amount of string
    literal data in the program may cause this error. Unlike C 5.10,
    5.00 cannot move string literals out of DGROUP with the /Gt option.
    This problem can be corrected with the "C 5.00 /Gt Fix" application
    note, which is available from Microsoft Product Support Services by
    calling (206) 454-2030.

 2. Reduce the stack size.

 3. Use a large data model (compact, large, or huge). Try applying the
    /Gt compilation option to lower the threshold.

 4. Use the FAR keyword to move data out of DGROUP.

 This error is documented in "Linker Error Messages" in the "Microsoft
 QuickC Compiler for IBM Personal Computers and Compatibles
 Programmer's Guide," Section D.4, Page 374. It is also in the file
 ERRMSG.DOC on Compiler Disk 1 for Microsoft C Version 5.10, on the
 Setup disk for Microsoft C Version 5.00, in the file README.DOC on
 Disk 1 for Microsoft Macro Assembler Version 5.10, and in the file
 CVREADME.DOC on the CodeView for MS-DOS disk for Microsoft FORTRAN
 Version 4.10. It is not found in the "CodeView and Utilities,
 Microsoft Editor, Mixed-Language Programming Guide" manual.

 Nonfatal errors indicate problems in the executable file. LINK
 produces the executable file. Nonfatal error messages have the
 following format:

    location : error L2xxx: messagetext

 In these messages, location is the input file associated with the
 error, or LINK if there is no input file. If the input file is an .OBJ
 or .LIB file and has a module name, the module name is enclosed in
 parentheses.

 Additional reference words: appnote


 57. Link Error L2028 Caused by HEAPSIZE, STACKSIZE and DGROUP Size

 Product Version(s): 5.01.21 | 5.01.21
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 17-JUL-1990    ArticleIdent: Q49935

 The error L2028 "Automatic data segment plus heap exceeds 64K" was
 omitted from the linker error messages in the "CodeView and Utilities,
 Microsoft Editor, Mixed-Language Programming Guide" manual that
 accompanies Microsoft C 5.10. This error occurs when the stack and
 data plus the near heap exceeds 64K. The near heap size is set with
 the HEAPSIZE option in the .DEF file.

 The error can be corrected by using one of the following methods:

 1. Reducing the amount of data in the default data segment.

 2. Decreasing the stack size that was set by /ST:xxxx at the link line
    or by the STACKSIZE option in the .DEF file.

 3. Decreasing the amount of near heap that is being requested with the
    HEAPSIZE option in .DEF file.


 58. Specifying Link Options with "-" Causes L4046, L1083, or U1013

 Product Version(s): 5.01.21
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 10-NOV-1989    ArticleIdent: Q50333

 LINK command line switches must begin with the linker's option
 character, the forward slash (/). While it is valid to begin
 compilation switches with a dash (-), the same is not true for the
 linker.

 Code Example
 ------------

 #--------------------
 # test make file
 #--------------------

 test.obj : test.c test.h
      cl -c -Zi -G2sw -W3 test.c

 test.exe : test.obj test.def
      link test, -CO -align:16, NUL, os2, test

 You type:
         make test

 Microsoft (R) Program Maintenance Utility  Version 4.07
 Copyright (C) Microsoft Corp 1984-1988. All rights reserved.

   link test, -CO -align:16, NUL, os2, test

 Microsoft (R) Segmented-Executable Linker  Version 5.01.21
 Copyright (C) Microsoft Corp 1984-1988.  All rights reserved.

 TEST.DEF(12) : warning L4046: module name different from output file name
 LINK : fatal error L1083: cannot open run file
 test(16) : fatal error U1013: 'link test, -CO -align:16, NUL, os2, test'
          : error 2


 59. /PACKCODE Incompatible with IOPL Segments with LINK 5.01.21

 Product Version(s): 5.01.21
 Operating System:   OS/2
 Flags: ENDUSER | S_C
 Last Modified: 10-NOV-1989    ArticleIdent: Q50702

 LINK Version 5.01.21 does not support the combination of using the
 /PACKCODE switch and having code segments declared as IOPL (i.e., as
 having I/O privilege).

 When combining segments as directed by the /PACKCODE option, LINK
 5.01.21 will combine the IOPL segment(s) with other segments that do
 not have I/O privilege. The result is an invalid executable that
 returns the system error SYS1059 when it is invoked.

 The lack of ability to combine these options is a limitation of this
 particular linker version. LINK Version 5.03 allows the combination of
 /PACKCODE and IOPL segments without a problem.


 60. LINK : Warning L4011 Caused By Invalid /PACKCODE Group Size

 Product Version(s): 3.65 4.06 4.07 5.01.21 5.03 | 5.01.21 5.03
 Operating System:   MS-DOS                      | OS/2
 Flags: ENDUSER | S_C S_QUICKC S_QUICKASM S_PASCAL DOCERR
 Last Modified: 10-NOV-1989    ArticleIdent: Q50705

 The LINK code packing option, /PAC[:n], groups together neighboring
 code segments into the same segment of maximum size "n" bytes. The
 results of using /PAC will only be reliable when "n" is in the range
 of 0 to 65500. Page 278 of the "Microsoft C 5.1 CodeView and
 Utilities" reference manual states the default value for "n" is 65530.
 This is incorrect.

 The linkers from the following products were tested with the /PAC
 option to determine their behavior with various values of "n":

    C 5.10
    Pascal 4.00
    FORTRAN 5.00
    QuickC 1.01
    QuickC 2.00
    QuickASM 2.01

 Note: Linkers were checked in both real and protected mode where
 appropriate.

 The following table shows the acceptable values that can be used with
 the /PAC[:n] option and what error message will occur when the value
 of "n" is out of range:

 ----------------------------------------------------------------------
 Value of "n"      LINK Vers.   Error Message
 ----------------------------------------------------------------------
 0 to 65500        3.65         No Errors/Warnings
                   4.06         No Errors/Warnings
                   4.07         No Errors/Warnings
                   5.01.21      No Errors/Warnings
                   5.03         No Errors/Warnings

 65501 to 65536    3.65         LINK : warning L4011:
                   4.06         LINK : warning L4011: PACKCODE value
                                exceeding 65500 unreliable
                   4.07         (same as above)
                   5.01.21      (same as above)
                   5.03         (same as above)

 65537 and over    3.65         LINK : fatal error L1005:
                   4.06         LINK : fatal error L1005: packing limit
                                exceeds 65536 bytes
                   4.07         (same as above)
                   5.01.21      (same as above)
                   5.03         (same as above)
 ----------------------------------------------------------------------

 Note : With LINK Version 5.03 and later, the /PAC option has been
 changed to /PACKC to differentiate /PACKC[ODE] from the new
 /PACKD[ATA] option.


 61. How and When to Specify Stack Size (Clarification)

 Product Version(s): 3.65 4.06 4.07 | 5.01.21
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q50950

 Question:

 When I want to specify a certain stack size for a program, should I
 use the /F compiler option, the /ST linker option, or both?

 Response:

 This depends on how you are compiling and linking. If you using the CL
 command to compile and link, the /F compiler option is all that is
 necessary. This option will pass the correct size of the stack to the
 linker.

 On the other hand, if you are invoking the compiler and the linker
 separately (as in a make file), the /ST link option can be used to get
 the desired stack size. The /ST link option is documented on Page 123
 of the "Microsoft C Optimizing Compiler User's Guide."

 No stack information is stored in the object module. Therefore, using
 the /F and /c (compile only) options together and then invoking link
 separately will not generate the desired stack size. The /F compile
 option is documented on Page 102 of the "Microsoft C Optimizing
 Compiler User's Guide."


 62. Linking Method May Result in Unexpected Increase in .EXE Size

 Product Version(s): 3.x 4.06 4.07 5.01.21 5.03 | 5.01.21 5.03
 Operating System:   MS-DOS                     | OS/2
 Flags: ENDUSER |
 Last Modified: 21-FEB-1990    ArticleIdent: Q58689

 Question:

 When my program is linked in the following manner

    link  file1.obj file2.obj library.lib;

 the resulting executable file is much larger than if the program is
 linked this way:

    link  file1.obj file2.obj,,,library.lib;

 What causes the difference in size?

 Response:

 This is expected behavior, the difference in size is due to the
 difference in linking method.

 The first method has the library name in the same field as the object
 files. Libraries entered in this field are called "load libraries" as
 opposed to "regular libraries." Link automatically links in every
 object module in a load library; it does not search for unresolved
 external references first.

 The effect of using a load library is exactly the same as if you had
 entered all the names of the library's object modules as separate
 object files on the link command line. This feature is useful if you
 are developing software using many modules and want to avoid having to
 retype each module on the LINK command line.

 With the second method, LINK links in only the objects from the
 library that are required for program execution.

 Please see documentation on LINK, such as Section 12.1.2 of the
 Microsoft C 5.1 "CodeView and Utilities Software Development Tools for
 the MS-DOS Operating System" manual (Page 257) for more information.


 63. Linker Uses Library Sequence to Resolve External References

 Product Version(s):
 Operating System:   1.x 2.x 3.x 4.06 4.07 5.01.21 5.02 5.03 | 5.01.21 5.02 5.
 Flags: MS-DOS                                  | OS/2
 Last Modified: 26-FEB-1990    ArticleIdent: Q57706
 ENDUSER |

 "The MS-DOS Encyclopedia," Pages 407 and 408, states the following:

    When a public symbol required to resolve an external reference is
    declared more than once among the object modules in the input
    libraries, LINK uses the first object module that contains the
    public symbol. This means that the actual executable code or data
    associated with a particular external reference can be varied by
    changing the order in which LINK processes its input libraries...

    Each individual library is searched repeatedly (from first library
    to last, in the sequence in which they are input to LINK) until no
    further external references can be resolved.

 The following simple case demonstrates the concept:

    Module MAIN   Library A     Library B1    Library C     Library B2
    +---------+   +----------+  +----------+  +----------+  +----------+
    | calls A |   | contains |  | contains |  | contains |  | contains |
    +---------+   |    A,    |  |    B     |  |    C,    |  |    B     |
                  | calls  C |  +----------+  | calls  B |  +----------+
                  +----------+                +----------+

 The linker determines which copy of Module B to use depending on the
 library sequence. For example, when you link with the following, the
 Module B from Library B2 is selected:

    LINK MAIN,,,A B1 C B2;

 The linker looks first in Library C and, unable to resolve the
 reference, proceeds to the next library, B2. If the linker is still
 unable to resolve the reference, it continues searching at Library A.

 A slightly more complex case, when Library A contains both Module A
 and Module B, produces different results, as shown below:

    Module MAIN   Library A     (remove B1)   Library C     Library B2
    +---------+   +----------+                +----------+  +----------+
    | calls A |   | contains |                | contains |  | contains |
    +---------+   |    A,    |                |    C,    |  |    B     |
                  | calls  C |                | calls  B |  +----------+
                  +----------+                +----------+
                  | contains |
                  |    B     |
                  +----------+

 Link with "LINK MAIN,,,A C B2;". In this case, Module B from Library A
 is selected.

 Although the linker always follows the same rules for resolution, it
 gets more difficult to determine which version of a module will be
 selected in more complex cases. When feasible, you can avoid this
 problem by putting your selected versions in an .OBJ instead of an
 .LIB. The linker uses any .OBJs to resolve references before it
 uses libraries.

 For more information, refer to "The MS-DOS Encyclopedia," Article 20:
 "The Microsoft Object Linker," in the "Object Module Order" section,
 Pages 703-706.


 64. Calling Overlaid Functions Through Pointers Not Supported

 Product Version(s): 1.x 2.x 3.x 4.06 4.07 5.01.21 5.02 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER | S_C S_QuickC
 Last Modified: 30-JAN-1990    ArticleIdent: Q58098

 LINK does not support using function pointers for calling functions in
 overlays unless the function is being called from within the same
 overlay. If an overlaid function is being called from the root or from
 a different overlay, then the call must not be made through a pointer.

 LINK cannot support calling overlaid functions indirectly through
 pointers because the address of the indirect function is determined at
 load time.

 In a program with overlays, a normal function call (that is, not a
 call through a pointer) is recognized by the linker and an interrupt
 call is placed into the .EXE in place of the function call. When the
 function is called at run time, the interrupt directs control to the
 overlay manager. The overlay manager checks whether the right overlay
 is loaded into memory, loads it if necessary, and calls the function.
 Because there is a fixup record in the .OBJ for the function call, the
 linker can set everything up correctly.

 On the other hand, with a function pointer, the compiler creates a
 fixup record for the address that the pointer references. However,
 there is no indication in the fixup record that this address is for a
 function. Therefore, if you link the function in as an overlay, the
 linker does not insert a call to the overlay manager and instead does
 a standard fixup.

 As a result, if you indirectly call a function located in a not-as-yet
 loaded overlay, the overlay does not get loaded. Nevertheless, control
 is still transferred to the address at which the function is thought
 to reside, which can only mean disaster for the executing program.


 65. /PAU Linker Option Doesn't Function in Some Versions of LINK

 Product Version(s): 3.61 3.65 3.69 5.01.20 5.05 | 5.01.20 5.05
 Operating System:   MS-DOS                      | OS/2
 Flags: ENDUSER |
 Last Modified: 21-FEB-1990    ArticleIdent: Q58781

 The /PAU (PAUSE) linker option tells LINK to pause in the link session
 and display a message before it writes the executable file to disk,
 allowing you to insert a new disk on which to store the executable
 file.

 In Microsoft LINK.EXE Versions 3.61, 3.65, 3.69, 5.01.20, and 5.05,
 the /PAU linker option does not pause the link session.

 Microsoft is researching this problem and will post new information
 here as it becomes available.

 In versions where the /PAU linker option functions correctly, LINK
 displays the following message before it creates the executable file:

    About to generate .EXE file
    Change diskette in drive ___ and press <ENTER>

 LINK resumes processing after the ENTER key is pressed.


 66. /INC and Overlays Are Not Supported at the Same Time

 Product Version(s): 5.01.20 5.01.21 5.02 5.03
 Operating System:   MS-DOS
 Flags: ENDUSER | docsup
 Last Modified: 15-MAY-1990    ArticleIdent: Q59279

 LINK.EXE does not support the use of /INCREMENTAL (or /INC) switch and
 overlays at the same time. This is because ILINK.EXE, which is invoked
 by the /INC option, does not support overlays. One of the two
 operations is ignored.

 The linker produces a working executable file, but one of the
 following WARNING messages may be produced:

    L4013: Overlays: option ignored for segmented-executable file
    L4014: /INCREMENTAL : Option ignored for realmode executable file

 If no warning message is produced, the linker takes an unpredictable
 path. If this is the case, the executable file that is produced could
 be corrupted and should NOT be relied upon.


 67. Incomplete EXPORTS List May Cause L2022 and L2029

 Product Version(s): 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-MAR-1990    ArticleIdent: Q59385

 Compiling and linking a Windows program and receiving the following
 two link errors can be caused by an incomplete EXPORTS list:

    LINK : error L2022: ProcedureName : export undefined
    LINK : error L2029: 'ProcedureName' : unresolved external

 Windows programming involves the creation of a .DEF (definitions)
 file. All Windows procedures to be exported must be listed in this
 file. The following is an example:

    EXPORTS     ProcedureName

 When this list is incomplete, the L2022 error is generated. The L2029
 error can be generated if the case of the EXPORT line doesn't match
 the case of the actual function.

 Listing all procedures to be exported in the .DEF file prevents both
 of these errors.

 Note: These errors can also occur with Presentation Manager programs
 or programs that use DLLs under OS/2.


 68. Why the /HIGH Switch Is Not Used with High-Level Languages

 Product Version(s): 3.65
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 15-MAR-1990    ArticleIdent: Q59535

 The linker option /HIGH is used with assembly language programs to
 load an .EXE file as high as possible in memory. Without the /HIGH
 option, LINK places the .EXE file as low as possible.

 /HIGH is not used with high-level languages because it prohibits the
 use of dynamic memory allocation by the program. Furthermore, C
 run-time start-up code specifies /DOSSEG, which forces low load and
 Microsoft run-time segment layout.

 When a program is linked with /HIGH, MS-DOS loads the program at the
 highest possible memory location available, usually 0xFFF0. All memory
 between the program's segments (which are high) and the program's PSP
 (which is low) is now considered program RAM, owned by the program.
 You can no longer allocate or free that memory.

 Therefore, calls to routines such as malloc() and free() fail. This
 causes problems for the following reasons:

 1. Some memory is dynamically allocated during function calls from
    high-level languages.

 2. The memory structure required by Microsoft high-level languages for
    tracking used/freed memory is not available.

 You can use /HIGH if you write your own start-up code, but your
 programs cannot call most of the routines from the C run-time library.

 The only reason /HIGH is still available to the linker is that early
 versions of Microsoft FORTRAN and Microsoft Pascal generated code that
 had to be linked with /DSALLOCATE, which relocates all addresses
 within DGROUP in such a way that the last byte in the group has the
 offset 0xFFFF. The /HIGH switch is used in conjunction with the
 /DS(ALLOCATE) switch.

 For more information, search the knowledge base with the following
 query:

    S_LINK and /HIGH and /DS

 You can also read the section "Using the /HIGH and /DSALLOCATE
 Switches" on Page 719 ff in the "MS-DOS Encyclopedia."


 69. OS/2 Module Definition File Syntax

 Product Version(s): 5.01.21 5.02 5.03 5.05
 Operating System:   OS/2
 Flags: ENDUSER | S_C
 Last Modified: 16-MAR-1990    ArticleIdent: Q59536

 The following is extracted from Ray Duncan's "Advanced OS/2
 Programming," Page 737:

    Module definition (DEF) files are simple ASCII text files that are
    interpreted by the linker during the construction of an application
    program, dynlink library, or device driver. The directives in DEF
    files cause information to be built into the executable file's
    header, which is later interpreted by the system when the program,
    library, or driver is loaded.

    Enter all DEF file directives and keywords in uppercase letters.
    File, segment, group, and procedure names can be lowercase or
    uppercase. Lines beginning with a semicolon (;) are treated as
    comments.

    Figure E-1. DEF file directives documented in Appendix E
    --------------------------------------------------------

    CODE        Assigns characteristics to code segments
    DATA        Assigns characteristics to data segments
    DESCRIPTION Embeds text in executable file
    EXETYPE     Specifies host operating system
    EXPORTS     Names functions exported for dynamic linking by other
                programs
    HEAPSIZE    Specifies initial size of local heap (C programs only)
    IMPORTS     Names functions that will be dynamically linked at load
                time
    LIBRARY     Builds dynlink library or device driver
    NAME        Builds application program
    OLD         Specifies ordinal compatibility with previous version of
                dynlink library
    PROTMODE    Flags file as executable in protected mode only
    REALMODE    Allows file to be executed in real mode
    SEGMENTS    Assigns characteristics to selected segments
    STACKSIZE   Specifies size of stack used by primary thread
    STUB        Embeds MS-DOS-compatible program in new executable file

 For further information, refer to Appendix E, Module Definition File
 Syntax, in "Advanced OS/2 Programming" or Chapter 19, Using Module-
 Definition Files, in the "Microsoft FORTRAN CodeView and Utilities
 User's Guide," packaged with FORTRAN Version 5.00.


 70. Linker Error L4047 May Be Benign

 Product Version(s): 5.10    | 5.10
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 18-APR-1990    ArticleIdent: Q59936

 The following linker error may be a benign error if it occurs with an
 application that links with the C Version 6.00 start-up code:

    L4047 - Multiple code segments in module of overlayed program
            incompatible with /CO

 This is a new error for LINK Version 5.10 and is to be expected.

 If an application is built with the C Version 6.00 run-time library,
 there is a second segment to hold floating-point math routines. This
 segment (EMULATOR_TEXT) does not have any CodeView information in it.
 However, from the linker's perspective, the extra segment MAY be an
 error and it is warning the user of such. In this case, it is a benign
 warning message.


 71. NODATA and pwords Parameters Reversed in EXPORT Statement Docs

 Product Version(s): 5.01.21 5.02 5.03 5.05 5.10 | 5.01.21 5.02 5.03 5.05 5.10
 Operating System:   MS-DOS                      | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 25-MAY-1990    ArticleIdent: Q61605

 The EXPORT statement used in module definition (.DEF) files is
 incorrectly documented in several places with the last two parameters
 reversed. The "pwords" parameter should be the last parameter, but it
 is listed second from the end. The "NODATA" parameter is listed last,
 but should be second from the end. The correct EXPORT statement syntax
 is as follows:

    entryname [=internalname] [@ord[RESIDENTNAME]] [NODATA] [pwords]

 Note that the "pwords" parameter is listed as "iopl-parmwords" in some
 of the documentation.

 The documentation with the incorrect EXPORT statement syntax with
 reversed parameters is as follows:

 - The C version 6.00 online help for LINK under the EXPORT statement
   syntax

 - On Page 334 of "The Microsoft CodeView and Utilities User's
   Guide" for version 2.30 in Section 19.9, "The EXPORTS
   Statement" (shipped with FORTRAN 5.00 and BASIC PDS 7.00)

 - On Page Update-52 of "The Microsoft CodeView and Utilities
   Update" for version 2.20 in Section 7.8, "The EXPORTS
   Statement" (shipped with C 5.10, MASM 5.10, and Pascal 4.00)


 72. Fatal /nologo and /e Switch Interaction

 Product Version(s): 1.20   | 1.20
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.20
 Last Modified: 22-JUN-1990    ArticleIdent: Q62375

 Using the /nologo switch in conjunction with /e switch can cause ILINK
 version 1.20 to fail. The problem will occur when an incremental link
 cannot be performed and the command specified by the /e switch is
 performed instead. If the /e switch is preceded anywhere on the
 command line by /nologo, then the link will fail.

 For example, the following command line

     ILINK /nologo /e "link hello;" hello.exe

 where hello.obj exists but hello.exe doesn't, will produce the
 following messages:

    Microsoft (R) Segmented-Executable Linker  Version 5.10
    Copyright (C) Microsoft Corp 1984-1990.  All rights reserved.

    LINK : fatal error L1089:  : cannot open response file
    ILINK : warning L4252: file '/e.exe' does not exist
    ILINK : performing full link
    ILINK : fatal error L1233: 'link' returned 2

 Placing the /nologo switch after the /e switch on the command line
 will alleviate the problem.

 Microsoft has confirmed this to be a problem with LINK version 1.20.
 We are researching this problem and will post new information here as
 it becomes available.


 73. L4050 Incorrectly Documented in Online Help

 Product Version(s): 5.10   | 5.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr buglist5.10 S_PWB
 Last Modified: 24-JUL-1990    ArticleIdent: Q63235

 When linking a very small program with /EXEPACK, Microsoft LINKer
 version 5.10 sometimes gives the following error message:

    LINK: warning L4050: file not suitable for /EXEPACK; relink without

 The online Help documentation returns the following incorrect
 information:

    LINK warning L4050

    too many public symbols for sorting

    The linker uses the stack and all available memory in the near
    heap to sort public symbols for the /MAP option. If the number of
    public symbols exceeds the space available for them, this warning
    is issued and the symbols are not sorted in the map file but are
    listed in an arbitrary order.

    Reduce the number of symbols.

 The correct documentation for this error (except the number) is as
 follows and can be found in the online Help under L1114:

    Fatal LINK error L1114

    file not suitable for /EXEPACK; relink without

    For the linked program, the size of the packed load image plus
    packing overhead was larger than that of the unpacked load image.

    Relink without the /EXEPACK option.

 Because of its noncritical nature, this LINKer error was changed from
 its previous status of a fatal error to a simple warning in LINK
 version 5.10. The warning associated with L4050 in earlier versions of
 the LINKer will rarely appear in LINK 5.10, but if it does, it will
 have the number L4070.



 74. Parenthesis in Filename May Cause L1027: Unmatched Parenthesis

 Product Version(s): 3.x 4.06 4.07 5.01.21 5.03 5.05 5.10 | 5.01.21 5.03 5.05
 Operating System:   MS-DOS                               | OS/2
 Flags: ENDUSER |
 Last Modified: 10-JUL-1990    ArticleIdent: Q63624

 When linking object files into executable programs, the error L1027:
 "Unmatched left/right parenthesis" may be incorrectly generated for
 files that contain a parenthesis in the filename. This will only occur
 when the object module is in the current directory and either of the
 following conditions is true:

 1. If the object module being linked has a left parenthesis as the
    first character in its name, but NOT a right parenthesis as the last
    character.

 2. If an object filename has a right parenthesis as the last
    character in the name, but NOT a left parenthesis as the first.

 If the object module is NOT in the current directory, then the L1027
 error will occur only if the second condition above is true.

 This information applies to all versions of LINK.EXE that support
 overlays.

 Normally, parentheses are put around the names of one or more object
 modules when linking to inform LINK that the enclosed modules are to
 be in an overlay. Therefore, if a left (or right) parenthesis comes
 immediately before (or after) the name of an object module, LINK will
 expect a right (or left) parenthesis immediately after (or before) the
 name. If the parentheses do not match, a fatal L1027 error will be
 generated.

 For example, the following LINK command line causes an "Unmatched left
 parenthesis" error when the object module ABC.OBJ is in the current
 directory:

    link (abc;

 However, if ABC.OBJ is in a subdirectory, then the parenthesis is
 embedded in the middle of the path/filename string and no error is
 generated, as shown below:

    link temp\(abc;

 For the same reason, a file ABC).OBJ will NOT give an error if linked
 with the following line:

    link abc).obj;

 On the other hand, leaving off the .OBJ extension will result in the
 L1027 error:

    link abc);

 By the same reasoning, the placement of a left or right parenthesis in
 the middle of an object filename does not cause an error. The
 following three LINK lines all work correctly:

    link a(bc;
    link a()bc;
    link a)bc;


 75. ILINK 1.20 and 1.21 Are Not Backwards Compatible

 Product Version(s): 1.20 1.21 | 1.20 1.21
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 24-OCT-1990    ArticleIdent: Q65817

 Using ILINK version 1.20 or 1.21, after doing a full link using a
 bound linker earlier than version 5.10 or a DOS linker earlier than
 version 4.10, causes the following message:

    ILINK : warning L4267: invalid .ILK file
    ILINK : performing full link

 If you use the ILINK version that came with the linker you are using,
 the .ILK file will be recognized correctly. ILINK versions 1.20 and
 1.21 are not "backwards compatible" and will not work correctly with
 earlier .ILK files.


 76. Unexpected DOS Error: 14 Generated by Using /INC

 Product Version(s): 5.10
 Operating System:   MS-DOS
 Flags: ENDUSER | s_quickc s_c
 Last Modified: 24-OCT-1990    ArticleIdent: Q66055

 Programs linked with the /INC (Prepare for Incremental Link) switch
 cause the following error if the program is executed using the
 Microsoft Windows version 3.00 Run command:

    Unexpected DOS error: 14.

 The Run command is located on the File menu in both the Windows
 Program Manager and the File Manager. If the program is run from a
 prompt in real DOS or in a DOS session of Windows 3.00, it executes
 properly.

 While this seems like a problem with the Microsoft Linker, Windows 3.0
 is actually at fault here. The use of the /INC switch causes the
 linker to create a segmented executable. When Windows attempts to run
 this .exe, it fails to recognize that it is a full screen application
 (ie: not a windows app) and subsequently tries to execute it as a
 Windows application. This bug has been entered into the Windows bug
 database and should be fixed in a future release.

 Note: This may appear to be a problem with QuickC and/or C version
 6.00 if the incremental link option is turned on. In fact, it is a
 linking issue, not a compiler issue.

 To workaround this problem, turn off the /INC switch.


 77. Response Filename Cannot Exceed 32 Characters

 Product Version(s): 5.01.21 5.03 5.05 | 5.01.21 5.03 5.05
 Operating System:   MS-DOS            | OS/2
 Flags: ENDUSER | buglist5.01.21 buglist5.03 buglist5.05 fixlist5.10
 Last Modified: 12-NOV-1990    ArticleIdent: Q66698

 When using a complete path specification for a response file with
 LINK.EXE versions 5.01.21, 5.03, and 5.05, there is a limit of 32
 characters that cannot be exceeded. The following example illustrates
 this:

    LINK @d:\c600\files\project\test\myfile.lnk

 This will fail with the following error:

    LINK : Fatal error L1089 : D:\C600\FILES\PROJECT\TEST\MYFIL :
         cannot open response file

 In LINK version 5.10, this limit has been increased to 255 characters.


 78. Linker Does Not Search Specified Drive for Libraries

 Product Version(s): 5.01.21 5.03 5.05 5.10 5.11  | 5.01.21 5.03 5.05 5.10 5.1
 Operating System:   MS-DOS                       | OS/2
 Flags: ENDUSER | buglist5.01.21 buglist5.03 buglist5.05 buglist5.10 buglist5.
 Last Modified: 12-NOV-1990    ArticleIdent: Q66699

 A library name can be embedded into an .OBJ module for the linker to
 search to resolve external references. This library name can either be
 the library name itself or the full path to the library. In the case
 of the full path to the library, the linker cannot handle a drive
 specifier.

 For example, with Microsoft C, the #pragma comment command is used to
 specify the library. If the following line is used

    #pragma comment (lib, "c:\C600\LIB\graphics.lib")

 the compiler will add a COMENT record to the .OBJ instructing the
 linker to search the C600\LIB subdirectory on drive C for the
 GRAPHICS.LIB library.

 The problem is that the linker will not search drive C but will
 instead search the default drive. When the library and/or path is not
 found, it will prompt for the path to the library. This is an error.

 Microsoft has confirmed this to be a problem in the Segmented Linker
 versions 5.01.21, 5.03, 5.05, 5.10, and 5.11. We are researching this
 problem and will post new information here as it becomes available.


 79. L2002 When Creating a Dynamic Link Library

 Product Version(s): 5.10 5.11
 Operating System:   OS/2
 Flags: ENDUSER | buglist5.10 buglist5.11
 Last Modified:  4-DEC-1990    ArticleIdent: Q67004

 The code sample below produces the following error when compiled and
 linked with the following switches:

 cl /c /Gs /Alfu /ML foo.c

 link foo.obj, foo.dll,,, foo.def;

 Error
 -----

    L2002: fix-up overflow at 2 in segment FOO_TEXT
     frm seg _DATA, tgt seg _DATA, tgt offset 0

 This error is produced when creating a dynamic link library and
 specifying _loadds on function entry (either with the /Au switch or
 the _loadds keyword). If each segment that comprises the default data
 segment is of zero length, the linker will return this error. In
 earlier linkers, the error wasn't generated.

 The following are three possible workarounds:

 1. If the function does not contain any static data, compile with the
    option /Aw (DS not reloaded on function entry) and/or remove the
    _loadds keyword from the function declaration.

 2. Turn on stack checking (compile without /Gs option).

 3. Declare data so at least one of the segments in DGROUP is not zero
    length.

    a. For _DATA, declare initialized global or static data.

    b. For _CONST, declare a constant in the program.

    c. For _BSS, declare uninitialized static data.

 Microsoft has confirmed this to be a problem in versions 5.10 and
 5.11. We are researching this problem and will post new information
 here as it becomes available.

 Sample Code
 -----------

 void foo(int i)
 {
    char c;

    c=i;
 }


 80. NOF Is Default for LINK, Not /F as C "Reference" States

 Product Version(s): 5.10   | 5.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr S_C
 Last Modified:  4-JAN-1991    ArticleIdent: Q67085

 On pages 30 and 31 of the "Microsoft C Reference" manual shipped with
 C versions 6.00 and 6.00a, there are contradictory references to the
 far-call translation options available for LINK. On page 30 under the
 /F[ARCALLTRANSLATION] option, far-call translations are listed as
 being "turned on by default." On the other hand, on page 31 under the
 /NOF[ARCALLTRANSLATION] option, far-calls are listed as being "off by
 default."

 The statement on page 30 is the one that is incorrect because the
 correct default for far-call translations is "off." Far calls are done
 only when /F is explicitly specified to LINK.

 Note that when the CL command is used to invoke LINK, CL itself is
 responsible for passing the /F option to the linker.


 81. EXE Checksum Incorrect If linked with /CO or /E

 Product Version(s): 3.xx 4.0x 4.10 5.0x 5.10 5.13 | 5.0x 5.10 5.13
 Operating System:   MS-DOS                        | OS/2
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q67795

 According to "The MS-DOS Encyclopedia," a DOS .EXE file contains a
 checksum value in the .EXE file header. This checksum value should
 allow the summation of all words in the .EXE file to equal FFFFh.
 However, if you use the /Exepack or the /COdeview options when linking
 a program, the checksum value will not be calculated correctly.
 Current versions of MS-DOS ignore this checksum so this will not cause
 any noticeable problems.

 Sample Code:
 ------------

 #include <stdio.h>
 #include <stdlib.h>

 main (int argc, char * argv[])
 {
    FILE * fp;
    unsigned int nxt= 0, sum= 0;
    unsigned char bl, bh;

    if (argc != 2)
       exit (-1);
    if ((fp= fopen (argv[1], "rb"))== NULL)
       exit (-1);
    while (! feof(fp))
    {
       bl= fgetc (fp);
       if (! feof(fp))
          bh= fgetc (fp);
       else
          {
          bl= 0;
          bh= 0;
          }
       sum= sum+ nxt;
       nxt= (unsigned int) bh* 256U+ (unsigned int) bl;
    }
    nxt&= 0xFF;
    sum+= nxt;
    printf ("sum = %X\n", sum);
 }


 82. L1008: "Segment Limit Too High" May Be Caused by Missing Colon

 Product Version(s): 3.x 4.06 4.07 5.01.21 5.03 5.05 5.10 | 5.01.21 5.03 5.05
 Operating System:   MS-DOS                               | OS/2
 Flags: ENDUSER |
 Last Modified: 17-DEC-1990    ArticleIdent: Q46733

 When linking, the following error may be caused by incorrectly
 specifying the parameters for the /SE switch on the link command line
 with the colon:

    LINK : fatal error L1008: SE: segment limit set too high

 To generate the error, link using the /SE switch, then insert a space
 and the number of segments for the linker to use, such as the
 following:

    LINK /SE 1024

 The correct syntax for the /SE option is with a colon separating the
 switch from the numeric argument as follows:

    LINK /SE:1024


 83. The Purpose of Module Definition Files

 Product Version(s): 5.01.21 5.02 5.03 5.05 5.10 5.13 | 5.01.21 5.02 5.03 5.05
 Operating System:   MS-DOS                           | OS/2
 Flags: ENDUSER |
 Last Modified: 17-DEC-1990    ArticleIdent: Q27134

 Module-definition files (.DEF) are used by LINK when building Windows
 and OS/2 programs and dynamic-link libraries (DLLs). A .DEF file
 describes the name, size, format, functions, and segments of an
 application or DLL.

 A module-definition file contains one or more module statements. Each
 module statement defines an attribute of the executable file. The
 module statements and the attributes they define are listed below:

 Statement         Attribute
 ---------         ---------

 NAME              Name and type of application
 LIBRARY           Name of dynamic-link library
 DESCRIPTION       One-line description of the module
 CODE              Default attributes for code segments
 DATA              Default attributes for data segments
 SEGMENTS          Attributes for specific segments
 STACKSIZE         Local-stack size, in bytes
 EXPORTS           Exported functions
 IMPORTS           Imported functions
 STUB              Adds a DOS Version 3.x executable file to the beginning
                   of the module, usually to terminate the program when
                   run in real mode
 HEAPSIZE          Local-heap size, in bytes
 PROTMODE          Specifies that the module runs only in OS/2 protected
                   mode
 REALMODE          Specifies that the module is for real-mode Windows.
 OLD               Preserves export ordinal information from a previous
                   version of the library

 The following rules govern the use of these statements in a module-
 definitions file:

 1. If you use either a NAME or a LIBRARY statement, it must precede
    all other statements in the module-definition file.

 2. You can include source-level comments in the module-definition
    file, by beginning a line with a semicolon (;). The OS/2 utilities
    ignore each such comment line.

 3. Module-definition keywords (such as NAME, LIBRARY, and SEGMENTS)
    must be entered in uppercase letters.

 For more information, refer to the utility reference or online help
 that accompanied your particular compiler or assembler.


 84. Working Around Link Error "L1064: Out of Memory"

 Product Version(s): 5.03 5.05 5.10 5.13 | 5.03 5.05 5.10 5.13
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER |
 Last Modified: 17-DEC-1990    ArticleIdent: Q45718

 The linker error "L1064: Out Of Memory" is new with LINK version 5.03,
 which was first shipped to individuals using IMSL libraries with
 FORTRAN 4.10, and was then shipped with FORTRAN 5.00. The description
 of the error is as follows (from the "Microsoft FORTRAN, Microsoft
 CodeView and Utilities User's Guide"):

    The linker was not able to allocate enough memory from the
    operating system to link the program. On OS/2 try increasing the
    swap space. Otherwise, reduce the size of the program in terms of
    code, data, and symbols. On OS/2, consider splitting the program
    into dynalink libraries.

 In DOS, the only ways to work around the error are the following:

 1. Remove any memory-resident software or device drivers that may be
    limiting the available memory of the machine.

 2. Reduce the program size, as described above.

 In OS/2, the easiest way to work around the error is to increase the
 swap space, as follows:

 1. Close other screen groups and remove other processes from
    memory to free up both RAM and swap space on the swap drive.

 2. Create more free disk space on the drive that is pointed to by
    the SWAPPATH setting in the CONFIG.SYS file. (Delete or move files,
    or change the setting to a drive with more free space.)

 3. Possibly DECREASE the swap value set by the SWAPPATH variable (do
    this with caution -- read below).

 Explanation of the SWAPPATH Setting in CONFIG.SYS
 -------------------------------------------------

 Swapping must be enabled via the MEMMAN setting in CONFIG.SYS for the
 SWAPPATH setting to be acknowledged at all (usually "MEMMAN=SWAP" or
 "MEMMAN=SWAP,MOVE").

 The default setting for SWAPPATH after setting up OS/2 is usually as
 follows:

    SWAPPATH=C:\OS2\SYSTEM 512

 The drive setting indicates the drive and directory where the space
 for the swapper file will be allocated. If no SWAPPATH variable is
 set, the swapper file is allocated in the root directory on the boot
 drive. The number that follows indicates the amount of free space
 which must be left on this drive when the swapper file has grown to
 its maximum size. (This number, by itself, says nothing about the
 maximum size of the swapper file.) Given the settings above, the
 maximum size of the swapper file can be easily calculated by the
 following:

    (free space on Drive C) - (SWAPPATH value) = max. swap file size

 Therefore, increasing the SWAPPATH value DECREASES the amount of space
 available for the swapper file.

 The swapper value can be decreased, and the system will allow values
 down to 0 (zero). However, because OS/2 does time-slicing between
 processes and may need to write to the disk in question, decreasing
 the swapper value below 512K (the system default) is not recommended.
 This workaround should be used only if you have the value set to
 greater than 512K (the range of valid values is from 0 to 32,767). If
 this is the case, set the SWAPPATH value to 512 and reboot the
 machine. If this method does not solve the problem, you must clear
 space on the hard disk by deleting or moving files.


 85. Patches Available for Running Utilities Under Novell NetWare

 Product Version(s): 5.10
 Operating System:   MS-DOS
 Flags: ENDUSER | appnote SC0381.ARC s_codeview s_pwb s_c
 Last Modified:  6-FEB-1991    ArticleIdent: Q68659

 When LINK version 5.10 is run under a Novell network, LINK may fail
 with the following error:

    L1085: cannot open temporary file

 In addition, the C version 6.00 Setup program (SETUP.EXE), the
 Programmer's WorkBench (PWB) for DOS versions 1.00 and 1.10, and
 real-mode CodeView (CV.EXE) versions 3.00, 3.10, and 3.11 may all hang
 when run under some Novell NetWare software.

 These problems are directly related to the network software, but may
 be corrected with a set of patch files available from Microsoft as an
 application note titled "Network Patches for Utilities" (SC0381).
 Application notes can be obtained by calling Microsoft Product Support
 Services at (206) 637-7096.

 The "Network Patches for Utilities" application note can also be found
 in the Software/Data Library by searching on the keyword SC0381, the Q
 number of this article, or S12898. SC0381 was archived using the
 PKware file-compression utility.

 The following is the complete text of the application note, which
 includes the details of the problems mentioned above:

 ======================================================================
                     Network Patches for Utilities
 ======================================================================

 The enclosed Network Patches for Microsoft Utilities disk contains the
 following five files:

    README.DOC
    CVPATCH.EXE
    PWBPATCH.EXE
    SETUPFIX.EXE
    LINK.EXE

 These files solve conflicts with certain network setups. Please be
 sure to make backup copies of the original files.

 Network Patch Files
 -------------------

 When run under certain network software, some Microsoft utilities may
 hang. The enclosed patch files are designed to correct these problems
 for CodeView versions 3.00, 3.10, and 3.11; the Programmer's WorkBench
 (PWB) versions 1.00 and 1.10; and the C 6.00 Setup program.

 To install the patches, first copy the patch files (PWBPATCH.EXE,
 CVPATCH.EXE, and SETUPFIX.EXE) to the directories where you have
 installed PWB, CodeView, and Setup, respectively. Each patch assumes
 that the utility file it is to patch is in the same directory.

 Run SETUPFIX.EXE to patch SETUP.EXE. The original file will be saved
 as SETUP.BAK. Run CVPATCH.EXE to patch CV.EXE. The original file will
 be saved as CV.BAK. Run PWBPATCH.EXE to patch PWBED.EXE. The original
 file will be saved as PWBED.BAK. The patched utilities should run free
 of network interference.

 Microsoft LINK Version 5.13
 ---------------------------

 LINK version 5.13 includes code to work around another problem that
 sometimes occurs when running on a network. On large projects, the
 linker needs to open some temporary files to work around DOS memory
 limitations. LINK version 5.10 (supplied with C 6.00) will sometimes
 fail in its attempts to open a temporary file when run under certain
 network software.

 The problem actually lies in the network software, not the linker.
 When the network is loaded, the return value from an open call
 sometimes gets corrupted. When the call fails, it is because an "Out
 of handles" error (EMFILE) is returned as a "No such file or
 directory" error (ENOENT). If this occurs, LINK 5.10 halts with an
 "L1085: cannot open temporary file" error.

 LINK 5.13 includes a change to correct for the above situation (even
 though the problem is in the network software). When LINK version 5.13
 receives an ENOENT error on a failed open call, it will still try to
 free some file handles and reopen the temporary file, regardless of
 the error returned.

 To make the correction, locate LINK version 5.10 and replace it with
 LINK version 5.13 from the enclosed disk. Again, be sure to save a
 backup copy of the original file (LINK 5.10).


 86. L2025 LINK Error May Be Caused by Conflicting Library Routines

 Product Version(s): 3.x 4.06 4.07 5.0x 5.10 5.13 | 5.01.21 5.02 5.03 5.10 5.1
 Operating System:   MS-DOS                       | OS/2
 Flags: ENDUSER | s_lib
 Last Modified: 24-JAN-1991    ArticleIdent: Q44465

 All variables and routines in a module within a library will be linked
 into a program when any single variable or routine residing in that
 module is referenced. This can cause the following linker error if two
 or more modules contain definitions for the same symbol:

    L2025  symbol defined more than once

 For example, in the diagram below, module1 contains routines "a", "b",
 and "c". The module2 contains routines "c", "d", and "e". When main()
 references "a" and "e", the linker links module1 and module2 from the
 library. This results in "c" being defined twice. Removing "c" from
 one of the modules, recompiling the module, and replacing the module
 in the library with the LIB utility operator "-+" will prevent "c"
 from being multiply defined.

                         +-----------+
                         |           |
                         | calls "a" |
                         | calls "e" |
                       / |           | \
                      /  +-----------+  \
                     /       main()      \
                    v                     v
                +-------+             +-------+
                |   a   |             |   c   |
                |   b   |             |   d   |
                |   c   |             |   e   |
                |       |             |       |
                +-------+             +-------+
                 module1               module2

 For each routine you want to be linked separately, compile a separate
 object file and add it to the library.






 Microsoft `M' Editor
 =============================================================================


 1. How to Put Microsoft Editor (M or MEP) into 43-Line Mode

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-SEP-1988    ArticleIdent: Q28580

 To use the Microsoft Editor (M.EXE or MEP.EXE) in EGA 43-line mode,
 the TOOLS.INI file must be modified to include the following
 statement:

 HEIGHT:41

 (The number 41 is used because the last two lines are used by the
 editor as status/error lines. See Page 59 of the "Microsoft Editor for
 MS OS/2 and MS-DOS: User's Guide".)

 Once the TOOLS.INI is modified, the editor must be re-initialized.
 This process is done with the Initialize command. The default key
 stroke for this command is SHIFT+F8. Appendix A lists the values for
 the other .INI files provided with the editor. The following example
 demonstrates this process:

 1. Load TOOLS.INI.
 2. Modify TOOLS.INI.
 3. Save the file (ARG ARG SETFILE or leave and re-enter).
 4. Use the Initialize command (SHIFT+F8).

 After the initialization, the changes in the TOOLS.INI become active
 and the 43-line mode is in use.

 M.EXE runs in MS-DOS real mode, and MEP.EXE runs in OS/2 protected
 mode.


 2. Creating Macros for the Microsoft Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-SEP-1988    ArticleIdent: Q23051

 Macros for the Microsoft Editor are sequences of editor functions. For
 example, a macro to delete the word to the right of the cursor is
 defined as follows:

 worddelete:=arg meta pword sdelete

 The above macro is named "worddelete". To associate "worddelete" with
 a particular keystroke, the following command is needed:

 worddelete:ALT+W

 The macro "worddelete" is now bound to the keystroke "ALT+W". Note
 that the macro definition (i.e., ":=") resembles a Pascal assignment
 statement, but the keybinding uses a colon to delimit the macro name
 from the key to which it is assigned. The following is another
 example:

 filestamp:=curfilenam curfileext " - " curdate " " curtime
 filestamp:ALT+S

 This macro creates a file-time stamp that contains the filename, the
 current date, and the current time; it is assigned to the keystroke
 "ALT+S".


 3. File Size Limitations for the Microsoft Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | TAR62237
 Last Modified: 29-AUG-1988    ArticleIdent: Q23609

 Question:

 What is the largest file the Microsoft Editor can load?

 Response:

 The size of the file is controlled by the operating system, not by
 the editor. The editor will read in a file of any number of bytes;
 however, you are limited by the temporary file space.

 The size of the drive pointed to by the TMP variable is the limiting
 factor. Because TMP often points to a (relatively small) RAM drive,
 such as VDISK or MS-RAMDRIVE, this is the most common file size
 limitation.

 A safe rule-of-thumb is that your TMP drive may need to be up to
 two times the size of the file being edited.

 The maximum number of lines a file can contain is 0x7FFFFFFF, but you
 will run out of disk space before you have too many lines.

 Both MS-DOS and OS/2 currently limit disk size (hence, file size)
 to 64K sectors, which normally is 32 megabytes.


 4. Unassigning Predefined Keys

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | TAR62300
 Last Modified:  1-SEP-1988    ArticleIdent: Q23754

 The following are two ways to unassign a predefined key:

 1. Assign the key to a different function.
 2. Assign the key to the "unassigned" function.

 If ALT+A currently is assigned to the ARG function, you can assign
 it to another function by putting the following line in your
 TOOLS.INI file:

 NewFunct:ALT+A

 If you don't want ALT+A to be assigned to any function, place the following
 line in your TOOLS.INI file:

 Unassigned:ALT+A.


 5. Error C1015 "Can't Open Include File" with MEP

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | S_C buglist1.00
 Last Modified:  2-NOV-1988    ArticleIdent: Q35140

 The example program below generates the following error:

 Error C1015 "Can't open include file"

 The program must be compiled with one of the output-file switches
 (such as /Fc) or through a make file to generate this error.

 The include file os2.h opens two other include files: os2def.h and
 bse.h. The bse.h include file, in turn, opens three other include
 files: bsedos.h, bsesub.h, and bseerr.h.

 Microsoft has confirmed this to be a problem in Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.

 The compiler attempts to open the last include file and generates the
 C1015 error. The total file count at this point is 15, as follows:

  1. stdin
  2. stdout
  3. stdprn
  4. stderror
  5. stdaux
  6. MEP
  7. source
  8. listing file
  9. os2.h
 10. os2 def.h
 11. bse.h
 12. bsedos.h
 13. bsesub.h
 14. bseerr.h
 15. tmp file

 The following sample code demonstrates the problem:

 #define INCL_BASE
 #include <os2.h>

 void main (void)
 void main (void)
 {
 }



 6. Maximum Number of Defined Macros Allowed in TOOLS.INI File

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | TAR63148
 Last Modified: 17-MAY-1988    ArticleIdent: Q24696

 Question:
    Is there a maximum number of macros, predefined and user-defined,
 allowed in the TOOLS.INI file?

 Response:
    The maximum number of defined macros allowed is 1024.


 7. BRIEF TOOLS.INI File Assigns Two Commands to F5 in M.EXE

 Product Version(s): 1.00    | 1.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified:  1-SEP-1988    ArticleIdent: Q30474

 Problem:

 After I configure the Microsoft M.EXE Editor in the BRIEF mode and
 invoke Psearch (F5 key), I receive the following error message:

 "Invalid argument."

 However, Msearch (ALT+F5) functions correctly.

 Response:

 The BRIEF TOOLS.INI file assigns two commands to F5. The first
 occurrence in the file is for Psearch and the second is for
 DeleteWindow.

 To correct the problem, one of the commands should be mapped to a
 different key. Make sure the new key is not already in use.

 The following is an example of the incorrect portion of the
 BRIEF.INI file:

    ; TOOLS.INI file for BRIEF(tm) configuration
    [M]
           .
           .
           .
    Psearch:F5
           .
           .
           .
    ; WINDOWS
    ;
    ; Delete Current Window is F5
    DeleteWindow:=meta window
    DeleteWindow:F5
    ;
    ;
    ;
    ; BRIEF is a trademark of UnderWare, INC.


 8. Assigning Key Sequence to ENTER and BACKSPACE Keys

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 29-AUG-1988    ArticleIdent: Q25407

 Functions can be assigned to the ENTER and BKSP (BACKSPACE) keys in
 the TOOLS.INI file, as in the following example:

 emacsnewl:enter
 emacscdel:bksp

 Consult Chapter 6 of the "Microsoft Editor User's Guide," titled
 "Function Assignments and Macros."


 9. CALLTREE Ignores Conditional Compilation Statements in Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_C H_MASM
 Last Modified: 17-MAY-1989    ArticleIdent: Q44417

 The CALLTREE utility provided with the Microsoft Editor can be used to
 produce a graphical call-tree listing of a project. The following
 command line is an example of this utility. This command line creates
 a file called CALLS.TXT showing the relationship of the functions
 found in the four C source files shown below:

    calltree /c calls.txt main.c sub1.c sub2.c sub3.c

 If any of the files use conditional compilation directives, these are
 disregarded by CALLTREE and any functions that would not have been
 called appear in the call listing. An example of code that produces a
 misleading call listing is shown below. Although only one set of calls
 is compiled, both sets show up in the file produced by CALLTREE.

     void main( void )
     {
     #ifdef DEBUG
         dshow();
         ddone();
     #else
         fshow();
         fdone();
     #endif
     }

 To avoid this situation, a preprocessor listing should be produced
 using the /P switch with CL, and CALLTREE should then be run on the
 resultant file.

 This is a limitation of the utility. CALLTREE is meant to be a
 general-purpose tool for C and assembly programs, and is not designed
 to do any parsing or syntax checking.


 10. Microsoft Editor Fails to Find TOOLS.INI Using DOS Version 2.x

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q28590

 Problem:

 When running the M.EXE editor under DOS Versions 2.x, the editor does
 not find the TOOLS.INI file. The error reported is "Unable to Read
 TOOLS.INI[]".

 The following demonstrates the problem:

 1. Rename QUICK.INI to TOOLS.INI.
 2. Set the environment variable INIT to the directory c:\mytools
    as follows:

    SET INIT=c:\mytools

 3. Load the M.EXE editor. It will come up with default settings,
    instead of reading TOOLS.INI.

 When running DOS Version 3.20 on an IBM PC AT, M.EXE correctly finds
 the TOOLS.INI file.

 Response:

 M.EXE and MEP.EXE use their startup name to find the right section in
 TOOLS.INI. For example, if you rename the editor to Z, it will look
 for [z] instead of [m] in the editor's section in TOOLS.INI.

 This process occurs in all cases except under DOS Versions 2.x. Under
 any 2.x version of DOS, the name of your program is not available, and
 instead, the compiler provides the arbitrary name "C".

 To work around this limitation in DOS Versions 2.x, change the
 editor's tagged section in TOOLS.INI file to use the tag [c] instead
 of [m]. If it is necessary to share files with DOS Versions 3.x
 systems, the editor's section in TOOLS.INI can be tagged [m c].

 The editor uses the same method to name the following, where * is
 replaced by the editor name or by "C" under DOS Versions 2.x:

 1. The virtual memory file, *-XXXX.VM
 2. The history-and-state file, *.TMP
 3. The compiler message file, *.MSG


 11. Using Full Pathnames to Compile Programs with M or MEP

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | TAR75085
 Last Modified: 20-OCT-1988    ArticleIdent: Q29150

 The full pathname of a file is not transferred to the compiler when an
 ARG COMPILE is executed in the Microsoft Editor for MS-DOS and OS/2.
 The following is an example:

 1. Invoke M.EXE as follows:

 M \c5\source\test.c

 2. Compile the program with ARG COMPILE. (The default value is
    ALT+A SHIFT+F3). The following line is displayed:

    CL /c /Zep /D LINT_ARGS test.c

    The full pathname is not given.

 If you plan on compiling from other directories, you should define
 the compile command using the %|F option. The default option %s uses
 only the filename. For example, the TOOLS.INI file could be modified
 as follows to get the default compile with the full pathname:

 extmake:c cl /c /Zep /D LINT_ARGS %|F

 You also can select portions of the full pathname, and use the name
 more than once, as in the following example:

 %d|F - obtains the drive (and colon)
 %p|F - obtains the path
 %f|F - obtains the filename (no extension)
 %e|F - obtains the extension

 You can combine the "dpfe" any way you wish, as in the following:

 %dpf|F.xyz

 This combination produces the drive, path, and filename, with the
 extension .XYZ added to the filename.


 12. Editor "User's Guide" C-Extension Sample Generates Warnings

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 12-JUL-1988    ArticleIdent: Q29730

 Problem:
     When I compile the sample program on Page 85 of the "Microsoft
 Editor for MS OS/2 and MS-DOS: User's Guide," I get two warning
 messages.
    These warning messages are generated on the following two sections
 of the sample program:

    1. struct swiDesc swiTable [] = {
             { NULL, NULL, NULL }
        };

    2. struct cmdDesc cmdTable [] = {
             { "Upper", Upper, 0, BOXSTR | TEXTARG },
             { NULL, NULL, NULL, NULL }
        };

 Response:
   These warnings will not cause a problem. You can, however, make the
 following two changes:

    1. struct swiDesc swiTable [] = {
             { NULL, NULL, 0 }
        };

    2. struct cmdDesc cmdTable [] = {
             { "Upper", Upper, 0, BOXSTR | TEXTARG },
             { NULL, NULL, 0, 0 }
        };


 13. Missing Semicolon on Line 17 of Example on Page 85 in Manual

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 29-AUG-1988    ArticleIdent: Q29731

    On Page 85 of the "Microsoft Editor for MS OS/2 and MS-DOS: User's
 Guide," there is a missing semicolon on line 17.
    The following line is incorrect:

    cfile = FileNameToHandle("", NULL)

    It should read as follows:

    cfile = FileNameToHandle("", NULL);


 14. M.EXE Editor Macro to Join Current Line with Next Line

 Product Version(s): 1.00    | 1.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 29-AUG-1988    ArticleIdent: Q30030

    The following macro will join the current line with the following
 line, leaving one space between the last character on the current line
 and the first character of the next line.
    Place the following three lines in the [M] and/or [MEP] section(s)
 of your TOOLS.INI file, or enter them from the keyboard using the
 ASSIGN function (ALT+= in the default keyboard setup):

    ;Macro to join current line with next line.
        join:=endline right arg down begline sdelete
        join:alt+j

    The following is a description of how the join macro works:

    1. Endline moves one place beyond the last character on the current
       line.
    2. Right moves one character further, to insert a space.
    3. arg introduces the argument to the next command (in this case,
       sdelete).
    4. down begline moves to the first character on the next line.

    This process defines a Streamarg for the command sdelete (S stands
 for Stream).
    Note that sdelete should be used, not ldelete, because the down
 begline sequence would have defined either a Linearg or a Boxarg,
 neither of which would join the lines.
    Use sdelete because it closes the stream of characters and/or white
 space between the starting cursor position and the ending cursor
 position.


 15. Microsoft Editor Macro Moves Text with TAB Key

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  6-JAN-1989    ArticleIdent: Q30033

 The TAB key only moves the cursor. It does not move both the cursor
 and the text under the cursor (as it does in QuickC, Word, and many
 other editors).

 To move text and the cursor, put the following macro in your TOOLS.INI
 file in the [M] and/or [MEP] section(s):

    ;Macro to tab with insertion, as in QuickC and Word
        emacstab:=arg tab sinsert tab
        emacstab:ctrl+tab

 The "emacstab" macro (there is no significance to the name other than
 its similarity to M.EXE's EMACSNEWL and EMACSDEL functions) is invoked
 by pressing CTRL+TAB.

 Note: assigning this macro to CTRL+TAB will only function on
 enhanced-style keyboards. Older-style keyboards must use another set
 of keys for this macro assignment. On the older keyboards, assigning
 this macro to CTRL+TAB causes the macro to be ignored.

 The emacstab macro functions as follows:

 1. The Arg command introduces the argument (in this case, a
    "stream" arg).

 2. The Tab command moves you one tab stop to the right.

 3. The Sinsert command moves the highlighted text over to the tab
    stop.

 This macro leaves your cursor back where it started, so one more TAB
 moves your cursor to the right (on top of the shifted text).


 16. C Extension to Make Psearch Prompt for an Input in M.EXE

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 23-MAY-1988    ArticleIdent: Q30285

 Question:
    I wish to emulate the Brief Psearch (Plus Search) with the M.EXE
 editor. I want Psearch to prompt me to enter a search string. Can this
 be done with a macro or do I have to use a Microsoft C extension?

 Response:
     This emulation cannot be done with macros. However, it can be done
 with Microsoft C extensions.
     The following is an example of how to do so in a Microsoft C
 extension:

     1. Use DoMessage() to output a string saying something similar to
 the following:

     "Please enter the search string:"

     2. Use KbUnHook() to disable M.EXE's "logical keyboard." This
 gives you the "focus" of the keyboard so that keyboard input is no
 longer read by the editor, thus freeing you to input a string from the
 user.
     3. Parse the keyboard input and then process it appropriately by
 invoking the Psearch function.
     4. Use KbHook() to reenable the logical keyboard in M.

     The following is an alternate method:

     Use "ReadChar()" instead of "KbUnHook()" and "KbHook()."
 (Mentioned in steps two and four above.)

     For more information on the functions available for writing C
 extensions, please read the files EXT.DOC and EXT.H that are included
 with the Microsoft Editor Version 1.00.
     For general information on programming C extensions, please
 consult Chapter 8 of the "Microsoft Editor User's Guide."
     Appendix A of the "Microsoft Editor User's Guide" provides a
 comprehensive list of editing functions such as Psearch.
     Psearch searches forward for the previously defined string or
 pattern. Msearch (Minus Search) searches backward for the previously
 defined string or pattern.


 17. Debug Shown on M.EXE Help Screen Is Not a Supported Switch

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 15-JUN-1988    ArticleIdent: Q30365

    The Debug numeric switch that appears in the information file of
 the help screen in the Microsoft Editor Version 1.00 has not been
 implemented.
    There is no function associated with Debug.


 18. M.EXE C Extensions Documented in UTILITY.DOC, Not README.DOC

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | docerr
 Last Modified: 26-MAY-1988    ArticleIdent: Q30534

    Page 70 of the "Microsoft Editor User's Guide" incorrectly states
 the following:

    "To create a successful C extension, you need to follow these
 guidelines:
        1. Check the README.DOC file to see what functions you can call
 from the standard C run-time library."

    Contrary to the above manual statement, C extensions are documented
 in UTILITY.DOC on the release disk, not in the README.DOC.



 19. Making Assignments to PLUS, MINUS and PRINT SCREEN Keys

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | tar66615
 Last Modified:  1-SEP-1988    ArticleIdent: Q31485

 It is possible to make key assignments to the PLUS, MINUS, and
 PRINT SCREEN keys on the numeric keypad.

 For more information on function assignments, macros, and keystrokes,
 consult section 6.2.1 of "The Microsoft Editor User's Guide."


 20. How to Load a C Extension that Is Not in Current Directory

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | TAR75933 docerr
 Last Modified:  8-JUN-1988    ArticleIdent: Q30826

    Page 84 of the "Microsoft Editor for OS/2 and MS-DOS User's Guide"
 incorrectly infers that the M.EXE editor will search for a C-extension
 module along the DOS PATH under MS-DOS or OS/2 real mode when you
 place the following statement in the TOOLS.INI file:

    load:myext.exe

    To search for a C-extension module along the DOS PATH, you must
 instead use the following load switch syntax in the TOOLS.INI file:

    load:{$ENVAR: | dos path}filename.ext

 where you have the option of using $ENVAR: (a DOS environment
 variable) or an explicit directory path specification.
    You can prefix your filename with $PATH: or $INIT:. For example,
 "$PATH:filename.ext" means the "filename.ext" is to be found in the
 directories in the DOS PATH. This format is valid in any filename
 context. The following example will go to the STDIO.H file that
 actually is being used by the compiler:

    <arg> "$INCLUDE:stdio.h" <setfile>

    Also, when operating under OS/2, $ENVAR:, the explicit DOS path,
 and the extension on the filename are ignored. Instead, filename.DLL
 is searched for in your LIBPATH. Please note that LIBPATH under OS/2
 is not an environment variable. LIBPATH is a directive in the
 CONFIG.OS2 file.
    The following are examples of using the load switch in TOOLS.INI:

    ; load 'my.ext' from the current directory.
    ; Under OS/2, load my.dll from LIBPATH.
    load:my.ext

    ; load 'your.ext' from either the current directory or one
    ; of the directories on path
    ; Under OS/2, load 'your.dll' from LIBPATH
    load:$PATH:your.ext

    ; load 'c:\init\ourext'.
    ; Under OS/2, load 'ourext.dll' from LIBPATH
    load:c:\init\ourext



 21. An Example Where a Protect Mode C Extension Will Not Load

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | TAR76121 TAR76251
 Last Modified:  8-JUN-1988    ArticleIdent: Q30827

 Problem:
    I am trying to create an extension to the MEP.EXE editor. I am
 unable to get the editor to load my C extension. To simplify things I
 tried to get the editor to load the sample SKEL; however, I was
 unsuccessful. I receive the following error messages when loading:

    "cannot load skel - invalid argument"
    "skel is an illegal setting"

    My LIBPATH is c:\os2\dll and skel.dll is placed there. If skel.dll
 is not in my libpath I would get the error "no such file or
 directory". My MAKE and DEF files for SKEL are as follows:

 SKEL MAKE FILE
 #
 # Makefile for the MEP Editor Extensions
 #
 SYS=\os2\dll

 .c.obj:
  cl -c -Gs -Asfu -G2 -Lp $*.c

 .obj.dll:
  link  /NOI /NOD exthdrp.obj $*.obj,$*.dll,nul.map,,$*.def;

 skel.obj:    skel.c skel

 skel.dll:    skel.obj skel.def

 $(SYS)\skel.dll:  skel.dll
        copy skel.dll $(SYS)

 SKEL DEF FILE

 LIBRARY  SKEL

 EXPORTS
  _ModInfo
  SKEL

 Response:
    The extension is not loaded because the DEF file is incorrect. The
 file should be as follows:

 SKEL.DEF:
    LIBRARY

    EXPORTS
            _ModInfo
            EntryPoint

    This file should be used with all the extensions that are written.
 It need not be modified.



 22. Tags Let You Use the Same TOOLS.INI File for M and MEP

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | TAR76127
 Last Modified:  8-JUN-1988    ArticleIdent: Q30828

 Question:
    I have the same commands for M and for MEP. I want to load the
 QUICKHELP utility if I am running OS/2. However, in my TOOLS.INI file,
 if I put in the following information, MEP never reads the rest of
 the TOOL.INI file:

    [mep]
     load:qhmep
    [m mep]
     rest of the commands
     .
     .

    How should I do this without making two (almost identical) files,
 one for [m] and one for [mep]?

 Response:
    Through the use of tags, it is possible to use the same TOOLS.INI
 file in both protect mode and real mode/DOS. The tag must specify the
 program name along with the version of the operating system as in the
 following example:

    [m-3.2]    => MS-DOS 3.2
    [m-10.0]   => OS/2 1.0 protect mode
    [m-10.0R]  => OS/2 1.0 real mode
    [m-10.10]  => OS/2 1.1 protect mode
    [m-10.10R] => OS/2 1.1 real mode

    The following change should be made to your TOOLS.INI file:

        [m mep]
                 commands that are non operating system dependent
             .
             .
             .

        [mep-10.0]
             load:qhmep

    The number used in the tag is the major and minor version number of
 of the operating system being used. Under OS/2 this information can be
 found by calling the API routine DosGetVersion. The call can be made
 from any language that supports the use of the API,including C Version
 5.10, MASM Version 5.10, FORTRAN Version 4.10, PASCAL Version 4.10,
 and BASCOM Version 6.00. Under DOS, this information is displayed with
 the DOS VER command.


 23. Setting TMPSAV in TOOLS.INI file; M.TMP Cannot Be Suppressed

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | TAR76606
 Last Modified:  8-JUN-1988    ArticleIdent: Q30829

 Question:
    How do I get the Microsoft Editor (both ME and MEP) to not create
 and use the M.TMP to record past editing sessions?
    I have tried setting the switch tmpsave:0 in the TOOLS.INI file,
 but this does not solve the problem. Is there some other switch I have
 not set properly or a way to exit without creating M.TMP?

 Response:
    There is no way to prevent the creation of the temporary file.
    The TMPSAV switch is used to control the maximum number of files
 about which information is kept between editing sessions. This
 information includes the cursor position and window layouts.
    When you edit one of these files again, the screen starts up as you
 left it. The default value is 20. If TMPSAV is set to 0, it causes all
 files to be saved. All other numeric values refer to the number of
 files that will be saved. The /t option specifies that any files
 edited are temporary; they are not saved in the M.TMP file.



 24. Protected-Mode C Extensions Fail with "Protection Fault"

 Product Version(s): 1.00 | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 29-AUG-1988    ArticleIdent: Q31009

 Problem:
    I am writing C extensions for the protected mode of OS/2. All my
 extensions fail with a general-protection fault. The sample program on
 Page 85 of the "Microsoft Editor for MS OS/2 and MS-DOS: User's Guide"
 also fails.

 Response:
    Page 78 of the "Microsoft Editor for MS OS/2 and MS-DOS: User's
 Guide" incorrectly states that the second argument is a NULL pointer.
    The programs are crashing because the incorrect value is being
 passed to the FileNameToHandle routine. This routine requires a
 pointer to a null string, not a null pointer.
    For example, the following statement

    cfile=FileNameTohandle("",NULL);

 should read as follows:

    cfile=FileNameTohandle("","");


 25. Two Toned Colors in <assign> Pseudo File Can Occur

 Product Version(s): 1.02    | 1.02
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | buglist1.02
 Last Modified: 29-JAN-1990    ArticleIdent: Q58029

 The <assign> pseudo file can consist of lines in blocks that alternate
 in color starting at the middle of the file. This appears as if you've
 changed multiple editor options, which have just been activated, when
 no changes were actually made. This does not affect the way M.EXE (or
 MEP.EXE) operates.

 To see the blocks of alternating color, follow the steps below:

 1. Invoke the editor.

 2. Press ALT+A <ASSIGN> F2, which implies ARG <ASSIGN> SETFILE.

 3. Press ALT+BACKSPACE, which implies UNDO.

 4. Press F9 ALT+BACKSPACE, which implies META UNDO.

 5. Page down until you see the colored blocks.

 Microsoft has confirmed this to be a problem with the Microsoft Editor
 Version 1.02. We are researching this problem and will post new
 information here as it becomes available.


 26. Return Type for ReadCmd Is PSWI, Not PCMD

 Product Version(s): 1.00 | 1.00
 Operating System:   OS/2 | MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 12-JAN-1989    ArticleIdent: Q31143

 Page 7 of the EXT.DOC file, located in the SOURCE\ME\EXT directory of
 the Microsoft C Optimizing Compiler Version 5.10, incorrectly lists
 the return type for the ReadCmd command as being PCMD.

 The correct return type is PSWI, which is documented in the EXT.H
 file.


 27. MEP Crashes OS/2 when Switching from Real-Mode Screen Group

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |  TAR75546 TAR76522
 Last Modified: 28-OCT-1988    ArticleIdent: Q31144

 When running in OS/2 protected mode, the system may crash when
 switching between protected mode and real mode and using the ALT+ESC
 sequence. It may take several iterations of ALT+ESC before the failure
 occurs.

 The system crashes when switching from the real-mode session into a
 protected-mode session that is running MEP. When the system crash
 occurs, the following message appears:

     TRAP 000D

     <register contents>

     The system detected an internal processing error
     at location # 3430:0590
     Exception while in kernel mode

     The system is stopped

 This is not a problem in MEP; it is a problem in OS/2.

 You can work around this problem by not running MEP in the original
 ("default") protected-mode screen group. Instead, start a second
 protected-mode screen group and run MEP there. To move to the second
 protected-mode screen group, do the following:

 1. Press ALT+ESC from real mode to get to the original
    protected-mode screen group.

 2. Press ALT+ESC again to get to the MEP screen group.

 Running MEP in a second screen group prevents you from switching
 directly from real mode into the MEP screen group.

 Another workaround for this problem is to use the CTRL+ESC hotkey
 rather than the ALT+ESC command to leave the real-mode screen group.
 The CTRL+C hotkey brings you back to the program selector. Once
 there, you can select the next screen group by using the mouse or
 cursor keys.


 28. "Unable to Read TOOLS.INI" Message Appears in OS/2 with MEP

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  8-JUN-1988    ArticleIdent: Q31155

     MEP.EXE, the OS/2 version of the Microsoft editor, will give the
 following message when the INITIALIZE function is invoked (i.e.,
 SHIFT-F8 in the default keyboard setup):

    "Unable to read TOOLS.INI"

    This message will appear if the editor's name is left as MEP while
 the TOOLS.INI tag for the editor is labeled [M]. The two names must
 match.
    To correct the problem, either rename the editor to M, or label the
 tag [MEP].
    The tag can be set to [M MEP] if you wish to use the same TOOLS.INI
 settings for both real-mode and protected-mode versions of the editor.


 29. Purpose of ECH.EXE with the Microsoft Editor

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  8-JUN-1988    ArticleIdent: Q31280

    ECH.EXE is used by the editor to generate the list of files you
 receive when you do <arg> "*.C" <setfile>.



 30. NOSOFTCR Parameter in TOOLS.INI Disables Auto Indentation

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | tar69375
 Last Modified: 14-JUN-1988    ArticleIdent: Q31486

    The automatic indentation at the beginning of lines can be
 disabled.
    The NOSOFTCR parameter prohibits the Microsoft Editor from making
 indentation "guesses." NOSOFTCR is specified in the TOOLS.INI file, as
 follows:

    nosoftcr:



 31. Features Supported when Editing TextArgs in Microsoft Editor

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | tar69726
 Last Modified:  6-JAN-1989    ArticleIdent: Q31487

 When editing TextArgs, not all editing features are supported. The
 following features are supported:

 QUOTE, INSERT, SDELETE, RIGHT, LEFT, UP, DOWN, HOME, and END

 When an unsupported feature is entered, the editor will beep. Macros
 may be used, but they can contain only supported features.

 The END key allows you to find the length of the search/replace
 string; pressing ARG clears the entire string.


 32. UTILITY.DOC: Filetab Switch Expands Tabs

 Product Version(s): 1.00 | 1.00
 Operating System:   OS/2 | MS-DOS
 Flags: ENDUSER | tar71845
 Last Modified: 16-JUN-1988    ArticleIdent: Q31488

    Information about the filetab switch can be found in the
 UTILITY.DOC file that comes with the Microsoft BASIC Compiler Version
 6.00, the Microsoft C Compiler Version 5.10, the Microsoft FORTRAN
 Compiler Version 4.10 and the README.DOC for Microsoft MASM Version
 5.10.
    The filetab switch is a numeric switch that determines how the
 editor translates tabs when loading a file into memory. The value of
 the switch gives the number of spaces associated with each tab column.
    For example, the setting "filetab:4" assumes a tab column every four
 positions on each line of a file.
    Every time the editor finds a tab character in a file, it loads the
 buffer with the number of spaces necessary to get to the next tab
 column. Depending on the value of the entab switch, the editor also
 uses the filetab switch to determine how to convert spaces into tabs
 when writing a file.
    The default value of filetab is eight (8).



 33. Tabs Expanded to Eight Spaces; Filetab Switch Changes Spacing

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | Tar70793
 Last Modified:  1-SEP-1988    ArticleIdent: Q31489

 Question:

 Why are tabs expanded to eight spaces even though I set the tabstop
 variable and the entab switch?

 Response:

 Neither the tabstops or the entab switch affect how tabs are expanded
 when the file is read. The filetab switch is used to determine how
 many spaces to expand each tab. For example, "filetab:4" will expand
 each tab in the file to four spaces.

 The entab switch controls how the editor converts multiple spaces
 into tabs when a line is changed or a file is saved. The default is
 one (1). The following chart shows different values and their
 meanings:

 Value   Meaning

 0       Tabs are not used to represent white space.
 1       All multiple spaces outside of quoted strings
         are converted to tabs (default).
 2       All multiple spaces are converted to tabs.

 Tabstops control the number of spaces between each logical tabstop
 for the editor. The default is four (4).


 34. Resizing Windows

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | tar63957
 Last Modified:  1-SEP-1988    ArticleIdent: Q31490

 It is not possible to directly resize windows in the Microsoft Editor.
 A window can only be opened or closed. To resize a window, it must be
 closed and then reopened. Direct resizing of windows is not currently
 possible.

 This feature is under review and will be considered for inclusion in a
 future release.


 35. Parentheses Matching in Microsoft Editor; Arg Meta PBal

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | tar63957
 Last Modified: 31-OCT-1988    ArticleIdent: Q31491

 The Microsoft Editor has the capability of matching parentheses
 without altering the current file. Meta PBal prevents the file from
 being edited while balancing parentheses and brackets.

 The following are various other options for Pbal:

 1. Pbal: Scan backwards through the file, balancing parentheses and
    brackets. The first unbalanced one is highlighted when found. If it
    is found and is not visible, the editor displays the matching line,
    with the highlighted matching character. Note that the search does
    not include the current cursor position, and that the scan only
    looks for more left brackets or parentheses than right, not just an
    unequal amount.

 2. Arg Pbal: Performs similarly to Pbal, except that it scans
    forward in the file and looks for more right brackets or parentheses
    than left.

 3. Arg Meta Pbal: Performs similarly to Arg Pbal except that the
    file is not updated.


 36. Editing Nonexisting Files with the Microsoft Editor

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | tar62913
 Last Modified: 16-JUN-1988    ArticleIdent: Q31492

    If the Microsoft Editor is invoked to edit a nonexisting file, it
 creates a file with a length of zero in the DELETED directory in
 addition to creating a new file. This occurs with the backup switch
 set to "undel" (the default) in the TOOLS.INI file.
    This behavior is expected and is program design for the product.
 When the Microsoft Editor is invoked to edit an existing file, the
 previous version is moved to the DELETED directory.
    The EXP command allows you to remove this file, and all other files
 from the DELETED directory.



 37. Macro to Toggle HOME Key

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | tar66615
 Last Modified: 12-JAN-1989    ArticleIdent: Q31493

 You can create a macro to do the following:

 1. Press HOME key (cursor goes to beginning of line).

 2. Press HOME key again (cursor goes to top of window).

 3. Press HOME key again (cursor goes to top of buffer).

 This technique usually is used to create a toggle key, but it is
 equally applicable to the desired three-step toggle. The technique is
 as follows:

 home1:= begline arg "home2:f10" assign
 home2:= home arg "home3:f10" assign
 home3:= mark arg "home1:f10" assign
 home1:f10

 After following this procedure, the F10 key will toggle among begline,
 home, and mark.


 38. Inserting Time and Date into Files

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-MAY-1989    ArticleIdent: Q40176

 To write a macro to insert the time and date into your file, use the
 following insert commands:

    Command     Action

    Curdate     Inserts current date
    Curday      Inserts current day of the week
    Curfile     Inserts current filename
    Curfileext  Inserts current file extension
    Curfilenam  Inserts base name of current file
    Curtime     Inserts current time
    Curuser     Inserts name specified in USER environment variable

 The following macro can be inserted into your TOOLS.INI to insert the
 filename, time, and date:

 ;Macro for time and date.
     Header:= Curfilenam tab Curtime tab Curdate
     Header:Alt+H


 39. Macro to Enter Form Feed or Control Characters in Editor

 Product Version(s): 1.00 | 1.00
 Operating System:   DOS  | OS/2
 Flags: ENDUSER | tar62237
 Last Modified:  1-NOV-1988    ArticleIdent: Q31495

 The form-feed characters and control characters below can be entered
 in a file being edited by the Microsoft Editor.

 The following macro inserts a linefeed, (CTRL+L), and a newline, and
 binds it to the F6 key. To enter a CTRL+L, use the Graphic assignment
 on Page 48 of the "Microsoft Editor User's Guide" when editing your
 TOOLS.INI file:

 graphic:ctrl+l

 FFM:="L" newline   ; Instead of the L shown here, insert a CTRL+L
 FFM:F6             ; with the quote function "CTRL+P CTRL+L"

 The macro below allows you to enter control key values. The
 following line binds "quote" to F5. Quote allows you to enter any key
 as input (i.e., control key values, etc). This means if you type "F5"
 followed by a "CTRL+X", you will see a "\030" instead of "arg":

 quote:F5.


 40. "Unsupported Video Mode" When Loading Microsoft Editor

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 28-JUL-1989    ArticleIdent: Q31498

 It is possible when loading M.EXE or MEP.EXE to receive an
 "Unsupported video mode, please change modes and restart" error
 message. This message may mean that the hardware is not supported.

 Graphics cards supported in this situation include IBM's CGA, EGA,
 MCGA, MDPA, and VGA and the Hercules card. An example of an
 unsupported system is the 8514 video adapter.

 In MS-DOS (or OS/2 real mode), the Microsoft Editor (M) supports the
 8514/A graphics card, but in OS/2 protected mode, MEP Version 1.00
 does not support this graphics card. A "video mode not supported"
 error message occurs in protected mode.

 The Microsoft Editor Version 1.02 supports the 8514/A graphics card in
 both real and protected mode. This version is currently available with
 FORTRAN 5.00.


 41. Environment Variables Used by the Microsoft Editor

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 16-JUN-1988    ArticleIdent: Q31547

    The Microsoft Editor uses the following environment variables:

    1. TMP: This directory stores all temporary files.
    2. INIT: This directory stores the TOOLS.INI, M.TMP, and temporary
 files if TMP is not set.

    Please note, if neither environment variable is set, all temporary
 files except M.TMP are written to the root directory of the disk being
 used. M.TMP is written to the current directory.
    The environment variables usually are set in the AUTOEXEC.BAT file.
 For example the following lines can be placed in the AUTOEXEC.BAT
 file:

     SET INIT=c:\init
     SET TMP=c:\temp

    Also, if the TMP environment variable ends with a semicolon, the
 temporary files (i.e., swapping files) will not be created. The editor
 will try to use the semicolon in the name of the file that is created.


 42. Editor Utilities DOS Version 2.x and 8086/8 Corrections

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q31801

 The following files are included in this application note:

    MEGREP.EXE, RM.EXE, UNDEL.EXE, ECH.EXE and EXP.EXE.

 These files are replacements for the original utilities that were
 shipped with the Microsoft Editor Version 1.00. They have been updated
 to correct two specific problems only; they do not include any additional
 functionality over the originals.

 These files correct the problem of embedded 286 instructions that
 prevented the programs from correctly running on 8086 and 8088
 machines (the machines would hang). The files also have been updated
 to correct problems when used with DOS Version 2.x.

 To install the files, copy the files from the appnote disk over the
 files (of the same names) that are installed on the machine.

 This application note can be obtained by calling Microsoft Product
 Support Services at (206) 454-2030.


 43. Preventing Generation of Tabs in the Edited Disk Files

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 25-JUL-1988    ArticleIdent: Q32033

    It is impossible to search for a tab or replace a string with a tab
 in the M editor.
    When a file is being edited, there are no tab characters in the
 file. When the M editor reads from disk to memory, it converts tabs to
 spaces. When it writes from memory to disk, it converts spaces to tabs
 (unless you set the ENTAB switch to 0).
    This may create problems when devices other than your machine
 access the file. For example, if you edit a source file on your IBM PC
 with the M editor, then try to compile the source file on a mainframe,
 the source file may not compile because of the tabs in the disk file
 created by the M editor.
    The solution is to set ENTAB to 0 in the TOOLS.INI file; this value
 will prevent tabs from being used to represent white space when
 writing from memory to disk.
    For more information on the ENTAB switch, please refer to Table 7.2
 on Page 59 of the "Microsoft Editor User's Guide."


 44. M Hangs on Tandy 2000 with MS-DOS Version 2.11

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  1-SEP-1988    ArticleIdent: Q32052

 M, the Microsoft Editor for MS-DOS, hangs when run on a Tandy 2000
 computer running MS-DOS Version 2.11.

 M does not support the Tandy 2000. There is no workaround to this
 incompatibility.


 45. Scrolling One Line at a Time

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |  buglist1.00
 Last Modified: 20-OCT-1988    ArticleIdent: Q32053

 Problem:

 The editor jumps seven lines at a time when I Scroll off the top or
 bottom of the screen. I want it to Scroll one line at a time, but it
 Scrolls four lines at a time when I set VSCROLL to 1.

 Response:

 Hike and Scroll are designed to be independent functions; however,
 they are incorrectly tied together.

 Microsoft has confirmed this to be a problem in Version 1.00 of the
 editor. We are researching this problem and will post new information
 as it becomes available.

 A workaround to this problem is to set both VSCROLL and HIKE to 1 in
 your TOOLS.INI file in the [M] section, as in the following example:

 [M]
     hike:1
     vscroll:1


 46. Installing M with Msetup

 Product Version(s): 1.00    | 1.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | h_fortran
 Last Modified: 19-JUL-1988    ArticleIdent: Q32094

 Question:
    The FORTRAN Version 4.10 setup program did not install the
 Microsoft Editor. I could not find any documentation on how to use
 msetup in the UTILITIES.DOC. How do I set up the Editor?

 Response:
    To run the msetup program, place the "Microsoft Editor" disk in
 Drive A and type "msetup". A help screen will be displayed showing
 the syntax for using msetup. An example of running msetup is as
 follows:

    A:>msetup c: \m \init \binp

    This procedure will install the M Editor and M tools (MEGREP, ECH,
 UNDEL, etc.) in the M directory, TOOLS.INI in the INIT directory, and
 MEP in a BINP directory. If you do not specify any directories, the
 program will use default directories. It will show these default
 directories on the screen and prompt you for any changes. These
 directories must be created before running msetup; otherwise, it will
 not be installed correctly.
    Please note that when the msetup prompts you for the type of
 emulation to use for the TOOLS.INI file, a TOOLS.INI file will not be
 created if you type a "0" for the default tools (the defaults are
 already built into Editor). If any of the other emulations are used,
 msetup will rename the appropriate file to TOOLS.INI and install it.


 47. Exit Does Not Save Files when NoAutosave Is Set

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 31-OCT-1988    ArticleIdent: Q32095

 When the boolean switch Autosave is disabled (by setting it to
 NoAutosave), a file will not be saved when exiting the editor.

 As documented on Page 61 of the "Microsoft Editor User's Guide," when
 the Autosave switch is turned on, the current file is saved when the
 user switches away from it. When Autosave is off (NoAutosave), the
 file must be explicitly saved when desired; this can be done by
 entering Arg Arg Setfile (ALT+A ALT+A F2 in the default keyboard
 setup).


 48. Arg *.* Setfile: "Bad Command or Filename" Error

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | tar78150
 Last Modified: 29-AUG-1988    ArticleIdent: Q32224

    Entering the command Arg *.* Setfile causes M to display a list of
 all files in the current directory.
    ECH.EXE is a utility used to generate the list of files for ARG
 textarg SETFILE. If this utility cannot be found, you will receive a
 message saying "Bad command or filename." ECH.EXE must be located in a
 directory on the path.


 49. Using the SHORTNAMES Switch

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | tar78150
 Last Modified: 31-MAR-1989    ArticleIdent: Q32225

 SHORTNAMES is a boolean switch. When it is set (the default), if you
 type <arg> "foo" <setfile>, you will be sent to the first file in your
 history list with the base name "foo". You do not have to specify the
 full pathname for a file in another directory. If there is no
 d:\path\foo.xxx anywhere in your file history, you only get foo.

 If you have a file "foo" in your current directory, SHORTNAMES still
 tries to find a file in your history list first. The history of files
 is stored in M.TMP. The number of files saved is determined by the
 TMPSAV switch.

 To disable this feature, set noshortnames: in your TOOLS.INI file.

 To avoid this behavior without changing the switch value, include a
 period in the path specification. For example, enter <arg> "foo."
 <setfile>, which will look only in the current directory. The presence
 of any path character (".", etc.) disables the SHORTNAMES feature for
 the file being referenced.


 50. Cancel Clears the Type-Ahead Buffer

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | tar75933
 Last Modified: 19-JUL-1988    ArticleIdent: Q32226

    The Cancel command clears the type-ahead buffer. This is a feature
 of the editor and is not considered a problem.
    Cancel is mapped to the ESC key in the default keyboard setup.


 51. Loading a TAGGED Section Reinitializes the Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00 tar76973
 Last Modified: 29-AUG-1988    ArticleIdent: Q32228

 When a TAGGED section is initialized (<arg> "section name"
 <initialize>), all current macros are destroyed before
 reinitialization.

 The curdate, curtime, etc., macros are reset, your extmake: settings
 are set to the default, and the OS-dependent and video-dependent
 sections of TOOLS.INI are read in. If you type <initialize>, the main
 section is read in place of the TAGGED section.

 Microsoft has confirmed this to be a problem in Version 1.00. We
 are researching this problem and will post new information as it
 becomes available.



 52. The extmake Compile Switch Is Case Sensitive

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified:  1-MAY-1989    ArticleIdent: Q32242

 The following extmake entry will be ignored, causing the default
 command line to be used:

 extmake:C cl /c /Zi /Od %s

 Microsoft has confirmed this to be a problem in Version 1.00. We
 are researching this problem and will post new information as it
 becomes available.

 Although there is no case sensitivity for the extmake switch name, the
 extension specified ("C" in this example) must be in lowercase. If the
 extension is not in lowercase, the help screen will show a separate
 entry for that extension, as follows:

    C   cl /c /Zi /Od %s
    c   cl /c /Zep /D LINT_ARGS %s

 The second command line will be used when compiling a C program.


 53. Loading Tagged Sections in OS/2 Version 1.10

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | docerr
 Last Modified: 29-AUG-1988    ArticleIdent: Q33348

 Problem:

 I have followed the instructions on Page 64 of the "Microsoft Editor
 User's Guide" for loading tagged sections in OS/2, but the editor
 never loads this section. My TOOLS.INI file has a tag titled [M MEP]
 containing assignments for both protected and real modes and a tag
 titled [M-10.0] for OS/2 protected-mode assignments. I am running
 Microsoft OS/2 Version 1.10.

 Response:

 Your [M-10.0] tag is not loaded in OS/2 Version 1.10 because [M-10.0]
 means OS/2 Version 1.00. The version number should be changed from
 10.0 to 10.10; your tag should be [M-10.10]. If you want the tag to
 work correctly for both OS/2 Versions 1.00 and 1.10, create a tag
 titled [M-10.0 M-10.10].

 This information is not contained in the "Microsoft Editor User's
 Guide."


 54. C.TMP Files in Current Directory

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  2-SEP-1988    ArticleIdent: Q34251

 Question:

 Every time I edit a file with the Microsoft Editor, I receive a C.TMP
 file in that directory. I am using DOS Version 2.10. Why is it
 creating this file?

 Response:

 The C.TMP file is where the editor keeps its information about
 previous files that have been edited. This file normally is called
 M.TMP; however, due to a limitation of DOS Versions 2.x, the editor
 believes its name is C rather than M.

 The files are placed in the directory where the file was edited
 because unless the INIT environment variable is set, the .TMP file is
 written to the current directory.

 When using M on DOS Versions 2.x, change the tag field of the TOOLS.INI
 from [M] to [C] and set the INIT environment variable to the directory
 that contains TOOLS.INI.



 55. How to Perform Spell Checking in M

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 29-AUG-1988    ArticleIdent: Q34274

 Question:
    Does the Microsoft Editor have any spell checking capabilities?

 Response:
    The M editor does not have built-in spell checking. If you have a
 separate spell-check program you can write a macro to invoke it on
 your current file.
    For example, you could use the spell checker that comes with
 Microsoft Word Version 4.00 by doing the following:

     [M]
         ...
         Spell:=Arg "spell-am " Curfile Shell
         Spell:ALT+S

    The macro works as follows:

    1. Arg introduces an argument to the shell command.
    2. "spell-am" is the name of the spell-check utility
       included in Word Version 4.00.
    3. Curfile is the name of the current file you are editing. Note
       the space at the end of "spell-am "; this space is needed so the
       argument you pass to Shell is "spell-am YourCurrentFile" instead
       of "spell-amYourCurrentFile".
    4. The Shell command invokes COMMAND.COM and passes it the
       spell-am command. When spell-am completes its spell-check,
       it will return to the editor.


 56. Changing Height Switch Not Sufficient to Change Video Modes

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-SEP-1988    ArticleIdent: Q34411

 Microsoft Editor does not immediately change video modes (CGA/EGA/VGA)
 when changing the numeric switch HEIGHT: to either 23, 41, or 48 in the
 TOOLS.INI file.

 For the new height setting to take effect, one of the following must
 be done:

 1. The INITIALIZE function can be invoked to force the editor to
    update its settings based on the switch values in TOOLS.INI. This
    will reset the video-display configuration. (INITIALIZE is ALT+F10
    for Quick and EPSILON emulation, SHIFT+F10 for BRIEF emulation, or
    SHIFT+F8 for the default emulation).

 2. The assignment can be made directly to the editor by invoking
    <arg> height:41 <assign>. In the default keyboard configuration,
    this would be ALT+A "height:41" ALT+=.

 3. While editing the "height:41" line in TOOLS.INI, move to the
    beginning of the line and enter <arg> <assign>, which is ALT+A
    ALT+= in the default keyboard assignments.

 The video mode is stored in the M.TMP file in the directory pointed to
 by the TMP environment variable; if TMP is not set, M.TMP is placed in
 the current default directory. Invoking the INITIALIZE function causes
 M to reset the settings in M.TMP based on the settings in TOOLS.INI.


 57. Accessing Switch Values in C Extensions

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  2-SEP-1988    ArticleIdent: Q35025

 There is no direct function call to access switch values defined in
 the editor, such as rmargin or vscroll or hike, in your C Extension.
 However, you can find the value by using fExecute() to switch to the
 help file, then use the psearch or msearch functions to locate
 rmargin. At the end of that line you will find the value associated
 with rmargin.

 The following is an example:

 fExecute("Arg \"<assign>\" Setfile");  /* switch to "<assign>" file   */
 fExecute("Mark");                      /* go to beginning of it       */
 fExecute("Arg \"rmargin\" Psearch");   /* search for "rmargin"        */
 fExecute("Pword");                     /* get the number after it     */

 You also can use the GetLine() function to read through the <assign>
 file; this method involves more coding, but it will run faster than
 using fExecute() to execute macros.


 58. Passing Textargs to M with the /E Switch

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-SEP-1988    ArticleIdent: Q35028

 Question:

 How can I pass textargs to the editor using the /e command-line
 switch?

 Response:

 Type in the name of the function you want the editor to execute. If
 you want to use more than one function, enclose the functions in
 double-quotation marks. If your functions require arguments, use the C
 syntax for specifying quotation marks within strings, i.e., the
 backslash escape character (\). Thus, a double-quotation mark within
 a string is specified with \".

 The following examples demonstrate various methods of passing
 command-line arguments to M:

 m /e psearch myfile

 This example invokes the Microsoft Editor on the file "myfile",
 passing it the command "psearch" to be executed immediately. The
 psearch will search for whatever string was last specified (in the
 search buffer).

 m /e "mark psearch" myfile

 This example again edits "myfile", but this time it passes two
 commands to M: "mark" and "psearch". The Mark command goes to the
 beginning of the file, and psearch searches forward for an occurrence
 of the search-string (which must have been specified in a previous
 search).

 m /e "arg \"search string\" psearch" myfile

 This example passes the editor the following string:

 "arg "search string" psearch"

 The \" characters are a C escape sequence that evaluates to a
 double-quotation mark ("); as a result, the entire string has a string
 embedded in it. The effect of this command is to tell the editor to
 search for the literal text "search string".

 m /e "arg \"\\\"a quoted search string\\\"\" psearch" myfile

 This is the most complicated case of argument passing. It
 passes the following string to the editor:

 "arg "\"a quoted search string\"" psearch"

 This command searches for the QUOTED literal text ""a quoted search
 string"".  The "\" and \"" are necessary to cause M itself to postpone
 evaluation of the double-quotation marks until actual search time.


 59. A Workaround for the MGREP Problem in M/MEP Version 1.02

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 29-JAN-1991    ArticleIdent: Q68386

 In the M/MEP Editor version 1.02, there is a problem in the MGREP
 function; it will fail to find some matches to the query in the file.
 (This is due to certain regular-expression matches failing when they
 shouldn't.) Below is a macro that will use the MEGREP.EXE utility to
 search for a string, and return the results in the compile window. The
 benefits are:

 1. It should be faster, especially under OS/2.

 2. If run under OS/2, it will be a background process enabling you
    to continue working.

 Macro Code
 ----------

 Add the following to your TOOLS.INI file. You can then assign it to a
 keystroke, if desired:

 megreplist:="*.c *.h"
 mg1:=copy arg "<megrep>" setfile mark emacsnewl mark paste begline
 mg2:="arg arg \"megrep \\\"" endline "\\\" " megreplist
 mg3:=" \" compile" begline arg endline execute setfile
 megrep:= mg1 mg2 mg3

 The following is another option, which avoids using an extra
 pseudo-file:

 megreplist:="*.c *.h"
 mg:= copy arg "<clipboard>" setfile            \
      begfile "megrep \"" endline "\" " megreplist  \
      begline arg arg endline compile setfile

 Notes
 -----

 1. The first macro is in three parts due to line-length limits of the
    knowledge base; the macro could be just one line. The second macro
    uses line continuation characters to achieve the same result as
    breaking up the first macro.

 2. The macro assumes that all files on disk are up to date.


 60. MHELP Driver Not Completely Compatible with QuickC Help Files

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_quickc buglist1.02
 Last Modified:  5-MAR-1990    ArticleIdent: Q58603

 The MHELP driver cannot process some cross-references inherent to the
 QuickC Versions 2.00 and 2.01 help files. Results range from the MHELP
 message "Cannot Process Cross Reference," to hanging the computer. In
 general, direct reference to a QuickC help file from within the editor
 is fine. However, moving around within the help file system using the
 built-in cross-references produces unpredictable results.

 The MHELP driver seems unable to access unformatted text files such as
 header, source, and DOC files. For example, QuickC allows you to
 access both the README.DOC file and QuickC header files from within
 the help system. Attempting these feats from within M leads to one of
 the following problems:

 1. "Cannot Process Cross Reference," if file not found.

 2. DOS will hang the machine if the file is found.

 3. OS/2 may cause a SYS 1943 protection violation if the file is
    found.

 The M editor also cannot use the <back> menu option to access a
 previously viewed help file. Attempting this yields the message
 "Cannot Process Cross Reference" at the bottom of the screen. The
 syntax of the <back> cross-reference in unencrypted help form is
 help file to access the previous help screen. This undocumented
 feature is not allowed in MHELP.

 Certain series of cross references cause sporadic errors. You should
 be careful to avoid internal cross-referencing within the QC help
 files. The problem can be shown with the following sequence using the
 QuickC and QuickAssembler help files from within the M Editor.

    <arg> seg <F1> <TAB> <RETURN> <TAB> <RETURN> <TAB>

 This example reaches the help-contents window via the "seg" example
 program. Upon reaching this point, it may hang DOS with the run-time
 error R6003 or R6001. OS/2 displays a black box in the upper-right
 corner of the screen and may crash at this point.

 Microsoft has confirmed this to be a problem with the M Editor Version
 1.02. We are researching this problem and will post new information
 here as it becomes available.


 61. Compiling in M Produces No .OBJ File

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q35233

 If compilation from within the editor gives no .OBJ file when the
 same compilation outside of M succeeds in creating an object module,
 check the CONFIG.SYS files setting.

 In one case, a user had "files=25" while running under DOS Version
 3.20, which doesn't support a file setting greater than 20. If files
 exceed 20, DOS uses its default of eight files. When the user set
 "files=20" an .OBJ was created from a compilation within M.


 62. Creating Windows in M and MEP

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-MAY-1989    ArticleIdent: Q35235

 Question:

 How can I create multiple windows and edit multiple files with the
 Microsoft Editor?

 Response:

 Both horizontal and vertical windows can be created. You can have up
 to eight windows on the screen.

 To create a horizontal window, position the cursor on the screen where
 you would like the window break and press ARG WINDOW (ALT+A F6 in the
 default).

 This process creates a new window with a copy of the file you were
 currently editing. You then can load a different file into that window
 (ARG SETFILE ALT+A F2).

 To create a vertical window, position the cursor on the screen where
 you would like the window break and press ARG ARG WINDOW (ALT+A ALT+A
 F6 in the default). You then can load a different file into the
 window.

 Once you have several windows on the screen you can move around from
 window to window using the WINDOW command (F6 in the default setup).

 See also section 4.6 of the "Microsoft Editor User's Guide."

 Note: Each window must have a minimum of five lines and 10 columns to be
 created.


 63. M Does Not Respond to Changes in the Height Switch

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 31-MAR-1989    ArticleIdent: Q35252

 The Microsoft Editor does not change video modes (EGA/VGA) when
 changing the numeric switch height to either 23, 41, or 48 in the
 TOOLS.INI file.

 The INITIALIZE function must be invoked to reset the video display
 configuration. (INITIALIZE = ALT+F10 for Quick and EPSILON emulation,
 SHIFT+F10 for BRIEF emulation, or SHIFT+F8 for the default emulation).

 The video mode also is stored in the M.TMP file in the directory
 pointed to by the INIT environmental variable or the current default
 directory.


 64. Toggling Display Modes: 25-, 43-, and 50-Row Modes

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | MS-DOS
 Flags: ENDUSER |
 Last Modified: 14-NOV-1988    ArticleIdent: Q37628

 The following Microsoft Editor macro allows you to toggle the EGA
 display between 25-row mode and 43-row mode by pressing ALT+E:

 ;Macro to toggle 25/43 line EGA modes
     to23:=arg "height:23" assign
     to41:=arg "height:41" assign
     toggle23:=to23 arg "toggle41:alt+e" assign
     toggle41:=to41 arg "toggle23:alt+e" assign
     toggle41:alt+e

 The example below is a variation of the above macro. It allows you to
 toggle the VGA display between 25-row mode, 43-row mode, and 50-row
 mode by pressing ALT+E. Instead of switching back and forth between
 two modes, it cycles through all three.

 The macro is as follows:

 ;Macro to toggle 25/43/50 line VGA modes
     to23:=arg "height:23" assign
     to41:=arg "height:41" assign
     to48:=arg "height:48" assign
     toggle23:=to23 arg "toggle41:alt+e" assign
     toggle41:=to41 arg "toggle48:alt+e" assign
     toggle48:=to48 arg "toggle23:alt+e" assign
     toggle41:alt+e

 These macros should be placed in your TOOLS.INI file as described
 in Chapters 6 and 7 of the "Microsoft Editor User's Guide."

 Note: the "toggle" functions in these macros not only set the video
 mode, they also change the assignment of function ALT+E. This makes
 these macros similar to self-modifying code. For example, "toggle23"
 not only sets the video mode to 23-rows (with a call to "to23"), it
 also assigns ALT+E to "toggle41" by using the following sequence:

    arg "toggle41:alt+e" assign

 This technique is very useful in learning to write macros.


 65. "Softer" Should Be "Softcr" in M 1.0 User's Guide

 Product Version(s):
 Operating System:   1.00   | 1.00
 Flags: MS-DOS | OS/2
 Last Modified: 18-DEC-1989    ArticleIdent: Q35256
 ENDUSER | docerr

 On Page 61 of the "Microsoft Editor User's Guide," there is a
 documentation error. Softcr is listed as Softer; the correct listing
 is Softcr.


 66. Why Compiling after Editing in M Shows Old Errors

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q35258

 When using the M editor (either M.EXE or MEP.EXE) to correct compiler
 or assembler errors, and then compiling/assembling from within M using
 the COMPILE function, it is possible to get the old set of errors
 returned. If the errors occur, check that the autosave switch is set
 correctly. If autosave is off, the corrections are not saved before
 compilation.

 When turned on, the autosave boolean initialization switch causes the
 current file to be saved whenever it is switched away from. The
 default value is on, i.e., the files are automatically saved. The
 setting can be changed from within the editor using Arg textarg Assign
 or else in TOOLS.INI.

 In either case, specify noautosave: to prevent automatic saving of
 files, or autosave: to restore automatic file saving.


 67. How to Read the Contents of the M Editor Clipboard

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 31-MAR-1989    ArticleIdent: Q35259

 The Clipboard is contained in a pseudofile named <clipboard>. It can
 be loaded the same way any other file is loaded. The contents of the
 Clipboard pseudofile can be examined in several ways.

 The pseudofile <clipboard> can be loaded with the command sequence Arg
 textarg Setfile, which is ALT-A <clipboard> F2 in default keystrokes.
 This process loads the named file. The contents of the clipboard then
 can be seen on the screen, and even can be edited and saved as a
 separate file.

 The file also can be loaded by bringing up the information file with
 the INFORMATION function (SHIFT-F1).

 Finally, if the clipboard is the file most recently switched from, the
 SETFILE function (F2) alone will call it up.

 The information file describes the nature of the Clipboard contents in
 two ways. The Clipboard line appears in the form in the list of
 files, as follows:

 <clipboard>                    *n lines

 Additionally, at the bottom of the information file is a line that
 gives information in one of two ways, as follows:

 n lines in line clipboard

 n lines in box clipboard

 This information indicates whether the Clipboard holds a block of text
 or a stream of text.


 68. How to Write Selected Text to a File in M Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-NOV-1988    ArticleIdent: Q35260

 To write a block or stream of text from a file currently being edited
 to another file (either new or currently existing), do the following:

 1. Select text by using Arg (ALT+A) and the cursor movement keys.

 2. Put the text block or stream into the Clipboard by using the
    functions Copy (CTRL+INSERT, or + on the keypad) or Ldelete
    (CTRL+Y) or Sdelete (DELETE).

 3. Load the desired new file (see the "Working with Multiple Files"
    section of the "Microsoft Editor" manual).

 4. Paste (SHIFT+INSERT) the contents of the Clipboard into the new
    file.

 When writing to a file that does not yet exist, another procedure can
 be used, as follows:

 1. Write the selected text to the Clipboard as described above.

 2. Use Setfile to load the <clipboard> pseudofile the same way that
    other files are loaded.

 3. When the Clipboard contents appear on the screen, save the file to
    the desired new filename with Arg Arg textarg Setfile (ALT+A ALT+A
    filename F2). If a file by that name already exists, it will be
    overwritten.

 4. Return to the originally edited file with Setfile (F2).

 The second method can be put into a macro in one of the following two
 ways:

 1. Create a macro definition for copying to a file of prespecified name
    by using, for example, the following:

 sendtofil:=copy arg "<clipboard>" setfile arg arg "foo.txt" setfile
 setfile

 Assign the macro to a keystroke with an argument of the following
 form, for example:

 sendtofil:alt+s.

 This macro can be placed in TOOLS.INI, or can be the textarg in the
 command to enter a macro, as follows:

 Arg textarg Assign (ALT+A textarg ALT+=).

 2. Create a macro definition for copying to a file of any name by
    using two macros in sequence, for example, as follows:

 send1:=copy arg "<clipboard>" setfile arg arg
 send2:=setfile setfile

 Enter and assign them as described above. To execute this set of
 macros, select the text block or stream, execute the first macro, type
 the desired filename, then execute the second macro.


 69. Macro to Print Part or All of a File from within M

 Product Version(s): 1.00  1.02 | 1.00 1.02
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER |
 Last Modified: 21-AUG-1989    ArticleIdent: Q35261

 Microsoft Editor Version 1.00 contains no built-in primitives for
 printing; there is no actual "print" command. However, a set of steps
 can be performed involving the shell function, and a macro can be
 written to execute the steps conveniently. The 1.02 version of the
 Microsoft Editor does contain a print function. For more information
 on Version 1.02's print function, please see Section 4.9, "Printing a
 File," in the "Microsoft Editor User's Guide for MS OS/2 and MS-DOS
 Operating Systems."

 The following is a sample macro for the 1.00 Editor:

    print1:=copy arg "<clipboard>" setfile
    print2:=arg arg "PRINT.TMP" setfile
    print3:=arg "print PRINT.TMP" shell
    print4:=arg "del PRINT.TMP" shell setfile
    print:=print1 print2 print3 print4

 Note: The DOS PRINT command is a resident program. If you shell out of
 M and invoke the PRINT command for the first time, PRINT will be
 loaded above M and you will fragment memory. To prevent this, invoke
 the PRINT command before entering M, so that it will be loaded into
 low memory.

 The following explains the above example:

 1. copy: This copies the currently selected region into the
    clipboard. This way, you can select a region, using a boxarg or
    linearg, and then execute this macro to print it. Because the
    selected region defines what is to be printed, it can be modified
    to suit your needs.

 2. arg "<clipboard>" setfile: This loads the <clipboard> pseudo file
    as the current file.

 3. arg arg "PRINT.TMP" setfile: This saves the contents of the current
    file (which is now <clipboard>) to the file PRINT.TMP.

 4. arg "print PRINT.TMP" shell: This executes a DOS shell that prints
    PRINT.TMP.

 5. arg "del PRINT.TMP" shell setfile: This executes a DOS shell that
    deletes PRINT.TMP, then uses Setfile to return to the original file.


 70. The Difference between M and MEP

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35522

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 The Difference between M and MEP?

 M.EXE is the Microsoft Editor that runs under DOS or MS OS/2 real
 mode. MEP.EXE runs under MS OS/2 protected mode only. You may want to
 rename MEP.EXE to M.EXE. Functionally, the two editors are the same,
 except for slight differences in background compilation.


 71. Reassigning Default Keystrokes for Editor Functions

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35523

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 Reassigning the Default Keystrokes for Editor Functions

 The function can simply be assigned to an unused keystroke, as
 follows:

 Home:Ctrl+H

 Consult your "Microsoft Editor User's Guide" for valid keystroke
 combinations. If necessary, you can unassign a keystroke by assigning
 it to the function Unassigned, as follows:

 Unassigned:Ctrl+Home


 72. Separating TOOLS.INI Entries for M

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35524

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 Making Separate TOOLS.INI Entries for M if You Want to Have Different
 Configurations for M Running Under DOS, OS/2 Real Mode, or OS/2
 Protected Mode, or a Combination of the Three

 Various combinations of tags can be used in TOOLS.INI to set up
 different configurations for different environments. Each environment
 has its own recognized tag. The following is an example:

 Environment:                  Tag:

 MS-DOS                        [M-3.30] (your particular
                                        DOS version)
 OS/2 real mode                [M-10.0R]
 OS/2 protected mode           [M-10.0]

 The following is an examples of combinations:

 MS-DOS and OS/2 real mode     [M-3.30 M-10.0R]
 OS/2 real and protected mode  [M-10.0R M-10.0]

 If you have renamed M.EXE, the "M" used in the tag must be replaced
 with the name you are using for the editor. However, each M-XX.XX
 sub-tag only can appear once in a tag. For example, if you used the
 double tags above, and you were running M in OS/2 real mode, only the
 information from first tag would be loaded.

 By using these tags, only certain sections will be loaded from
 TOOLS.INI to initialize the editor, depending on the environment in
 which the editor is running. The statements in the [M] section are
 always loaded.


 73. Loading a New File into the Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35525

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note is
 available from Microsoft Product Support Services by calling (206)
 454-2030

 Loading a New File into the Editor

 Loading a new file into the editor can be done by using the keystrokes
 corresponding to the following functions:

 Arg textarg Setfile, where textarg is the name of the file you wish to
 load.


 74. Exiting without Saving

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35526

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 How to Exit without Saving

 Normally, when the keystroke for exit is invoked, the file will be
 saved before exiting. However, typing the keystroke for "Meta" before
 the exit keystroke allows you to exit without saving your file.


 75. Merging Two Files Together

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35527

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 How to Merge Two Files Together

 A separate file can be merged into the current file by using the
 keystrokes corresponding to the following functions:

    Arg Arg textarg Paste, where textarg is the name of file to be merged.


 76. Placing Control Characters in Text of File

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35528

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 Placing Control Characters in the Text of My File

 The editor function "Quote" can be used to place special characters in
 your text. Use the keystroke assigned to "Quote", then enter the
 combination of keys necessary to produce the character. For example, a
 Form Feed would be a combination of the CTRL key and the L key.


 77. Compiling the Program Currently Loaded in Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35529

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 How to Compile the Program Currently Loaded in the Editor

 The current file can be compiled by using the keystrokes corresponding
 to the following functions:

    Arg Arg textarg Compile, where textarg is the compiler command
    line typed as you normally would outside of the editor; however,
    the filename does not have to be the current file.

 The text switch "extmake" can be entered in TOOLS.INI to associate a
 frequently used command line with a particular file extension. The
 following is an example:

    extmake:c cl /Zi /Od %s

 The %s will be replaced with the current filename.


 78. Differences between the vscroll and hike Numeric Switches

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35530

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 The Differences between the vscroll and hike Numeric Switches

 The vscroll switch determines how many lines are vertically scrolled
 when the cursor is moved to a location not visible in (outside of) the
 current window but within vscroll lines of the edge of the current
 window.

 The hike switch determines the cursor position when an editing
 function moves the cursor more than vscroll lines beyond the edge of
 the current window. In this case, the cursor would appear hike lines
 from the top of the window.

 Note: Currently, these switches are broken. Even when vscroll is
 correctly set to 1, hike will overide it if hike has a greater value
 than vscroll. Until this problem is corrected, both switches must be
 set to 1 to scroll one line at a time.


 79. Making the Editor Default to Insert Mode

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35531

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 How to Make the Editor Default to Insert Mode

 The boolean switch "Enterinsmode" can be set in the TOOLS.INI file to
 allow the editor to start up in insert mode rather than overtype mode.
 This switch is off by default, but can be set by adding the following
 entry to TOOLS.INI:

    enterinsmode:


 80. Saving Files Under a Different Name

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35532

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 How to Save Your File Under a Different Name

 Saving a file under a different name can be done by including a
 textarg when saving a file without exiting, as follows:

    Arg Arg textarg Setfile, where textarg is the filename you wish to
    save the file under.


 81. "Unable to Open Swapping File c:\temp\m-0029.vm"

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35533

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 "Unable to Open Swapping File c:\temp\m-0029.vm No Such File or
 Directory" Error

 The editor assumes that environment variables are set so that
 important editor information can be loaded from and saved to your
 disk. The following is an example:

    SET INIT=c:\init
    SET TMP=c:\temp

 In this example, c:\temp would be the directory that would hold
 temporary or swapping files, usually named M-0029.VM. This file is
 used to allow the editor to switch to previous files. C:\INIT would
 hold TOOLS.INI and M.TMP. The swapping file also would be stored here
 if the TMP variable was not set. If neither of these variables is
 set, the swapping file would be stored in the root directory and M.TMP
 would be stored in the current directory.

 However, if the TMP variable is set to a directory that does not
 exist, or if extra characters were included after the "p" in "c:\temp"
 such as a space or a semicolon, the swapping file will not be created
 and the error above will be generated.


 82. Why the Editor Cannot Find or Load TOOLS.INI

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35534

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 Why the Editor Can't Find or Load the TOOLS.INI File

 There are several reasons this problem may occur. First of all, you
 may have never created a TOOLS.INI file. If TOOLS.INI is not in the
 working directory, the INIT environment variable must specify the
 directory that contains this file. Within the TOOLS.INI file, there
 must be a tag that has the same name as the editor (M.EXE), as
 follows:

    [m]

 If you have renamed the editor you also must rename the tag. Entries
 concerning the editor then would follow after this tag. Under DOS
 Versions 2.x, the Microsoft Editor looks for a [c] tag rather an [m]
 tag or whatever you have renamed M.EXE to.


 83. Keeping the Editor from Saving Backup Files

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35535

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 How to Keep the Editor from Saving Backup Files

 The text switch "Backup" determines what happens to old copies of
 files that are modified. If you do not wish to keep any backup files,
 a value of "none" can be given, as follows:

    Backup:none

 Backup files can be saved in two ways. A value of "bak" will save the
 previous version of the file with a .BAK extension. A value of "undel"
 will save a history of old copies of your file in a hidden directory
 disk space.

 Older copies can be restored by using UNDEL.EXE. Typing "undel" will
 list all the backup copies; "undel <filename>" will either restore the
 file, or if there is more than one backup, it will allow you to choose
 which version you would like to restore. Because these files take up
 actual disk space, they should be periodically removed from the disk
 by using EXP.EXE. Typing "exp" will delete these files permanently.


 84. How to Write and Use C Extensions

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35536

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 C Extensions and How to Write and Use Them

 C extensions allow you to further customize the editor by creating new
 editor functions and switches through programs that you write in the C
 programming language. They are much more powerful than macros because
 macros depend on the existence of editor functions.

 C extensions are compiled with a special memory-model that does not
 use a main() function, but rather uses special names and structures
 that the editor alone recognizes. They are linked with an object
 module that makes low-level functions used within the editor itself
 available to be called by your C extension. The file produced from
 linking is separate from the main program but is loaded into memory
 with the editor. The editor then will call your module whenever you
 invoke one of your C extension functions.


 85. Developing Macros

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  4-MAY-1989    ArticleIdent: Q35537

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 Develop my Own Macros

 Developing a macro is similar to programming in a high-level language.
 Each macro represents a command. Instead of a collection of library
 routines, you have a collection of editor functions. You begin with an
 idea of a process that you would like to be performed by simply
 pressing one keystroke.

 Suppose you would like to be able to move the cursor to the lower-left
 corner of the editing window. You know you can do this "manually" with
 the arrow keys that are assigned to the "Left" and "Down" editor
 functions. However, it can be simplified more. "Meta Down" moves the
 cursor to the bottom of the window; "Meta Begline" moves the cursor to
 the first column of the line. Together, these functions will do the
 job.

 This macro must now be given a unique name, for example, "Bottom". The
 TOOLS.INI statement would look as follows:

    Bottom:=Meta Begline Meta Down

 A macro also can be a combination of other macros. The following is an
 example:

    Waydown:=Meta Down
    Wayleft:=Meta Begline
    Bottom:=Waydown Wayleft

 Suppose that the "Meta Begline" command did not exist. You would need
 to find some way to know that the cursor is in the first column.
 Almost all of the editor functions have boolean (TRUE/FALSE) Return
 Values that can be useful in developing macros.

 For the "Bottom" macro, you know that "Begline" will at least move the
 cursor to the first nonblank character on the line. Any further cursor
 movement would have to be done using "Left". "Left" returns TRUE when
 the cursor moves and FALSE when the cursor does not move.

 You would want to move left until the cursor does not move anymore,
 i.e., move left until "Left" returns FALSE. The editor allows you to
 do this with Macro Conditionals. The following is an example:

    Bottom:=Begline :>LT Left +>LT Meta Down

    :>LT   defines a label LT
    +>LT   if Left returns TRUE, go to label LT
           if Left returns FALSE, continue

 Macro Conditionals and a table of Return Values can be found in the
 "Microsoft Editor User's Guide."

 The final step is to assign the macro to a keystroke, as follows:

    Bottom:CTRL+END


 86. Saving without Exiting

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote
 Last Modified:  6-JAN-1989    ArticleIdent: Q35538

 The following information is taken from an application note called
 "Microsoft Editor Questions and Answers." The application note also is
 available from Microsoft Product Support Services by calling (206)
 454-2030.

 Saving without Exiting

 You can save a file without exiting by using the keystrokes
 corresponding to the following functions:

    Arg Arg Setfile.

 A macro can be written to perform these functions in one keystroke
 (Alt+S), as follows:

    Save:=Arg Arg Setfile
    Save:Alt+S


 87. None Assignment Must Be Lowercase

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-NOV-1988    ArticleIdent: Q35648

 When using the backup:none option in the TOOLS.INI file, the none
 cannot begin with a capitol N.

 The "None is an illegal setting" error will be generated if you have
 Backup:None (capitol N) in the TOOLS.INI file.

 The correct form is backup:none


 88. Width Function Not implemented

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q35649

 Some graphics cards allow the monitor to go into modes greater than 80
 columns. The Microsoft Editor has a function called Width to allow
 more than 80 columns, however, this function has not yet been
 implemented.

 This feature is under review and will be considered for inclusion in
 a future release.


 89. M on an AMDEK System 88 XT Clone

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 30-SEP-1988    ArticleIdent: Q35817

 Problem:

 When running M on an AMDEK System 88, which is an XT clone, the M
 editor hangs the machine requiring a warm boot. The machine was using
 an EPC Keyboard that is an AT style keyboard.

 Response:

 This is a known incompatibility with this hardware configuration and M
 Version 1.00. AMDEK is aware of this problem and has a patch that they
 can send you. To obtain a patch, call AMDEK at (408) 435-2832. The
 patch contains the following three files:

 READ.ME
 CLREPC.EXE
 SETEPC.EXE.

 The problem is that M was checking the keyboard, which in this case
 was an AT style keyboard, and assuming it was running on an AT clone.
 This situation caused the hang.

 By running SETEPC.EXE, a switch is set so M sees the keyboard as a XT
 keyboard and everything functions properly. CLREPC.EXE clears this
 switch.


 90. Placing the NULL Character in a File with M/MEP

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q35819

 Problem:

 I would like to place the null character in a file using M or MEP. I
 have tried using the Quote function and successfully put other
 non-printable characters in the file, such as the bell character.
 However, attempts to place a null in the file with the Quote function
 were ignored. Is this possible?

 Response:

 No. Placing null characters in a file with M/MEP is not possible. The
 editor uses null-terminated strings internally, as well as NULL return
 values from some character functions. Because the editor uses the null
 character, you are not allowed to use null.


 91. Case Sensitivity of Switches

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 31-OCT-1988    ArticleIdent: Q36415

 The BACKUP text switch is case sensitive with the arguments given it.
 The arguments "undel", "bak", and "none" need to be lowercase, otherwise
 an error will be reported.



 92. Intitialize function is Shift+F8

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  2-NOV-1988    ArticleIdent: Q36567

 There is a documentation error on Page 64 of the "Microsoft Editor for
 MS OS/2 and MS-DOS Operating Systems User's Guide". The line

 3. Invoke the Initialize function (press F10).

 should read as follows :

 3. Invoke the Initialize function (press SHIFT+F8)

 The F10 should be replaced with SHIFT+F8. SHIFT+8 is the default.


 93. Percent (%) Character in Filenames

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 20-OCT-1988    ArticleIdent: Q36570

 The Microsoft Editor cannot handle a percent sign as the first
 character in the filename (%test.dat). While this is a valid DOS
 filename, it will cause garbage to be printed on the status line and
 may generate a run-time error.

 Microsoft has confirmed this to be a problem in Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.

 If you fill a line with 250 characters (the maximum), then press HOME
 to go to the beginning of the line and delete the line by pressing
 CTRL-Y, the editor will crash with the following error:

         run-time error R6003
         -integer divide by 0

 Both of the above problems only occur when a percent sign is used as
 the first character in the filename. To work around this problem, do
 not use the percent sign as the first character.



 94. How Tabs Are Treated in the Microsoft Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 14-OCT-1988    ArticleIdent: Q36580

 Problem:

 Some text editors preserve tab characters automatically. These editors
 maintain tabs (ASCII 9 characters) as they are stored in a file, and
 distinguish between tab characters and spaces.

 The Microsoft Editor translates tab characters into spaces. This
 behavior only affects lines that you modify. If you load and save a
 file without changing any lines of text, the lines are written back to
 disk with all tab characters and spaces intact. Only the modified
 lines are affected by this conversion.

 It is not possible to disable this translation of tab characters into
 spaces in a modified line.

 In the Microsoft Editor, "tab"  is both a function name and the name
 of a key. The TAB key is assigned to the tab function by default. As a
 function, tab is nothing more than a move-to-next-column movement
 function. The placement of columns in determined by the TABSTOPS
 switch.

 When ever you edit a line, tab characters are translated to space
 characters using the FILETAB switch. So modified lines in the file are
 stored in the editor with spaces only. The FILETAB switch determines
 how the editor translates tab characters to spaces when reading in a
 line of text. If ENTAB is set to 1 or 2, then FILETAB also determines
 how the editor translates spaces to tabs when you save the file to
 disk. (Again, only modified lines are affected.)

 If you need to view the tabs as they are situated in your file you can
 use the TABDISP switch to show you which spaces will be compressed
 into a tab character at the next write to the disk file.


 95. 43- and 50-Line Modes

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q36613

 The M editor can make use of the 43-line EGA text mode and 50-line VGA
 text mode. The "height" numeric switch in the TOOLS.INI file specifies
 the number of lines used in the editing window; however, this number
 does NOT include the dialog and status display lines. Thus, to use 43
 lines of text you must set height=41; to use 50 lines you must set
 height=48.


 96. Microsoft System Journal M macros Fail

 Product Version(s): 1.00 1.01 | 1.00 1.01
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 20-OCT-1988    ArticleIdent: Q36798

 In the September 1988 issue of the "MS System Journal," the article
 entitled "Customizing the Features of the M Editor Using Macros and C
 Extensions" contains erroneous examples.

 Both of the macros below fail in Version 1.00. Only the Bigprint macro
 fails in Version 1.01.

 The following is an example:

 Macro 1)

 ;print selected text macro
 print1:= copy arg "<clipboard>" setfile
 print2:= arg arg "TEMP.DAT" setfile setfile
 print3:= arg "PRINT TEMP.DAT" shell
 print4:= arg "DEL TEMP.DAT" shell
 printa:=print1 print2 print3 print4
 Printa:alt+P

 The above macro is supposed to print selected text. In M Version 1.00
 it works correctly the first time it is called from inside a file.
 However, it fails on subsequent calls to the macro prior to exiting
 the file. It does work correctly in the unreleased Version 1.01
 referenced in the article.

 The following macro is supposed to print the entire file. Instead, it
 prints only the line on which the cursor sits when the macro is
 called. As mentioned above, this fails in both Versions 1.00 and the
 unreleased Version 1.01 referred to in the article on Pages 59-72.

 The following is an example:

 Macro 2)

 ;bigprint macro to print entire file
 select1:= arg ppage
 select2:= arg arg "endoffile" mark
 select3:= arg mpage
 select4:= arg "endoffile"
 selectall:= select1 select2 select3 select4
 bigprint:=meta +>nometa cancel selectall meta :>nometa meta printa

 bigprint:Alt+z
 ;end of bigfoot macro.


 97. meta Anomalous Behavior

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 31-OCT-1988    ArticleIdent: Q37072

 The following macros written for the M editor exhibit anomalous
 behavior for the function modifier meta. It appears that meta cannot
 modify itself, as demonstrated by the following macros.

 Microsoft has confirmed this to be a problem in Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.

 Consider the following macros:

    MetaTest:= meta meta +> "meta off"=>0 :>1 "meta on":>0
    MetaTest:alt+0
    ; the above macro is supposed to check to see if the function
    ; modifier meta, invoked by the F9 key, is on or off. Compare
    ; the results of this macro with the macro immediately following.
    MetaTest1:= meta +> "meta off"=>0 :>1 "meta on":>0
    MetaTest1:alt+1
    ; the MetaTest1 macro fails to differ from the MetaTest macro in
    ; a significant manner. in contrast, consider the following
    ; macro, employing the insetmode function modifier.
    InsertTest:=insertmode insertmode +> "ins off"=>0 :>1 "ins on":>0
    InsertTest:alt+2.


 98. MASM m.exe Is Different than FORTRAN m.exe when Using DOS Comp

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | h_fortran
 Last Modified:  6-JAN-1989    ArticleIdent: Q38015

 Question:

 When I do a Comp command at the DOS prompt, why do the FORTRAN Version
 4.10 and MASM Version 5.10 packages contain m.exe files that differ at
 offset 15F9F, where the MASM m gives 37 and the FORTRAN m gives 38?
 Which one should I use for mixed-language programming?

 Response:

 This behavior is an error that was discovered after MASM Version 5.10
 was released, but before FORTRAN Version 4.10 was shipped. You can see
 this by invoking the editor and entering SHIFT+F1, which gives you
 file information. The date given in the MASM file is Jan. 29, 1987
 (hex37) when it should be Jan. 29, 1988 (hex 38). Other than this
 character in the date, they are identical, so you can use either one
 for mixed-language programming.


 99. Selecting Large Text Blocks with Microsoft Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  4-MAY-1989    ArticleIdent: Q38309

 Question:

 When I want to select a large block of code for the clipboard, I press
 ALT+A, then the DOWN ARROW key until I reach the last line I want to
 select. This process is very slow if the block I am selecting is
 several pages long (almost a whole file). Is there a way to move
 faster to select a block than by using the CURSOR key (such as the
 equivalent of ^K-B and ^K-K in Wordstar)?

 Response:

 CTRL+PGDN (Ppara) serves this purpose, as documented on Pages 91 and
 104 of the "Microsoft Editor for MS OS/2 and MS-DOS Operating Systems:
 User's Guide." This key sequence will move you to a new paragraph each
 time you press the keys. If the movement sequence you want to use
 contains an Arg, it is either used by the command or canceled.

 A faster method is to define a couple of macros to help out. First, we
 need a macro that will mark the beginning spot in the text, as
 follows:

    txtmark:=arg arg "first" mark
    txtmark:alt+t

 The second macro automates using the mark as an argument, as follows:

   callmark:=arg "first"
   callmark:alt+u

 You can put these lines in your TOOLS.INI file.

 To use this pair, move to the first spot, press ALT+T, then move up or
 down using any movement keys to the second spot. Finally, press ALT+U
 and press a key that allows a markarg as an argument. (The Copy and
 Ldelete functions are among these.) Note: no highlighting occurs, so
 you'll have to be careful.

 Note: if you want the argument to be entire lines rather than a box,
 the cursor MUST be in the same column when you press ALT+U as it was
 when you pressed ALT+T. If you put it in a different column, you will
 be selecting a box argument rather than a line argument.


 100. Moving to the Beginning of the Line with Microsoft Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  6-JAN-1989    ArticleIdent: Q38310

 Question:

 Is there a way to go to column 1 of the screen with a key sequence
 instead of pressing the LEFT ARROW key until the cursor stops at
 column 1? I find myself wasting a lot of time doing this repetitive
 chore. The HOME key only takes me to the beginning of the text on the
 line, not the beginning of the line, which is where I want to be if I
 want to delete a line, for example. I currently use ^K-S with the
 Wordstar extension.

 Response:

 Meta Begline (F9 HOME in the standard configuration) will do it. If
 you'd like it on one key, you can assign the functions to a key using
 the macro facility.


 101. Inserting a Line from Clipboard into File with Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-MAY-1989    ArticleIdent: Q38311

 Question:

 I am confused by the way a line is inserted from the clipboard into a
 file. It seems to depend on whether Insert is On or Off. Also, it
 sometimes pushes the other lines down and sometimes it pushes the
 existing line to the right. I see no consistency to all this. Can you
 explain the concepts?

 Response:

 The Insert mode has no bearing on line insertion. However, how you
 delete the line has a lot to do with it. In general, don't use the
 DEL key for multiple-character deletions. It is usually assigned to
 the sdelete function, which always deletes a stream of text, as
 documented on Page 107 of the "Microsoft Editor for MS OS/2 and MS-DOS
 Operating Systems: User's Guide."

 A stream is all of the text between the place where the cursor was
 when you typed Arg and where it is when you press sdelete, regardless
 of the beginning and ending cursor columns or how many lines are
 contained in the region. Whenever you mark an area and press sdelete
 (the DEL key), you will delete the STREAM you have marked, even
 though the region highlighted may look different.

 It's usually best to use CTRL+Y (Ldelete) for deletions which begin
 and end on different lines. Note that the COPY key (CTRL+INS) does not
 accept stream arguments, therefore, it always copies the highlighted
 area.


 102. Use a Colon when Assigning a Macro to a Keystroke

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 12-JAN-1989    ArticleIdent: Q39574

 There is a documentation error on Page 50 of the "Microsoft Editor
 User's Guide." Section 6.3.2 incorrectly shows a semicolon when
 assigning a macro to a keystroke as follows:

    Header;ALT+H

 The correct example should contain a colon as follows:

    Header:ALT+H


 103. Quote Function and Typing in Graphic Characters in M

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 16-MAY-1989    ArticleIdent: Q39806

 Question:

 I want to input some graphics characters in the M editor. However,
 when I try to input the ASCII character 31 using the ALT key and the
 numeric keypad, the M editor beeps and displays the following message:

    "ctrl+_ is not assigned to any editor function"

 For the ASCII character 30, the M editor displays the following
 message:

    "ctrl+^ is not assigned to any editor function."

 How can I input those characters?

 Response:

 Use the editing Quote function in the M editor. The Quote function is
 associated with CTRL+P by default. After the Quote function is
 invoked, the following keystroke is taken literally. This function is
 mentioned in the "Microsoft Editor for MS OS/2 and MS-DOS Operating
 Systems User's Guide" on Page 105.

 The first 32 characters in the ASCII character set have two
 conflicting uses. As standard ASCII characters, they are used for
 communications control and printer control. They are also used by IBM
 to represent some useful graphics characters.

 Using the Quote function in the M editor can prevent these ASCII
 characters from being interrupted as control characters.


 104. M Hangs if the textarg Given to ArgCompile Is Incomplete

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 12-JAN-1989    ArticleIdent: Q40235

 If you want to compile a program inside the M editor using the
 following command, textarg should contain the full compile line as
 typed at the DOS prompt:

    Arg Arg textarg ArgCompile

 The following is an example:

    cl /Zi /Od demo.for

 If textarg contains just the name of the program (demo), the hard disk
 light will come on and the message "compilation complete" will appear
 on the bottom of the screen even though demo.for was not compiled.

 If textarg contains the full program name (demo.for), your computer
 hangs if you press SHIFT+F3. Sometimes, there will be lost clusters
 and allocation errors as reported by chkdsk.

 This problem was not encountered under OS/2.



 105. Redirecting Errors to an Error File in M

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-MAY-1989    ArticleIdent: Q40177

 Under DOS, M Version 1.00 will store the error messages in the M.MSG
 file. This file is located in the directory the TMP environment
 variable points to. If TMP is not set, this file is located in
 the current working directory. Under OS/2, MEP uses named pipes, so
 there is no file to look at.


 106. FileWrite() Function Fails to Write Back Out to the File

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-MAY-1989    ArticleIdent: Q40356

 Problem:

 I have a problem using the FileWrite Function programming with the M
 and MEP Editor Version 1.00. I want to read a file (EXAMPLE.DOC) and
 write exactly the same in a new file (FOO.DOC).

 Response:

 To test the example below, you only have to create a file named
 EXAMPLE.DOC. See the compiler switches at the end of this article. The
 second file FOO.DOC is created, but it is never written to it always
 has zero length.

 This is a problem with MEP Version 1.00's FileWrite() function. This
 is one of the problems that kept the filter extension described in the
 "Microsoft Systems Journal" September 1988 from working in Version
 1.00.

 Microsoft has confirmed this to be a problem in Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.

 The following is a short example where the problem (Function FileWrite
 does not write) occurs:

 #include "ext.h"
 #define TRUE    -1
 #define FALSE   0
 #define NULL    ((char *) 0)

 flagType pascal EXTERNAL Write(
 unsigned int argData,
 ARG far * pArg,
 flagType fMeta)
 {
     flagType flg;
     PFILE pFile;
     char  *p = "EXAMPLE.DOC";
     char  *w = "FOO.DOC";

     if((pFile = FileNameToHandle(p,NULL)) == 0)
     {
         pFile = AddFile(p);
         FileRead(p, pFile);
     }
     flg = FileWrite(w, pFile);
     return (flg);
 }

 struct swiDesc  swiTable[] ={
     { NULL, NULL, 0 }
 };

 struct cmdDesc  cmdTable[] ={
     {"Write", Write, 0, NOARG },
     {NULL,  NULL, 0, 0}
 };

 void EXTERNAL WhenLoaded (void)
 {
     SetKey("Write", "alt+w");
     DoMessage("Write function now loaded.");
 }

 /*

 *** Compiler switches I used ***

 cl /c /Gs /Asfu %1.c
 cl /Lp /AC /Fe%1.dll exthdrp.obj %1.obj skel.def

   */


 107. Optimizing C or QuickC 2.00 Required for Writing C Extensions

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_C S_QuickC
 Last Modified: 17-MAY-1989    ArticleIdent: Q39997

 Question:

 I would like to customize the Microsoft Editor by writing C
 extensions. Can I use QuickC Version 1.00, QuickC Version 1.01, or
 QuickC Version 2.00?

 Response:

 No. You must use the Microsoft C Version 4.00 Optimizing Compiler or a
 later version to write C extensions to the Microsoft Editor. QuickC
 Versions 1.00 and 1.01 cannot be used because they do not support the
 required switch /Asfu.

 However, Version 2.00 does support the /Asfu switch when using QCL.
 Therefore, you can use Version 2.00 and QCL to create C extensions.

 For more information, see Pages 68 and 83 of the "Microsoft Editor for
 MS OS/2 and MS-DOS Operating Systems: User's Guide."


 108. Search and Replace Macro for M Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 12-JAN-1989    ArticleIdent: Q39998

 Question:

 Can you write a macro to perform a search and replace on a particular
 string? When I try to do so, the replace function prompts me for a
 string argument. I want the replace function to read the string from
 the macro.

 Response:

 The following is an example of a replace macro that accepts its
 argument from inside the macro:

    myreplace:=replace "oldtext" newline "newtext" newline

 When the myreplace macro is invoked, all the occurrences of "oldtext"
 string, from the cursor position to the end of the file, are replaced
 with the "newtext" string. The use of the newline function allows the
 macro to respond to the replace-function prompt for a string argument.

 To define the myreplace macro and assign it to the F12 key, enter the
 following keystrokes from inside the M editor:

    ALT+A
    MyReplace:=replace "oldtext" newline "newtext" newline
    ALT+=

    ALT+A
    MyReplace:F12

 To execute the myreplace macro, press the F12 key.


 109. M.TMP Reset When Window Closed

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | mep buglist1.00
 Last Modified: 15-MAY-1989    ArticleIdent: Q40681

 Question:

 When I invoke the M editor, open a second window (arg F6 or arg arg
 F6), and close the first window (meta F6), my M.TMP file is reset. The
 only file in my M.TMP file is the one that I edited to perform this
 operation. Is there a way to prevent this from happening?

 Response:

 This phenomena occurs whenever you close a window that has had a file
 opened in it. Hence, if you open a file in the second window, then
 close the second window, M.TMP is reset. To avoid this behavior, don't
 close a window in which a file has been opened.

 Microsoft has confirmed this to be a problem in Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.



 110. QHMEP.DLL Remaps Two Keys in MEP Version 1.00

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 16-MAY-1989    ArticleIdent: Q41324

 Problem:

 I have remapped the keys CTRL+S and CTRL+P in MEP Version 1.00 to the
 psearch and up functions. After loading the extension QHMEP.DLL, which
 comes with the Version 1.06 OS/2 SDK, the two keys CTRL+S and CTRL+P
 are not mapped to psearch and up anymore. Furthermore, these keys
 cannot be reassigned back to psearch and up. I seem to be locked out
 of using these keys.

 Response:

 This problem occurs because the editor is taking over these keys,
 preventing them from being reassigned.

 Microsoft has confirmed this to be a problem in MEP Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.



 111. Useful Macros for the Microsoft Editor

 Product Version(s): 1.00    |  1.00
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 16-MAY-1989    ArticleIdent: Q40755

 Below are macros for the Microsoft Editor that allow you to save a
 marked portion of a file and insert it into another file. Also, there
 are macros that speed up marking large areas of text.

 To save a marked area of a file, mark the area and invoke this macro
 by typing ALT+V. Note that although the macro is broken onto two lines
 here, you should put it on one line in your TOOLS.INI file.

 savemark:=copy arg "command /c del c:\\t" shell arg "\\t" setfile
           refresh paste setfile
 savemark:alt+v

 A one-key way to include the file in another file is to use the macro
 by typing ALT+I:

 insertmark:=arg arg "\\t" paste
 insertmark:alt+i

 To mark the top and bottom of the text area, use these macros. Type
 ALT+T to place the marker, then ALT+U to use it. Type CTRL+INS or
 CTRL+Y to copy or delete the text. Note that if your cursor is not in
 the same column when you type ALT+U as when you typed ALT+T, the area
 marked will be a box rather than a set of lines. Note also that the
 marked area will NOT show up on the screen.

 tempmark:=arg arg "temp" mark
 usemark:=arg "temp"
 tempmark:alt+t
 usemark:alt+u



 112. Using Brief Emulation and Tags in TOOLS.INI

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 17-MAY-1989    ArticleIdent: Q41475

 If you invoke a tagged section from your TOOLS.INI when using the
 Microsoft editor with brief keystroke emulation, some of the key
 assignments will revert back to the default.

 Microsoft has confirmed this to be a problem in Version 1.00. We are
 researching this problem and will post new information as it becomes
 available.

 As demonstrated in the following example, some of the keystrokes are
 reassigned to the default keystrokes if you rename the BRIEF.INI file
 to be TOOLS.INI and then add a new tag section:

 [m-mono]
     height:23
     fgcolor:07
     errcolor:0F
     stacolor:70
     infcolor:70

 Start editing a file, then bring in this new tag field by typing the
 following:

    arg "mono" shift+f10

 The following demonstrates this behavior and all compile lines revert
 to default:

    window             will change from F1 to unassigned
    help               will change from ALT+H to F1
    argcompile         will change from ALT+F10 to F5
    save               will change from ALT+W to undefined
    linemark           will change from ALT+I to undefined
    linetotop          will change from CTRL+T to undefined
    leftsideofwindow   will change from SHIFT+HOME to undefined
    rightsideofwindow  will change from SHIFT+END to undefined
    createhorizwindow  will change from F3 to undefined
    createvertwin      will change from F4 to undefined
    deletewindow       will change from F5 to undefined



 113. Minimum Requirements for Writing a M Extension

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 16-MAY-1989    ArticleIdent: Q42241

 Question:

 What files and software do I need to be able to write an extension for
 the Microsoft Editor?

 Response:

 To create C extensions, you need to have the following files and
 software present in your current directory (or directories listed in
 the PATH or INCLUDE environment variables, as appropriate):

 1. The Microsoft C Optimizing Compiler Version 4.00 or later;
    or Microsoft QuickC Version 2.00

 2. The Microsoft Overlay Linker Version 3.60 or later; or the
    Microsoft Segmented-Executable Linker Version 5.01

 3. EXTHDR.OBJ (supplied with the editor) or EXTHDRP.OBJ (a file
    supplied with the editor for creating protected-mode extensions)

 4. EXT.H header file provided with the editor

 5. SKEL.DEF, the standard definitions file supplied with the editor;
    to be used with all extension

 You need a minimum 150K of available memory for the editor to load a C
 extension at run time in addition to the size of the extension itself.


 114. 43- and 50-Line Modes with the IBM 8514 Monitor

 Product Version(s): 1.00 1.02
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00 fixlist1.02
 Last Modified: 28-JUL-1989    ArticleIdent: Q42365

 The Microsoft Editor does not go into 43- or 50-line line mode on the
 IBM 8514 monitor.

 Version 1.00 of the Microsoft Editor does not support higher line
 modes with the IBM 8514 monitor. Regardless of the switch setting you
 give in the TOOLS.INI file, it always comes up in 25-line mode.

 For example, setting the height:41 or height:48 switch in the
 TOOLS.INI file results in the Microsoft Editor coming up in 25-line
 mode.

 Microsoft has confirmed this to be a problem in Version 1.00 of the
 Microsoft Editor. This problem was corrected in the Microsoft Editor
 Version 1.02.


 115. Savecur and Restcur Save Relative Position in File, on Screen

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS2
 Flags: ENDUSER |
 Last Modified: 17-MAY-1989    ArticleIdent: Q42758

 The Microsoft Editor functions Savecur and Restcur save the current
 cursor position relative to the file and the screen. Therefore, the
 screen will be restored exactly as it appeared when the Savecur
 function was invoked.

 The following macros were intended to scroll the screen up and down
 while leaving the cursor position relative to the terminal screen to
 be stationary:

 ReposDown:=Savecur Meta Up Up Restcur
 ReposDown:Ctrl+Down

 ReposUp:=Savecur Meta Down Down Restcur
 ReposUp:Ctrl+Up

 Because Savecur and Restcur preserve and restore the cursor position
 relative to the screen, the macros appear to do nothing. But actually,
 each executes correctly. For example, the ReposDown does the following:

 1. Savecur : saves the current position relative to the file and the
              screen

 2. Meta Up : moves the cursor to the top of the screen

 3. Up      : moves the cursor up one line, (thus scrolling the screen
              down one line)

 4. Restcur : restores the screen to the original configuration
              (appears as if nothing had happened)

 One way to achieve the desired result is to use the Mark function. The
 Mark function saves the current location in the file. The relative
 screen position is not preserved, whereas the Savecur and Restcur
 functions do save the relative screen position.

 The following macros give the desired result:

 ReposDown:=Arg Arg "tag" Mark Meta Up Up Arg "tag" Mark Up
 ReposDown:Ctrl+Up

 ReposUp:=Arg Arg "tag" Mark Meta Down Down Arg "tag" Mark Down
 ReposUp:Ctrl+Down

 The word "tag" is an arbitrary tagname for the Mark function.


 116. Copy Is a Reserved Word

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 17-MAY-1989    ArticleIdent: Q42763

 The word copy is a reserved word in the Microsoft Editor. If you write
 an M extension and name it "copy", the editor will load but not
 execute your extension.

 If you name the function (for example) cpy rather than copy, it will
 work correctly.

 The following declaration incorrectly uses the reserved word "copy."
 Renaming the the function "cpy" will resolve the problem:

 flagType pascal EXTERNAL copy (argData, Parg, fMeta)
 unsigned int argData;
 ARG far *Parg;
 flagType fMeta;



 117. A C Extension to Select an Arbitrary Number of Lines of Text

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | extension highlight select
 Last Modified:  1-JUN-1989    ArticleIdent: Q43006

 To select an arbitrary number of lines of text in the Microsoft
 Editor, I must use the Arg function, then use the DOWN ARROW key until
 the desired number of lines are selected. This is inconvenient if more
 than a few lines are to be selected.

 This article provides a simple editor extension that selects the
 number of lines you specify.

 For information on loading the function, refer to the M editor
 reference manual.

 To invoke the function, use the Arg key to introduce the argument
 (i.e., the number of lines to be selected), then press the key
 assigned to the function. In Version 1.00 of M, the selected text will
 not be highlighted.   In Version 1.02 of M, the selected text will be
 highlighted, however further cursor movements will change the selected
 area without altering the highlighted area.

 ================ Make file ===============

 BASE=select
 CFLAGS=-c -W2 -Asfu -Gs
 LINKFLAGS=/NOI /NOD

 $(BASE).obj : $(BASE).c
     cl $(CFLAGS) $(BASE).c

 $(BASE).exe : $(BASE).obj
     link exthdr.obj $(BASE), $(BASE), \
     $(LINKFLAGS),clibcer.lib;

 ================ select.c ================

 #include "ext.h"
 #include <stdlib.h>

 #define TRUE    -1
 #define FALSE   0
 #define NULL    ((char *) 0)

 flagType pascal EXTERNAL Select (argData, pArg, fMeta)
 unsigned int argData;
 ARG far * pArg;
 flagType fMeta;
 {
     int  nCount, i ;

     if (pArg->argType == TEXTARG)
         if (nCount = atoi (pArg->arg.textarg.pText))
             {
             for (i = 0 ; i < nCount ; i++)
                 fExecute ("Arg Down") ;
             }

     return TRUE;
 }

 struct swiDesc  swiTable[] =
 {
     {   NULL, NULL, NULL    }
 };

 struct cmdDesc  cmdTable[] =
 {
     {"Select", Select, 0, TEXTARG},
     {NULL,  NULL, NULL, NULL}
 };

 WhenLoaded ()
 {
      SetKey("SELECT","ALT+B");
      return TRUE;
 }


 118. Cannot Use Standard Device Names as Filenames

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 17-MAY-1989    ArticleIdent: Q43074

 You cannot use the standard device names (COMx, LPTx, and CON) as the
 base filename in the Microsoft Editor.

 For example, the command "M COM1.C" under DOS will attempt to open the
 communications port for editing and will hang the computer.

 This information has been tested for the following devices: COM1,
 COM2, LPT1, LPT2, CON. The different devices give slightly different
 results. COM1 and COM2 will hang the computer immediately, but the
 others will give errors or hang when the file is saved.

 The protect-mode editor behaves in the same fashion.


 119. Accessing Predefined Switches in C-Extension

 Product Version(s): 1.02   |  1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | FindSwitch
 Last Modified: 17-MAY-1989    ArticleIdent: Q43436

 When writing a C extension for Microsoft Editor Version 1.02, you can
 access the predefined editor switches through the function
 FindSwitch(). FindSwitch() is intended to be used to access the values
 of the predefined editor switches, not to modify the values. Modifying
 the switches through FindSwitch() has undefined results.

 The following code fragment retrieves the value of the switch
 "tabstops" for use in your C extension:

 #include "ext.h"
       .
       .
       .

 PSWI pTabStops ;
 int  nTabStops ;
       .
       .
       .

 pTabStops = FindSwitch ("tabstops") ;
 nTabStops = *(pTabStops->act.ival) ;

 Any change to the value of the switch "tabstops" made outside your
 C extension will be reflected in the value of nTabStops inside your
 C extension.

 You can find the FindSwitch() prototype in the include file EXT.H. The
 function FindSwitch() is not available in the Microsoft Editor Version
 1.00.

 The structure, swiTable, consists of a series of structures, each
 structure describing a user-defined switch. The purpose of swiTable is
 to add user-defined, not predefined, switches. It is incorrect to name
 the predefined switches in the switch table. For that reason the
 following example is incorrect as it names "tabstops," a predefined
 switch:

 struct swiDesc swiTable [] =
  {
   {"tabstops", &nTabStops, NUMERIC | RADIX10}   /*  INCORRECT  */
   { NULL, NULL, 0}
  } ;

 Do not modify the predefined switches through the switch table. You
 can change the values of the predefined switches from within an
 editing session or in TOOLS.INI.


 120. The Editor Can Be Very Slow When MEP Memory Limit Is Pushed

 Product Version(s): 1.00 1.02
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 17-MAY-1989    ArticleIdent: Q44000

 Problem:

 I have a file FOO, which is 21733 bytes long and contains 850 lines.
 When I perform the following steps the compiler appears to hang. In
 fact, however, the compiler is being forced to go to disk for its own
 memory management.

 When performing the steps described below with the README.DOC from C
 Version 5.10 (which is 64964 bytes) and running on a 16mHz machine,
 after Arg Refresh, it took almost 30 seconds for MEP to return
 control.

 This problem is due to the fact that MEP does its own memory
 management. When you do Arg Refresh, MEP must reread the buffer
 containing the modified file from disk. In addition, MEP must store
 back to disk the buffer containing the last block of text pasted to
 the file. This swapping of two large files is what causes the delay.

 Microsoft has confirmed this lack of speed to be a limitation with
 Version 1.00 and 1.02 of the Microsoft Editor. We are researching this
 problem  and will post new information as it becomes available.

 To duplicate this problem, perform the following steps:

 1. Invoke the following to run the editor:

       [C:\]m foo

 2. Make some changes to modify the buffer.

 3. Issue the following command to the editor:

       arg "bar" setfile

    The editor responds "File c:\bar does not exist, create?"

 4. Respond "y" for yes. You are now in bar's buffer.

 5. Issue the following command to read in the original contents of the
    file:

       arg arg "foo" paste

    This process should work correctly.

 6. If you now want to get rid of the new buffer, issue the following
    command:

       arg refresh

    The editor responds with something similar to the following:

       "Do you really want to delete the buffer?"

 7. Respond "y" for yes.

    The editor appears to hang.


 121. Why Syntax Errors Might Not Display While Compiling in M

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  1-MAY-1989    ArticleIdent: Q43647

 Question:

 While inside the Microsoft Editor, I compiled a program that I know
 contained syntax errors. The message "Compilation Complete - return
 code is x" (where "x" is an integer value) appeared, signifying that
 an error had occurred while compiling.

 I pressed SHIFT+F3 to display those errors and the message "No more
 compilation messages" was displayed on the bottom of the screen. Why
 aren't my program's error messages displayed inside the editor?

 Response:

 You see error messages only if the compiler or linker runs correctly
 and passes the error messages in the correct format to the editor; if
 the compiler itself fails, you will not see any messages.

 Because M spawns the compiler, you could be running out of file
 handles. You know that the system has run out file handles if the
 M.MSG file is not created. Setting files=20 in your CONFIG.SYS file
 should correct the problem.

 Other possible causes for not getting error messages are as follows:

 1. You could be running out of memory. You can check this by shelling
    out of M.EXE (with SHIFT+F9) and issuing the DOS CHKDSK command to
    display the available memory.

 2. The compiler might not be able to find the specified file.
    Consider the following example, in which you invoke M.EXE as
    follows:

       C:\> M c:\c5\source\test.c

    If you compile the program with ARG COMPILE, the information line
    displays the following:

       CL /c /Zep /D LINT_ARGS test.c.

    The compiler will not find TEST.C in the current directory, so an
    error is returned.

    For more information, query on the following phrases:

       Microsoft Editor
       full path

 3. The EXTMAKE switches might have been incorrectly modified in the
    TOOLS.INI file, as in the following example:

       EXTMAKE:bas BC /Zi /O %s

    The line above is incorrect because it is missing a semicolon (;)
    at the end. The command line following the extension must be complete.
    Both the Microsoft BASIC Compiler and MASM will prompt you for
    additional information if a semicolon is not at the end of the line.

 4. Make sure the options used are valid for the compiler. In the
    following example, the option /Fa is an invalid option for the
    QCL.EXE compiler:

       QCL /Fa filename.c

 5. The compiler must be in the current path. If the compiler fails to
    execute, due to some problem external to the editor, M will
    display the ambiguous message "No more compilation messages."

    A good way to check the validity of the Compile command and to check
    for the presence of the compiler is to type in the compile line with
    all of the options directly from DOS.


 122. MEP GP Faults After Consecutive Searches.

 Product Version(s): 1.00
 Operating System:   OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified:  1-JUN-1989    ArticleIdent: Q44887

 MEP gets an access violation and crashes after several searches for a
 string.

 Microsoft has confirmed this to be a problem with MEP.EXE Version
 1.00. This problem was corrected in MEP.EXE Version 1.02.

 Note: Version 1.02 of the Microsoft Editor is only available with
 FORTRAN 5.00. The documentation required for M and MEP Version 1.02
 make it impossible to release except with a major language release.

 The text file that caused MEP to fail was 54400 bytes and contained
 the string "error" in 81 different locations. To reproduce this
 problem, search for the string "error". The default keystrokes are

    Arg "error" F3

 for the first search, and the following for each additional search:

    F3

 On the 81st search, the Microsoft Editor for Protect, generates a
 General Protection Violation.


 123. Status Line Input with a Blinking Cursor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | GETINPUT.ARC S12311.EXE
 Last Modified: 13-SEP-1989    ArticleIdent: Q44925

 Question:

 Is it possible in the Microsoft Editor to write an extension that will
 accept a line of input from the user, preferably from the status line?

 Response:

 Version 1.02 of the Microsoft Editor offers a very convenient way to
 do this. The GetString() callback function performs exactly this type
 of input. Version 1.00 of the Editor, however, does not have such a
 callback. It is possible to put together a routine that reads user
 input using the ReadChar() function in M Version 1.00. However, since
 ReadChar() waits for the next available character, there is no
 convenient way to flash a cursor during input when using this
 approach.

 The function provided below is a status-line input routine that does
 provide a flashing cursor. It uses the KbHook() and KbUnHook()
 functions to prevent the editor from scanning the keyboard and then
 reads the keyboard directly using the kbhit() and getch() functions
 from the C run-time library.

 An example C extension that demonstrates this function is available
 in the Software\Data Library. This file can be found by searching on
 the keyword GETINPUT, the Q number of this article, or S12311.
 GETINPUT was archived using the PKware file-compression utility.

 Status-Line Input Routine
 -------------------------

 #include "ext.h"
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <conio.h>

 #define TRUE            1
 #define FALSE           0

 typedef unsigned        BOOL;

 char *GetInput( int BufLen, char *theBuffer );

 /* GetInput provides a means of getting user input from the status line
  * with a blinking cursor in a manner similar to M 1.02's GetString().
  * KbUnHook is used to capture keyboard input. KbHook restores normal
  * keyboard reading to the editor.
  *
  * Receives:    BufLen - Length of input buffer
  *              theBuffer - Pointer to input buffer
  *
  * Returns:     A pointer to the modified buffer, or NULL if ESC was
  *              used to cancel input.
  */
 char *GetInput(
     int             BufLen,
     char            *theBuffer )
 {
     char            Key;                        /* ASCII code of key */
     int             i = 0;                      /* Position in buffer */
     BOOL            CursorOn = TRUE;            /* State of cursor */
     int             FlashCount = 0;             /* Cursor state counter */
     int             CursorToggleCount = 100;    /* Iterations between changes
                                                    in cursor state */
     char            *r;                         /* Return pointer */

     /* Unhook the keyboard so that the editor no longer intercepts
      * keystrokes.
      */
     KbUnHook();

     /* Get keyboard input from user, stopping when ESC or ENTER is hit.
      * Characters not in the range of 32 to 127 are ignored.  Backspace
      * will work properly.  No more than (BufLen - 2) characters may
      * be entered.
      */
     do
     {
         /* Flash a cursor while waiting for the next keypress.
          */
         while( !kbhit() )
         {
             if( ++FlashCount == CursorToggleCount )
             {
                 FlashCount = 0;
                 CursorOn = !CursorOn;
                 if( CursorOn )
                 {
                     strcat( theBuffer, "_" );
                     DoMessage( theBuffer );
                 }
                 else
                 {
                     theBuffer[i] = '\0';
                     DoMessage( theBuffer );
                 }
             }
         }

         /* Snarf the key
          */
         Key = (char)getch();

         /* Handle backspace.
          */
         if( (Key == 8) && (i > 0) )
         {
             theBuffer[--i] = '\0';
             DoMessage( theBuffer );
         }

         /* Handle normal character.
          */
         if( (Key >=32) && (Key <= 127) && (i < BufLen - 2) )
         {
             theBuffer[i++] = Key;
             theBuffer[i] = '\0';
             DoMessage( theBuffer );
         }
     } while( (Key != 13) && (Key != 27) );

     /* If ESC was pressed, toss the input and NULL the input buffer,
      * else perform a little cleanup.
      */
     if( Key == 27 )
     {
         theBuffer[0] = '\0';
         DoMessage( theBuffer );
         r = NULL;
     }
     else
     {
         if( CursorOn )
             theBuffer[i] = '\0';
         DoMessage( theBuffer );
         r = theBuffer;
     }

     /* Restore normal keyboard input.
      */
     KbHook();

     return( r );
 }


 124. CALLTREE Produces No Warnings When Out of Disk Space

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_C H_MASM H_Fortran S_PasCal
 Last Modified: 23-JUN-1989    ArticleIdent: Q45618

 The CALLTREE.EXE utility shipped with the Microsoft Editor (included
 with MASM, Optimizing C, FORTRAN, and Pascal) does not produce a
 warning if it runs out of disk space while writing output files. It
 simply closes the file being currently written and attempts to produce
 the next file. If the disk has no space free, the file will be created
 and closed with a length of 0 (zero) bytes. No error messages are
 produced in any case.

 Microsoft is aware of this limitation of CallTree. The error checking
 and messages features are under review and will be considered for
 inclusion in a future release.


 125. Documentation Errors in "Configuring On-Line Help" for M 1.02

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 11-SEP-1989    ArticleIdent: Q46272

 There are several documentation errors in the section "Configuring
 On-Line Help" on Page 101 of the "Microsoft Editor User's Guide for MS
 OS/2 and MS-DOS Operating Systems." This is the documentation for the
 Microsoft Editor (M) Version 1.02, which first became available with
 FORTRAN Version 5.00. These errors prevent access to M help. The
 documentation says to add the following tagged section to your
 TOOLS.INI file:

    [m-help.mxt mep-help.mxt]
    helpfiles:path\file.hlp

 The tag header should be as follows:

    [m-help mep-mhelp]

 Including ".mxt" prevents M from accessing help.

 Also, in the paragraph labeled Number 2 that describes installation
 for on-line Help when running under OS/2 protected mode only, there is
 a misprint. The following sentence refers to a nonexistent file
 "MHELP.DLL":

    MHELP.DLL is an extension to the editor.

 The correct file is MHELP.PXT, so the sentence should read as follows:

    MHELP.PXT is an extension to the editor.


 126. CMD.EXE Shell Fails with Incorrect COMSPEC

 Product Version(s): 1.00 1.02
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified: 26-SEP-1989    ArticleIdent: Q47763

 Question:

 When I attempt to shell out of the MEP editor environment via the
 Shell editor function (SHIFT+F9), why does the following message
 appear at the bottom of the screen?

    Spawn failed on C:\OS2\CMD.EXE   - No such file or directory

 Response:

 The problem is usually due to an incorrect setting of the COMSPEC
 environment variable in the CONFIG.SYS file. A faulty setting of this
 variable, which informs the operating system of the command
 interpreter's location, prevents the DOS EXEC system call from finding
 and executing the command interpreter. Use the following procedure to
 eliminate the problem:

 1. Verify that the CMD.EXE file is in the directory specified by the
    COMSPEC environment variable.

 2. Ensure the syntax correctness of the COMSPEC setting. There should
    be no spaces on either side of the equal sign, and a carriage
    return must appear immediately following the last character of the
    path and filename setting.

        Correct example:       SET COMSPEC=C:\OS2\CMD.EXE<cr>

        Incorrect examples:    SET COMSPEC = C:\OS2\CMD.EXE<cr>
                               SET COMSPEC=C:\OS2\CMD.EXE;<cr>
                               SET COMSPEC=C:\OS2\CMD.EXE<space><cr>

 Under MEP 1.02, the COMSPEC environment variable is used to locate the
 command interpreter. If the command interpreter is not found according
 to the COMSPEC variable, the "Spawn failed...." error message is
 displayed. MEP Version 1.02 does not use the PATH environment variable
 for additional searching of CMD.EXE.

 Under MEP Version 1.00, however, the PATH variable is used when the
 CMD.EXE is not found via the COMSPEC setting. Hence, if the spawn
 failure error occurs when attempting to shell out of the MEP 1.00
 environment, examine the COMSPEC setting and also verify that CMD.EXE
 is traversed by the search path of the PATH environment variable in
 the CONFIG.SYS.


 127. Curtime Function Pulls In Time Editor Was Invoked

 Product Version(s): 1.00 | 1.00
 Operating System:   OS/2 | MS-DOS
 Flags: ENDUSER | buglist1.00 fixlist1.02
 Last Modified: 28-JUL-1989    ArticleIdent: Q46790

 The Microsoft Editor Version 1.00 does not implement the Curtime
 function correctly. The manual states that the current time will be
 inserted at the cursor when this function is invoked. Actually, the
 time the editor was invoked is inserted at the cursor. To get around
 this problem, simply initialize the editor before calling the Curtime
 function.

 Microsoft has confirmed this to be a problem in Version 1.00. This
 problem was corrected in Version 1.02 of the Microsoft Editor.

 The following macro illustrates how the Curtime function is invoked.
 This macro should be placed in the TOOLS.INI file under the [m] tag.

    time:=Curtime
    time:ALT+T

 When editing a file, pressing ALT+T inserts the time that the editor
 was loaded at the cursor. To obtain the current system time, either
 invoke the Initialize function by pressing SHIFT+F8 before ALT+T, or
 change the macro as follows:

    time:=Initialize Curtime
    time:ALT+T

 Now, pressing ALT+T inserts the current system time at the cursor.

 This function is documented on Pages 30 and 96 of the "Microsoft
 Editor User's Guide," which is contained in the "CodeView and
 Utilities, Microsoft Editor, Mixed-Language Programming Guide" manual
 from the Microsoft C Optimizing Compiler Version 5.10.


 128. QUICK.INI Needs Modification for Use with M 1.02 or MEP 1.02

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 28-JUL-1989    ArticleIdent: Q46802

 To use the QUICK.INI file provided with the Microsoft M Editor Version
 1.02 as the TOOLS.INI file, it is necessary to make two modifications
 to the file. Without the modifications the editor gives the following
 error messages:

    Argcompile is not an editor function               press any key...
    Help is not an editor function                     press any key...

 To get past the Argcompile error message, add the following line to
 the TOOLS.INI file before the Argcompile:F5 line:

    Argcompile:=arg compile

 The Argcompile macro is also defined in the TOOLS.PRE file provided
 with the editor. The Help:F1 line is a leftover from previous versions
 of the editor and is not implemented in this version. To eliminate the
 Help error message, either delete or comment out the Help:F1 line.


 129. Documentation Error for "Mark" Functions in M User's Guide

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  2-AUG-1989    ArticleIdent: Q47236

 On Page 179 of the Version 1.02 "Microsoft Editor for MS OS/2 and
 MS-DOS Operating Systems: User's Guide," there is a documentation
 error. In the section of the reference table describing the "Mark"
 function, the marker deletion and marker definition descriptions are
 reversed. To define a marker at the cursor position, the correct
 syntax is Arg Arg textarg Mark. To delete a marker definition, the
 syntax is Arg Arg textarg Meta Mark. The entries SHOULD appear as
 follows:

    Entry                         Function
    -----                         --------

    Arg Arg textarg Mark          Defines a file marker at the
                                  initial cursor position. This
                                  does not record the file marker
                                  in the file specified by the
                                  markfile switch, but allows you
                                  to refer to this position as
                                  textarg.

    Arg Arg textarg Meta Mark     Deletes a marker definition.

 On Page 39, the reference to Arg Arg textarg Mark is correct.


 130. CopyBox Function Doesn't Work Across Files

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | S_C S_Pascal H_Fortran H_MASM
 Last Modified: 26-SEP-1989    ArticleIdent: Q47765

 CopyBox is a C-extension function for the Microsoft editor that is
 designed to copy square regions of text from one location to another,
 including to another file.

 This function works properly when copying to the same file, but fails
 when copying to another file. The function appears to work
 successfully, but the copied text does not appear in the target file.
 This lack of functionality has been corrected in Version 1.02 of the
 editor.

 You can work around this problem by using the GetLine and PutLine
 functions. A line can be read from the source file, trimmed to get the
 proper portion of the line, and then written to the target file. This
 procedure must be followed for each line of the box to copy.


 131. Getting SYS2070 While Using MEP

 Product Version(s): 1.02
 Operating System:   OS/2
 Flags: ENDUSER | MEP
 Last Modified: 26-SEP-1989    ArticleIdent: Q47767

 Problem:

 When I start MEP, I receive the following error:

      |---------------------------------------------------------------|
      | SYS2070: The system could not demand load the                 |
      | application's segment. MSHELP HELPGETINFO is in error.        |
      | For additional detailed information also see message SYS0127. |
      |---------------------------------------------------------------|
      |                     End the program                           |
      |_______________________________________________________________|

 After selecting "End the program," I receive the following message:

    A non-recoverable error occurred.
    The process ended.

 Response:

 The MEP program is picking up an old version of MSHELP.DLL. The likely
 source is from the OS/2 Presentation Manager Toolkit. To correct this
 problem, replace the old MSHELP.DLL with the current MSHELP.DLL.

 If there is no MSHELP.DLL on the LIB path, then MEP loads and seems to
 function correctly, but there will be no help available.


 132. Possible Explanation for "Cannot Close This Window" Error

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 26-SEP-1989    ArticleIdent: Q47770

 Problem:

 Under M Version 1.00 I have two horizontal windows open, each viewing
 separate files. When I attempt to close a window (META+WINDOW or F9+F6),
 I sometimes get the error message "Cannot close this window." Under
 seemingly similar conditions, this error message does not occur and
 the window closes properly.

 Response:

 This message occurs when you attempt to close a window that contains
 modified text. If you want to abandon edits on the file, you can
 reread the file using SHIFT+F7 and then successfully close the window.


 133. ECH.EXE Utility Is Used Internally by the Microsoft Editor

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 26-SEP-1989    ArticleIdent: Q47772

 ECH.EXE is a character echoing utility that is included with the
 Microsoft Editor (M) Version 1.00. This utility is mentioned in the
 appendix of the editor's user guide simply because it is an external
 file.

 The file is used with the Setfile command using wildcards. When
 issuing the command "Arg *.* Setfile", M will use ECH.EXE to display
 the files in alphabetical order. If ECH.EXE is not found in the
 current path, the message "NO MATCHING FILES" is generated.

 If this error message occurs in a subdirectory that does contain
 files, then ECH.EXE is not being found.

 M 1.02 does not use this external file. The utility has been
 incorporated into the editor.


 134. Invoking M or MEP with the /D Switch Prevents Initialization

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | reinitialize
 Last Modified: 26-SEP-1989    ArticleIdent: Q48687

 Invoking the Microsoft M editor with the /D switch to prevent it from
 initializing from the TOOLS.INI file also prevents the Initialization
 function (SHIFT+F8) from reading the TOOLS.INI file.

 There is currently no workaround for this designed limitation other
 than to exit the editor and re-invoke M without using the /D switch.


 135. Microsoft Editor (M) Version 1.02: On-Line Help Not Loaded

 Product Version(s): 1.02
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 26-SEP-1989    ArticleIdent: Q48130

 Trying to access on-line help after initializing (reloading the editor
 settings from TOOLS.INI) generates the following message:

    Online Help Not Loaded

 The following steps will demonstrate the problem:

 1. M (Start the editor, with or without a file.)

 2. F1 (Request on-line help -- success.)

 3. SHIFT+F8 (Initialize editor settings.)

 4. F1 (Request on-line help -- receive error message.)

 Microsoft is researching this problem and will post new information
 as it becomes available.


 136. Invalid Arg Filename Followed By F2 Causes Screen Error

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.00
 Last Modified: 26-SEP-1989    ArticleIdent: Q48871

 When trying to read in a file with the Arg Setfile function, an
 improper filename returns an operating system error. If the Microsoft
 editor (M) is in split-screen mode, any horizontal divider bars are
 lost in MEP. The error contains the two following lines, which cause
 the screen to scroll one position erroneously:

    Next filSYS1041: The name specified is not recognized as an
    internal or external command, operable program, or batch file.

 In M, screen integrity is preserved, but the following error is
 returned:

    Bad command or filename.

 For example, invoke arg (ALT+A) to start an argument and enter about
 20 or so shifted numbers (e.g. ^&%$&^%$^%$#^%$#^%$@%(^&*(*^&&*), and
 then invoke Setfile (F2).

 The screen becomes corrupted and the next keystroke may crash the
 editor with an integer divide by 0 (zero).

 Microsoft has confirmed this to be a problem with the Microsoft Editor
 Version 1.00. We are researching this problem and will post new
 information as it becomes available.


 137. How to Search and Replace Control Characters with M Editor

 Product Version(s): 1.00 1.01 1.02 | 1.00 1.01 1.02
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified: 10-OCT-1989    ArticleIdent: Q49010

 To search for and replace control characters with the M editor, use
 the following procedure:

 1. Invoke the search and replace function (CTRL+\).

    The editor prompts with "Query Search String:".

 2. Invoke the quote function (CTRL+P).

 3. Type the control character and press ENTER.

    The editor prompts with "Replace string:".

 4. Invoke the quote function.

 5. Type the control character.


 138. Background Color Greater Than Seven Causes Region to Blink

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 26-FEB-1990    ArticleIdent: Q57585

 It is possible to configure both the background and foreground color
 of the various text items that the Microsoft Editor (M) displays. If
 you attempt to set the background color to a color greater than seven,
 the color region blinks. This behavior, however unusual, is expected,
 and is documented in the "Microsoft Editor for MS OS/2 and MS-DOS
 User's Guide" on Page 87.

 The following M Editor color switches control the colors of various
 text display regions:

    Switch        Controls
    ------        --------

    hgcolor       Background and text color
    hgcolor       Search highlight colors
    infocolor     Information message colors
    selcolor      Cursor highlight colors
    stacolor      Status line colors
    wdcolor       Window border colors

 The following are the colors these switches can be set to:

    Black                 0
    Blue                  1
    Green                 2
    Cyan                  3
    Red                   4
    Magenta               5
    Brown                 6
    Light Gray            7
    Dark Gray             8   Will blink when set to background
    Light Blue            9   Will blink when set to background
    Light Green           A   Will blink when set to background
    Light Cyan            B   Will blink when set to background
    Light Red             C   Will blink when set to background
    Light Magenta         D   Will blink when set to background
    Light Yellow          E   Will blink when set to background
    White                 F   Will blink when set to background

 These colors are set in your TOOLS.INI as follows:

                +------------------- Background Color
                |
                v

    colorswitch:BF <---------------- Foreground Color

 The following example, inserted in your TOOLS.INI, sets the foreground
 and background colors of the editing windows (90 percent of the
 screen):

    fgcolor:62 < ------------------- Green

            ^
            |
            +----------------------- Brown


 139. M Editor Version 1.00 Does Not Clear Compiler Error Buffer

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER  | buglist1.00 fixlist1.02
 Last Modified: 11-OCT-1989    ArticleIdent: Q49536

 When using the compile function from within the editor, the errors
 stored in memory are not cleared. Thus, if you do not go through all
 errors with the nextmsg function, the errors remain even if another
 compile is done. Therefore, if the second compile process does not
 produce any errors, the errors from the previous compile show up and
 put the cursor on an unpredictable line.

 To work around this problem, make sure you look at all of your error
 messages from each compile.

 Microsoft has confirmed this to be a problem with the Microsoft Editor
 Version 1.00. This problem was corrected in Version 1.02 of the
 Editor.


 140. Configuring On-Line Help for M 1.02

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q49576

 The following is the correct way to configure on-line help for the
 Microsoft Editor (M) Version 1.02 for both MS-DOS (real mode) and
 OS/2 (protected mode).

 Copy files from the distribution disk, as follows:

 1. Under MS-DOS real mode, copy M.HLP and MHELP.MXT to any directory
    specified in the PATH environment variable in the AUTOEXEC.BAT
    file.

 2. Under OS/2 protected mode, copy M.HLP and MHELP.PXT to any
    directory specified in the PATH environment variable in the
    STARTUP.CMD file. Also copy MSHELP.DLL to any directory listed in
    the LIBPATH variable in the CONFIG.SYS file.

 3. For both DOS and OS/2, perform both the preceding steps.

 Other Microsoft products include .HLP files that the editor can
 read. If you want to add additional .HLP files to help, you must
 include the following tagged section in your TOOLS.INI:

 1. Include the following tagged section:

       [M-MHELP]                    ; For DOS real mode

       [MEP-MHELP]                  ; For OS/2 protected mode

       [M-MHELP MEP-MHELP]          ; For both DOS and OS/2

 2. Add the following switch to load in the help files:

       Helpfiles: M.HLP .BAS:C:\QB\QB.HLP .C.H:C:\QC\QC.HLP .PAS:C:\QP\QP.HLP

    This is an example of help files that are loaded upon startup of M
    or MEP. Help searches QB.HLP first when the file has a .BAS
    extension, QC.HLP when the current file has a .C or .H extension,
    and QP.HLP when the current file has a .PAS extension. Please note
    that these help files come with their respective language, not M
    1.02.

 For more information on this topic, refer to the Microsoft Editor for
 MS OS/2 and MS-DOS Operating Systems: User's Guide" that accompanies
 with M 1.02.


 141. Undocumented Switch "Sethelp" for M Version 1.02

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 24-JAN-1991    ArticleIdent: Q50012

 If you have the M (or MEP) Editor version 1.02 configured for online
 help, you can use the undocumented "Sethelp" switch to load additional
 help files within the editor by using the following syntax:

    Arg textarg Sethelp      ;ALT+A textarg ALT+S

 Textarg corresponds to the full pathname of the .HLP file you want to
 load. By default, the sethelp function is mapped ALT+S.

 For example, load the QC.HLP help file that comes with QuickC with the
 following command:

    ALT+A D:\QC\QC.HLP ALT+S

 Now you could place the cursor on printf (or any other C language item
 that is in the Help file) and press F1 to get help on that topic.


 142. Printing Double Quotation Marks from within an M Editor Macro

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q50223

 To get double quotation marks ("") printed from within a macro in the
 M Editor, use the backslash key (\) followed by the double quotation
 marks (""). The following example (placed in the correct section of
 the TOOLS.INI file) demonstrates how this is done:

    text:=arg "say \"hello\"" paste
    text:alt+z

 In this case, pressing ALT+Z inserts the following string into your
 text, with the double quotation marks around the word hello.

    say "hello"


 143. Controlling the Use of Tabs in the Microsoft Editor

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q50588

 The Microsoft Editor (M) provides the following two ways of using tab
 characters:

 1. Treat tabs as real characters.

 2. Convert each tab into a series of spaces. This is controlled
 through the use of the "realtabs" switch. Other switches may also
 effect the way tabs appear to be handled by the editor.

 The following chart, taken from Section 7.2.6 of "Microsoft Editor for
 MS OS/2 and MS-DOS User's Guide" describes the switches dealing with
 tabs.

 1. realtabs

    On by default, controls whether or not tabs are treated as real tab
    characters.

 2. entab

    Controls the extent to which the editor converts a series of tabs
    and spaces to tabs when saving a file. The following are the valid
    choices:

       0 - The editor does not replace spaces by tabs. If realtabs is off,
           tabs are converted to spaces.

       1 - (default) The editor can replace a series of tabs and spaces by
           tabs when the tabs fall outside of quoted strings.

       2 - The editor will replace all series of tabs and spaces with
           tabs.

    Note: The entab switch only effects the lines you modify during the
    current editing session.

 3. filetab

    Controls the meaning of tab characters on a disk file. If realtabs
    is on, the filetab switch determines tab alignment. If realtabs is
    off, the filetab switch determines how the editor translates tab
    characters to spaces when a line of text is modified.

    If entab, as described above, is set to 1 or 2, filetab also
    determines how the editor translates spaces to tabs when you save
    the file to disk.

    Note: The filetab switch only effects the lines you modify during
    the current editing session.

 4. tabalign

    When off (the default), the cursor may be placed anywhere inside a
    column of a tab character. If turned on, along with realtabs, the
    cursor is placed to the first column position of tab characters.

 5. tabstops

    Determines the size of columns associated with the TAB and BACKTAB
    ( SHIFT+TAB) keys. This only moves the cursor and has no effect on
    the actual tab character. The default value is 4.

    The following example sets up tabs so that they act the same way
    they do in other editors, such as QuickC or Word:

       realtabs:yes
       tabalign:yes
       graphic:tab
       trailspace:yes
       filetab:4

 The trailspace switch is needed to use tabs on blank lines. The
 tabdisp switch may also be used with realtabs to make the tab
 characters visible on the screen.


 144. Mhelp Function Is Always Assigned to SHIFT+F1

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 17-JUL-1990    ArticleIdent: Q50642

 In the Microsoft Editor (M) Version 1.02, the mhelp function is like
 any other function that can be assigned to any key. However, mhelp is
 always assigned to SHIFT+F1 unless this key is unassigned using the
 unassigned keyword in the m-mhelp block of the TOOLS.INI file.

 It is perfectly acceptable to assign the mhelp to any key, and it will
 work properly with that keystroke. However, in addition to the newly
 assigned key, the mhelp function is always assigned to SHIFT+F1. This
 assignment can be taken out by placing the following line in the
 [M-MHELP] section of the TOOLS.INI file:

    [M-MHELP]
    unassigned:shift+f1


 145. Adding helpwindow in TOOLS.INI as a Switch

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q50644

 To get the Microsoft Editor (M) to recognize helpwindow as a switch in
 the TOOLS.INI file, the switch must be under the [M-MHELP] or
 [MEP-MHELP] tag section. The example below shows what a TOOLS.INI file
 might look like:

    [M-MHELP MEP-MHELP]
    nohelpwindow:

    [M MEP]
      .
      .

 The helpwindow switch can also be set in the environment by typing the
 following:

    <arg> nohelpwindow: <assign>


 146. Searching in the M Editor with Regular Expressions

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 30-NOV-1989    ArticleIdent: Q51324

 Question:

 When using the M Editor, every time I execute a search command using a
 Regular Expression, the editor takes the command literally and doesn't
 recognize the textarg as a Regular Expression. How can I get this
 search to work?

 Response:

 The correct method is as follows:

       arg arg textarg <search_function>

               arg -> ALT+A
           textarg -> A Regular Expression (i.e., ^S[te].*end)
 <search_function> -> Psearch, Msearch, Replace, Qreplace

 For more information, see Chapter 5, Pages 51-63, in the "Microsoft
 FORTRAN Microsoft Editor User's Guide."


 147. mgreplist Incorrectly Documented As megreplist in Example

 Product Version(s): 1.02
 Operating System:   MS-DOS
 Flags: ENDUSER | docerr
 Last Modified: 15-MAR-1990    ArticleIdent: Q51622

 The examples given on Pages 180 and 181 of the FORTRAN "Microsoft
 Editor User's Guide" incorrectly identifies the megreplist command as
 mgreplist. The documentation shows the following:

    megreplist:="DATA.FIL *.FOR $INCLUDE:*.H"

 This should be the following:

    mgreplist:="DATA.FIL *.FOR $INCLUDE:*.H"

 The megreplist macro does not exist and should be changed to
 mgreplist.

 The example above sets mgreplist to a series of files to be searched
 when Mgrep is called. If the textarg string (specified as an argument
 to Mgrep) is found in any of these files, the instance will be
 reported in the pseudo file <compile>. All succeeding calls to Mgrep
 will reset this file.

 The following are the files that are searched in the above example:

 1. DATA.FIL.

 2. Any file in the current directory with a .FOR extension.

 3. Any file along the INCLUDE environment variable path with a .H
    extension.


 148. C Extensions: Link Errors on __acrtused and _main Explained

 Product Version(s): 1.00    | 1.02
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER |
 Last Modified: 21-DEC-1989    ArticleIdent: Q51636
 Question :

 I am writing a C extension for the Microsoft Editor (M). When I link,
 I get the following error message:

    c:\usr\lib\CLIBCE.LIB(dos\crt0.asm)
            error  L2044:  __acrtused
            symbol multiply defined, use /NOE  pos
            1CC Record type: 53E4

    LINK : error L2029: Unresolved externals:
    _main in file(s):  c:\usr\lib\CLIBCE.LIB(dos\crt0.asm)
    Two errors were detected.

 I am compiling and linking as follows:

    cl /c /Gs /Asfu c_extension.c
    link /NOI /NOE exthdr.obj c_extension.obj, c_extension;

 These options seem to be correct according to the Editor manuals. Why
 am I getting these linker errors?

 Response:

 The linker gives these error messages if you are linking with a
 run-time function that must be initialized from the C start-up source
 code. This start-up source code is not used within a C extension.

 The art of writing C extensions for M Version 1.00 is documented in
 Chapter 8 of the Editor section of the "CodeView and Utilities,
 Microsoft Editor, Mixed-Language Programming Guide," which is included
 with C 5.00, C 5.10, Pascal 4.00, FORTRAN 4.10, and MASM 5.10.
 References to M Version 1.02 extensions are discussed in Chapter 8 of
 the "Microsoft Editor User's Guide," which came with FORTRAN 5.00.

 Please contact Microsoft Product Support Services at (800) 454-2030 to
 obtain an application note that discusses further techniques of writing C
 extensions for the Microsoft Editor.


 149. U1013 Link: Error 2: Not Enough Memory for Exec in M

 Product Version(s): 1.00 1.02
 Operating System:   MS-DOS
 Flags: ENDUSER | s_nmake s_make
 Last Modified: 23-JAN-1991    ArticleIdent: Q57653

 Question:

 In DOS, I am spawning either MAKE or NMAKE within the Microsoft Editor
 (M), and I receive an error message from the Editor on the status line
 saying "U1013 : Link file.obj: Error 2." What does this error mean and
 how do I get around it?

 Response:

 The U1013 error means that one of the procedures called by MAKE or
 NMAKE returned a nonzero error code. In this case, the error can be
 understood as M's equivalent of a "Not enough memory for exec" error,
 meaning that there is not enough memory for the parent process to
 execute a child process. The error typically occurs when you spawn
 either MAKE or NMAKE from within the Editor, the compilation is
 complete, and the link process is beginning.

 If you receive this error, you may be able to free up memory by
 removing any TSRs and unnecessary device drivers. However, the best
 workaround would be to use MAKE or NMAKE to link your file outside of
 M, because M will have problems exec'ing the linker in any sizable
 application due to the size of LINK and MAKE.


 150. Mgrep Can Skip Occurrences of Pattern When Using Mgreplist

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.02
 Last Modified: 16-JAN-1990    ArticleIdent: Q57705

 "Mgrep" may find every other occurrence of a search string when used
 to search a list of input files defined my the "mgreplist" macro.

 Mgrep searches all files defined by the mgreplist macro, then writes
 the location of a match to the <compile> pseudo file. When using
 either regular expression search patterns or standard search strings,
 mgrep may post every other occurrence of the matched string to the
 <compile> pseudo file. This also causes SHIFT+F3 to display every
 other match in the file being searched.

 To see the problem, set the mgreplist:="test.dat" where TEST.DAT
 contains the following:

    #include1
    #include2
    #include3
    #include4
    #include5
    #include6
    #include7
    #include8
    #include9
    #include10
    #include11
    #include12

 Invoke the mgrep search on the string "include" and then press
 SHIFT+F3 to view the next match. You will see that only every other
 occurrence of "include" is found. Also, if you view the <compile>
 pseudo file it will only contain a list every other occurrence of
 "include".


 151. M "Keyboard" Switch Doesn't Work As Documented

 Product Version(s): 1.02
 Operating System:   MS-DOS
 Flags: ENDUSER | S_FORTRAN buglist1.02
 Last Modified: 20-JAN-1990    ArticleIdent: Q57750

 The Microsoft Editor (M) Version 1.02 "keyboard" switch, documented on
 Page 198 of the the "Microsoft Editor User's Guide for MS OS/2 and
 MS-DOS Operating Systems," does not work as documented.

 The switch was implemented to allow control of which BIOS keyboard
 calls are used to get keystrokes. The "compatible" setting uses the
 standard INT 16H, AH = 0 to get keystrokes. The "enhanced" setting
 uses INT 10H, allowing the F11 and F12 keys to be read, and allowing
 you to use old versions of packages that may fail when your keyboard
 is treated as enhanced.

 If you set the "keyboard" option in your TOOLS.INI file by adding a
 line reading

    keyboard:"compatible"

 and then bring up the editor, M accepts the setting, but fails to set
 correctly. If you press SHIFT+F1 for help and choose Current
 Assignments, the list of current key assignments is given. The
 keyboard switch will now be set to the following:

    keyboard::enhanced

 Note the double colon, and that the compatible option has been
 changed to enhanced.

 If you try to set the option within the editor by entering the
 following, the editor returns the same options as above:

    ALT+A keyboard:compatible ALT+=

 Microsoft has confirmed this to be a problem in the Microsoft Editor
 Version 1.02. We are researching this problem and will post new
 information here as it becomes available.


 152. Incorrect Message from "searchall" with Regular Expressions

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | M MEP buglist1.02
 Last Modified: 23-JAN-1990    ArticleIdent: Q57932

 The Microsoft Editor searchall function (that is, SHIFT+F6) may return
 the following invalid error message when using regular expressions:

    +'pattern' not found

 'pattern' is the actual regular expression for which the search was
 requested.

 In this situation, searchall still finds all occurrences of the search
 pattern correctly -- only the message is incorrect.


 153. Version 1.02 of M and MEP Incorrectly Reports Version As 1.2

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 26-FEB-1990    ArticleIdent: Q58687

 If you access help for the Microsoft Editor (M/MEP) Version 1.02, the
 version is incorrectly displayed as 1.2, rather than 1.02. This
 incorrect version number appears in both the internal online help and
 when invoking help from the command line with the /? switch.

 The following information is incorrectly displayed when using the /?
 command-line switch for help:

    Microsoft (R) Editor Version 1.2
    Copyright (C) Microsoft Corp 1987-1989. All rights reserved
    Usage: [/D] [/e cmd-string] [/m mark] [/r] [[/t] filename]*


 154. Quote Function (CTRL+P) Can Fail to Work Properly

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.00 buglist1.02
 Last Modified: 26-FEB-1990    ArticleIdent: Q58720

 The Quote function (CTRL+P) in conjunction with CTRL+I or CTRL+T fails
 to display the valid character associated with that key sequence. For
 CTRL+P with CTRL+I, a space character (Hex 20) results instead of the
 correct foreground color rectangle with a background color dot (hex
 09). For CTRL+P with CTRL+T, a lowercase "a" with an accent mark (hex
 A0) results instead of the paragraph sign (hex 14).

 The Quote function reads one keystroke from the keyboard and treats it
 literally. This is useful for inserting text into a file that happens
 to be assigned to an editor function. For example, the key sequence
 Quote (CTRL+P) CTRL+A displays a happy face character.

 For the Quote CTRL+I sequence, the only workaround is to use a Quote
 TAB key sequence. This puts the correct hex value in that position
 (09H), but the correct character is not displayed and the tab is
 treated as a tab by the M Editor.

 For the Quote CTRL+T sequence, there is no workaround.

 Microsoft has confirmed this to be a problem with the M Editor Versions
 1.00 and 1.02. We are researching this problem and will post new
 information here as it becomes available.



 155. Replacing Normal String Takes Longer Than Regular Expression

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.00 buglist1.02
 Last Modified: 15-MAR-1990    ArticleIdent: Q59085

 Replacing a regular expression takes less time than replacing a normal
 string in the Microsoft M Editor, Versions 1.00 and 1.02. To
 demonstrate the time difference, perform test replacements in the
 following manner:

 1. Load the M Editor with a large file -- greater than 5000 lines.

 2. Perform and time a replacement on a regular expression, one that
    fails to match in the file, for example:

       arg arg CTRL+L     zzzz   <- search for this regular expression
                          zzzz   <- replace with this regular expression

 3. Perform and time a replacement on a normal string (one that fails
    to match in the file), for example:

       arg CTRL+L     zzzz   <- search for this string
                      zzzz   <- replace with this string

 The string replacement may take twice as long as the
 regular-expression replacement. To obtain the higher replace speed,
 use the regular-expression replacement (arg arg CTRL+L) even when you
 are not fully using the regular-expression syntax.

 Note that a psearch on a regular expression psearch is NOT quicker
 than a psearch on a normal string.

 Microsoft has confirmed this to be a problem in Versions 1.00 and
 1.02. We are researching this problem and will post new information
 here as it becomes available.

 For details on regular expression, refer to the "Microsoft Editor
 User's Guide," Chapter 5, "Regular Expressions."


 156. Incorrect Version Numbers Cause Tagged Sections to Be Ignored

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | pwb
 Last Modified: 25-MAY-1990    ArticleIdent: Q59256

 With the Microsoft Editor (M) or the Programmers WorkBench (PWB), it
 is possible to include information in your TOOLS.INI file that is
 specific to the operating system you are using. For information on how
 to create sections with tags, see the "Microsoft Editor User's Guide,"
 Section 7.5.1. However, you must be sure to include a trailing 0
 (zero) on the label for OS/2 versions 1.10 or 1.20. Failure to do so
 causes these sections to be ignored by the Editor.

 The following headers cause the tagged sections to be ignored when
 running under OS/2 version 1.10:

    [M-10.0 M-10.1]
    fgcolor:0B
    hgcolor:30
    stacolor:0E

    [M-3.30 M-10.0R M-10.1R]
    fgcolor:0E
    hgcolor:E0
    stacolor:0B

 The tags must be rewritten as follows:

    [M-10.0 M-10.10]
    fgcolor:0B
    hgcolor:30
    stacolor:0E

    [M-3.30 M-10.0R M-10.10R]
    fgcolor:0E
    hgcolor:E0
    stacolor:0B

 Furthermore, the tagged sections must not be placed in the middle of
 an [M] or [M MEP] tagged section. They must be placed before or after
 the [M] or [M MEP] sections. Failure to do this causes information
 located below these sections to be ignored in the DOS compatibility
 box.

 Note: For the PWB, the above examples would change to PWB-xxxx instead
 of M-xxx.


 157. Unassigning Help Keystrokes Must Be Done Under

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 13-MAR-1990    ArticleIdent: Q59494

 It is possible with the Microsoft Editor Version 1.02 to disable
 an assigned keystroke so that it invokes no editor function at all.
 The keystroke can then be assigned to any other function or macro. By
 putting the disable information in the M Editor section of the
 TOOLS.INI file, the changes will be in effect whenever the Editor is
 invoked. For further information, see the Version 1.02 edition of
 "Microsoft Editor User's Guide," Section 6.2.3, Page 70.

 To regularly disable a keystroke that has been assigned to any preset
 Editor HELP function, such as F1 or SHIFT+F1, the command must be
 placed under the [M-MHELP MEP-MHELP] tag in TOOLS.INI -- not under the
 [M MEP] tag.

 For example, to disable the keystroke for F1, include the following
 line in your TOOLS.INI file:

    unassigned:F1

 Placing this line under the section tagged [M MEP] rather than the
 [M-MHELP MEP-MHELP] tag causes this command to be ignored. This is
 also applicable to the undocumented "sethelp" function, whose default
 keystroke is ALT+S. You can unassign ALT+S, as well as reassign a
 different keystroke to "sethelp", but it must be done under the
 [M-MHELP MEP-MHELP] tag.


 158. Using RIGHT ARROW on Dialog Line Locks Keyboard or GP Faults

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.02
 Last Modified: 15-MAY-1990    ArticleIdent: Q59527

 Manipulating text on the dialog line must be handled differently in
 the Microsoft Editor (M) Version 1.00 than in 1.02. If you use an M
 Version 1.00 procedure in M Version 1.02 under DOS, the keyboard will
 lock up and alternating screens of jumbled characters may appear on
 the screen. Under OS/2, you will get a GP fault resulting in the
 termination of MEP by the operating system.

 The problem can be observed by using the following steps from within
 the editor:

 Note: Remember that under DOS your machine will hang!

 1. Press ALT+A to invoke the <arg> function.

 2. Type any character (for example, the letter "d").

 3. Hold down the RIGHT ARROW key. When the text in the dialog line has
    scrolled off the left side of the screen, in M 1.00 the editor will
    issue a beep. In M 1.02, the machine will lock in DOS or GP fault
    in OS/2. This problem occurs even if you omit Step 2, but it is
    more difficult to see the error.

 To retain the same functionality in M 1.02, instead of using the RIGHT
 ARROW key to move the cursor to the right, use the SPACEBAR. Using
 the SPACEBAR rather than the RIGHT ARROW key allows you to take
 advantage of the maximum arg line limit without the error.

 Microsoft has confirmed this to be a problem in Version 1.02. We are
 researching this problem and will post new information here as it
 becomes available.


 159. Reference to "Push" Function Incorrect Editor User's Guide

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 17-JUL-1990    ArticleIdent: Q60339

 On Page 61 of the "Microsoft Editor User's Guide" for Microsoft C
 5.10, there is a documentation error. It is stated that the Boolean
 switch Savescreen is "for use with the Push and Exit functions." Since
 there is no "Push" function, this should read "for use with the Shell
 and Exit functions."


 160. Prototype in User's Guide for tglcase() Is Incorrect

 Product Version(s): 1.02    | 1.02
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 15-APR-1990    ArticleIdent: Q60487

 In the sample program for a C extension on Page 126 of the "Microsoft
 Editor User's Guide" for Microsoft FORTRAN 5.00 and Microsoft BASIC
 PDS Version 7.00, the prototype for tglcase() is incorrect.

 The function is prototyped as follows:

    flagType pascal EXPORT tglcase (unsigned int, ARG far *, flagType);

 It should be as follows:

    flagType pascal EXTERNAL tglcase (unsigned int, ARG far *, flagType);

 Note: The word EXTERNAL replaces EXPORT.


 161. Creating a Compile Window Macro for the M Editor Version 1.02

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 27-JUL-1990    ArticleIdent: Q63950

 The macro below creates a "compile window" in either the M or MEP
 Editor version 1.02 when you press ALT+C. Note that a compile window
 is helpful for viewing general compilation errors and errors generated
 from utilities that were invoked.

 The following macro, CompWindow, can be added to the [M] or [MEP]
 tagged section of the TOOLS.INI file to create a compile window:

    CompWindow:= savecur home meta down  \
                 up up up up arg window  \
                 window arg "<compile>" setfile  \
                 window restcur

    CompWindow: alt+c

 The CompWindow macro above creates a compile window by performing the
 following steps:

 1. Use the "savcur" function to save the current position of the
    cursor.

 2. Use the "home" function to place the cursor in the upper-left
    corner of the screen. This function guarantees that the cursor will
    be in a left-most position when the compile window is created.

 3. Use the "meta down" function to move the cursor to the bottom of
    the window without changing the column position.

 4. Use "up up up up arg window" functions to create a horizontal
    window four lines above the bottom of the screen. A larger compile
    window can be created by adding more "up" functions to this line in
    the macro.

 5. Use the 'arg "<compile>" setfile' function to create a
    dynamic-compile log. More information concerning the
    dynamic-compile log can be found on Pages 47-48 of the "Microsoft
    Editor User's Guide."

 6. Finally, the original position of the cursor is restored in the
    original window by using the "window restcur" functions.

 7. The macro is assigned to the ALT+C keystroke, although any unused
    keystroke may be used.

 Error messages will now be displayed in the compile window when
 running a compilation or invoking a utility.


 162. C 6.00 UNDEL.EXE Is Not Compatible with the Microsoft Editor

 Product Version(s): 1.00 1.02 | 1.00 1.02
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 25-JUL-1990    ArticleIdent: Q64024

 If backup copies of files are stored in the \DELETED subdirectory by
 the M Editor, typing "undel" should bring up a listing of backup
 copies. However, if the C 6.00 version of UNDEL.EXE is used, the
 following message will be displayed: "

    0(0) bytes in 0 deleted files.

 The C 5.10 version of UNDEL.EXE will successfully bring up a listing
 of backup copies saved by either the M Editor or the Programmer's
 WorkBench (PWB).

 This problem can be reproduced by setting the text backup switch in
 the M section of the TOOLS.INI file to "undel". After saving various
 copies, backups are added to the \DELETED subdirectory and a listing
 can be brought up by using the C 5.10 UNDEL.EXE. Using the C 6.00
 version of UNDEL.EXE causes the erroneous message listed above to be
 displayed. This incompatibility was caused by adding OS/2 version 1.20
 filename support to UNDEL.EXE and EXP.EXE.

 As a workaround, rename the C 5.10 UNDEL.EXE to UNDEL51.EXE and the C
 6.00 UNDEL.EXE to UNDEL60.EXE.


 163. Invalid Switch and Extensions in Brief Emulation

 Product Version(s): 1.02   | 1.02
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  6-FEB-1991    ArticleIdent: Q67762

 The M editor version 1.02 comes with a BRIEF.INI file, which contains
 the key settings for Brief emulation. If you want Brief emulation, you
 must rename this file to "TOOLS.INI". This file will generate the
 following three messages when M loads the TOOLS.INI file during
 initialization:

    mhctx is not an editor switch
    load:$PATH:ulcase - no such file or directory
    load:$PATH:justify - no such file or directory

 The messages are caused by the following three lines:

    Line 223: "mhctx:Alt+H"
    Line 263: "load:$PATH:ulcase"
    Line 369: "load:$PATH:justify"

 Deleting these three lines will not change the performance of the M
 editor, and will eliminate the messages they cause when M is
 initialized.






 Microsoft NMake [Make Utility]
 =============================================================================


 1. NMAKE and the Backslash "\" Character

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  3-MAY-1989    ArticleIdent: Q43064

 The backslash "\" character in NMAKE has two different meanings
 depending on how it is used. One of its uses is as a line-continuation
 character. The other use is as a path specifier.

 The primary use of "\" is as a line continuation-character. For
 example, if you have a dependency line that extends more than one
 line, use the "\" character to continue to the next line. It is
 correct to include a space prior to the "\" or to append it to the
 last dependent, as in the following examples:

 FOO : obj1 obj2 obj3 obj4 obj5 \  (CORRECT)
 obj6 obj7...etc.

 FOO : obj1 obj2 obj3 obj4 obj5\   (CORRECT)
 obj6 obj7...etc.

 The "\" character is also used as a path specifier. When "\" is the
 last character on the line and is meant as a path specifier, you must
 precede it with the caret "^" character to tell NMAKE to override its
 meaning as a line-continuation character.

 The following macro definition is an example demonstrating the use of
 "\" as a path specifier:

 exe_dir = c:\bin^\    (CORRECT)

 exe_dir = c:\bin\     (INCORRECT)

 The following will be interpreted as a line-continuation character.

 exe_dir = c:\bin\     (INCORRECT)

 Preceding the "\" with another "\" will nullify the meaning as a
 line-continuation character. However, when this macro is expanded,
 both backslashes will appear, producing an incorrect path.


 2. NMAKE Is Case Sensitive

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified:  3-MAY-1989    ArticleIdent: Q43999

 It is not clearly stated in the manual that NMAKE IS case sensitive.
 Case sensitivity is imposed on the following:

 1. Macros

    For instance, if you define "TEXT" as a macro, you must use $(TEXT)
    to insert it. If $(text) is used, the macro is undefined and
    nothing happens.

 2. Predefined Macros (.SUFFIXES;.PRECIOUS, CC, etc.)

    Predefined macros such as .SUFFIXES must be in all in uppercase
    letters. If you use .suffixes, NMAKE returns the error ".suffixes
    too long: truncated to 8.3".

 3. File extensions

    When adding file extensions to the .SUFFIXES list, you must
    preserve case. For example, to add the file extension .dll to the
    suffix list, you would put the following line in your makefile:

       .SUFFIXES : .dll

    Then, all files with the .dll extension must have the .dll
    extension in lowercase letters.


 3. NMAKE Uses "makefile " Ignoring File Name on Command Line

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QuickC
 Last Modified: 10-NOV-1989    ArticleIdent: Q44777

 When using NMAKE, you normally put the makefile's name on the command
 line as follows:

    NMAKE test.mak

 Although this works correctly for most cases, if there is a file named
 "makefile." in the current working directory, NMAKE uses that file
 instead of the one specified on the command line.

 To be sure NMAKE uses the makefile specified on the command line, you
 must have a /F switch before the makefile name as follows:

    NMAKE /F test.mak

 This is expected behavior, as documented on Page 156 of the "Microsoft
 QuickC ToolKit" manual for QuickC Version 2.00.


 4. Modifications for an Existing Make File Used with MAKE

 Product Version(s): 1.00   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_quickc  s_c  h_FORTRAN
 Last Modified: 16-JAN-1990    ArticleIdent: Q44130

 Question:

 What modifications need to be made to an existing make file that was
 used with MAKE, and why?

 Response:

 To use NMAKE on make files originally designed for MAKE, the first
 descriptor block (target:dependent) must be a pseudotarget (see QuickC
 Version 2.00 ToolKit, Sections 7.3.5 and 7.5) that lists all of the
 original make targets in the file as the dependent files. The
 following is an example:

    ALL : test.exe test1.exe test2.exe

 The reason you must include a pseudotarget descriptor block as the
 first descriptor block in a make file is that the previous MAKE
 utility tested EACH descriptor block sequentially throughout the file.
 NMAKE, however, tests only the FIRST descriptor block unless targets
 are specifically listed on the NMAKE command line. By using a
 pseudotarget, ALL in the above example, NMAKE must now assume
 that each dependent is out of date and attempt to make it. NMAKE now
 searches the make file for each dependent file listed (test.exe,
 test1.exe, and test2.exe) to see if a descriptor block exists for it.
 This causes NMAKE to behave just like MAKE.

 Example:
 -------

    ALL : test.exe test1.obj

    test1.obj : test1.c
            cl /c test1.c

    test.exe : test.obj test1.obj
            link test test1;

 Without the pseudotarget, NMAKE tests only the first descriptor block
 and ignores any following descriptor block.


 5. How to Specify Paths in Inference Rules in NMAKE

 Product Version(s): 1.00   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_quickc  s_c  h_FORTRAN
 Last Modified: 23-MAR-1990    ArticleIdent: Q44131

 Question:

 How to I specify paths in inference rules?

 Response:

 Note: For a complete description of this feature, see QuickC Version 2.00
 Toolkit, Section 7.3.3. One of the most powerful new features of
 NMAKE is that it allows paths to be specified in an inference rule.

 The syntax of an inference rule without paths is as follows:

    .fromext.toext:

 This syntax is somewhat limited, however, because both the "fromfile"
 and the "tofile" are evaluated as if they existed in the current
 directory. With NMAKE, a path specifier may be added to an inference
 rule by doing the following:

    {frompath}.fromext{topath}.toext:

 Note: If you use a path on one element of the inference rule, you must
 use it on both. For instance, if you want to compare any .c file in
 the current directory with its .obj file in my object directory, the
 inference rule would look like the following:

 {.}.c{c:\objects}.obj:
         cl /c $<;

 Note that the fromext (.c) has to be preceded with a path. In the case
 of the current directory, the ".", or current directory works nicely.

 When NMAKE encounters a descriptor block that has no commands
 following, it will look for an inference rule that matches the
 descriptor block. When checking for matching, NMAKE expects that the
 base name of both the target and the dependents be the same. Also, the
 paths must match exactly. In other words, the following descriptor
 line would not use the inference rule just defined because the paths
 do not match on the .obj file:

    test.obj : test.c

 In this case, the predefined inference rule for .c.obj: would be
 invoked. To invoke the inference rule just defined, the descriptor
 line would be as follows:

    c:\objects\test.obj : test.c


 6. Multiple Targets in NMAKE Do Not Work

 Product Version(s): 2.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist2.00 docerr S_QUICKC
 Last Modified:  2-JUN-1989    ArticleIdent: Q44757

 Multiple targets in the QuickC Version 2.00 NMAKE utility do not work
 properly. The example on the top of Page 167 of the "Microsoft QuickC
 Tool Kit" manual shows that each target listed before the dependencies
 should be evaluated; however, only the first target is evaluated, and
 the others are ignored. Make files that are simplified even more
 respond the same way.

 The following make file demonstrates the problem:

     target1.exe target2.exe: depend1.obj depend2.obj
         echo $@

 For the make file to work properly, change the file to the
 following:

     BUILD: target1.exe target2.exe

     target1.exe: depend1.obj depend2.obj
         echo $@

     target2.exe: depend1.obj depend2.obj
         echo $@

 Microsoft has confirmed this to be a problem in QuickC Version 2.00.
 We are researching this problem and will post new information as it
 becomes available.



 7. Modifying a QuickC 2.00 Make File to Run MAKE

 Product Version(s): 1.00   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_quickc  s_c  h_FORTRAN
 Last Modified: 26-MAY-1989    ArticleIdent: Q44133

 Question:

 What modifications must I make to a make file generated by QuickC
 Version 2.00 so that I can run NMAKE on it and use my Microsoft C
 Version 5.10?

 Response:

 Only a few modifications must be made to allow a make file generated
 by QuickC to invoke C Version 5.10. The following three items need to
 be changed:

 1. Change the CC macro from qcl to cl. To do this, locate the
    following line in the make file generated by QuickC and change qcl
    to cl:

       CC=qcl

 2. Take out references to ilink. The ilink references are embedded
    into your make file if you have the ilink option turned on in your
    environment. The following line in the make file

       ilink -a -e "link $(LFLAGS) @$(PROJ).crf" $(PROG)

    must be changed to the following:

       link "$(LFGLAGS) @$(PROJ).crf" $(PROG)

 3. Remove any compiler switches in the make file that cl will not
    recognize. To eliminate this problem, turn off incremental compile
    in the QuickC environment prior to making the make file.


 8. NMAKE Version 1.00 with "!" and User and Predefined Macros

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | S_QuickC buglist1.00 fixlist1.01
 Last Modified: 30-NOV-1989    ArticleIdent: Q48859

 The following NMAKE file does not produce the correct results when
 using NMAKE Version 1.00, which is supplied with the Microsoft QuickC
 compiler Version 2.00. The file replaces the user-defined macro in the
 second command line with the predefined macro in the first command
 line. The workarounds are as follows:

 1. Remove the "!" at the beginning of the first command line, which
    causes the command to be executed for each dependent file if the
    command uses one of the special macros $? or $**.

 2. Do not use a predefined macro for the first command.

 3. Do not use the predefined macro $**, a complete list of dependent
    files, for the dependent files in the first command line.

 4. Do not use a user-defined macro in the second command line.

 5. Update to the Microsoft QuickAssembler package, which is shipped
    with NMAKE Version 1.01, in which this problem is corrected.

 More information on the NMAKE utility can be found starting on Page
 155 of the "Microsoft QuickC Toolkit" manual. The following is the
 NMAKE file that fails:

 SOURCE=test.c

 test.exe: $(SOURCE)
     !$(CC) $**
     copy $(SOURCE) new

 This produces the following output:

 cl test.c
 copy cl new

 The following is the NMAKE file with the first workaround:

 SOURCE=test.c

 test.exe: $(SOURCE)
     $(CC) $**
     copy $(SOURCE) new

 This produces the following correct output:

 cl test.c
 copy test.c new

 The following is the NMAKE file with the second workaround:

 SOURCE=test.c

 test.exe: $(SOURCE)
     !cl $**
     copy $(SOURCE) new

 This also produces the correct output.

 The following is the NMAKE file with the third workaround:

 SOURCE=test.c

 test.exe: $(SOURCE)
     !$(CC) $(SOURCE)
     copy $(SOURCE) new

 This also produces the correct output.

 The following is the NMAKE file with the fourth workaround:

 SOURCE=test.c

 test.exe: $(SOURCE)
     !$(CC) $(SOURCE)
     copy test.c new
     copy $(SOURCE) new

 This produces the following output:

 cl test.c
 copy test.c new
 copy test.c new


 9. Incrementally Updating Libraries with NMAKE

 Product Version(s): 1.00 1.01 1.10 1.11 1.12 | 1.11 1.12
 Operating System:   MS-DOS                   | OS/2
 Flags: ENDUSER |
 Last Modified: 25-FEB-1991    ArticleIdent: Q48862

 The repetition modifier "!" (without the quotation marks) provided in
 NMAKE allows libraries to be maintained and incrementally updated very
 easily. By using this modifier with the special macro for dependents
 out-of-date with the target (for example, "$?"), the library update
 becomes an automated part of modifying a project.

 The following NMAKE makefile keeps FOO.LIB up-to-date based on the
 four object files listed in the OBJS macro. These object files can be
 based on C or assembly source files. The list of source-file types can
 be extended by adding the appropriate inference rules to the
 description file.

 Sample NMAKE Makefile
 ---------------------

     #
     # List of object files to be kept in library
     #
     OBJS = foo1.obj foo2.obj foo3.obj foo4.obj

     .c.obj:
         cl /c $?

     .asm.obj:
         masm $?;

     foo.lib : $(OBJS)
         !lib foo.lib -+ $?;

 The command for the library dependency line uses a predefined macro
 and a special NMAKE directive. Placing "$?" on the end of the LIB line
 expands to the list of all dependents that are out-of-date with the
 target. This list combined with "!" causes the LIB line to be executed
 once for each member in the list.

 If FOO1.OBJ and FOO3.OBJ are out-of-date with respect to FOO.LIB, "$?"
 evaluates to "FOO1.OBJ FOO3.OBJ". With "!", the following commands are
 executed:

    lib foo.lib -+ foo1.OBJ;
    lib foo.lib -+ foo3.OBJ;


 10. Explanation of Why NMAKE May Not Produce .OBJ and .EXE Files

 Product Version(s): 1.00 1.10 1.11 | 1.00 1.11
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER |
 Last Modified: 27-OCT-1989    ArticleIdent: Q49502

 Question:

 When using the NMAKE utility, no warnings occur and the compiler
 appears to execute properly; however, the .OBJ and .EXE files are not
 created.

 If I use the MAKE utility on the same .MAK file, I get the following
 two warnings:

    warning U4000: Target does not exist.

    warning U4001: Dependent does not exist; Target not built.

 The first warning message is a standard warning that I would expect.
 Why is there a second and why aren't the .OBJ and .EXE files created?

 Response:

 Remove unexpected trailing characters from the .MAK file.

 This problem can occur because extra characters occur at the end of a
 line within the .MAK file. Common mistakes such as placing a trailing
 semicolon in the CL compile line or in the dependency line can cause
 this behavior. This applies to any unexpected characters, not just
 semicolons.

 The following example demonstrates the problem:

    file.obj: file.c <ENTER>
       CL /c /Lp file.c;  <-- Semicolon CANNOT be used with the CL command.

    file.exe: file.obj <ENTER>
       LINK file;      <-- OK, Semicolon CAN be used with the LINK command.

 Removing the semicolon at the end of the CL line eliminates the
 problem.


 11. Command Line Too Long in Makefile Can Cause Error: U1082

 Product Version(s): 1.00 1.01 1.10 1.11 1.12 | 1.11 1.12
 Operating System:   MS-DOS                   | OS/2
 Flags: ENDUSER | s_make
 Last Modified: 24-JAN-1991    ArticleIdent: Q49757

 NMAKE and MAKE require that all commands issued after a target
 dependency are less than the DOS command-line limit of 128 characters.
 If the command is too long, you may receive the following error

    U1082:  Not enough memory '...' cannot execute '...'

 where '...' is the command that was attempted. This problem most
 likely occurs with the link command line and can be easily resolved
 with a response file. Response files are documented in the utilities
 manual or the online help supplied with each compiler.


 12. Special Macros Not Recognized in NMAKE Inline Files

 Product Version(s): 1.00 1.01 | 1.00 1.01
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER |
 Last Modified: 10-NOV-1989    ArticleIdent: Q50693

 When you use special macros to indicate targets or dependents in
 inline files, NMAKE Version 1.00 will generate the error message
 U4108, "special macro undefined." These special macros are $@, $*,
 $**, and $?.

 To prevent the problem, avoid use of these special macros in inline
 files. Instead of using those << inline files, create the response
 file in a separate NMAKE target, and redirect TYPE and ECHO commands
 to the desired file.

 $@ refers to the full name of the target, base plus extension. $*
 refers only to the base name of the target.

 $** represents the complete list of dependent files for the target. $?
 represents only the dependents that are out of date relative to the
 target.

 The following makefile will generate U4018 for $**:

 #makefile test
 FOO.EXE: *.OBJ
     LINK @<<FOO.LRF
 $**;
 <<

 To avoid the problem, break this up into two steps, the makefile and a
 linker response file with output redirected:

 #makefile test
 FOO.EXE: *.OBJ FOO.LRF
     LINK @FOO.LRF

 FOO.LRF: *.OBJ
     echo $**; >FOO.LRF


 13. Inference Rule May Fail If Blank Command Line Contains Spaces

 Product Version(s): 1.00 1.01 1.10 1.11 1.12 | 1.11 1.12
 Operating System:   MS-DOS                   | OS/2
 Flags: ENDUSER |
 Last Modified: 24-JAN-1991    ArticleIdent: Q50383

 When using inference rules in an NMAKE description file, the target/
 dependency line must be followed by a blank line (no space
 characters); otherwise, the inference rule commands will not be
 executed. NMAKE checks this line for any ASCII characters; if ANY
 characters exist, NMAKE will ignore the inference rule and try to
 execute the line, even if it contains only a space or spaces.

 The following is a simple example, which demonstrates this problem:

 .c.exe:
   cl $**

 ALL : main.exe

 main.exe : main.c
 <space>

 Nothing happens if this description file is passed to NMAKE because
 the space character will cause NMAKE to assume there are explicit
 commands following the target/dependency line, causing it to ignore
 the inference rule. Note that this is expected behavior for NMAKE.

 MAKE version 4.x inference rules/description blocks do not exhibit
 this behavior. This is something to keep in mind when converting
 description files from MAKE to NMAKE.


 14. Using "." for Path in Inference Rules Causes U1073

 Product Version(s): 1.00 1.01 | 1.01
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.01
 Last Modified: 18-DEC-1989    ArticleIdent: Q51723

 NMAKE does not accept a dot (.) to identify the current directory in
 inference rule paths. When specifying paths for each of the
 extensions, using the following form

    {frompath}.fromextension{topath}.toextension

 and using "{.}" (without the quotation marks) to indicate the current
 directory for the "topath", causes the following error:

    NMAKE : fatal error U1073: don't know how to make 'filename.ext'

 To work around this, the current directory for topath must be
 specified with "{}". However, both notations are acceptable when
 specifying the "frompath".

 The following makefile causes the error:

 .SUFFIXES: .h .c .obj .exe

 #macros
 a=tools.h
 jbo=grdemo.obj turtle.obj menu.obj
 cc=qcl -c

 #inference rules
 {d:\qc2\work}.c{.}.obj:          #*** the '{.}' must be '{}' ***
  $(cc) $<

 {}.obj{d:\qc2\lib}.exe:
  link $(**R),,, graphics.lib;

 #target-dependencies
 run: d:\qc2\lib\grdemo.exe

 d:\qc2\lib\*.obj: d:\qc2\work\*.c

 d:\qc2\lib\grdemo.exe: $(jbo)


 15. Redirecting NMAKE 1.00/1.01 Output with -p Gives False Errors

 Product Version(s): 1.00 1.01
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00 buglist1.01 fixlist 1.11
 Last Modified: 24-JAN-1991    ArticleIdent: Q57500

 Redirecting the output of NMAKE version 1.00 or 1.01 can cause
 inference rules to fail if all of the following conditions are met:

 1. The inference rules are in uppercase letters.
 2. The -p option is used.
 3. The output is redirected.

 This problem is somewhat obscure, and it can be frustrating if you
 unwittingly meet all of these conditions. The error message displayed
 depends on the inference rule used, but it resembles the following:

    NMAKE : warning U4017: ignoring rule .C.OBJ (extension not in
            .SUFFIXES)

 The above error message is displayed with the following description
 file initiated with the command "NMAKE -p > out.txt":

 Description File
 ----------------

 # start

 .C.OBJ:
   cl $*

 main.obj : main.c

 # end

 Microsoft has confirmed this to be a problem in NMAKE versions 1.00
 and 1.01. This problem was corrected in NMAKE version 1.11.


 16. Missing Right Parenthesis in Sample NMAKE File Hangs Machine

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | h_fortran s_quickc s_quickasm buglist1.00
 Last Modified: 15-MAR-1990    ArticleIdent: Q59069

 If you forget the right parenthesis in an IF "$(flag)"=="comparison"
 line in a makefile and run the makefile through NMAKE, you can receive
 machine hangs or corrupt COMMAND.COM messages under DOS or an Internal
 Processing Error under OS/2.

 Microsoft has confirmed this to be a problem with Version 1.00. We are
 researching this problem and will post new information here as it
 becomes available.

 The following makefile, simplified from the sample makefile on Page
 172 of the "QuickC ToolKit" manual, demonstrates this problem:

 debug=Y
 CC=qcl
 !CMDSWITCHES +D
 HELLO.EXE : HELLO.OBJ
 !IFDEF debug
 !   IF "$(debug"=="y"
                 LINK /CO hello;
 !   ELSE
                 LINK hello;
 !   ENDIF
 !ELSE
 !   ERROR Macro named debug is not defined.
 !ENDIF

 Adding a right parenthesis after "$(debug solves the problem.

 The error seems to occur because NMAKE does not recognize the end of
 the line and continues to parse the line until the end of the file. A
 customer has reported receiving "U1076, Line too long" messages,
 followed by a DOS level error reading "Invalid COMMAND.COM - system
 halted."

 Testing the same problem under an OS/2 1.20 DOS Box returned Internal
 Processing Errors and halted the system with no other error messages.


 17. NMAKE 1.01 Does Not Properly Expand Wildcard Arguments

 Product Version(s): 1.01   | 1.01
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-MAY-1990    ArticleIdent: Q59254

 NMAKE version 1.01 doesn't properly expand wildcard command-line arguments.
 For example, if we were to have a makefile that looked similar to the
 following

 a.exe : a.c
     echo cl a.c

 b.exe : b.c
     echo cl b.c

 And we were to say:

 NMAKE *.exe /A

 NMAKE wouldn't properly expand "*.exe" to equate to both a.exe and
 b.exe; it would merely build only the first target in the list.

 NMAKE versions 1.00 and 1.10 do not exhibit this behavior.


 18. NMAKE /D /C Switches Suppress Modification Date

 Product Version(s): 1.00 1.01 1.10 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00 buglist1.01 buglist1.10 buglist1.11
 Last Modified: 18-NOV-1990    ArticleIdent: Q59384

 When using the NMAKE /D and /C switches together, the modification
 date of each file will not be displayed when the date is checked. A
 short description of each switch is described as follows:

    /D  Displays the modification date of each file when the date is
        checked.

    /C  Suppresses the NMAKE copyright message and prevents nonfatal
        error or warning messages from being displayed.

 Microsoft has confirmed this to be a problem with NMAKE Versions 1.00,
 1.01, and 1.10. We are researching this problem and will post new
 information here as it becomes available.


 19. Trouble with Filenames Containing a Dollar Sign ($)

 Product Version(s): 1.01    | 1.01
 Operating System:   MS-DOS  | OS/2
 Flags: ENDUSER | buglist1.01
 Last Modified: 14-MAR-1990    ArticleIdent: Q59409

 If you use a filename that contains a dollar sign ($) in a NMAKE
 description file, you can use the escape character (^) to tell NMAKE
 that the dollar sign is part of your filename, not a macro character.
 However, using the escape character within an inline response file
 does not work and you must use the double dollar sign ($$).

 Consider the following NMAKE description file:

     all:test^$.exe;

     test^$.obj: test^$.c
        cl /c test^$.c

     test^$.exe: test^$.obj
        link @<<
              test^$.obj,
              test^$.exe,
              NUL,;
     <<

 In this file, the escape character (^) is used to tell NMAKE that the
 $ is part of the filename TEST$.* and is not denoting the use of a
 macro. When TEST$.C is compiled, everything works correctly until you
 get to the inline response file for LINK. NMAKE does not interpret the
 ^ character, but instead passes it on to LINK.EXE. LINK then tries to
 link TEST^$.OBJ instead of TEST$.OBJ and fails. If you eliminate the ^
 to pass TEST$.OBJ to link, NMAKE fails with an error about an invalid
 macro.

 NMAKE is in error here. NMAKE should do one of two things when parsing
 the inline response file.

 1. NMAKE should interpret the ^ to leave the $ as part of the filename.

 2. NMAKE should ignore the $ so that you can just list TEST$.OBJ
    because it doesn't make sense to have macros in external response
    files when parsing an inline response file.

 Microsoft has confirmed this to be a problem with NMAKE Version 1.01.
 We are researching this problem and will post new information here as
 it becomes available.

 The following are two suggested workarounds:

 1. Use an external response file. Then your link line would appear
    similar to link @FILE.RES and you could put TEST$.OBJ directly in
    the response file.

 2. Use $$ as the escape sequence instead of ^$ in the inline response
    file. For example, change

       link @<<
           test^$.obj,
           test^$.exe,
           NUL,;
       <<

    to the following

       link @<<
           test$$.obj,
           test$$.exe,
           NUL,;
       <<

    and NMAKE will correctly pass TEST$.OBJ to the linker.


 20. In What Order Does NMAKE Build Files?

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 15-MAY-1990    ArticleIdent: Q59420

 Question:

 I need to have my source files built in a particular order but I can't
 get NMAKE to build them that way. NMAKE seems to build the source
 files in the order it wants. What is the order in which NMAKE builds
 files?

 It is definitely possible to specify the order in which NMAKE builds
 your files.

 The first thing NMAKE does is check the command line. You can specify
 the targets in the order you want them built and NMAKE will build them
 in that order. If NMAKE doesn't find any targets on the command line,
 it builds the first target in the description file.

 NMAKE will build all of the dependents in the order in which they are
 specified on the first target line. For most description files, the
 first target in the file is the ALL:FILENAME.EXE pseudotarget. In this
 case, NMAKE will build FILENAME.EXE, and then the order depends on the
 dependency for FILENAME.EXE.

 This can be more clearly explained in the following examples:

 Example 1
 ---------

 Consider the following description file:

             all:three.obj two.obj one.obj main.exe

             one.obj:one.c
                 cl /c one.c

             two.obj:two.c
                 cl /c two.c

             three.obj:three.c
                 cl /c three.c

             main.exe:three.obj one.obj two.obj
                 link one two three, main;

 In this example, the files are compiled in the order: THREE.C, TWO.C,
 ONE.C. After those three files are compiled, the link for MAIN.EXE is
 executed. They are executed in that order because that is the explicit
 order given in the first target in the file and NMAKE builds the first
 target in the file when nothing is specified on the command line.

 Example 2
 ---------

 Now, consider the following description file that has been slightly
 modified from the one shown in Example 1 above:

             all:main.exe

             one.obj:one.c
                 cl /c one.c

             two.obj:two.c
                 cl /c two.c

             three.obj:three.c
                 cl /c three.c

             main.exe:three.obj one.obj two.obj
                 link one two three, main;

 In this example the files are compiled in the order: THREE.C, ONE.C,
 TWO.C. After that, the link statement will then be executed because
 there is nothing specified on the command line, so NMAKE will build
 the first target in the file, which is MAIN.EXE. When NMAKE looks at
 what it needs to build MAIN.EXE, it sees the list of dependents and
 builds them in that order.

 In summary, NMAKE looks first on the command line. If nothing is found
 there, it builds the first target in the description file by building
 each of its dependents in the order specified. If the dependent of the
 first target specifies another target, the dependents of that target
 are built in the order they are specified and so on.


 21. Multiple Dependency Blocks Are Not Cumulative

 Product Version(s): 1.00 1.01 1.10 1.11 | 1.01 1.10 1.11
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER |
 Last Modified: 16-OCT-1990    ArticleIdent: Q59526

 Question:

 Specifying a target in multiple dependency blocks seems to confuse
 NMAKE. If my make file says something similar to the following

 FOO.EXE:: FOO1.obj
 FOO.EXE:: FOO2.obj
 FOO.EXE:: FOO3.obj
   link foo.exe

 FOO.EXE:: FOO.RES
   RC FOO.RES FOO.EXE

 and FOO1.OBJ and FOO2.OBJ are newer than FOO.EXE but FOO3.OBJ is not,
 FOO.EXE will not be built. To further confuse the issue, the following
 is the output from running NMAKE with the /d (display file dates)
 option:

 C:\>NMAKE /d foo.mak

   foo.exe                    Wed Mar 07 08:42:38 1990
     foo1.obj                 Thu Mar 08 15:25:44 1990
 ** foo1.obj newer than foo.exe
     foo2.obj                 Wed Mar 08 08:38:56 1990
 ** foo2.obj newer than foo.exe
     foo3.obj                 Thu Mar 01 09:49:52 1990
     foo.res                  Thu Mar 01 09:49:52 1990
 'foo.exe' is up-to-date.

 Obviously, NMAKE realizes the foo1 and foo2 .OBJs are newer, but
 FOO.EXE is never linked. Why not?

 Response:

 The multiple dependency construct, indicated by a double colon (::)
 following the target, is very useful in NMAKE because it allows the
 programmer to specify what operations are to take place on a target
 based on various dependents. For instance, in PM (Presentation
 Manager) programming the MAKE file can indicate that if the .OBJs
 change, execute the linker to rebuild the application. On the other
 hand, if all that changes is the resource file, only the resource
 compiler needs to be executed.

 However, there is a limitation to this feature. The command block for
 a target-dependency group MUST immediately follow it. They are not
 cumulative like normal dependency blocks. Therefore, one workaround to
 the above example is the following:

 FOO.EXE:: FOO1.obj
   link foo.exe

 FOO.EXE:: FOO2.obj
   link foo.exe

 FOO.EXE:: FOO3.obj
   link foo.exe

 FOO.EXE:: FOO.RES
   RC FOO.RES FOO.EXE

 The second alternative is to put all the dependencies on the same
 line as the target, for example:

 FOO.EXE:: FOO1.obj FOO2.obj FOO3.obj
   link foo.exe

 FOO.EXE:: FOO.RES
   RC FOO.RES FOO.EXE


 22. A Complete Example of Utilizing Paths in NMAKE

 Product Version(s): 1.00 1.01 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER |
 Last Modified: 18-APR-1990    ArticleIdent: Q60340

 The make file shown below is an NMAKE example of using paths in
 macros, inference rules, and target dependencies (descriptor blocks).
 This is a working example of what is described on Page 298 of the
 "Microsoft FORTRAN CodeView and Utilities User's Guide" and Page 168
 of the "Microsoft QuickC Tool Kit."

 This make file compares the modification dates of the .H and the .C
 files with the .OBJ files, and the .OBJ files with the .EXE files. If
 any of the dependent files have changed more recently than the target
 files, the specified series of commands is executed. The .H and the
 .C files in the work directory are compared to the .OBJ files of the
 lib directory.

 If any of the source file(s) have changed since the last .OBJ was
 .created, then it is recompiled and copied from the current
 directory to the lib directory. The .OBJ files in the lib directory
 are compared to the .EXE files in the current directory. If any of the
 .OBJ files have changed since the last .EXE was created, then the
 .OBJs are relinked.

 Sample Make File
 ----------------

 #macros

 objdir =d:\qc2\lib
 wrkdir =d:\qc2\work
 list   =$(objdir)\grdemo.obj $(objdir)\turtle.obj \
 $(objdir)\menu.obj
 cc     =qcl -c

 #inference rules

 #compile
 {$(wrkdir)}.c{$(objdir)}.obj:
  $(cc) $<
  copy $(*F).obj $(*R).obj
  erase $(*F).obj

 #link
 {$(objdir)}.obj{}.exe:
  link $(**R);

 #target-dependencies

 run: grdemo.exe

 $(objdir)\*.obj: $(wrkdir)\$$(@B).c $(wrkdir)\menu.h \
 $(wrkdir)\turtle.h

 grdemo.exe: $(list)


 23. NMAKE May Invoke MASM Instead of the C Compiler

 Product Version(s): 1.00 1.01 1.11 | 1.01 1.11
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | docsup s_pwb h_fortran
 Last Modified: 17-JUL-1990    ArticleIdent: Q60746

 When using an NMAKE file in combination with adding /Fa to the
 compiler options within Programmer's WorkBench (PWB), NMAKE will
 invoke the Macro Assembler, if it is in the current search path.

 This does not occur the first time you build your application, but it
 does occur the second time, and thereafter, because of the generation
 of the .ASM created by the compiler.

 Files with the .ASM extension have a predefined inference rule within
 NMAKE to invoke MASM. However, the inference rule for .ASM files takes
 place before the rule for files with the .C or .OBJ extension.
 Therefore, if you have a filename with the same base name, but one has
 an .ASM extension and the other has a .C extension (as is the case
 with the /FA switch), the .ASM file will be assembled before the .C
 file will be compiled. Since the assembly step generates an .OBJ file
 that is newer than the .C file, the .C file is never compiled.

 Use the following procedures to work around this behavior:

 1. The best workaround is to use /Fa [LSTFILE.EXT] with a filename
    included as a compiler option, instead of allowing the /Fa option
    to default to its <filename>.ASM.

    Example: /Fa <filename>.ASC

    In using this method, the .C file will be compiled, instead of the
    .ASM version being assembled.

 2. Use the /Fc compiler option in place of the /Fa option (if you just
    want to look at an assembly source listing). This produces a .COD
    file (combined assembly and C source listing).

 3. Use the /R switch for the NMAKE invocation to ignore inference
    rules and macros that are predefined or defined in the TOOLS.INI
    file.

 For a more in-depth discussion on the /R switch and its effects, see
 the following references:

 1. The "Microsoft C Advanced Programming Techniques" reference manual

    Page(s) 112-114 Predefined macros
            118-119 Predefined inference rules
            125     /R Switch

 2. The "Microsoft FORTRAN, CodeView and Utilities User's Guide"

    Page(s) 288     /R Switch
            295-297 Predefined macros
            299-230 Predefined inference rules

 3. The "Microsoft QuickC Toolkit" reference manual

    Page(s) 158     /R Switch
            165-197 Predefined macros
            169     Predefined inference rules


 24. Looking for Files in Different Directories

 Product Version(s): 1.00 1.01 1.10 1.11 | 1.01 1.10 1.11
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER | s_c s_quickc s_quickasm h_fortran
 Last Modified: 17-JUL-1990    ArticleIdent: Q60867

 If you use the "directory search" feature of NMAKE (curly braces "{}")
 to use a separate directory for some files, the location of these
 files cannot be inferred in subsequent dependency rules.

 The following code example demonstrates this confusion:

    test.exe: {\obj}test.obj
       link \obj\test.obj graphics.lib;

    test.obj: test.c test.h
       cl /c /Fo\obj\test.obj test.c

 If TEST.EXE and \OBJ\TEST.OBJ were up to date and we were to change
 one of the dependencies for TEST.OBJ, nothing would happen. This is
 because \OBJ\TEST.OBJ doesn't have any dependencies. The TEST.OBJ
 dependency line is only for the current directory. If we were to
 change the TEST.OBJ line to the following

    {\obj}test.obj: test.c test.h

 a change to TEST.C or TEST.H would cause \OBJ\TEST.OBJ and TEST.EXE
 to be updated.

 Note: NMAKE has a predefined inference rule for C.EXE that causes
 TEST.EXE to be relinked in the above example if it is out of date with
 TEST.C.


 25. /MAKE Option Is Invalid with NMAKE

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 25-MAY-1990    ArticleIdent: Q61619

 On Page 43 of the "Microsoft C Reference" manual for version 6.00,
 NMAKE is described as being upwardly compatible with the earlier MAKE
 utility through the use of the /MAKE option. Since NMAKE does not
 support the /MAKE option, it produces the error "U1065:  Invalid
 option 'm'."

 To work around this problem, you can either use the earlier MAKE
 utility, or use a pseudo-target on the first line of your make file.
 The pseudo-target line should read as follows:

    ALL: [target name.exe/obj]

 For more information about the differences between MAKE and NMAKE, see
 Section 6.9 of the "Microsoft C Advanced Programming Techniques"
 manual for version 6.00.


 26. Using "!" and "$?" Do Not Work as Expected with NMAKE 1.11

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.11
 Last Modified:  6-FEB-1991    ArticleIdent: Q61808

 Applying the "!" (exclamation point) operator to the beginning of a
 command line using the macro "$?" should cause the command to be
 executed once for every out-of-date dependent file. (This is
 documented on Page 108 of the "Advanced Programming Techniques" manual
 included with the Microsoft C Optimizing Compiler version 6.00.)

 This feature works correctly in NMAKE version 1.00, but does not work
 as expected in version 1.11. NMAKE version 1.11 is included with the
 Microsoft C Compiler version 6.00.

 In version 1.11 of NMAKE, the $? macro evaluates to the list of every
 dependent, regardless of whether it is out of date or not. This is not
 the correct behavior.

 To re-create this problem, save the following lines to a file called
 MAKEFILE:

    new.lib: a.obj b.obj c.obj
        !lib $@-+$?;

 Assuming that only a.obj is out-of-date with respect to new.lib, the
 following will be produced upon running NMAKE:

 1. NMAKE 1.00:

       lib new.lib-+a.obj;

 2. NMAKE 1.11:

       lib new.lib-+a.obj
       lib new.lib-+b.obj
       lib new.lib-+c.obj

 Example 1 above shows the correct function of the $? macro.

 Fortunately, the problem above is easy to fix.  NMAKE performs
 correctly if two colons (::) are placed after the target new.lib on
 the dependency line.  The NMAKE file has been re-written below so that
 the $? macro will work with NMAKE 1.11.

 MODIFIED NMAKE FILE
 -------------------
 new.lib::a.obj b.obj c.obj
    !lib $@-+$?;

 The use of the two colons on the dependency line is described on page
 109 of the Advanced Programming Techniques manual included with the
 Microsoft C compiler version 6.00.

 Microsoft has confirmed this to be a problem with NMAKE version 1.11.
 The problem has been resolved with later versions of NMAKE.


 27. NMAKE U1001 Illegal Character Caused by Corrupted MAKEDIR

 Product Version(s): 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.11
 Last Modified:  4-DEC-1990    ArticleIdent: Q61978

 NMAKE version 1.11 may produce a U1001 "syntax error: illegal
 character <character> in macro" while building a project.

 NMAKE has an internal macro, MAKEDIR, which contains the full drive
 and path to the directory from where NMAKE was invoked. This macro is
 corrupted in NMAKE version 1.11 under DOS. Rather than the correct
 pathname, the macro contains "garbage" or graphics characters. This
 macro can cause the U1001 "illegal character" error message.

 To display the contents of MAKEDIR, invoke NMAKE with the /P switch.
 This switch causes all macros to be displayed to the screen. To work
 around this problem, manually set MAKEDIR in the .MAK file for the
 project. Set it to the drive and path where the project is being
 built. If MAKEDIR is manually set in the .MAK file, it will override
 the default setting and correct the problem.

 Microsoft has confirmed this to be a problem with NMAKE version 1.11.
 We are researching this problem and will post new information here as
 it becomes available.

 NMAKE version 1.11 comes with Microsoft C Professional Development
 System version 6.00 for MS-DOS and MS OS/2.

 This problem does not occur with NMAKE version 1.10. The problem
 occurs only with the DOS version of NMAKE, not the protected mode
 version of NMAKE version 1.11.


 28. Can't Use Multiple Description Blocks with NMAKE Version 1.10

 Product Version(s): 1.10
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.10 fixlist1.11 b_basiccom
 Last Modified: 25-JUL-1990    ArticleIdent: Q62332

 Page 639 of "Microsoft BASIC 7.0: Programmer's Guide" explains how you
 can use NMAKE to specify more than one description block for the same
 target.

 The example given on this page is the proper way to specify more than
 one description block; however, this feature does not function
 correctly in NMAKE version 1.10. It does function correctly in NMAKE
 version 1.11.

 NMAKE version 1.10 shipped with the Professional Development System
 (PDS) BASIC version 7.00. NMAKE version 1.11 shipped with Microsoft C
 Professional Development System (PDS) version 6.00.

 The following example specifies more than one description block for
 the same target by using two colons (::) as the separator instead of
 one. The following example is taken from Page 639 of "Microsoft BASIC
 7.0: Programmer's Guide":

       TARGET.LIB :: A.ASM B.ASM C.ASM
          MASM A.ASM B.ASM C.ASM;
          LIB TARGET -+A.OBJ -+B.OBJ -+C.OBJ;
       TARGET.LIB :: D.BAS E.BAS
          BC D.BAS;
          BC E.BAS;
          LINK D.OBJ E.OBJ;
          LIB TARGET -+D.OBJ -+E.OBJ;

 Given the two description blocks above, NMAKE should update the
 library named TARGET.LIB. In the first description block, if any of
 the assembly language files have changed more recently than the
 library, the assembly files will be assembled and the library will be
 updated with the new .OBJs. In the second description block, the BASIC
 files that have changed should be compiled and the library should also
 be updated with the new OBJs.

 When using NMAKE version 1.10, the commands in the first description
 block are executed correctly; however, the commands in the second
 description block are never executed.

 Microsoft has confirmed this to be a problem in NMAKE version 1.10.
 This problem was corrected in version 1.11.


 29. Expression in Brackets "

 Product Version(s): 1.00 1.01 1.10 1.11 | 1.01 1.10 1.11
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER |
 Last Modified: 27-JUN-1990    ArticleIdent: Q63146

 When using the !IF directive in conjunction with the square brackets
 "[]" in the NMAKE utility, all expressions inside square brackets will
 be evaluated when NMAKE initially reads the makefile, before any
 commands are executed (and before dependency blocks are evaluated).

 The square brackets are used within NMAKE to denote program
 invocations in expressions within an !IF directive, as documented in
 Section 6.3.5, Pages 120-121 of the "Advanced Programming Techniques"
 manual shipped with the Microsoft C compiler version 6.00.

 By design, all the program invocations are executed when NMAKE starts
 up, regardless of whether or not they are contained in a dependency
 block. The return values of these program invocations can then be used
 within the !IF expression to evaluate the expression.

 The following makefile displays this behavior:

    test.exe: test.c
    !IF ( [check /f] < 3 )
       cl test.c
    !ENDIF

 In this example, the program "check /f" will be executed each time the
 makefile is called, regardless of whether or not the file TEST.EXE is
 up to date.


 30. Changing Directories in Make Files Not Supported by NMK.COM

 Product Version(s): 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.11 S_QUICKC S_C
 Last Modified: 31-AUG-1990    ArticleIdent: Q64028

 Using a command to change directories in a make file will cause
 unexpected results with NMK.COM version 1.11. This is a side effect of
 a problem with NMAKE.EXE where directory changes within make files are
 executed while processing the make file, and the current directory is
 not reset upon exit.

 NMK spawns NMAKE to do its processing. While NMAKE is processing, if
 it sees a change drive/directory command, it must make the change to
 finish processing the make file. The problem is that it doesn't reset
 the drive when it is through processing. This causes NMK, when control
 is returned to it, to spawn the actual commands from the final
 drive/directory, rather than where it was originally invoked.

 The make file below, if run from Drive D, will demonstrate the
 problem. It works properly with NMAKE.EXE but not with NMK.COM.

 all: cded.exe

 cded.exe: cded.obj
   c:\
   copy cded.obj cded.exe

 cded.obj: cded.mak
   copy cded.mak c:\cded.obj

 To work around the problem, add a line at the end of each place block
 where you change the drive/directory to the original one (if known).
 For example, change the above make file to the following:

 all: cded.exe

 cded.exe: cded.obj
   c:\
   copy cded.obj cded.exe
   d:

 cded.obj: cded.mak
   copy cded.mak c:\cded.obj


 31. Spaces in Inference Rules Corrupt NMAKE Macro Expansion

 Product Version(s): 1.00 1.11 | 1.00 1.11
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_quickc
 Last Modified: 28-AUG-1990    ArticleIdent: Q65084

 If a space is inserted between the target and dependent extensions in
 an inference rule, it will cause NMAKE's default macros to expand
 incorrectly. The correct syntax for inference rules is to list the
 dependent file extension followed by the target file extension WITHOUT
 any embedded spaces.

 The following sample make files demonstrate a few of the problematic
 results that are possible if spaces are used in an inference rule. In
 both cases below, note that it is the embedded spaces that cause NMAKE
 to invoke the commands incorrectly. Removing the spaces allows NMAKE
 to generate the desired commands.

 Example 1
 ---------

 {c:\source\}.c {c:\objs\}.obj:
   cl $*

 ALL: c:\objs\foo2.obj

 c:\objs\foo2.obj: c:\source\foo2.c

 Command executed by NMAKE:

 cl {c:\objs\}

 Example 2
 ---------

 .c .obj:
   cl $<

 ALL: foo.obj

 foo.obj: foo.c

 Command executed by NMAKE:

 cl


 32. In-line File in Inference Rule Causes Bad Macro Substitution

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.11
 Last Modified: 11-NOV-1990    ArticleIdent: Q66459

 Using an in-line file inside of an inference rule can cause improper
 results in macro substitutions following the in-line file. The example
 below demonstrates the problem.

 Make File Example
 -----------------

 EXENAME=test.exe
 SAMPLEDIR=\test

 .obj.exe:
   link @<<lrf     <--- In-line file with $(EXENAME) macro
 $<                     causes the problem.
 $(EXENAME);
 <<KEEP
   cd $(SAMPLEDIR)

 test.exe:test.obj

 test.obj:test.c

 The above NMAKE description file produces the following output:

    cl -c test.c
    link @lrf
    cd test.exe    <---- This is wrong.  It should be "cd \test"
 NMAKE: fatal error U1077: 'cd' return code 1
 Stop.

 The third line of the output is incorrect. The macro $(SAMPLEDIR) is
 replaced with the value of $(EXENAME).

 Microsoft has confirmed this to be a problem in version 1.11. We are
 researching this problem and will post new information here as it
 becomes available.


 33. Documentation Error: Extmake Syntax for %|partsF Incorrect

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  6-NOV-1990    ArticleIdent: Q66474

 The extmake syntax for determining the complete name of the first
 dependent in a NMAKE description file is incorrectly described in the
 "Advanced Programming Techniques" manual on Page 124.

 The extmake syntax described on Page 124 of the "Advanced Programming
 Techniques" manual lists the syntax as

    %|partsF

 where parts is one or more of the following:

    Letter            Description
    ------            -----------

    d                 Drive
    e                 File extension
    f                 File base name
    p                 Path
    s                 Complete name

 However, "s" is not a valid selection. You may use %s, or you may use
 %|partsF, where "parts" is one or more of the above (d, e, f, or p,
 but not s). The following makefile illustrates the problem.

 Sample Makefile
 ---------------

    sample.obj: sample.c
         cl /c %|sF

 If this makefile is run, it will produce the following error message:

    NMAKE : fatal error U1098: extmake syntax in sF incorrect

 The online help specifies the correct syntax for using the extmake
 switch:

    Letter     File-Specification Part
    ------     -----------------------

    p          Path
    d          Drive
    f          Base name
    e          Extension

 The makefile below shows the correct extmake syntax for obtaining the
 complete name of the first dependent:

 Correct Makefile
 ----------------

    sample.obj: sample.c
         cl /c %s


 34. Problem in NMAKE 1.11 with Multiple Dependency Blocks

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.11 fixlist1.12 s_c
 Last Modified:  9-NOV-1990    ArticleIdent: Q66571

 The sample makefile below will be correctly executed in all cases
 except if the target is missing. In that case, both sets of commands
 will be executed even though the second set is not necessary.

 Microsoft has confirmed this to be a problem in NMAKE version 1.11.
 This problem has been corrected in version 1.12, which shipped with
 Microsoft COBOL version 4.00.

 Multiple Dependency blocks are supposed to be evaluated one at a time.
 In the sample makefile, because the target is missing when NMAKE is
 invoked, it assumes that both sets of commands will need to be
 invoked. This is incorrect behavior.

 Sample Makefile
 ---------------

 test.exe :: test.obj test.def
     link /nod test,,,slibcew libw, test.def
     rc test.res

 test.exe :: test.res
     rc test.res


 35. NMAKE 1.11 Fails to Stop If Command Is Redirected

 Product Version(s): 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.11 fixlist1.12
 Last Modified:  9-NOV-1990    ArticleIdent: Q66572

 If the command line that NMAKE invokes is redirected to another
 output file and the command returns a non-zero return code, NMAKE
 version 1.11 will not stop the build process.

 Microsoft has confirmed this to be a problem in the DOS version of
 NMAKE.EXE. This problem has been corrected in version 1.12.

 The following is a sample make file that, with NMAKE version 1.11,
 will fail to stop if the compiler returns an error; with version 1.12,
 it correctly stops the build process:

 all: foo.exe

 foo.obj: foo.c
    cl /c /AS foo.c >foo.err

 foo.exe: foo.obj
    link /NOI /NOE foo.obj;

 The easiest way to workaround this is to redirect from the command
 line, for example:

    nmake /f foo.mak >foo.err

 The drawback to this is that you can only have one error log.


 36. NMAKE /N Doesn't Work Across Multiple Dependency Blocks

 Product Version(s): 1.11 1.12 | 1.11 1.12
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.11 buglist1.12
 Last Modified:  7-NOV-1990    ArticleIdent: Q66644

 Given the sample makefile below and the fact that mod2.c has been
 changed, invoking NMAKE /N displays the following commands:

    cl /c -c mod2.c
    lib sub.lib -+ mod2.obj;

 However, if NMAKE is run without the /N parameter, the following
 commands will be executed:

    cl /c -c mod2.c
    lib sub.lib -+ mod2.obj;
    link boss.obj,,,sub.lib;

 The /N switch is used to debug the logic of makefiles without actually
 processing them. In this case, the commands that /N indicates will be
 executed are not the same as those that actually are executed. This is
 caused by the multiple dependencies for sub.lib. If the makefile is
 changed to eliminate the multiple dependency blocks, the /N switch
 will function correctly.

 Microsoft has confirmed this to be a problem in NMAKE versions 1.11
 and 1.12. We are researching this problem and will post new
 information here as it becomes available.

 Sample Code
 -----------

 CFLAGS=/c

 .obj.exe:
         link $<,,,sub.lib;

 all:boss.exe

 boss.exe:boss.obj  sub.lib

 boss.obj:

 sub.lib:: mod1.obj
         lib $@ -+ mod1.obj;

 sub.lib:: mod2.obj
         lib $@ -+ mod2.obj;


 37. U4007 Error Can Be Caused By Not Using Quotation Marks

 Product Version(s): 1.11 1.12
 Operating System:   OS/2
 Flags: ENDUSER |
 Last Modified:  7-NOV-1990    ArticleIdent: Q66646

 If you have a makefile for OS/2 that uses long filenames, you must use
 quotation marks around the long filenames. For instance, if the
 following makefile is used, it will generate the U4007 error message
 ("file name too long:  truncating to 8.3"):

 Sample Makefile
 ---------------

 all: thisisalongfilename.exe

 thisisalongfilename.exe: thisisalongfilename.obj
    link thisisalongfilename.obj;

 thisisalongfilename.obj: thisisalongfilename.c
    cl /c /Tcthisisalongfilename.c

 If the makefile above is changed to the following version, the error
 will not be generated:

 Sample Makefile
 ---------------

 all: "thisisalongfilename.exe"

 "thisisalongfilename.exe": "thisisalongfilename.obj"
    link "thisisalongfilename.obj";

 "thisisalongfilename.obj": "thisisalongfilename.c"
    cl /c /Tc"thisisalongfilename.c"

 For more information on this behavior, please see the README.DOC file
 shipped with Microsoft C version 6.00.


 38. Cause of U4004 Error Message

 Product Version(s): 1.10   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified:  7-NOV-1990    ArticleIdent: Q66649

 The U4004 error message is generated by NMAKE when it encounters
 multiple build dependency blocks for a single target. The following is
 a sample makefile:

 all: tty.exe

 tty.res: tty.rc tty.dlg tty.h
     rc -r tty.rc

 tty.obj: tty.c
    cl -c -AS -Gsw -Os -Zdp tty.c

 wstdio.obj: wstdio.c
    cl -c -AS -Gsw -Os -Zdp wstdio.c

 tty.exe: tty.obj wstdio.obj tty.def
     link /NOD tty wstdio,,,libw slibcew,tty.def
     rc tty.res

 tty.exe: tty.res tty.dlg tty.h
    rc tty.res

 To eliminate the error, use the multiple dependency block separator --
 a pair of colons (::). In the above makefile, the two dependency
 blocks for tty.exe should use this syntax. The multiple dependency
 block separator is documented further on page 109 of the "Advanced
 Programming Techniques" manual, as well as in the online help.

 The following is the corrected makefile:

 all: tty.exe

 tty.res: tty.rc tty.dlg tty.h
     rc -r tty.rc

 tty.obj: tty.c
    cl -c -AS -Gsw -Os -Zdp tty.c

 wstdio.obj: wstdio.c
    cl -c -AS -Gsw -Os -Zdp wstdio.c

 # Note the use of the double colon below and in the next block...

 tty.exe:: tty.obj wstdio.obj tty.def
     link /NOD tty wstdio,,,libw slibcew,tty.def
     rc tty.res

 tty.exe:: tty.res tty.dlg tty.h
    rc tty.res


 39. Link Not Performed During Build or Make

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.00 fixlist1.10 fixlist1.11 s_c s_link s_pwb
 Last Modified: 14-DEC-1990    ArticleIdent: Q67482

 During a build inside the Programmer's WorkBench (PWB) (using PWB.COM)
 or while using NMK.COM from the command line, the build operation
 returns successfully but no .EXE file is created.

 This problem may be caused by an incorrectly set COMSPEC environment
 variable. If the COMSPEC environment variable contains any extra
 characters, NMK.COM fails to properly spawn the linker. This affects
 the PWB as well because, under DOS, PWB.COM spawns the build commands
 the same way as NMK.COM. Two examples of COMSPEC environment variables
 that cause this problem are shown in the following:

    COMSPEC=C:\COMMAND.COM /E:512 /P
    COMSPEC=C:\COMMAND.COM;

 Microsoft has confirmed this to be a problem in PWB.COM version 1.00
 and NMK.COM version 1.00. This problem was corrected in PWB.COM
 version 1.10 and NMK.COM version 1.11.


 40. NMK.COM Will Execute PWB.SHL If it Exists

 Product Version(s): 1.00 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | S_C S_PWB S_QUICKC S_NMK
 Last Modified: 28-DEC-1990    ArticleIdent: Q67776

 NMK.COM will execute the PWB.SHL file if it exists in the subdirectory
 specified by the TMP environment variable. After spawning NMAKE to
 parse the desired makefile, PWB.SHL will be executed as a batch file
 with the commands listed in reverse order.

 This is expected behavior since NMK actually spawns NMAKE with the /z
 option. This instructs NMAKE to preprocess the makefile, writing out
 the commands to be performed into the file PWB.SHL, which is placed in
 the directory pointed to by the TMP environment variable. After NMAKE
 is finished, NMK reads the PWB.SHL file and executes the required
 commands. Once it is finished, the PWB.SHL file is set to 0 bytes or
 deleted.

 To see this behavior, create a file and name it PWB.SHL, placing the
 following two lines in it:

    type listing.txt
    dir > listing.txt

 Place this file in the subdirectory pointed to by the TMP environment
 variable. The following command will spawn NMAKE /z in an attempt to
 parse PROGRAM.MAK, and then execute PWB.SHL:

    nmk /f program.mak

 PWB.SHL will be set to 0 bytes or deleted after all commands have been
 executed.

 If PROGRAM.MAK does not exist, NMAKE will report an error informing
 you of that fact, and then NMK will proceed to execute PWB.SHL as
 described above.

 If you do not have a TMP environment variable, PWB.SHL will be
 executed if it exists in the current subdirectory.

 A side effect to be aware of is the following scenario. If you have
 shelled out of the Programmer's WorkBench to run your program (from
 the Execute selection on the Run menu) and your program hangs, forcing
 you to reboot, a PWB.SHL file will be left in your TMP subdirectory.
 If, after rebooting, you happen to run NMK before going into PWB, NMK
 will find the PWB.SHL file in the TMP subdirectory and execute it,
 causing PWB to be invoked even though you had not explicitly invoked
 PWB since the reboot.


 41. NMAKE Does Not Expand Wildcard Characters

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified:  6-FEB-1991    ArticleIdent: Q67794

 Page 107 of the "Advanced Programming Techniques" manual that shipped
 with Microsoft C version 6.00 states:

    NMAKE expands wild cards in target names when it reads the
    description file.

 NMAKE does not expand these wildcard characters when passing the
 wildcard to the compiler. The example given works correctly because
 the compiler expands the wildcard on its own. If you use a compiler
 that does not expand wildcards, the example given will not work.


 42. NMAKE Default Is to Build Only the First Target in a Makefile

 Product Version(s): 1.00 1.01 1.11 1.12 | 1.01 1.11 1.12
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER |
 Last Modified: 15-JAN-1991    ArticleIdent: Q40184

 The NMAKE file maintenance utility will only "make" the first target
 in the makefile if no target is explicitly given on the command line.

 Although the following sample makefile will both compile and link
 PROG1.EXE when used with MAKE, it will only compile when the NMAKE
 utility is used. This is an important consideration when porting
 makefiles from MAKE to NMAKE.

 # Sample makefile MAKEFILE1

 PROG1.OBJ : PROG1.C
     cl /Zi /c PROG1.C

 PROG1.EXE : PROG1.OBJ
     link /CO PROG1.OBJ

 If all files are out of date with PROG1.C, and MAKEFILE1 is executed
 with the standard invocation as follows

    NMAKE /f makefile1

 the only command executed from MAKEFILE1 will be the following:

    cl /Zi /c prog1.c

 The LINK command will not be executed because NMAKE did not receive a
 specific target; thus, it only makes the first target in the makefile.
 To achieve the desired results, the desired target (PROG1.EXE) must be
 specified on the NMAKE command-line or the following line could be
 added to MAKEFILE1 (it must be the first line in the makefile):

    ALL : PROG1.EXE

 This pseudotarget "ALL" will be made because it will be the first
 target in the makefile. By using the pseudotarget, it is guaranteed
 that all dependencies will be made because the dependents are always
 out of date. This will force NMAKE to make all targets dealing with
 PROG1.EXE.

 Please refer to the NMAKE documentation shipped with your compiler or
 assembler for more information.


 43. Accessing Environment Variables Inside MAKE or NMAKE Makefile

 Product Version(s): 1.00 1.01 1.10 1.11 1.12 | 1.01 1.10 1.11 1.12
 Operating System:   MS-DOS                   | OS/2
 Flags: ENDUSER | s_make
 Last Modified: 23-JAN-1991    ArticleIdent: Q59141

 You can access environment variables within a MAKE or NMAKE makefile
 in the same way that you access user-defined macros. The only
 difference is that the names of environment variables must be
 capitalized when used in this manner. For example:

 SOURCE=c:\mysource
 # the INCLUDE "macro" will pick up your INCLUDE environment variable

 file.obj : $(SOURCE)\file.c $(INCLUDE)\file.h
     cl /c /Zi /Od $(SOURCE)\file.c


 44. Recursively Calling NMAKE Using the MAKEFLAGS Macro

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 17-JAN-1991    ArticleIdent: Q68234

 According to page 113 of the "Microsoft C Advanced Programming
 Techniques" manual, if you want to invoke NMAKE recursively, the macro
 $(MAKEFLAGS) can be used to pass the command-line switches to the
 recursively invoked NMAKE. However, the $(MAKEFLAGS) macro will
 contain only the letters of the switches and will not contain the
 actual command-line syntax.

 For example, if the original command line contained "/D /N", the
 $(MAKEFLAGS) macro will contain "DN". This results in NMAKE trying to
 use the $(MAKEFLAGS) macro as the name of the makefile, rather than as
 command-line switches. To use the $(MAKEFLAGS) macro to invoke NMAKE
 recursively, it is necessary to precede it with a hyphen (-) or
 forward slash (/) so that NMAKE uses the macro as a set of
 command-line switches. The documentation should read:

    $(MAKE) -$(MAKEFLAGS)


 45. Placing a Target File in Different Directory Than Dependents

 Product Version(s): 4.07   | 4.07
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_make
 Last Modified:  6-FEB-1991    ArticleIdent: Q46354

 To put a target file in a directory different from its dependent file
 in a makefile, you must explicitly name the path for the target file.
 When compiling, use the /Fo switch and a path to place the .OBJ file
 in a different directory from the source. When linking, give the full
 pathname when specifying the .EXE file parameter.

 The following example demonstrates both aspects:

 # MAKE SURE THERE IS A TRAILING BLANK AFTER THE FINAL BACKSLASH
 LONGPATH=e:\c51\binr\
 SHORTPATH=e:\c51\

 pixel.obj:  $(LONGPATH)pixel.c
 # USE /Fo SWITCH TO PUT .OBJ FILE IN DIFFERENT DIRECTORY
   cl /Fo$(SHORTPATH) /c $(LONGPATH)pixel.c

 Note that if you use a macro in the makefile for the pathname (as
 shown above), then you must be sure the final backslash (\) in the
 pathname is followed by a trailing space. If there is no trailing
 space, the backslash will be interpreted as a line-continuation
 character. When you create the makefile, use an editor that will
 preserve a trailing space, such as the Programmer's WorkBench or the
 Microsoft Editor (if you set the "trailspace" switch).


 46. Extmake Switch Does Not Expand Macros

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.11
 Last Modified: 24-JAN-1991    ArticleIdent: Q68379

 The following NMAKE description file shows that macro substitution
 does not occur when using the extmake switch.

 To show the error, set SUBDIR to a subdirectory and execute NMAKE on
 the makefile while in ANOTHER subdirectory.

 Sample Makefile
 ---------------

 SUBDIR = subdir

 foo.exe: $(SUBDIR)\foo.c
      cl %|pfeF

 Resulting command:  cl $(SUBDIR)\foo.c

 The workaround for this particular problem is to replace the extmake
 switch with the predefined macros (that is, $** and $?).


 47. The D Modifier to $? Is Broken in NMAKE Version 1.11

 Product Version(s): 1.11   | 1.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.11 fixlist1.12
 Last Modified: 24-JAN-1991    ArticleIdent: Q68381

 The D modifier to the $? macro is supposed to return the directory and
 drive portion of the dependent. This does not work properly with NMAKE
 version 1.11. Instead, the full pathname and filename are returned.
 This was corrected in NMAKE version 1.12, which shipped with Microsoft
 COBOL version 4.00.

 Sample Makefile
 ---------------

 all : c:\dos\command.com
    echo The D modifier of $? is $(?D)


 48. $$(@F) Macro Doesn't Work with NMAKE Version 1.01

 Product Version(s): 1.01   | 1.01
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | buglist1.01 fixlist1.11
 Last Modified: 24-JAN-1991    ArticleIdent: Q68388

 The $$(@F) macro illustrated on page 297 of the "Microsoft FORTRAN
 CodeView and Utilities User's Guide" for version 5.00 will not
 function correctly in NMAKE version 1.01. This has been corrected in
 NMAKE version 1.11, which shipped with Microsoft C version 6.00.

 The following is the example from page 297:

 DIR=c:\include
 $(DIR)\global.h $(DIR)\types.h $(DIR)\macros.h: $$(@F)
      !COPY $? $@

 With NMAKE version 1.01, this will only work for the first file in the
 list. Subsequent files are not processed. NMAKE 1.11 correctly copies
 all three files to the c:\include directory.


 49. NMK Displays Only First of Multiple Commands

 Product Version(s): 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.11 S_C S_NMK
 Last Modified:  1-FEB-1991    ArticleIdent: Q68658

 NMK version 1.11 displays only the first of multiple commands it is
 executing when the exclamation point (!) command modifier is used with
 the predefined macro $? or $**.

 The ! command modifier executes the command for each dependent file if
 the command uses the predefined macro $? or $**. The $? macro refers
 to all dependent files that are out-of-date with respect to the
 target. The $** macro refers to all dependent files in the description
 block.

 The sample makefile below echoes each filename to the screen. The
 NMAKE output shows the correct result; each ECHO command is displayed
 and executed. Likewise, the NMK output executes each ECHO command;
 however, only the first command is displayed to the screen.

 Sample Makefile
 ---------------

 ALL: foo1.c foo2.c foo3.c
       !ECHO $**

 Output:

       NMAKE                      NMK
 -----------------         -----------------
       ECHO foo1.c               ECHO foo1.c
 foo1.c                    foo1.c
       ECHO foo2.c         foo2.c
 foo2.c                    foo3.c
       ECHO foo3.c
 foo3.c

 Microsoft has confirmed this to be a problem in NMK version 1.11. We
 are researching this problem and will post new information here as it
 becomes available.


 50. NMAKE Doesn't Allow CD Command That Only Specifies Drive

 Product Version(s): 1.11 1.12 | 1.11 1.12
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | buglist1.11 buglist1.12
 Last Modified:  5-FEB-1991    ArticleIdent: Q68836

 DOS and OS/2 command lines allow you to see the current directory of a
 drive by using the CD (change directory) command. For example, the
 command "CD D:" will return the current directory for the D drive.
 Because this is a valid DOS or OS/2 command, NMAKE should allow you to
 perform the command without error. However, when the NMAKE file below
 is executed, the following message occurs:

    NMAKE: fatal error U1077: 'cd' :return code '1'

 NMAKE treats the CD command as a special case and fails to execute the
 command correctly.

 Sample NMAKE File:

 all:
    cd d:

 Microsoft has confirmed this to be a problem in NMAKE versions 1.11
 and 1.12. We are researching this problem and will post new
 information here as it becomes available.


 51. NMK Macros Do Not Override Environment Variables

 Product Version(s): 1.11
 Operating System:   MS-DOS
 Flags: ENDUSER | buglist1.11
 Last Modified:  6-FEB-1991    ArticleIdent: Q68946

 Macros that are created to redefine environment variables (such as
 INCLUDE, LIB, and PATH) do not work correctly when the description
 file is executed using NMK.COM, rather than NMAKE.EXE.

 The description file below, when executed by NMAKE.EXE, will look for
 the include files in the directory "E:\C\INCLUDE". If the same
 description file is executed by NMK.COM, the include directory will be
 determined by the include environment variable.

 Sample Code
 -----------

 INCLUDE=E:\C\INCLUDE

 FOO.EXE : FOO.OBJ
    link foo.obj;

 FOO.OBJ : FOO.C
    cl /c foo.c

 Note: This example will reproduce the problem correctly only if the
 following conditions are met.

 1. FOO.C exists.
 2. FOO.C contains a line of the form:

       #include <INC_FILE.H>

 3. INC_FILE.H exists in the directory "E:\C\INCLUDE".
 4. INC_FILE.H does not exist in the default include directory.

 Finally, NMK does change the variable for arguments that are in the
 makefile. Therefore, to work around the problem above, you can use the
 following example:

 INCLUDE=E:\C\INCLUDE

 FOO.EXE : FOO.OBJ
    link foo.obj;

 FOO.OBJ : FOO.C
    cl /c /I$(INCLUDE) foo.c






 Microsoft Development Utilities
 =============================================================================


 1. Hyphen in File or Directory Name Causes LIB Error U2155

 Product Version(s): 3.00 3.04 3.07 3.08 3.10 3.11 3.14 3.17 | 3.10 3.11 3.14
 Operating System:   MS-DOS                                  | OS/2
 Flags: ENDUSER | s_lib dash minus sign
 Last Modified: 16-JAN-1991    ArticleIdent: Q67880

 The Microsoft Library Manager utility LIB.EXE does not allow file or
 directory names to contain a hyphen (-) character. If a file or
 directory name containing a hyphen is passed to LIB.EXE, the following
 error will be generated:

    LIB : error U2155: <path> : module not in library; ignored

 Although a hyphen is a valid character for a DOS or OS/2 filename, LIB
 interprets this character as the extraction operator that tells LIB to
 remove an object module from an existing library. Since LIB is
 assuming everything following the hyphen is the name of an object
 module that you want removed, and since this is not an actual module
 name, the U2155 error is generated.

 A common situation where this error may occur is while installing one
 of the Microsoft language products that build combined libraries
 during the installation process. You may receive the U2155 error when
 running a Setup program if you have specified a directory name during
 setup that contains a hyphen. For example, many C users install the C
 compiler in a directory called MS-C, but Setup then fails when LIB is
 called to build the combined libraries in that directory.

 This is expected behavior for LIB.EXE and is the result of the
 established command-line syntax. Unless the command-line syntax is
 changed, the hyphen cannot be recognized as a filespec character
 instead of an operator.


 2. How to Add a Category in QuickHelp

 Product Version(s): 1.70   | 1.40 1.70
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_qh s_helpmake
 Last Modified: 24-JAN-1991    ArticleIdent: Q66631

 When creating a help database with HELPMAKE, new categories may be
 added to the Microsoft Advisor help system for use in the QuickHelp
 utility. To add selections that will appear under the QuickHelp
 Categories menu, use the topic "List categories." Under the List
 categories topic, list the selections that need to be added to the
 menu.

 The following is a sample help file:

    File CATEGORY.TXT
    -----------------

       .context List categories
       Category1
       Category2

       .context Category1
       This is the information under the first category.

       .context Category2
       This is the information under the second category.

 For the file CATEGORY.TXT shown above, the HELPMAKE command line will
 appear as follows:

    helpmake /E8 /Ocategory.hlp category.txt

 The choice of /E8 for partial compression is strictly arbitrary in
 this case, and is shown for demonstration purposes only. The maximum
 compression can be achieved by using /E15, and no compression is
 denoted by /E0.

 When the above help database is added to the list of databases for the
 Advisor, the topics "Category1" and "Category2" will be added under
 the Categories menu.

 The items that are placed in the List categories topic should be
 topics that are already defined with ".context" strings; otherwise,
 when the item is selected from the Categories menu, a message will be
 displayed stating that the topic could not be found.

 When using HELPMAKE with the "/C" option, which preserves case
 sensitivity, you must use the string "List categories" exactly. The
 case is important. Failure to use the exact case for each letter will
 cause the Advisor to ignore the categories you have added.


 3. Help Files for QuickC Require Special "Backtrace" Declaration

 Product Version(s): 6.00 6.00a | 6.00 6.00a
 Operating System:   MS-DOS     | OS/2
 Flags: ENDUSER | docerr s_quickc s_helpmake
 Last Modified: 11-FEB-1991    ArticleIdent: Q68678

 When creating a help file using the Microsoft Helpmake utility, !B is
 defined to have the effect of backtracing to the previous help screen
 (if available). However, this is true only when using QuickHelp or the
 Programmer's WorkBench (PWB). If an attempt is made to use this help
 file with QuickC, the link will issue a beep and no backtrace will be
 allowed.

 The documentation included with Microsoft C version 6.00 does not
 reference the exclamation (!) character as being a special function.
 However, on pages 20-21, the "Professional Advisor Library Reference"
 lists all the options available for this command. It also states that
 the !CQ.HB command will allow QuickC version 2.00 compatibility.
 However, it should be noted that the compatibility for this function
 is for QuickC version 2.50 as well. The use of this command gives
 complete compatibility through C versions 6.00 and 6.00a, as well as
 QuickC versions 2.50 and 2.00.

 Another error in the documentation is that !CQ.HB must be in all
 lowercase letters (that is, !cq.hb). HelpMake will not issue an error
 message with an uppercase command, but it will also not allow a
 backtrace to be performed.


 4. Omitting .LIB Extension with BIND Gives U1268 Error

 Product Version(s): 1.10 1.30 | 1.10 1.30
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_bind
 Last Modified: 15-JAN-1991    ArticleIdent: Q29135

 Question:

 When I try to bind an application using the BIND utility, I receive
 the following error message:

    BIND : fatal error U1268: duplicate infile given

 This is my BIND command line:

    bind file.exe c:\c\lib\os2 c:\c\lib\api

 What is causing this error?

 Response:

 This error occurs with BIND if you do not specify the .LIB extension
 for the libraries, OS2.LIB and API.LIB. The correct command line is as
 follows:

    bind file.exe c:\c\lib\os2.lib c:\c\lib\api.lib

 Note that BIND version 1.00 displays the same error, but does not
 display an error number.


 5. C 6.00 Utility Support for OS/2 Long Filenames

 Product Version(s): 6.00
 Operating System:   OS/2
 Flags: ENDUSER | s_link s_nmake s_c
 Last Modified: 28-JAN-1991    ArticleIdent: Q58487

 The utilities shipped for Microsoft C version 6.00 provide limited
 support for OS/2 long filenames introduced in OS/2 version 1.20.

 The following is a list of the limitations:

 1. Long filenames with quotation marks are supported via the command
    line. For example:

       "fooo bar"

 2. Embedded quoted long filenames on the command line are not
    supported. For example:

       d:\foo\" bar xyzzy"

 3. Link supports one quoted long filename per argument. For example

       "foo bar"+"bar foo"

    will resemble the following:

       "foo bar+bar foo"

 4. NMAKE provides long filename support inside the makefile with the
    restriction (beyond 1 and 2 above) that target and dependent names
    cannot have a period (.) as the first character (conflicts with
    inference rules). For example:

       ".foo bar.c".".foo bar.exe"


 6. Modifying Existing Help Files with HELPMAKE (QuickC Example)

 Product Version(s): 1.00 1.04 1.05 1.06 | 1.04 1.05 1.06
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER | s_helpmake s_qh
 Last Modified: 24-JAN-1991    ArticleIdent: Q40599

 You can add to or change the information in the online help files that
 are accessible from QuickHelp, PWB, and QuickC. To accomplish this, do
 the following:

 1. Decompress the existing help file using HELPMAKE.EXE.

 2. Edit the resulting source listing of the help file.

 3. Recompress this modified file using HELPMAKE.EXE.

 The example below illustrates this process.

 There is a known coding error in the Font function examples in the
 QuickC 2.00 online help. This error occurs in the following code line:

    strcat (fondir, "\*.fon") ;

 This statement should be corrected to read as follows:

    strcat (fondir, "\\*.fon") ;

 To correct this online example in the GRAPHICS.HLP file, do the
 following:

 1. Decompress GRAPHICS.HLP, as follows:

       HELPMAKE /D /Ographics.src /V Graphics.hlp  > decode.log

    /D  Tells HELPMAKE to decode GRAPHICS.HLP
    /O  Tells HELPMAKE to name the output file GRAPHICS.SRC
    /V  Tells HELPMAKE to be verbose in decoding information

    "> decode.log"  redirects decoding information to DECODE.LOG.
    This DOS redirection is not necessary, but is helpful.

 2. Edit GRAPHICS.SRC

    Using an editor of your choice, search GRAPHICS.SRC for the
    code line that contains "\*.fon". When you locate the strcat()
    instruction mentioned above, you will notice that the line already
    correctly reads as follows:

       strcat (fondir, "\\*.fon") ;

    This is the correct coding for the C language. However,
    HELPMAKE.EXE views the backslash, "\", as a flag for instructions.
    Therefore, the first "\" is interpreted and is subsequently not
    viewable in the online help.

    If you intend a "\" to be viewed from within the online help, you
    must type two backslashes. That is why the strcat() instruction is
    displayed in the online help with only one "\".

    To display two successive backslashes from within online help, you
    must type four backslashes in the source file, which HELPMAKE will
    interpret and compress into a helpfile.

    In this example, you would modify the following statement

       strcat (fondir, "\\*.fon") ;

    to read as follows:

       strcat (fondir, "\\\\*.fon") ;

 3. Recompress GRAPHICS.SRC into a help file, as follows:
    (This process may take up to 10 minutes with this file.)

    HELPMAKE /E15 /A: /W128 /Ographics.hlp graphics.src /V > encode.log

    /E15   Tells HELPMAKE to fully compress GRAPHICS.SRC
    /A:    Tells HELPMAKE to view a ':' as an operator
    /W128  Tells HELPMAKE to truncate lines longer than 128 characters
    /O     Tells HELPMAKE to name the output file GRAPHICS.HLP
    /V     Tells HELPMAKE to output verbose encoding information

    "> encode.log" redirects encoding information to ENCODE.LOG
    This is helpful, but it is not necessary.

 4. Copy the new GRAPHICS.HLP to the directory with your other
    help files.

 For further information, refer to the printed or online documentation
 supplied with your version of HELPMAKE.


 7. HELPMAKE Interprets Backslashes as Formatting Flags

 Product Version(s): 1.00 1.04 1.05 1.06 | 1.04 1.05 1.06
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER | s_helpmake
 Last Modified: 24-JAN-1991    ArticleIdent: Q40598

 The Microsoft HELPMAKE utility interprets a backslash (\) as a
 formatting flag. If you want to display a backslash in the online
 help, you must type two successive backslashes (\\). The first
 backslash is interpreted; the second is displayed.

 For further information on formatting flags, refer to the HELPMAKE
 documentation in the utilities manual, or the online help supplied
 with your particular compiler.


 8. HELPMAKE: "/A:" Must Be Used When Using Colon (:) Commands

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | s_helpmake s_quickc docerr
 Last Modified: 28-JAN-1991    ArticleIdent: Q42771

 In at least two places in the "Microsoft QuickC Tool Kit" version 2.00
 manual, it is implied that the colon (:) is used as a default for
 HELPMAKE commands. However, it is never explicitly stated that
 HELPMAKE must be invoked with the "/A:" option when encoding the help
 database.

 In fact, for any HELPMAKE colon (:) command to be recognized and
 correctly interpreted during the encoding process, the "/A:" switch
 must be used. For example, to encode the source file HELPTEST.SRC into
 the help database HELPTEST.HLP, the following line should be used
 (where "/A:" specifies the control character; "/E" indicates that the
 file is being encoded, not decoded; and "/O" gives the destination
 filename):

    HELPMAKE /A: /E /OHELPTEST.HLP HELPTEST.SRC

 HELPMAKE options may be in either uppercase or lowercase letters.


 9. Specifying Anchor Blocks in Help Files in RTF

 Product Version(s): 1.05   | 1.05
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 31-JAN-1991    ArticleIdent: Q68688

 Rich Text Format (RTF) is a text format supported by Microsoft Word
 and other word processors. HELPMAKE.EXE can use an RTF file (and the
 RTF symbols) to create help databases for the Microsoft Advisor.
 However, because \a (Anchor text for cross-reference) is not an RTF
 symbol, there is no documented method for creating hyperlinks that
 have more than one word.

 When Helpmake encodes RTF, any text between an RTF code and hidden
 text on a single line becomes a hyperlink. For example, the following

    {\bHyperlink here}{\vhyperlink.dat}

 will cause "Hyperlink here" to be displayed in bold type, and be a
 hyperlink to the topic "hyperlink.dat". To create an anchor block of
 unformatted text, use the \plain code. For example, the following

    {\plainplain hyperlink}{\vhyperlink.dat}

 will cause "plain hyperlink" to be displayed in normal text, and be a
 hyperlink to "hyperlink.dat". If you want to create a hyperlink that
 has only one word, anchor blocks are not needed. Finally, a link must
 fit entirely on one line. You cannot continue invisible or anchored
 text over a line break.

 Sample Code
 -----------

    {\rtf0
    >> open \par
    {\b Include:}   <fcntl.h>, <io.h>, <sys\\types.h>, <sys\\stat.h>

    {\b Prototype:}  int open(char *path, int flag[, int mode]);\par
        flag: O_APPEND  O_BINARY   O_CREAT  O_EXCL  O_RDONLY\par
         O_RDWR    O_TEXT   O_TRUNC  O_WRONLY\par
         (can be joined by |)\par
        mode: S_IWRITE  S_IREAD   S_IREAD | S_IWRITE\par
    \par
    {\b Returns:}    a handle if successful, or -1 if not.\par
      errno:  EACCES, EEXIST, EMFILE, ENOENT\par
    \par
    {\b See also:}   {\plain Example Program}{\v open.ex},\par
    {\ul Template}{\v open.tp}, access, chmod, close,\par
    creat, dup, dup2, fopen, sopen, umask\par
    }

 For more information, see the online help and Chapter 7 in the
 "Microsoft C Advanced Programming Techniques" manual.


 10. RTF Codes \fi<n> and \li<n> Use Twips Instead of Spaces

 Product Version(s): 1.06   | 1.06
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr
 Last Modified: 31-JAN-1991    ArticleIdent: Q68694

 The Rich Text Format codes \fi<n> and \li<n> used for creating help
 files are incorrectly described in the online help. The online help
 states that the code \fi<n> indents the first line of the paragraph
 <n> spaces, and the code \li<n> indents the entire paragraph <n>
 spaces from the left margin.

 However, the value of <n> is the number of twips and not the number of
 spaces. A twip is 1/20 of a point or 1/1440 of an inch; 180 twips
 approximates one space (that is, \li720 will indent the entire
 paragraph four spaces).

 Page 4 of the "Professional Advisor Library Reference" describes the
 RTF codes \fi and \li but does not mention the <n> parameter to indent
 the paragraphs.

 Page 155 of the "Microsoft C Advanced Programming Techniques" manual
 describes the correct syntax for the RTF codes but does not mention the
 format for <n>.


 11. Help Databases Not Properly Decoded by HELPMAKE.EXE

 Product Version(s): 1.03 1.05 1.06 | 1.03 1.05 1.06
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | buglist1.03 buglist1.05 buglist1.06
 Last Modified:  6-FEB-1991    ArticleIdent: Q68989

 When using HELPMAKE.EXE to decode concatenated help databases, you
 must use the "Decode Split" option (/DS). If a concatenated help
 database is decoded with either "Decode" (/D) or "Decode Unformatted"
 (/DU), HELPMAKE may be caught in an infinite loop that will eventually
 fill the hard disk.

 If OS2.HLP is decoded with

    helpmake /D /Ooutfile OS2.HLP

 HELPMAKE will decompress the first database in OS2.HLP over and over
 until either the disk fills up or you stop the program (with a
 CTRL+BREAK, for instance).

 If OS2.HLP is decoded with

    helpmake /DS OS2.HLP

 it is broken into STRUCT.HLP, MACROS.HLP, and TABLES.HLP. These help
 files can then be decoded properly with the /D or /DU option.

 If you don't know how a help file is assembled, the following are the
 steps to take to decompress it:

 1. Save a backup copy of the help file in case of problems.

 2. Rename the help file to "TEMP.HLP".

 3. Split the file as follows:

       HELPMAKE /DS TEMP.HLP

    If the file is not a concatenated database, you will get a single
    file with the name of the help database as it was originally built
    (the internal database name).

    If the file is a concatenated database, you will get individual
    help files with the internal database names. For OS2.HLP, these are
    STRUCT.HLP, MACROS.HLP, and TABLES.HLP.

 4. Decode the resulting files as follows:

       HELPMAKE /D TEMP1.HLP /OTEMP1.SRC
       HELPMAKE /D TEMP2.HLP /OTEMP2.SRC

 Microsoft has confirmed this to be a problem with HELPMAKE.EXE versions
 1.03, 1.05, and 1.06. We are researching this problem and will post new
 information here as it becomes available.


 12. Always Use Latest Version of HIMEM and Other Memory Utilities

 Product Version(s): 2.50 2.60
 Operating System:   MS-DOS
 Flags: ENDUSER | s_codeview s_himem s_ramdrive s_smartdrv
 Last Modified: 15-JAN-1991    ArticleIdent: Q60830

 The newest versions of the memory management utilities (HIMEM.SYS,
 RAMDRIVE.SYS, and SMARTDRV.SYS) should be used at all times. For
 instance, if you use CodeView Version 3.00 (first shipped with
 Microsoft C Version 6.00) and you use a version of HIMEM.SYS earlier
 than what was shipped with the C 6.00 package, you may experience a
 number of problems, including the following:

 1. You may get spurious error messages such as "Not enough extended
    memory available," even if you have more than enough extended
    memory installed.

 2. You may receive the error "CV1319: CodeView initialization error"
    when trying to invoke CodeView.

 3. Your computer may hang or reboot.

 As memory management technology progresses, the Microsoft tools and
 utilities that use the technology are also updated. Therefore, it is
 critical that the latest versions of the memory utilities (HIMEM.SYS,
 RAMDRIVE.SYS, SMARTDRV.SYS, etc.) be installed. Tools such as CodeView
 and the Programmer's WorkBench (PWB) depend on features that are
 available only in the latest versions.


 13. Using LIB to Combine Two Libraries

 Product Version(s): 3.00 3.04 3.07 3.08 3.10 3.11 3.14 3.17 | 3.11 3.14 3.17
 Operating System:   MS-DOS                                  | OS/2
 Flags: ENDUSER | s_lib
 Last Modified: 15-JAN-1991    ArticleIdent: Q25108

 The Microsoft Library Manager utility (LIB.EXE) can be used to combine
 two libraries into one.

 The following is an example of how to add the contents of LIB1.LIB to
 LIB2.LIB in a single LIB command:

    LIB LIB2.LIB+LIB1.LIB;

 You may also have LIB prompt you for input, in which case the input
 and prompts will appear as follows:

 LIB <RETURN>
 Library name: LIB2.LIB <RETURN>
 Operations: +LIB1.LIB <RETURN>

 Note that the .LIB extension is required; otherwise, LIB will assume
 LIB1 is an object module.


 14. Using EXEHDR or EXEMOD to Change the Stack Size of an .EXE

 Product Version(s): 1.00 2.01 | 1.00 2.01
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_exehdr s_exemod
 Last Modified:  6-FEB-1991    ArticleIdent: Q25321

 The EXEHDR and EXEMOD utilities can be used to change the stack size
 of a program. EXEHDR runs in both DOS and OS/2, while EXEMOD is an
 older utility that only runs under DOS.

 To view the current size of the stack, no options are used. Both
 EXEHDR and EXEMOD will produce a table of information with a line such
 as the following:

    Initial SS:SP 0000:0800 0

 The offset portion of this line gives the current stack size in hex.
 In this example, the stack size is set at 2K. If you wanted to change
 it to 4K, you could use the /STACK option of EXEHDR or EXEMOD in the
 following way:

    EXEHDR file /STACK 1000

 -or-

    EXEMOD file /STACK 1000


 15. Replacing Real Mode Family API Functions in Bound Applications

 Product Version(s): 1.00 1.10 1.30 | 1.00 1.10 1.30
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | s_bind
 Last Modified: 15-JAN-1991    ArticleIdent: Q39812

 Question:

 How do I create a bound application that uses the system calls in
 protected mode and uses my calls in real mode? The real mode call must
 access global data in my program.

 I would like to bind a program so that it will use the system
 VioGetConfig() function in protected mode, but will use my rewritten
 VioGetConfig() function when run in real mode. Everything compiles and
 links correctly, using either my function or the system function.
 However, my VioGetConfig accesses an initialized global int that is
 declared above the main(), which still compiles and links error free.
 But when I link the main with the system VioGetConfig, then bind the
 .EXE giving it the user's version of VioGetConfig, I get an unresolved
 external on the external global variable from the assembly routine.

 Response:

 The original strategy is probably the best method and should work
 correctly in the general case, that is, in the BIND step, specify the
 user version of VioGetConfig(). The problem is the global int
 variable. BIND does a link of the following:

    API stub loader
    API library modules
    protected-mode image with no symbols

 The key point is that BIND has no access to the internal name space of
 the program. Thus any API routine, including one rewritten by the
 user, cannot see any of the program's data. You should rewrite your
 VioGetConfig() so it does not use the global variable, if possible.
 Otherwise you will have to use one of the methods discussed below.

 Rather than using BIND, do it yourself. In the main program, use code
 such as the following:

     /* Under what operating system we are running ? */

     if (_osmode == DOS_MODE)
     {
         /* We are running under DOS - real mode */

         VioGetConfigUser(); /* User version */
     }
     else
     {
         /* We are running under OS/2 - protected mode */

         VioGetConfig();     /* System version */
     }

 Another way to do this is to build a dual-mode .EXE, as follows:

 1. Build your real-mode program using user VioGetConfig.

 2. Write protected-mode main program using OS/2 VioGetConfig.

 3. In the .DEF file for the protected-mode program, add the following
    statement:

       STUB '<name-of-your-real-mode-app>'

 4. Link your protected-mode application. You will get two programs in one
    .EXE file. In protected mode, the system will load only the
    protected-mode version. In real-mode, the system will load only
    real-mode applications.


 16. Page Size May Cause Big Size Increase When Combining Libraries

 Product Version(s): 3.0x 3.11 3.14 3.17 | 3.11 3.14 3.17
 Operating System:   MS-DOS              | OS/2
 Flags: ENDUSER | s_lib
 Last Modified: 15-JAN-1991    ArticleIdent: Q44896

 Question:

 When I use LIB.EXE to combine my libraries with a third-party library,
 the resultant library is much larger than I expected it to be.

 The following is an example:

     LIB1.LIB    5K   bytes
     LIB2.LIB    250K bytes

     LIB1.LIB + LIB2.LIB  = 305K bytes

 Why is the combined file 50K larger?

 Response:

 This size difference may be the result of different page sizes among
 the libraries being combined. The page size of a library affects the
 alignment of modules stored in the library. When libraries with
 different page sizes are combined, the resultant library uses the
 largest page size from the constituent libraries. Thus, the actual
 increase in file size represents wasted space between modules in the
 library. To reduce the amount of wasted space, you should specify a
 smaller page size for the new library. This may be accomplished by
 using the library manager as follows:

    LIB BIG.LIB /PAGESIZE:16;

 This sets the page size for the library BIG.LIB to 16 bytes.

 As indicated in the library manager documentation, the page size must
 be an integer power of 2 from 16 to 32,768 bytes.


 17. Helpmake Binary Format Is Proprietary

 Product Version(s): 1.00 1.05 1.06 | 1.00 1.05 1.06
 Operating System:   MS-DOS         | OS/2
 Flags: ENDUSER | s_helpmake
 Last Modified: 15-JAN-1991    ArticleIdent: Q48292

 The binary format of the help files produced by the Microsoft Helpmake
 utility is proprietary information, and therefore, not available for
 distribution.


 18. CALLTREE Produces Argument Mismatch with Void Parameter List

 Product Version(s): 1.00
 Operating System:   MS-DOS
 Flags: ENDUSER | s_calltree buglist1.00 s_editor
 Last Modified: 15-JAN-1991    ArticleIdent: Q46896

 The CALLTREE utility program included with the Microsoft C version
 5.10 produces the following error message if a void parameter list is
 used for the function foo() and the options -a and -b are specified on
 the command line:

    Argument Mismatch Calling        foo  in  main.c(10)

 Microsoft has confirmed this to be a problem in version 1.00. We are
 researching this problem and will post new information here as it
 becomes available.

 The CALLTREE utility program can be used to produce a tree-like
 structure of function usage. Documentation on the options for CALLTREE
 can be found in the C 5.10 CodeView and Utilities manual in the
 "Microsoft Editor for the MS OS/2 and MS-DOS Operating Systems: User's
 Guide," section on pages 112-114.

 The following program demonstrates the problem:

 void foo(void);   /* prototye contains (void) */

 void main(void)
 {
   foo();     /* function call does not contain (void) */
              /* replace with foo(void); to prevent warning message */
 }

 void foo(void)
 {
   printf("Inside foo\n");
 }

 Invoke CALLTREE by issuing the following command:

 calltree -a -b back.out -w warn.out main.c

 The "warn.out" file will now contain the error message:

    Argument Mismatch Calling        foo  in  main.c(5)


 19. Incorrect Response File Used with LIB Causes U1183 Error

 Product Version(s): 3.1x   | 3.1x
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER |
 Last Modified: 30-AUG-1989    ArticleIdent: Q47016

 Question:

 I want to use a response file entitled LIB_OPS with the library
 manager just for specifying my library operations. When I invoke LIB
 with the command

    LIB mylib.lib @lib_ops, mylib.lst;<cr>

 it generates the following error:

    LIB : fatal error U1183 : 'cannot open response file'

 However, when I invoke LIB using the command prompts and supply my
 response file for the Operations prompt as follows, everything works
 correctly:

     .
     .
     Operations: @lib_ops<cr>
     .
     .

 What differentiates the two cases?

 Response:

 Using a response file on the command line of the library manager
 requires that the response filename be delimited correctly. This is
 mandated by the command-line parser, which considers trailing argument
 delimiters such as a comma or semicolon to be part of the response
 filename. Consequently, the parsing of the unknown filename prohibits
 DOS from locating and opening the correct response file. When a
 response file is detected on the LIB command line (via the "@"
 character), the command interpreter parses following characters as the
 filename argument until a DOS delimiter, either a space character or a
 carriage return, is encountered. Hence, LIB commands such as

    LIB @response;<cr>
    LIB mylib.lib @response, mylib.lst;<cr>

 generate the U1183 "cannot open response file" because the file
 "response" is actually parsed as "response;" and "response,",
 respectively, neither of which exist in the current working directory
 or those directories searched for by the DOS APPEND command. However,
 correctly delimiting the end of the response file argument with a
 space or carriage return allows the following LIB commands to work
 correctly:

    LIB @response ;<cr>
    LIB @response<cr>
    LIB mylib.lib @response ,mylib.lst;<cr>

 When operating the library manager with a response file containing
 information for one or more of the LIB arguments, it must be invoked
 in one of the following two ways:

 1. With the response file supplied on the LIB command line and the
    file's final character delimited correctly (by a space or carriage
    return).

 2. With no command line arguments and the response file used as a
    reply to the appropriate LIB command prompt.

 The first method is discussed and illustrated in the information
 above. The second method of using the library manager prompts is
 equally effective. However, when supplying a response file to a LIB
 command prompt, the filename must be delimited correctly as in the
 aforementioned, or the U1183 error occurs. The following example
 demonstrates the generation of this error due to incorrect delimiting
 of the response file:

 LIB<cr>

 Microsoft (R) Library Manager  Version 3.14
 Copyright (C) Microsoft Corp 1983-1988. All rights reserved

 Library name: mylib.lib<cr>

 Operations: @response;<cr>

 LIB : Fatal Error U1183:  Cannot open response file

 Correcting the response file argument to the Operations prompt as
 follows eliminates the problem:

 Operations: @response<cr>

 or

 Operations: @response thisisextrajunkbutwillworkcuzofthe<space>delimiter


 20. LIB Version 3.17 Available for Increased Library Capacity

 Product Version(s): 3.17   | 3.17
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | appnote SS0329.ARC s_lib
 Last Modified: 17-DEC-1990    ArticleIdent: Q66569

 The Microsoft Library Utility (LIB.EXE) version 3.17 is available to
 registered users of Microsoft language products who are experiencing
 difficulty creating libraries with older versions of LIB due to
 capacity limits. If you are the registered owner of a Microsoft
 language product, you may obtain LIB 3.17 as an application note from
 Microsoft Product Support Services by calling (206) 637-7096.

 LIB 3.17 can also be found in the Software/Data Library by searching
 on the keyword SS0329, the Q number of this article, or S12776. SS0329
 was archived using the PKware file-compression utility.

 Older versions of the Microsoft Library Manager are somewhat limited
 as far as the size of a library that can be created or the number of
 modules or symbols that a library can contain. These limits are not
 specific because the actual limits for any particular library are the
 result of a combination of factors including the number of modules,
 the number of symbols, the page size used, and the order in which
 items are added to the library.

 One indication of a library capacity problem is if a previously usable
 library suddenly causes the linker to generate the error message
 "L1101: invalid object module" after some additions to the library.

 Newer versions of LIB, such as version 3.17, have improved capacity
 over the earlier versions. Thus, libraries with a greater number of
 object modules, and/or a greater overall size, should be possible,
 even though the exact limits are still specific to each particular
 library.

 No documentation for the Library Manager is supplied with the
 application note because its usage and commands are identical to
 previous versions. Any questions concerning the usage, command syntax,
 or options for this version can be addressed by referring to existing
 LIB documentation.


 21. "Packed File Corrupt" Error

 Product Version(s): 3.x 4.x
 Operating System:   MS-DOS
 Flags: ENDUSER | s_link s_c h_fortran s_pascal s_quickc h_masm b_basic
 Last Modified: 12-FEB-1991    ArticleIdent: Q58225

 Question:

 When I attempt to run my program, I get the error message "Packed File
 Corrupt." What causes this error and how can I run my program?

 Response:

 The error is caused by a problem in the packed EXE loader that is
 incorporated into EXEPACKed files. This causes incorrect loading of
 packed files. The problem only occurs when the program is loaded into
 memory before the first 64K byte boundary.

 CHKDSK reports more than 589,824 bytes of free memory. Typically, this
 problem tends to occur with DOS Version 3.30 when you try to free up
 more memory by setting the files and buffers in your CONFIG.SYS file
 to less than their default values.

 To correct this problem, force DOS to load the program above the first
 64K of memory by increasing the amount of memory DOS uses. One way to
 do this is to fill up the first 64K segment with one or more copies of
 COMMAND.COM.

 You can also use copies of COMMAND.COM to diagnose the problem. Spawn
 a new command interpreter by typing "COMMAND" at the DOS prompt. Then
 try to run the program. Keep spawning copies of COMMAND.COM until the
 program runs. When the program runs, you have successfully filled the
 first 64K.

 If this method works, you may resolve the problem in a more permanent
 manner by increasing the number of files and buffers in the CONFIG.SYS
 file, and rebooting your machine.

 The EXEPACK utility compresses sequences of identical characters from
 a specified executable file. It also optimizes the relocation table,
 whose entries are used to determine where modules are loaded into
 memory when the program is executed. When the program is executed, it
 must first unpack the file into memory. It is the unpacking code that
 unpacks incorrectly and generates the "Packed File Corrupt" error.

 For more information on the EXEPACK utility, refer to Page 321 in the
 "Microsoft CodeView and Utilities" manual shipped with C version 5.10.
 For information on the /EXEPACK linker option, refer to the utilities
 manual or online help shipped with your particular version of the
 compiler or assembler.
 Additional reference words: b_quickbasic o_msdos h_mouse h_mspbrush


 22. CVPACK May Lose Type Information in Large Files

 Product Version(s): 2.01 3.01 | 2.01 3.01
 Operating System:   MS-DOS    | OS/2
 Flags: ENDUSER | s_cvpack s_codeview
 Last Modified:  5-FEB-1991    ArticleIdent: Q58718

 Certain type information such as that required to expand a structure
 using the "?? <structurename>" command in CodeView can be lost in
 large files when using CVPACK.

 Running CVPACK on very large executables may remove such information
 from the file. Before running CVPACK, internal information can be
 viewed and members can be expanded on structures; after CVPACK, only
 the structure's address is viewable.

 The reason this occurs is that CVPACK is stripping out information
 that CodeView needs to correctly display pointers to far data.

 In this case, CodeView attempts to provide information on the pointers
 to far data in the structure, but the information it gives is not
 correct. Observing the change in the structure's segment address
 before and after using CVPACK shows that this address changes while
 the offset address remains the same. Therefore, the correct
 information cannot be displayed, and CodeView emits a warning beep
 instead of showing the expanded structure elements.


 23. BIND Error "Import By Ordinal Not Defined: DOSCALLS.5"

 Product Version(s): 1.00   | 1.00
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_bind
 Last Modified: 27-DEC-1990    ArticleIdent: Q58929

 Question:

 When I use BIND version 1.00 to bind my OS/2 program, the following
 error message is returned:

    Import by ordinal not defined: DOSCALLS.5

 I bind my program with the following:

    BIND hello.exe -o hellob.exe

 Why do I get that error when I call FAPI functions by name and not
 their ordinal numbers?

 Response:

 The above error occurs because DOSCALLS.LIB must be listed on the BIND
 command line. Bind automatically searches for API.LIB and OS2.LIB
 (using the LIB environment variable), but not DOSCALLS.LIB.

 When using bind, DOSCALLS.LIB must be explicitly listed on the command
 line and the LIB environment variable must point to API.LIB and
 OS2.LIB. For example:

    BIND hello.exe c:\c510\lib\doscalls.lib -o hellob.exe


 24. LIB.EXE Failure When Trying to Build Large Libraries

 Product Version(s): 3.11   | 3.11
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_lib appnote
 Last Modified: 17-DEC-1990    ArticleIdent: Q59892

 When using versions of the Microsoft Library Manager (LIB.EXE) earlier
 than Version 3.14 to try to build large libraries with many symbols
 and modules, the LIB program may fail due to capacity limits.

 If you encounter various failures or random errors when trying to
 build a large library (for example, the Greenleaf Libraries), you
 should contact Microsoft Product Support at (206) 637-7096 to obtain a
 more recent version of LIB.EXE.

 LIB.EXE is shipped with all Microsoft language products for building
 and maintaining run-time libraries. Earlier versions of LIB run into
 problems when the library size approaches 200K or larger, but the
 point at which LIB may fail varies widely. LIB capacity is
 unpredictable because it is affected by such items as the number of
 symbols, the number of modules, and the length of symbol names.

 Sometimes, just changing the order in which modules are added to a
 large library will resolve the problem (or at least alter the point of
 failure or the particular errors generated). Some of the errors
 reported from capacity failures are U1174, U1188, and U1189.

 Errors such as U1174 and U1189 are documented only as being problems
 for which you should contact Microsoft Product Support. In general,
 these errors indicate major LIB capacity overflow problems and the
 best workaround is to update to a newer version of LIB.EXE.


 25. Bound Program Works Under OS/2, but Hangs Under DOS

 Product Version(s): 1.10   | 1.10
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_bind h_fortran s_link
 Last Modified: 15-JAN-1991    ArticleIdent: Q61469

 If you use BIND version 1.10 and the OS/2 Linker/2 Version 1.20, the
 program will bind error-free and will run correctly under OS/2, but
 will hang the machine if run under DOS.

 BIND version 1.10 creates an executable that hangs under DOS but runs
 correctly in OS/2 if the program is linked with the OS/2 linker
 version 1.20. Using BIND 1.10 with LINK version 5.03 resolves this
 problem, and using BIND 1.20 or later with the OS/2 linker also
 creates a valid executable for DOS and OS/2.


 26. Using /help Option with RM.EXE Displays EXP.EXE Online Help

 Product Version(s): 1.01   | 1.01
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_rm s_pwb s_editor docerr
 Last Modified: 17-DEC-1990    ArticleIdent: Q61967

 The utility program RM.EXE version 1.01 displays the wrong help screen
 when invoked with the /help option. The /help parameter is designed to
 invoke the Quick Help (QH) utility in order to display the online help
 for RM.EXE. Because the wrong utility name was written into the RM.EXE
 file, the help screen displayed for RM with /help is the help
 information for the EXP utility.

 This error is due to a problem in the RM.EXE file, rather than being a
 problem in the help files; thus there is no easy way to correct this
 problem. To access the correct help information for RM, one of the
 following methods may be used:

 1. Invoke Quick Help directly. Use RM as the parameter to indicate RM
    as the item on which to find help (for example, type QH RM at the
    DOS or OS/2 prompt).

 2. Invoke RM with the /help option (for example, type RM /help at the
    prompt) and when the EXP help screen appears, page down to the
    bottom where there is a link labeled "RM Command." Select this link
    and the RM help screen will be displayed.

 3. Help on RM can be accessed from within the Programmer's WorkBench
    (PWB) by selecting "Miscellaneous" on the main Help Contents screen
    (in the box titled Microsoft Utilities), and then selecting "RM
    Command" from the submenu.


 27. Helpmake Version 1.05 May Not Decode All Formatting

 Product Version(s): 1.05   | 1.05
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_helpmake buglist1.05 fixlist1.06
 Last Modified: 23-JAN-1991    ArticleIdent: Q64792

 HELPMAKE version 1.05 (shipped with Microsoft C version 6.00) does not
 decode all formatting information in help files decoded with the /D
 option. HELPMAKE version 1.03 (shipped with the OS/2 1.20 SDK) works
 as expected.

 This lack of decoding will result in no bold, green, italic, or
 underline formatting in help files that are compressed again with
 HELPMAKE.

 Microsoft has confirmed this to be a problem in HELPMAKE version 1.05.
 This problem was corrected in HELPMAKE version 1.06. HELPMAKE 1.06 was
 shipped with the Microsoft Advisor Library.

 Example
 -------

 The "\i" and "\p" options are not decoded in the sample below. This
 excerpt is from PWB 1.00 version of the PWB.HLP file.

 Note: Nonprintable characters are removed from these examples.

 From HELPMAKE version 1.03:

    +------- Browse Menu ---------+
    | \i\a\pGoto Definition...\v@L8001\v\i\p | Finds definition of symbol

 From HELPMAKE version 1.05:

    +------- Browse Menu ---------+
    | \aGoto Definition...\v@L8001\v | Finds definition of symbol


 28. QuickHelp Duplicate Search Brings Up Wrong Help

 Product Version(s): 1.70   | 1.70
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_qh buglist1.70 SDK
 Last Modified: 17-DEC-1990    ArticleIdent: Q67234

 In QuickHelp, if you select Duplicate Search from the View menu and
 enter a search string containing a wildcard, all the topics that match
 that string should appear. In some cases, however, all of the
 occurrences are NOT displayed, which causes the help topics to be out
 of sync with the information they bring up. When this problem occurs,
 you may select a topic, and help on a different topic will be
 displayed.

 One example of this problem occurs when searching on _dos* with the
 CLANG.HLP help file that comes with Microsoft C version 6.00. Another
 example is found when searching for wm_* in the SDKADV.HLP help file
 that comes with the Windows 3.00 Software Development Kit. In both
 cases, if you go to the end of the list of topics and bring up the
 information, the wrong help will be displayed.

 Microsoft has confirmed this to be a problem in QuickHelp version
 1.70. We are researching this problem and will post new information
 here as it becomes available.


 29. Hyperlink for MakeProcInstance in SDKADV.HLP Incorrect

 Product Version(s): 1.70   | 1.70
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | s_qh docerr
 Last Modified: 17-DEC-1990    ArticleIdent: Q67397

 When accessing the function MakeProcInstance() from the index in
 QuickHelp version 1.70, the help screen for Windows DataTypes is
 presented instead. This behavior may be duplicated by following the
 procedure outlined below:

 Start QuickHelp with an argument to get help on any windows topic, as
 follows:

    qh wndclass

 This will bring up the help screen for the wndclass structure. Now
 click the right button on the QuickHelp index, and then on the
 alphabetical section for M. At this point, if help for
 MakeProcInstance() is chosen, QuickHelp will, instead, bring up the
 help screen for Windows Data Types.

 If the SDKADV.HLP file is decoded using HELPMAKE, as follows

    helpmake /D /Osdk.doc sdkadv.hlp

 it becomes obvious that the reason for this error is that the
 hyperlink for MakeProcInstance() appears as follows in the decoded
 help file:

    \aMakeProcInstance function \vDatatypes\v

 This causes QuickHelp to display the DataTypes help screen instead of
 help for the appropriate function.

 This problem can be corrected by changing the above line to read as
 follows:

    \aMakeProcInstance function \vMakeProcInstance\v

 The SDKADV.HLP file must then be recompressed, as follows:

    helpmake /E0 /T /Osdkadv.hlp sdk.doc

 The choice of /E0 indicates no compression, and is strictly arbitrary
 in this case. If maximum compression is desired, the 0 argument to the
 /E switch may be left off, or /E15 may be specified.


 30. The Syntax for STACK Is Incorrect in EXEHDR Usage Statement

 Product Version(s): 2.01   | 2.01
 Operating System:   MS-DOS | OS/2
 Flags: ENDUSER | docerr s_exehdr
 Last Modified: 17-DEC-1990    ArticleIdent: Q67793

 When the /? parameter is used for EXEHDR, a listing is displayed
 detailing the various switches accepted by EXEHDR. This list
 incorrectly indicates that the /STACK switch must be followed by a
 hexadecimal number between 0h and ffffh. In reality, the /STACK switch
 must be followed by either a decimal number between 0 and 65535 or a
 hexadecimal number using C notation (0x0 - 0xffff).

 If any other format is used, EXEHDR will return the following error
 messages:

    EXEHDR: error U1110: malformed number xxxx
    EXEHDR: error U1115: option /STACK:xxxx ignored

